Re: [whatwg] Bug in 12.2.5.4.8 (The "text" insertion mode) when invoking the "spin the event loop" algorithm

On Fri, 27 Sep 2013, James Robinson wrote:
>
> 12.2.5.4.8 (The "text" insertion mode) defines an following algorithm 
> for dealing with inline <script> tags that aren't ready to execute when 
> parsed. I believe there are some subtle bugs with the way the algorithm 
> is specified.  More importantly, the invocation of the "spin the event 
> loop" algorithm makes it harder to reason about the system as a whole.  
> The algorithm in question runs when parsing a </script> at a script 
> nesting level (i.e. not one generated by document.write()):

They might have been generated by document.write(), it's just that they 
aren't being executed re-entrantly.


> Step 3 spins the event loop.  The issue is that while the tokenizer is
> blocked other tasks can run whenever the event loop is spun and cause
> changes that make the rest of the algorithm incorrect.  For example,
> consider:
> 
> <!DOCTYPE html>
> <script>
> window.setTimeout(function() {
> document.write("Goodbye");
> }, 50);

  </script> <!-- i'm assuming you were missing this here -->

> <link rel="stylesheet" type="text/css" href="long_loading.css"></link>

  <!-- note that </link> isn't valid, it is just ignored -->

> <script>
> window.alert("Hello");
> </script>
> 
> The algorithm in question will run when parsing the last </script>. The 
> second script can't execute until the stylesheet loads, so the spec 
> spins the event loop until that happens.  However, if the setTimeout 
> fires before long_loading.css loads then the document.write() call will 
> first perform an implicit document.open(), since there is no insertion 
> point, and blow away the entire Document.

True.


> This cancels any pending tasks but doesn't (as far as I can tell) cancel 
> already started tasks.

There's only ever one already-started task. "Spin the event loop" stops 
the previous task, waits until a condition is met, and then queues a new 
task that is the continuation of the previous task. While the event loop 
is spinning, that original task is ended.


> By my reading of the spec, the rest of the steps of the algorithm should 
> still run and the script should execute.

This appears to be true. The condition is "the parser's Document has no 
style sheet that is blocking scripts and the script's "ready to be 
parser-executed" flag is set", which becomes true when the <link> element 
is removed from the document by document.open(), if nothing else.

It's an interesting case. Every other instance where "spin the event loop" 
can become moot is a case where the Document also stops being active, 
meaning the task that "spin the event loop" then adds to the task queue 
never executes (only tasks for active Documents get executed).

I considered making the "spin the event loop" algorithm be canceled by the 
"document.open()" algorithm, but that would mean that if showModalDialog() 
is called and then its document is document.open()ed, it'd never return, 
which isn't what actually happens.

So I just made the specific case of the parser spin the event loop 
returning check whether the parser in question has been aborted; if it 
has, then it just stops without running the script.


> I propose that instead of spinning the event loop, we instead have step 
> 3 enter an asynchronous section if the script isn't ready to run yet 
> which queues a task once the script is ready to run.  Since this 
> algorithm only runs at a script nesting level of zero this is a fairly 
> minor tweak in overall behavior, but I believe it means that invoking 
> the tokenizer can never spin the event loop which is a nice property to 
> have.

Isn't that more or less exactly what "spin the event loop" does? I don't 
understand how this would solve the problem. You'd still end up resuming 
the parser after document.open() nukes the Document, leading to the script 
running and so forth.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

Received on Tuesday, 1 October 2013 18:47:13 UTC