Closed Bug 1274965 Opened 9 years ago Closed 2 years ago

Figure out the proper way to model the execution context stack

Categories

(Core :: JavaScript Engine, defect)

defect

Tracking

()

RESOLVED INCOMPLETE
Tracking Status
firefox49 --- affected

People

(Reporter: bzbarsky, Unassigned)

Details

ES has a concept of "execution context stack" (defined at <https://tc39.github.io/ecma262/#execution-context-stack>) which doesn't have a clear reflection in Gecko. I suspect we need to fix this. Some things that make this complicated: 1) Within ES itself, I think the execution context stack more or less corresponds to something our JS engine maintains. However HTML also pushes things onto this stack, to support entry settings stuff. I'm not sure whether it's worth doing that, though; we have a perfectly reasonable setup for the entry settings. The worry is whether the model mismatch will lead to subtle bugs wrt spec. 2) HTML supports setting aside this stack (yeah, I know, we're right now removing JS_SaveFrameChain!). It does this when it spins the event loop. See https://html.spec.whatwg.org/multipage/webappapis.html#spin-the-event-loop steps 3, 4, 10. Note that unlike our uses of JS_SaveFrameChain this bit is well-specced in principle and has clear semantics. Though I'm not sure we actually have anything quite like the implementation of "spin the event loop", nor whether it's really implementable sanely in situations where it's called with script on the stack... 3) The setting aside matters because microtask (and hence promise execution) only happens at the end of script execution, per spec, once the execution context stack is empty. See https://html.spec.whatwg.org/multipage/webappapis.html#clean-up-after-running-script step 5. This matters in practice for cases when an alert is up and the user clicks something in another tab: do promises run after every click handler or when returning to the event loop from event dispatch? Right now Gecko only runs microtasks from the event loop, not end of script execution, but if we wanted to change that we'd need to detect this empty execution context stack situation. Yes, this feels like crappy "JS_IsRunning" reintroduction. Except it only knows about content stuff, not chrome stuff, unless you're asking in chrome... Maybe what all this comes down to is that we need a runtime-wide "set aside the stack" thing that we do when we spin the event loop. And it would only affect microtask execution.
And I guess whatever thing we use to check for "empty stack" would principal-filter or something, to handle the case when a runnable calls chrome code that dispatches an event to content; that event should have microtasks run after every listener.
Oh, and the model mismatch for #1 might in fact matter. Consider something like: setTimeout(foo.dispatchEvent.bind(foo, whatever)) Per current spec proposals, I believe this will only execute microtasks once the dispatchEvent call finishes, because the call into the timeout handler will push a thing on the "execution context stack".... But the spec here may be in flux.
CC'ing Servo folks who probably should be aware of this, too.
Actually, if the spec stays as-is, maybe we can simply model this on the browser side as follows: 1) When popping the entry settings stack, if it's now empty (conceptually) execute microtasks. 2) When spinning the event loop, set aside (conceptually) the entry settings stack. We can do that either via actually setting it aside, or via pushing a "this is empty" thing on it or something. We'd still need to think a bit about the "chrome calls dispatchEvent" case and how to do that right....
Severity: normal → S3
Status: NEW → RESOLVED
Closed: 2 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.