This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 24724 - Can the microtask and stable state concepts be merged?
Summary: Can the microtask and stable state concepts be merged?
Status: RESOLVED FIXED
Alias: None
Product: WHATWG
Classification: Unclassified
Component: HTML (show other bugs)
Version: unspecified
Hardware: Other other
: P1 normal
Target Milestone: Unsorted
Assignee: Ian 'Hixie' Hickson
QA Contact: contributor
URL: http://www.whatwg.org/specs/web-apps/...
Whiteboard:
Keywords:
Depends on: 22296
Blocks: 24707
  Show dependency treegraph
 
Reported: 2014-02-19 04:46 UTC by contributor
Modified: 2014-05-13 19:18 UTC (History)
6 users (show)

See Also:


Attachments

Description contributor 2014-02-19 04:46:43 UTC
Specification: http://www.whatwg.org/specs/web-apps/current-work/
Multipage: http://www.whatwg.org/C#processing-model-4
Complete: http://www.whatwg.org/c#processing-model-4
Referrer: 

Comment:
Can the microtask and stable state concepts be merged?

Posted from: 58.187.186.41
User agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.58 Safari/537.36 OPR/20.0.1387.30 (Edition Next)
Comment 1 Philip Jägenstedt 2014-02-19 04:48:37 UTC
From https://www.w3.org/Bugs/Public/show_bug.cgi?id=24484#c6

> i think that it'd be clearer in the spec to have one notion of "do my stuff
> after script has done doing it's thing". i suggest refactoring the stable
> state stuff to use microtasks instead.

Filing a separate bug so that this gets considered.
Comment 2 Philip Jägenstedt 2014-02-19 04:50:22 UTC
Note that there are two places that perform a microtask checkpoint that do
not provide a stable state:

http://www.whatwg.org/specs/web-apps/current-work/#clean-up-after-running-a-callback
http://www.whatwg.org/specs/web-apps/current-work/#spin-the-event-loop

I'm not familiar enough with these concepts to say if it would be a problem to run the sync sections of HTMLMediaElement here.
Comment 3 Philip Jägenstedt 2014-02-19 07:37:29 UTC
Pre-emptive reply to "but these concepts are completely different!":

It is true, as the spec notes, that "A synchronous section never mutates the DOM, runs any script, or has any side-effects detectable from another synchronous section, and thus synchronous sections can be run in any order, and cannot spin the event loop."

This is rather different from microtasks, which have none of these properties.

However, does it really matter? If we use microtasks for HTMLMediaElement they can still avoid running scripts and modifying the DOM. They would run in a well-defined order, as opposed to synchronous sections, but so what?
Comment 4 Rafael Weinstein 2014-02-19 10:59:39 UTC
I asked Hixie about these properties and he said the motivation was so that they could be run in parallel.

AFAIK, no browser actually does this and it's hard to see how it would be worth it, given existing uses.
Comment 5 Philip Jägenstedt 2014-02-19 14:58:54 UTC
Thinking some more about the consequences of using microtasks in HTMLMediaElement:

The resource selection algorithm can be aborted, in which case one implicitly stops awaiting a stable state. With microtasks, one would have to explicitly remove them from the queue in load(), just like with the event firing tasks.

The step "Wait until the node after pointer is a node other than the end of the list. (This step might wait forever.)" would have to be made into a proper hook for source element insertion.

Breaking the algorithms that await a stable state into several pieces like this would make the spec look more complicated, I suppose, but it would be more similar to how it is actually implemented.
Comment 6 Philip Jägenstedt 2014-02-19 15:20:07 UTC
Relevant discussion on IRC:

http://krijnhoetmer.nl/irc-logs/whatwg/20140219#l-367
Comment 7 Philip Jägenstedt 2014-02-19 16:39:46 UTC
To continue the monologue, a quickfix which wouldn't require rewriting all the algorithms is to let "perform a microtask checkpoint" provide a stable state after running all the microtasks, and not provide a stable state anywhere else.

