Re: Scheduling multiple types of end-of-(micro)task work

On Thu, Oct 18, 2012 at 2:08 PM, Rafael Weinstein <rafaelw@google.com> wrote:
> CSS Regions regionLayoutUpdate brings up an issue I think we need to
> get ahead of:
>
>   https://www.w3.org/Bugs/Public/show_bug.cgi?id=16391
>
> For context:
> --------
> Mutation Observers are currently spec'd in DOM4
>
>     http://dom.spec.whatwg.org/#mutation-observers
>
> and delivery timing is defined in HTML
>
>     http://www.whatwg.org/specs/web-apps/current-work/#perform-a-microtask-checkpoint
>
> The timing here is described as a "microtask checkpoint" and is
> conceptually "deliver all pending mutation records immediately after
> any script invocation exits".
>
> TC-39 has recently approved Object.observe
>
>     http://wiki.ecmascript.org/doku.php?id=harmony:observe
>
> for inclusion in ECMAScript. It is conceptually modeled on Mutation
> Observers, and delivers all pending change records immediately
> *before* the last script stack frame exits.
>
> Additionally, although I've seen various discussion of dispatching DOM
> Events with the microtask timing, CSS regionLayoutUpdate is the first
> I'm aware of to attempt it
>
>     http://dev.w3.org/csswg/css3-regions/#region-flow-layout-events
>
> [I think this is wrong, and I'm hoping this email can help nail down
> what will work better].
>
> -------
>
> Strawman:
>
> I'd like to propose a mental model for how these types of work get
> scheduled. Note that my guiding principles are consistent with the
> original design of the the end-of-(micro)task timing:
>
> -Observers should be delivered to async, but "soon"
>
> -Best efforts should be made to prevent future events from running in
> a world where pending observer work has not yet been completed.
>
>
> Delivery cycles:
>
> 1) Script (Object.observe) delivery. This is conceptually identical to
> Mutation Observers.
>
> http://wiki.ecmascript.org/doku.php?id=harmony:observe#deliverallchangerecords
>
> 2) DOM (Mutation Observers) delivery.
>
> http://dom.spec.whatwg.org/#mutation-observers
>
> 3) End-of-task queue.
>
> This would be a new construct. Conceptually it would be a task queue
> like other task queues, except that its purpose is to schedule
> end-of-task work. Running it causes events to be dispatched in order
> until the queue is empty.
>
>
> Scheduling:
>
> A) Immediately before any script invocation returns to the browser
> (after the last stack frame exits), run (1). This can be purely a
> concern of the script engine and spec'd independent of HTML & DOM4.
>
> B) Immediately after any script invocation returns to the browser
> (microtask checkpoint), run (2). Note that delivering to each observer
> creates a new script invocation, at the end of which, (1) will run
> again because of (A).
>
> C) Immediately before the UA completes the current task, run (2). This
> is necessary incase DOM changes have occurred outside of a script
> context (e.g. an input event triggered a change), and is already
> implemented as part of DOM Mutation Observers.
>
> D) Run (3). Note that each script invocation terminates in running (1)
> because of (A), then (2) because of (B).

I think this is a good starting point. I don't have an opinion on the
issue that Olli brought up, but I would be surprised if there aren't
other callbacks that people want to do at the end of microtasks.

However, I suspect that we'll need to look at this in more detail once
we know what other things we want to do at end-of-task. While it's
clear to me that (1) should be run before (2). But it's not clear to
me that layout-scheduled callbacks (if there are any) should run after
MutationObserver callbacks.

And say that we add two different types of layout callbacks. It's not
clear that they should be mixed in a single queue as part of a (3)
step. We might want to run all callbacks of one of the types before we
run all the callbacks of another type, just like you are proposing to
run all MutationObserver callbacks before all layout callbacks.

A concrete example is that the FileAPI spec wants to automatically
revoke some URLs created using URL.createObjectURL at the end of a
microtask. Likely this should happen after (2), but it definitely
shouldn't happen as part of a generic queue in (3). Possibly it should
happen after (3) is done running. The nice thing about URL revokation
is that it doesn't run any callbacks, so it'll never cause (1)-(3) to
rerun.

I think the best way forward is to add some explicit hook in the HTML
spec which enables a spec to write language which would hook into this
mechanism. As we see what types of callbacks people want to run at the
end of a task we can figure out in which order they should run and if
they should share queue or not. And then we'll have to adjust the HTML
spec accordingly.

Ideally this stuff should of course live as a separate event-loop spec
and not part of HTML. That's true even without taking microtasks into
account. But since no editor has stepped with such a draft we'll have
to live with it living in HTML for now.

/ Jonas

Received on Thursday, 18 October 2012 22:15:57 UTC