the day supporting document.onload became a bug

Like many things on the web, the load event seems simple. It originates from the web's stone age – supported by Netscape 2 in 1996 and fired billions and billions of times since. It's probably the most widely used event for web scripting. Can it have secrets or quirks after so many years?

You might think you could write a one-sentence spec for it, along the lines of "when the document is done loading, dispatch a load event to any listeners created from BODY onload attributes, window.onload property or addEventListener('load') calls" – and implement it interoperably in a few hours on top of an otherwise solid DOM/JS core.

Simplicity is deception. Actually, the cool thing about the load event is that it seems so simple but is so weird.

Discovering what I didn't know about the load event started at the white "please wait" box that covers the contents on grainger.com (this site is now patched in browser.js)

I noticed that they did something like

document.onload=function(){
// code that shows the "please wait" box, an obvious mistake
}
.
.
<body onload="">

Aha: if you assign a listener for the document's load event but afterwards have an empty onload attribute on body, document.onload will be removed when the browser sees onload="". Right? I wrote a test case confirming that assumption and moved on to the next bug.

However, colleague Ola was also looking at the bug and could prove that the onload="" was a red herring. Removing it made no difference. Assigning anything to document.onload was a no-op in all other browsers. What?? How come we never noticed that?

So, we got a developer to remove document.onload support. I wanted it fixed by just ignoring assignments to document.onload, but being a thorough person Daniel made sure document would no longer be an event target for the load event.

To my consolation I wasn't the only person saying that must be wrong! This fix makes document.addEventListener('load'…) a no-op too. We're absolutely sure document.addEventListener('load'…) must keep working. The DOM Events spec doesn't say much about the load event, but it sort of implies sending it to the document. Besides, not sending load events to document anymore broke opera:config and dozens of browser.js patches.

Then we wrote another test case or two.

And it's true. No browser (except Opera) sends load events to "document"! They all skip document and go straight for window. BODY onload="" creates listeners on window, not on body. Even though event.target is the document, the event itself avoids the document like it had swine flu or something.

I assume it's been like that since 1996 and we never thought of testing that in other browsers before. Wow.

So, early afternoon on May 12th 2009, our support for document.onload turned from a feature into a bug. Good bye to the possibility of capturing all load events inside a document with a capturing listener (won't work with window.addEventListener because Mozilla turned out to be a chicken and not a dinosaur). Edit: luckily I was wrong here, see comments.

Actually it feels a bit .. evil .. to suddenly turn around and kill an old feature that's been with us for years, just because it's required for web compatibility. Oh well. At least I can confirm that you learn something old every day..

17 thoughts on “the day supporting document.onload became a bug

  1. That that Moz bug isn’t fixed is a shame. I queried it as wanted for Fx3.6/4 a month or so ago but no-one’s made any decision either way.

  2. I think we must have come oh-so-close to finding this years ago when I reported bug #166183 (old BTS), which was related to load events on document and window. :bug:I don't think the web will ever stop amazing me at it's level of complexities and subtle details.

  3. Shouldn't <html> be able to catch all load events inside a document, or does it get skipped somewhere along the line?

  4. I should not blog at the end of a long day without making sure every statement is tested. I'm totally wrong about dropping support for *capturing* load events with an event listener at document. (It works in Mozilla too, actually, and does still work in Opera after the document.onload fix. Good.)However, as lucideer points out this sadly will cause compatibility problems for user scripts. We know that this is likely going to happen 😦 without knowing how many scripts will be impacted yet.

  5. It's not an enormous issue. UserJavascript authors will at least be more motivated to update their scripts than authors of poorly made webpages.The biggest issue will be with users who currently have collections of UserJavascript installed, and won't update, who will then come in droves to complain about resultant webpage problems. Well…. maybe not quite droves 🙄

  6. Using onload on window feels wrong.

    ..probably why we've been oblivious to the fact that no other browser supports document.onload for so many years. Unfortunately, due to the rather silly mistake grainger.com did we need to worry about whether other sites make similar mistakes – which means sending load events to the document probably won't be implemented in Mozilla and won't re-appear in Opera.

    user script would need to use window.addEventListener("load"…) instead?

    Yes. Except if you want to capture all load events in the document (for example to do something to IFRAMEs that load inside) in which case you still use document.addEventListener with the third parameter set to true.

  7. /me edits his scripts. :knight:I presume, by the way, that this does not affect the 'DOMContentLoaded' event, only 'load'?

  8. Lowest common crapinator strikes for the billionth time….. aarghh ! The pain.. I'll basically have to patch ALL my user scripts. So, Mozilla had the bug for years and webkit copied them…. this is why I dearly hate Gecko.

  9. I presume that this does not affect the 'DOMContentLoaded' event?

    Correct, Sir.

    So, Opera will no longer follow specification?

    Technically, we will – because the spec tells you to send an event, but does not tell you where to send it. So we could decide to only send the event to the <HTML> element and still be conformant (which would of course be a spectacularly useless implementation because noone expects load events to go there..).Some specs just seem to like leaving essential details unspecified.

    Lowest common crapinator strikes for the billionth time

    Indeed. It feels much more correct and semantic to tell the document that it finished loading. But then, the Web often isn't supposed to make sense. Or at least it seems that way.I don't think the compat problems are that severe – as it has taken us this long to even discover the incompatible behaviour. But it would take clear specifications and certainty that the other browsers will change to match us to go back.

  10. Recently, I watched a recording of a leader from Google state that the creators of Chrome, Safari, Firefox and Opera are all working diligently and cooperatively to ensure that their respective browsers are Standards compliant. He was talking specifically in relation to HTML 5, but it was obvious that the statements he made were encompassing of the W3C Standards as a whole. He spoke of the collective goal being that, in time, users' experiences of computer software will be that "it just works."After reading the above blog entry, and with the Google guy's statements regarding cooperation in mind, I now wonder if the difference discovered and described in the blog entry above is likely to be brought up in discussion with other browser creators. Your blog entry, and the exchange of comments that follow it, indicate the following:that Opera's approach has been a logical one; andthat there are no known major problems resulting from the particular specification(s) being insufficiently specific.It sounds like making the specification a little more specific would not mean major rewrites of code in other browsers, so with the expectation that other browser creators, too, would want to treat the issue logically, maybe they would be open to at least investigating what they would need to do and what the ramifications to them would be.

  11. Possibly. But I guess noone wants to go through the trouble of carefully defining something that might cause compatibility issues when there is a working and widely used alternative, namely listening to load events sent to the window..

  12. Stomme poes writes:I don't read bug reports much anymore because of how often I saw "well the specs don't explicitly specify what's obvious to everyone else so this isn't a BUG, it's just our choice completely not working with any other vendors' choice" argument. When specs are ambiguous, and allows for differing, *incompatible* implementations, then for me as a web developer, there's no point in a spec at all in those instances, since I'm going to be writing browser-specific this and that. Nutscrape vs Exploder all over again : (

Leave a comment