Bug 82931

Summary: DOMContentLoaded and load events should fire asynchronously
Product: WebKit Reporter: jochen
Component: UI EventsAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: abarth, ahmad.saleem792, ap, bfulgham, cdumez, rniwa, tkent
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
test case
none
slightly better test case none

Description jochen 2012-04-02 13:03:22 PDT
According to http://www.whatwg.org/specs/web-apps/current-work/#the-end step 4 and step 7, the DOMContentLoaded and load events should be fired asynchronously. Currently, they're both fired synchronously.

Firefox seems to do this, all other browsers I tested (WebKit nightly, Opera 11, IE9) send the events synchronously

We could either push for an update to the spec, or send the signal asynchronously as well. The latter would allow for firing all events during DOM mutation asynchronously, without sending events that happen during DOM parsing after the load event (see e.g. issue 82778)
Comment 1 Adam Barth 2012-04-02 13:19:09 PDT
Can you attach the test you're using?  I'm not sure what you mean when you say we fire the load event synchronously.  Often the load event fires due to data coming in from the network, which happens asynchronously.
Comment 2 jochen 2012-04-02 13:26:05 PDT
Created attachment 135167 [details]
test case

That's my (lame) test-case. On Firefox, the timeout and load event come in an arbitrary order (reload a view times). On all other browsers I tested, load is always first.
Comment 3 Adam Barth 2012-04-02 13:27:55 PDT
That's not a good test case.  There's no necessary relation between when those events fire.  For example, transfer the HTML document with chunked encoding and make the server sleep for a minute between the </div> and the </body>.  All browsers will fire the timeout before the load event in that case.
Comment 4 jochen 2012-04-02 13:37:20 PDT
(In reply to comment #1)
> Can you attach the test you're using?  I'm not sure what you mean when you say we fire the load event synchronously.  Often the load event fires due to data coming in from the network, which happens asynchronously.

I read the spec as follows:

between step 1 (set the document readiness to interactive) and step 4 (fire DOMContentLoaded event), we should drop back to the message loop in any case.

If there are no scripts to be run when the documented finished parsing, we won't spin the message loop

same between steps 4 and 7
Comment 5 jochen 2012-04-02 14:17:49 PDT
I chatted with Adam a bit, and we both agree that the test case is lame.

We considered making events that are fired asynchronously but should come before the load event could just delay the load event, but this "delay" is done between the DOMContentLoaded and the load event, so it would be still observable that the events are fired in the wrong (as in not conforming to the spec) order.

Fixing this probably requires some non-trivial changes to FrameLoader, as it triggers e.g. DOMContentLoaded (fired in Document::finishedParsing) by invoking FrameLoader::finishedParsing in FrameLoader::stopLoading and then FrameLoader continues to mess with the document and its parser.
Comment 6 Ojan Vafai 2012-04-02 14:31:28 PDT
Created attachment 135188 [details]
slightly better test case
Comment 7 Ryosuke Niwa 2012-04-02 15:08:09 PDT
(In reply to comment #0)
> According to http://www.whatwg.org/specs/web-apps/current-work/#the-end step 4 and step 7, the DOMContentLoaded and load events should be fired asynchronously. Currently, they're both fired synchronously.
> 
> Firefox seems to do this, all other browsers I tested (WebKit nightly, Opera 11, IE9) send the events synchronously

I'm not certain if we want to change our behavior then.

It seems like there's some confusion here due to the bad test case. Could someone summarize the current state of this bug? (e.g. what's wrong with our current behavior, other browsers' behaviors, and possible solutions).
Comment 8 jochen 2012-04-02 16:05:38 PDT
(In reply to comment #7)
> (In reply to comment #0)
> > According to http://www.whatwg.org/specs/web-apps/current-work/#the-end step 4 and step 7, the DOMContentLoaded and load events should be fired asynchronously. Currently, they're both fired synchronously.
> > 
> > Firefox seems to do this, all other browsers I tested (WebKit nightly, Opera 11, IE9) send the events synchronously
> 
> I'm not certain if we want to change our behavior then.
> 

note that this assessment was based on a poor test, so it might as well be wrong.

> It seems like there's some confusion here due to the bad test case. Could someone summarize the current state of this bug? (e.g. what's wrong with our current behavior, other browsers' behaviors, and possible solutions).

The main issue is that if you create an asynchronous event either before the DOMContentLoaded event, or between the DOMContentLoaded event and the load event (depending on which code path is executed), the said event will not be fired before DOMContentLoaded or load respectively.

Lacking a good test case, it's hard to describe what other browsers are doing.

A possible solution would be to clean up all code paths such that 

- there's no sync code path from firing DOMContentLoaded to firing load (Document::finishedParsing to Document::implicitClose)
- there's no sync code path from setting the document's readiness to interactive to firing DOMContentLoaded (HTMLDocumentParser::prepareToStopParsing to Document::finishedParsing)
Comment 9 Ryosuke Niwa 2012-04-02 16:28:30 PDT
(In reply to comment #8)
> The main issue is that if you create an asynchronous event either before the DOMContentLoaded event, or between the DOMContentLoaded event and the load event (depending on which code path is executed), the said event will not be fired before DOMContentLoaded or load respectively.
> 
> Lacking a good test case, it's hard to describe what other browsers are doing.

How can we be talking about fixing a "bug" when we don't even know what we're testing. We need to figure out what other browsers are doing first, or else this whole discussion doesn't lead us anywhere.
Comment 10 Ojan Vafai 2012-04-02 17:00:46 PDT
(In reply to comment #9)
> (In reply to comment #8)
> > The main issue is that if you create an asynchronous event either before the DOMContentLoaded event, or between the DOMContentLoaded event and the load event (depending on which code path is executed), the said event will not be fired before DOMContentLoaded or load respectively.
> > 
> > Lacking a good test case, it's hard to describe what other browsers are doing.
> 
> How can we be talking about fixing a "bug" when we don't even know what we're testing. We need to figure out what other browsers are doing first, or else this whole discussion doesn't lead us anywhere.

That's nice in theory. In practice, browsers don't give a consistent set of APIs for determining how they behave here. All the tests that I've been able to come up with are racy and make it hard to tell definitively what a browser does.

I'm open to suggestions for how to test this better, but we should either try to match the spec or get the spec changed.
Comment 11 Ryosuke Niwa 2018-08-14 15:45:00 PDT
Latest spec: https://html.spec.whatwg.org/multipage/parsing.html#stop-parsing
Comment 12 Ahmad Saleem 2022-08-12 14:37:44 PDT
Latest requests across browsers:

*** Safari 15.6 on macOS 12.5 ***

[object HTMLBodyElement]
DOMContentLoaded
load
focus
postMessage

*** Safari Technical Preview 151 ****

[object HTMLBodyElement]
DOMContentLoaded
load
focus
postMessage

*** Chrome Canary 106 ***

[object HTMLBodyElement]
focus
postMessage
DOMContentLoaded
load

*** Firefox Nightly 105 ***

[object HTMLBodyElement]
focus
DOMContentLoaded
load
postMessage

________

I am not sure on web-spec but just wanted to posted updated results. I used "slightly better.." test case. Thanks!