Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the entry settings object for promise callbacks #5212

Merged
merged 1 commit into from
Feb 12, 2020

Conversation

domenic
Copy link
Member

@domenic domenic commented Jan 15, 2020

Closes #1426.

/cc @syg @littledan @bzbarsky @tschneidereit.

I was kind of waiting for tc39/ecma262#735 to land since that will change things, but I guess we should just fix this now, especially since #4571 needs to add something similar.

(See WHATWG Working Mode: Changes for more details.)


/infrastructure.html ( diff )
/webappapis.html ( diff )

@syg
Copy link
Contributor

syg commented Jan 15, 2020

We came up with a test where Chrome doesn't correctly thread the backup incumbent settings object for promise callbacks, though not in a way I yet understand...

Copy link
Contributor

@littledan littledan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These semantics (and the ones proposed at #4571 (comment)) seem reasonable to me.

Looks like this PR is about the entry Realm, not the backup incumbent settings object, so I don't see why mismatches there should block it from landing. (I'm not surprised if V8 doesn't handle this in the way Firefox does, and I'm worried it could be a bit complex to correct it.)

Minor: For entry, I'd editorially prefer it if we passed the realm up into HTML from the JS spec, but I'm fine with this landing as is; we can do whatever refactor later.

@domenic
Copy link
Member Author

domenic commented Jan 16, 2020

