The synchronous load event is trouble

SVG 1.2 Tiny says about the 'load' event:
> The event is triggered at the point at which the user agent finishes loading the element and any dependent resources (such as images, style sheets, or scripts). In the case the element references a script, the event will be raised only after an attempt to interpret the script has been made. Dependent resources that fail to load will not prevent this event from firing if the element that referenced them is still in the document tree unless they are designated as externalResourcesRequired. The event is independent of the means by which the element was added to DOM tree.

SVG 1.1 Full says about the event the is handled by the 'onload' event handler:
> The event is triggered at the point at which the user agent has fully parsed the element and its descendants and is ready to act appropriately upon that element, such as being ready to render the element to the target device. Referenced external resources that are required must be loaded, parsed and ready to render before the event is triggered. Optional external resources are not required to be ready for the event to be triggered.

The event is marked as bubbling and non-cancelable.

In Gecko, in the XML tree builder, the event is implemented as an event that fires synchronously when the </svg> end tag is parsed. I haven't implemented this event at all in the HTML5 parser in the hope that the SVG WG makes it undesirable characteristics go away.

I think the definition of the event has at least the following three problems:

 1) The firing of the event is synchronous with the parse. This is highly unusual. I'm not aware of any other standards-based feature requiring an event to be dispatched synchronously with the parse. Gecko has some non-stardards-based analogous behaviors, but, as I understand it, those behaviors cause scripts to run either from the task queue or from a deferred execution mechanism that isn't fully synchronous but isn't the task queue, either. Having scripts run as the side effect of the parse is generally trouble. It's impossible to eliminate </script> running scripts as a side effect of the parse, but I think we should get rid of all the other cases, so that parsing can be optimized with the assumption that only </script> may cause synchronous script execution (which requires the parser to go into a state that's safe for script execution).

 2) The event is defined to be fired at a particular point relative to parse but also relative to network activity. Scripts already have to block the parser for legacy reasons. However, all blocking of the parser due to external resources is bad for performance, so it would be desirable to allow styles to load asynchronously with the parse. As written, the spec text seems to establish </svg> as a point where the parser potentially has to yield to the event loop if there are pending style sheet loads. (I don't know how cross-resource 'use' works, but it seems trouble if those don't attach asynchronously.)

 3) As I understand it, a load event dispatched to an <svg> element embedded in an HTML document would bubble to the HTML <body> element and up. JavaScript libraries written for text/html may legitimately assume that the event handled by the 'onload' event handler is dispatched once per document life cycle. It seems to me that adding some embedded SVG to an HTML page has the potential of severely confusing pre-existing JavaScript code that is listening for the traditional HTML load event.

Considering the above, I propose removing the current SVG 'load' event behavior and then adding the following:

 A) If the root element is the <svg> element, dispatch the 'load' event to that element the same way the 'load' element is dispatched to the <body> element when <html> is the root element. (I.e. wait for external resources, then dispatch the event asynchronously from the task queue.)

If that's not enough and existing SVG content relies on the 'load' event being dispatched to each nested <svg> element also (I don't know what the legacy constraints are), then also add the following:

 B) When the end tag of a non-root <svg> element is parsed, dispatch a *non-bubbling* 'load' event to that element asynchronously from the task queue without waiting for external resources.

Henri Sivonen

Received on Thursday, 26 November 2009 12:14:14 UTC