Promise reaction job is not called when it is bound with Function.prototype.bind from iframe with discarded browsing context
Categories
(Core :: JavaScript Engine, defect, P1)
Tracking
()
People
(Reporter: roland, Assigned: arai)
References
(Regression)
Details
(Keywords: parity-chrome, parity-safari, regression)
Attachments
(4 files, 1 obsolete file)
|
841 bytes,
text/html
|
Details | |
|
541 bytes,
text/html
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
RyanVM
:
approval-mozilla-beta+
|
Details | Review |
|
48 bytes,
text/x-phabricator-request
|
RyanVM
:
approval-mozilla-beta+
|
Details | Review |
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
Steps to reproduce:
- Open https://hermanitos.ch/index.php/shop
- Open developer console
- Paste and run the following code:
(new Promise(function (resolve) {
resolve();
}))
.then(function () {
console.log('Hello')
})
.then(function () {
console.log('World')
}.bind(this));
Actual results:
Prints on the console:
Hello
Expected results:
Prints on the console:
Hello
World
Comment 1•4 years ago
|
||
Very strange. I can reproduce this issue on the site you mentioned, but not on e.g. http://example.org. The Promise stays pending. Arai do you have an idea? I thought maybe then is overwritten or something, but I doesn't look like it.
I tried to debug it myself and all core things what I checked were [native code]
Promise.toString()
Function.bind.toString()
(function () {
console.log('World')
}).bind.toString()
(new Promise(function (resolve) {})).then.toString()
(new Promise(function (resolve) {
resolve();
})).then(function(){}).then.toString()
This issue affects all sites which made with Ecwid: https://www.ecwid.com
So it might be an error in their code, but it looks like they triggered some kind of browser bug.
| Assignee | ||
Comment 3•4 years ago
|
||
it happens if a page loads https://app.ecwid.com/script.js?6848023
will investigate more.
Attached a reduced test.
I was able to narrow it down, but stuck. I think something in this injected script cause this issue:
https://d2scn539ulxr09.cloudfront.net/static/br/2021-30677-g515270bf75f/F57A9FB1FC384BAF8CF3B63EFDEAE420.cache.js
Comment 5•4 years ago
|
||
| Assignee | ||
Comment 6•4 years ago
|
||
there's the following code (prettified), in https://d2scn539ulxr09.cloudfront.net/static/br/2021-30677-g515270bf75f/A66F35FBA011F122D2A83F7B91CC58EA.cache.js
var frame = document.createElement('iframe');
frame.src = 'about:blank';
frame.style.display='none';
document.body.appendChild(frame);
Function.prototype.bind = frame.contentWindow.Function.prototype.bind;
frame.remove();
that seems to be related, given it's about Function.prototype.bind
| Comment hidden (obsolete) |
| Assignee | ||
Comment 8•4 years ago
|
||
fixed some typo
no change in the logic
| Assignee | ||
Updated•4 years ago
|
| Assignee | ||
Comment 9•4 years ago
|
||
it's a bug when creating a promise reaction job.
the spec requires using GetFunctionRealm, that handles bound function.
https://tc39.es/ecma262/#sec-newpromisereactionjob
27.2.2.1 NewPromiseReactionJob ( reaction, argument )
...
3. If reaction.[[Handler]] is not empty, then
a. Let getHandlerRealmResult be GetFunctionRealm(reaction.[[Handler]].[[Callback]]).
b. If getHandlerRealmResult is a normal completion, set handlerRealm to getHandlerRealmResult.[[Value]].
c. Else, set handlerRealm to the current Realm Record.
d. NOTE: handlerRealm is never null unless the handler is undefined. When the handler is a revoked Proxy and no ECMAScript code runs, handlerRealm is used to create error objects.
4. Return the Record { [[Job]]: job, [[Realm]]: handlerRealm }.
https://tc39.es/ecma262/#sec-getfunctionrealm
7.3.24 GetFunctionRealm ( obj )
...
3. If obj is a bound function exotic object, then
a. Let target be obj.[[BoundTargetFunction]].
b. Return ? GetFunctionRealm(target).
but we just use the function object's realm,
that's bind function's realm in this case.
mozilla::Maybe<AutoRealm> ar2;
if (handler.isObject()) {
...
JSObject* handlerObj = UncheckedUnwrap(&handler.toObject());
MOZ_ASSERT(handlerObj);
ar2.emplace(cx, handlerObj);
So, in the spec, the reaction job is created with the top-level frame's realm,
but we create the reaction job with iframe's realm.
and HostEnqueuePromiseJob doesn't call the reaction job if the iframe is removed from the tree.
| Assignee | ||
Updated•4 years ago
|
| Assignee | ||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
| Assignee | ||
Comment 10•4 years ago
|
||
Creating reaction job should use GetFunctionRealm with unchecked unwrap,
to support promise across chrome/content compartments.
Creating thenable job should use GetFunctionRealm with checked unwrap,
given thenable job across chrome/content compartments isn't supposed to happen
in normal case.
| Assignee | ||
Comment 11•4 years ago
|
||
Updated•4 years ago
|
Comment 12•4 years ago
|
||
Comment 13•4 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/0fcc1b66665f
https://hg.mozilla.org/mozilla-central/rev/ec84082e8780
Comment 14•4 years ago
|
||
Is this something we should consider uplifting to Beta?
| Assignee | ||
Comment 15•4 years ago
|
||
Comment on attachment 9234811 [details]
Bug 1723124 - Part 1: Use GetFunctionRealm when creating promise reaction/thenable jobs. r?jandem!
Beta/Release Uplift Approval Request
- User impact if declined: Website breakage (very edge case tho), parity with other browsers.
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: Yes
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Medium
- Why is the change risky/not risky? (and alternatives if risky): It changes the behavior around the security wrapper between privilege code and web content code, mostly hardening the boundary, but introduces extra paths than before.
- String changes made/needed:
| Assignee | ||
Updated•4 years ago
|
Comment 16•4 years ago
|
||
Comment on attachment 9234811 [details]
Bug 1723124 - Part 1: Use GetFunctionRealm when creating promise reaction/thenable jobs. r?jandem!
Approved for 92.0b3.
Updated•4 years ago
|
Comment 17•4 years ago
|
||
| bugherder uplift | ||
Description
•