Thanks @littledan! I agree there are definitely better editorial/layering ways to do this if we can make changes on the 262 side. (That holds for incumbent too, I think: #5213.)

@domenic
Copy link
Member Author

domenic commented Jan 22, 2020

@bzbarsky ping on this, the tests at web-platform-tests/wpt#21206, and perhaps the discussion in #5213.

@bzbarsky
Copy link
Contributor

So in terms of what Firefox implements here...

For a PromiseResolveThenableJob we seem to use the global of the thenAction argument (in spec terms) as the entry global, if I read the code right. That matches the proposed spec.

For a PromiseReactionJob we seem to use the global of the reaction's [[Handler]], if [[Handler]] is defined. That too matches the proposed spec.

For a PromiseReactionJob when [[Handler]] is not defined, I think we set the entry global to whatever the current global is at the point when we are creating the PromiseReactionJob, as far as I can tell. Which is not great. This is in fact somewhat observable, because we later do perform a "is it OK to run script in this global?" check, and if that returns false then the reaction's steps are not performed, I would think, even though they technically do not involve running script. I haven't looked at this stuff recently, but from code inspection it looks like this can happen for the then(non_callable) case (and similar for the rejection handler), something to do with "Async-from-Sync Iterator Objects", something to do with async functions (presumably the await special-case), and something to do with async generators.

There are certainly some interesting questions there. For example, if an async function is awaiting a promise and its window gets unloaded, and then the promise gets resolved, should the async function resume? In Gecko, I think it would, as long as the resolution happened from a window that was not yet unloaded. Per proposed spec it would in all cases, because the "check if we can run script" check gets skipped. What behavior do we want here?

@domenic
Copy link
Member Author

domenic commented Feb 11, 2020

What behavior do we want here?

I think the proposed spec is fairly reasonable, in that it tries to maintain a symmetry between promise.then().then(f) and promise.then(f). That is, it seems reasonable to me that introducing a no-handler then() should not introduce additional opportunities for scripting-is-disabled checks.

@bzbarsky
Copy link
Contributor

Sure, but the thing that await does is not really "no-handler" in an important sense. That is, when the promise being awaited resolves, some script will run, and the question is whether at that point a check for whether scripting is disabled should happen. This is a significant difference from the promise.then().then(f) case, no?

@domenic
Copy link
Member Author

domenic commented Feb 11, 2020

Hmm, I might be confused then. The spec only skips the check if there's no handler, whereas await has a handler which performs a continuation. Right?

@bzbarsky
Copy link
Contributor

Ah, interesting. So in terms of specification await has a non-observable handler function. In terms of implementation, it's implemented at least in SpiderMonkey as a PromiseReactionJob with no handler and some extra state of some sort, as far as I can tell (and I could very well be wrong!). So one just has to be very careful mapping from spec to implementation...

Copy link
Member

@annevk annevk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming here that arguments, arguments[2], and arguments[0] can never be undefined or equivalent.

Is there an issue somewhere that tracks the further refactoring @littledan mentioned?

@domenic
Copy link
Member Author

domenic commented Feb 12, 2020

Thanks!

I double-checked, and yeah, those are never undefined.

I think tc39/ecma262#735 is the refactoring.

@domenic domenic merged commit 344798b into master Feb 12, 2020
@domenic domenic deleted the entry-for-promise-jobs branch February 12, 2020 17:48
domenic added a commit to web-platform-tests/wpt that referenced this pull request Feb 12, 2020
@littledan
Copy link
Contributor

littledan commented Feb 12, 2020

I agree that these are never undefined. I think we'd need the further refactoring I alluded to in #5212 (review) to make this cleaner, but let's wait on that until tc39/ecma262#1597 goes through (which is the new tc39/ecma262#735).

moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Feb 17, 2020
… for promise jobs, a=testonly

Automatic update from web-platform-tests
Test entry and incumbent settings object for promise jobs

Follows whatwg/html#5212 and whatwg/html#5213.
--

wpt-commits: bc4ddbbddc566c3602d1af8d73c0225f8335855d
wpt-pr: 21206
xeonchen pushed a commit to xeonchen/gecko that referenced this pull request Feb 18, 2020
… for promise jobs, a=testonly

Automatic update from web-platform-tests
Test entry and incumbent settings object for promise jobs

Follows whatwg/html#5212 and whatwg/html#5213.
--

wpt-commits: bc4ddbbddc566c3602d1af8d73c0225f8335855d
wpt-pr: 21206
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this pull request Feb 18, 2020
… for promise jobs, a=testonly

Automatic update from web-platform-tests
Test entry and incumbent settings object for promise jobs

Follows whatwg/html#5212 and whatwg/html#5213.
--

wpt-commits: bc4ddbbddc566c3602d1af8d73c0225f8335855d
wpt-pr: 21206

UltraBlame original commit: 3017b5083bf29149178a2c1357796936a5a95065
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this pull request Feb 18, 2020
… for promise jobs, a=testonly

Automatic update from web-platform-tests
Test entry and incumbent settings object for promise jobs

Follows whatwg/html#5212 and whatwg/html#5213.
--

wpt-commits: bc4ddbbddc566c3602d1af8d73c0225f8335855d
wpt-pr: 21206

UltraBlame original commit: 3017b5083bf29149178a2c1357796936a5a95065
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this pull request Feb 18, 2020
… for promise jobs, a=testonly

Automatic update from web-platform-tests
Test entry and incumbent settings object for promise jobs

Follows whatwg/html#5212 and whatwg/html#5213.
--

wpt-commits: bc4ddbbddc566c3602d1af8d73c0225f8335855d
wpt-pr: 21206

UltraBlame original commit: 3017b5083bf29149178a2c1357796936a5a95065
backwardn pushed a commit to backwardn/v8 that referenced this pull request Feb 28, 2020
When a microtask is executed, we need to use an appropriate,
non-detached Context for its execution. Currently with
PromiseResolveThenableJobs [1], the Context used is always drawn from
the realm of the Promise constructor being used. This may cause
non-intuitive behavior, such as in the following case:

  const DeadPromise = iframe.contentWindow.Promise;
  const p = DeadPromise.resolve({
    then() {
      return { success: true };
    }
  });
  p.then(result => { console.log(result); });

  // Some time later, but synchronously...
  iframe.src = "http://example.com"; // navigate away.
  // DeadPromise's Context is detached state now.
  // p never gets resolved, and its reaction handler never gets called.

To fix this behavior, when PromiseResolveThenableJob is being queued up,
the `then` method of the thenable should be used to determine the
context of the resultant microtask. Doing so aligns with Firefox, and
also with the latest HTML spec [2][3].

This change is analogous to CL 1465902, which uses the realm of the
reaction handlers to determine the Context PromiseReactionJobs run in.

[1]: https://tc39.es/ecma262/#sec-promiseresolvethenablejob
[2]: https://html.spec.whatwg.org/C/#enqueuejob(queuename,-job,-arguments)
[3]: whatwg/html#5212

Bug: v8:10200
Change-Id: I2312788eeea0f9e870c13cf3cb5730a87d15609e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2071624
Commit-Queue: Timothy Gu <timothygu@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66507}
backwardn pushed a commit to backwardn/v8 that referenced this pull request Feb 29, 2020
This reverts commit 9325397.

