Re: Insertion point for script@onload

Ian asked me to move this information to bugs, so I've filed these
issues as the bugs below.

http://www.w3.org/Bugs/Public/show_bug.cgi?id=9983
http://www.w3.org/Bugs/Public/show_bug.cgi?id=9984

Adam


On Tue, Jun 22, 2010 at 9:52 AM, Adam Barth <w3c@adambarth.com> wrote:
> On Tue, Jun 22, 2010 at 2:36 AM, Henri Sivonen <hsivonen@iki.fi> wrote:
>> "Adam Barth" <w3c@adambarth.com> wrote:
>>> In double-checking our work with the HTML5 parser implementation in
>>> Minefield, we noticed that Minefield handles this case slightly
>>> different (likely due to the spec ambiguity above).  In particular,
>>> when the page calls document.write from the load event of a script
>>> tag, Minefield seems to believe there is no current insertion point
>>> and blows away the entire document:
>>>
>>> http://trac.webkit.org/export/LATEST/trunk/LayoutTests/fast/tokenizer/write-on-load.html
>>>
>>> Under the above interpretation of the spec, the load event shares the
>>> same insertion point record as the external script itself, resulting
>>> in the numerals in that test being printed in order from 1 to 7.
>>> That
>>> behavior appears to match the legacy WebKit and Firefox behavior and
>>> is, therefore, likely compatible with the web.
>>
>> Is there evidence of sites calling document.write() from the load handler of a script so often that calling document.write() from a script load handler needs to work?
>
> I don't have any such evidence at this time.
>
>> The off-the-main-thread parsing implementation in Minefield makes it necessary to know in advance which points in the network stream are eligible for document.write(). Since establishing a point eligible for document.write() is somewhat complex, it is only done at </script> and only for scripts that don't have defer or async specified in the source.
>
> The insertion point, in this case, is in fact such a point.  It's the
> same insertion point that we use for the external script itself
> (assuming the spec intends to create an insertion point for external
> scripts).
>
>> Furthermore, to be able to perform multiple DOM modifications in a script-unsafe batch, the HTML5 parser limits script execution of any kind to well-defined points (</script> mainly plus a couple of other cases that may go away as soon as other parts of Gecko are changed not to expect that behavior).
>
> I didn't understand this statement.  Script can execute at all kinds
> of crazy times (especially in light of DOM mutation events and
> plug-ins).  I don't understand how you can limit script execution to
> point in time when you have such well-defined insertion points.
>
>> For these reasons, I've made the parser forbid document.write() from all event handlers.
>
> This is unlikely to be correct.  For example, what if a script
> executing as a result of a <script> element (either external or
> inline) dispatches a synchronous event, such as a DOM mutation event
> or directly via dispatchEvent?  Surely a document.write call in such
> an event handler should respect the current insertion point.  That's
> certainly what the spec says for inline scripts.
>
>> When I did this, the event handler I particularly wanted to prevent from writing was the SVG load event handler. I wasn't thinking of <script onload>. While <script onload> of parser-inserted scripts is guaranteed to fire when the parser is at the </script> safe point (*if* the event fires synchronously!),
>
> The spec is explicit about when to fire script@onload synchronously.
> The behavior in the spec seems to patch previous versions of Firefox
> and WebKit.
>
>> I'd rather not punch a special hole for that event handler without a compelling use case or site compat requirement. (Also, it seems inconsistent to make load on <script> fire synchronously when load events in general are async.)
>
> I guess I don't fully understand the implementation constraints you're
> operating under.  There are two issues:
>
> 1) Should the script load even fire synchronously.
> 2) Should synchronous events that call document.write use the current
> insertion point.
>
> There are a number of benefits to firing the script load event synchronously:
>
> A) The behavior matches all the shipping browsers I've tested.
> B) Firing the script load event synchronously is more predictable for
> developers and less likely to lead to race conditions.
> C) There are unknown compatibility implications for changing when the
> event is fired.
>
> There are a number of benefits for having synchronous events use the
> current insertion point.
>
> a) The behavior matches all the shipping browsers I've tested.
> b) Reusing the current insertion point is more predictable for
> developers and less likely to lead to race conditions.
> c) Reusing the current insertion point better matches the mental model
> for how HTML documents are processed (basically, it abstracts away how
> much of the document input stream is buffered in the network layer and
> how much is buffered inside the tokenizer).
> d) There are unknown compatibility implications for changing how
> document.write in synchronous events behaves.
>
> The only "con" I see to (1) and (2) is a new implementation constraint
> in Gecko that I don't quite understand given that we're not creating
> any new insertion points (these events are just using insertion points
> that already exist for the <script> elements themselves).
>
> Adam
>

Received on Tuesday, 22 June 2010 21:53:52 UTC