The downside would be that synchronous sections and microtasks are never interleaved, so microtasks can't be used to test synchronous sections. On the other hand, since microtasks can modify the DOM, it does make sense to let them finished before calling it a stable state...
Comment 8 Ian 'Hixie' Hickson 2014-02-19 17:11:47 UTC
I don't want to merge them since they are quite different (one is serialised, the other is parallelisable; one is queued, the other is a joining of threads; they are editorially very different). However, I'm happy to have them defined such that they are implementable in terms of one another, modulo bug 24707. This would get you what you presumably want out of this.
Comment 9 Philip Jägenstedt 2014-02-19 17:17:57 UTC
(In reply to Ian 'Hixie' Hickson from comment #8)
> I don't want to merge them since they are quite different (one is
> serialised, the other is parallelisable; one is queued, the other is a
> joining of threads; they are editorially very different). However, I'm happy
> to have them defined such that they are implementable in terms of one
> another, modulo bug 24707. This would get you what you presumably want out
> of this.

Is what I suggested in comment #7 sound, or do you have something else in mind for "implementable in terms of one another"?
Comment 10 Ian 'Hixie' Hickson 2014-02-19 20:31:43 UTC
I'd probably do it more like queueing a microtask that provides a stable state, or something like that. I haven't check in detail yet. Depends somewhat on how we end up speccing microtasks.
Comment 11 Philip Jägenstedt 2014-02-20 16:18:20 UTC
(In reply to Ian 'Hixie' Hickson from comment #10)
> I'd probably do it more like queueing a microtask that provides a stable
> state, or something like that. I haven't check in detail yet. Depends
> somewhat on how we end up speccing microtasks.

I suppose the layering (stable state on top of microtasks) would be slightly cleaner that way. The only question is if all pending synchronous sections get run in a single microtask or if each "await a stable state" queues a separate microtask. I think the latter probably makes more sense, since otherwise the order of the synchronous sections and other microtasks queued by some piece of code would depend on whether or not some other code in the same script has previously run "await a stable state" or not...

I can probably live with any solution here that Rafael finds acceptable.
Comment 12 Ian 'Hixie' Hickson 2014-02-20 18:55:43 UTC
We provide a stable state without running microtask checkpoints in the pause algorithm. But I hadn't thought to check for the opposite before.

We run microtasks without providing a stable state in these cases:
 - spinning the event loop runs microtasks twice back to back and only then
   provides a stable state (maybe we should drop the first of the microtask runs,
   since running microtasks always runs all pending microtasks anyway, so the
   second is always a no-op, if I'm not missing anything here.)

 - cleanup after calling a callback runs microtasks but doesn't provide a stable
   state. This manifests for example in event dispatch — after each event, we
   run microtasks, but we wait until all the events have been processed before
   providing a stable state. So for example, if you have two click event handlers,
   and one creates a <video> with one src="" and the next changes the src="", the
   spec right now says the first one isn't fetched at all.

I think that's it.

I guess we can fix these without much controversy.
Comment 13 Philip Jägenstedt 2014-02-21 08:38:24 UTC
I just stumbled upon a problem with having synchronous sections run in any order. While they don't modify the DOM, they do queue tasks (to fire events). That is observable. Without realizing it, I've been writing tests that depend on the order of synchronous sections to match the order in which "await a stable state" happens.

A simplified test might be:

var v0 = document.createElement('video');
var v1 = document.createElement('video');
var order = [];
v0.onloadstart = v1.onloadstart = function(e) {
  order.push(e.target);
  if (order.length == 2) {
    assert_equals(order[0], v0);
    assert_equals(order[1], v1);
  }
}
v0.src = '';
v1.src = '';

In other words, whatever ends up spec'd here, the order in which synchronous sections run should be deterministic.
Comment 14 Ian 'Hixie' Hickson 2014-02-25 19:03:57 UTC
Each media element has a different task source, so those two events aren't guaranteed to be ordered anyway.
Comment 15 Philip Jägenstedt 2014-03-03 17:52:59 UTC
(In reply to Ian 'Hixie' Hickson from comment #14)
> Each media element has a different task source, so those two events aren't
> guaranteed to be ordered anyway.

Oh right, I keep forgetting about that since they weren't actually separate queues in Presto. (They kind of are in Blink/WebKit, although the order is still guaranteed in the simple example I gave.)
Comment 16 Philip Jägenstedt 2014-03-19 04:02:49 UTC
Any chance of progress on this? Other people are wanting to "await a stable state" in Blink as well now: https://codereview.chromium.org/200923002/
Comment 17 Rafael Weinstein 2014-03-24 19:40:09 UTC
Is the "I want alert to not block a video loading" the only thing currently blocking merging stable state and microtasks.

If so, I plan to just push blink to just merge them.
Comment 18 Philip Jägenstedt 2014-03-25 04:23:07 UTC
What does "just merge them" mean? It certainly looks like the spec is going to define "await a stable state" in terms of microtasks, and there are subtleties there which need testing. Before the spec materializes I don't know what test cases one should write.
Comment 19 Olli Pettay 2014-04-02 00:17:26 UTC
The answer to the (In reply to contributor from comment #0)
> Comment:
> Can the microtask and stable state concepts be merged?
No

Stable state happens between tasks.

There can be several microtasks within one task, and several
"end-up-microtask" points. For example end of each
top level event listener call.
It would be odd to start running stable state stuff after each
(top level) callback - or at least such change would be rather radical.
Comment 20 Rafael Weinstein 2014-04-04 17:52:52 UTC
As far as I can tell, the question is: "can the uses of stable state just post a microtask to do their work instead?"

The only reason I've heard why this won't work is Hixie's "I want to load a video, open an alert, and I want the video to load while the alert is open", which seems like a pretty trivial use in order to maintain an entirely separate notion in the spec.

I vote that the work done as a result of the browser "providing a stable state" simply post microtasks to do their work instead.
Comment 21 Christian Biesinger 2014-04-10 21:10:58 UTC
Any chance we can get this bug resolved soon? This is currently blocking implementation of the <picture> element in Blink. I'd like to get this implemented for image loading sooner than later, and ideally with the simpler version of just having a microtask.
Comment 22 Olli Pettay 2014-04-11 17:28:21 UTC
I assume will need to have stable state concept in workers too, and there
alert() case is very valid. Using sync XHR for example is totally ok,
and the more we expose stuff there, the more it will look like main thread.
Comment 23 Christian Biesinger 2014-04-11 18:35:47 UTC
It seems like it should be possible to run microtasks on a worker thread even while the main thread is blocked on an alert?

I mean, not sure if the spec is allowing that right now, but that shouldn't be a conceptual problem...
Comment 24 Olli Pettay 2014-04-11 18:57:27 UTC
I'm talking about worker case only. Synchronous stuff there and resource loading etc.
Comment 25 Ian 'Hixie' Hickson 2014-04-11 20:56:24 UTC
So the issues here are:

 - all synchronous sections (stable state consumers) run in parallel
 - we don't want to run synchronous sections until after all events have been 
   dispatched, when doing even dispatch, but we do want mutation observers to
   run after each one
 - the alert thing, though people seem to be ok with having video loads stall
   if the script shows an alert after setting the src (bug 24707)

We could do something for stable states similar to what we do for mutation observers:

 - whenever you currently wait for a stable state, you also make sure there's a 
   microtask queued for handling that stable state.
 - whenever you run that microtask, you provide a stable state.

...but that would still leave the problem with event dispatch...

Should we just not bother trying to maintain that invariant? It'll result in redundant Web traffic and stuff, but I guess it's understandable to authors...
Comment 26 Rafael Weinstein 2014-04-11 21:08:13 UTC
(In reply to comment #25)
> So the issues here are:
> 
>  - all synchronous sections (stable state consumers) run in parallel

My memory is that we discussed this and no one actually cares about this. IOW, you spec'd it this way thinking it'd be a perf win, but no one implements it that way nor plans to.

>  - we don't want to run synchronous sections until after all events have
> been 
>    dispatched, when doing even dispatch, but we do want mutation observers to
>    run after each one

Why is that?

>  - the alert thing, though people seem to be ok with having video loads stall
>    if the script shows an alert after setting the src (bug 24707)
> 
> We could do something for stable states similar to what we do for mutation
> observers:
> 
>  - whenever you currently wait for a stable state, you also make sure
> there's a 
>    microtask queued for handling that stable state.
>  - whenever you run that microtask, you provide a stable state.
> 
> ...but that would still leave the problem with event dispatch...
> 
> Should we just not bother trying to maintain that invariant? It'll result in
> redundant Web traffic and stuff, but I guess it's understandable to
> authors...
Comment 27 Ian 'Hixie' Hickson 2014-04-11 23:58:19 UTC
What's the benefit of losing the parallelisability? If there's a win from losing it, then ok, but it seems silly to explicitly require that it not be possible, especially if there's not really any black-box way to tell.

Comment 12 has an example of the multi-handler thing:
> for example, if you have two click event handlers, and one creates a <video>
> with one src="" and the next changes the src="", the spec right now says the
> first one isn't fetched at all.
Comment 28 Rafael Weinstein 2014-04-14 16:03:50 UTC
(In reply to Ian 'Hixie' Hickson from comment #27)
> What's the benefit of losing the parallelisability? If there's a win from
> losing it, then ok, but it seems silly to explicitly require that it not be
> possible, especially if there's not really any black-box way to tell.

Unless I misunderstand, you put this in here based on the idea that someone may do it someday. It seems to me that any addition to the spec must either be reflected in someone's actual implementation, or it's up to the person who adds it to justify its value.

The value of loosing it is decreased complexity in the spec (and blink which likes to have implementation abstractions closely match the spec language) -- and making progress towards only have a single "let script finish doing it's thing" mechanism (i.e. microtasks).



> 
> Comment 12 has an example of the multi-handler thing:
> > for example, if you have two click event handlers, and one creates a <video>
> > with one src="" and the next changes the src="", the spec right now says the
> > first one isn't fetched at all.
Comment 29 Ian 'Hixie' Hickson 2014-04-14 18:04:38 UTC
I guess it's not like these things are going to happen at the exact same time that often. Fine. I'll just make them use regular microtasks somehow.
Comment 30 Christian Biesinger 2014-04-14 19:53:07 UTC
OK great. Can I assume for now that https://www.w3.org/Bugs/Public/show_bug.cgi?id=24707 will be resolved in such a way that alert() will not provide a stable state anymore?
Comment 31 Ian 'Hixie' Hickson 2014-04-22 18:42:35 UTC
Sadly, yes, that's probably a good assumption.
Comment 32 Ian 'Hixie' Hickson 2014-04-22 18:43:01 UTC
(though I intend to keep an eye on implementations here and if I see a sign that they're not doing it that way, I will change it back.)
Comment 33 Philip Jägenstedt 2014-04-22 21:10:04 UTC
(In reply to Ian 'Hixie' Hickson from comment #29)
> I guess it's not like these things are going to happen at the exact same
> time that often. Fine. I'll just make them use regular microtasks somehow.

Assuming you intend to reword the media element algorithms to use microtasks, I'd be happy to review those changes. Both Presto and Blink/WebKit already have to split those algorithms into pieces, so this should make the spec more similar to the implementations.
Comment 34 Ian 'Hixie' Hickson 2014-05-13 19:17:58 UTC
This ended up being somewhat trivial to spec. Let me know if that's because I missed something important!
Comment 35 contributor 2014-05-13 19:18:59 UTC
Checked in as WHATWG revision r8630.
Check-in comment: Refactor 'stable states' to be defined in terms of microtasks
http://html5.org/tools/web-apps-tracker?from=8629&to=8630