Reason for revert: Causing blink layout failures. See 

https://ci.chromium.org/p/v8/builders/ci/V8%20Blink%20Linux%20Future/2684

Original change's description:
> Use context of then function for PromiseResolveThenableJob
> 
> When a microtask is executed, we need to use an appropriate,
> non-detached Context for its execution. Currently with
> PromiseResolveThenableJobs [1], the Context used is always drawn from
> the realm of the Promise constructor being used. This may cause
> non-intuitive behavior, such as in the following case:
> 
>   const DeadPromise = iframe.contentWindow.Promise;
>   const p = DeadPromise.resolve({
>     then() {
>       return { success: true };
>     }
>   });
>   p.then(result => { console.log(result); });
> 
>   // Some time later, but synchronously...
>   iframe.src = "http://example.com"; // navigate away.
>   // DeadPromise's Context is detached state now.
>   // p never gets resolved, and its reaction handler never gets called.
> 
> To fix this behavior, when PromiseResolveThenableJob is being queued up,
> the `then` method of the thenable should be used to determine the
> context of the resultant microtask. Doing so aligns with Firefox, and
> also with the latest HTML spec [2][3].
> 
> This change is analogous to CL 1465902, which uses the realm of the
> reaction handlers to determine the Context PromiseReactionJobs run in.
> 
> [1]: https://tc39.es/ecma262/#sec-promiseresolvethenablejob
> [2]: https://html.spec.whatwg.org/C/#enqueuejob(queuename,-job,-arguments)
> [3]: whatwg/html#5212
> 
> Bug: v8:10200
> Change-Id: I2312788eeea0f9e870c13cf3cb5730a87d15609e
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2071624
> Commit-Queue: Timothy Gu <timothygu@chromium.org>
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Reviewed-by: Shu-yu Guo <syg@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#66507}

TBR=verwaest@chromium.org,timothygu@chromium.org,syg@chromium.org

Change-Id: I81737750f8b369567ba586c5a2cfb489836b7e74
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:10200
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2081091
Reviewed-by: Francis McCabe <fgm@chromium.org>
Commit-Queue: Francis McCabe <fgm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66510}
pull bot pushed a commit to p-g-krish/v8 that referenced this pull request Mar 4, 2020
This is a reland of 9325397

Original change's description:
> Use context of then function for PromiseResolveThenableJob
> 
> When a microtask is executed, we need to use an appropriate,
> non-detached Context for its execution. Currently with
> PromiseResolveThenableJobs [1], the Context used is always drawn from
> the realm of the Promise constructor being used. This may cause
> non-intuitive behavior, such as in the following case:
> 
>   const DeadPromise = iframe.contentWindow.Promise;
>   const p = DeadPromise.resolve({
>     then() {
>       return { success: true };
>     }
>   });
>   p.then(result => { console.log(result); });
> 
>   // Some time later, but synchronously...
>   iframe.src = "http://example.com"; // navigate away.
>   // DeadPromise's Context is detached state now.
>   // p never gets resolved, and its reaction handler never gets called.
> 
> To fix this behavior, when PromiseResolveThenableJob is being queued up,
> the `then` method of the thenable should be used to determine the
> context of the resultant microtask. Doing so aligns with Firefox, and
> also with the latest HTML spec [2][3].
> 
> This change is analogous to CL 1465902, which uses the realm of the
> reaction handlers to determine the Context PromiseReactionJobs run in.
> 
> [1]: https://tc39.es/ecma262/#sec-promiseresolvethenablejob
> [2]: https://html.spec.whatwg.org/C/#enqueuejob(queuename,-job,-arguments)
> [3]: whatwg/html#5212
> 
> Bug: v8:10200
> Change-Id: I2312788eeea0f9e870c13cf3cb5730a87d15609e
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2071624
> Commit-Queue: Timothy Gu <timothygu@chromium.org>
> Reviewed-by: Toon Verwaest <verwaest@chromium.org>
> Reviewed-by: Shu-yu Guo <syg@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#66507}

Bug: v8:10200
Change-Id: I5af003a06c60b0c8cd19de47f847a947d40d046c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2082109
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Timothy Gu <timothygu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66586}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration Better coordination across standards needed topic: event loop topic: multiple globals
Development

Successfully merging this pull request may close these issues.

"Entry" concept is broken while executing enqueued jobs
5 participants