[whatwg] API to delay the document load event

David Bruant bruant.d at gmail.com
Mon Apr 29 05:44:59 PDT 2013


Le 29/04/2013 01:08, Glenn Maynard a écrit :
> On Sun, Apr 28, 2013 at 5:39 PM, David Bruant <bruant.d at gmail.com 
> <mailto:bruant.d at gmail.com>> wrote:
>
>     Le 29/04/2013 00:14, Robert O'Callahan a écrit :
>
>         We don't want to require people to do everything in Caja just
>         to support composition of independent scripts.
>
>     There are certainly more lightweight solutions than Caja to
>     achieve the same thing.
>
>
> Which is exactly the problem: you're saying there are multiple 
> solutions, which means incompatibility.
No, I meant "more lightweight solutions than Caja to achieve the same 
thing" (sorry for the copy/paste, I don't know how to phrase it better), 
so solutions that confine a widget in a div giving it the impression 
it's on its own full page, so using all standard APIs. A level of 
compatibility that's actually hard to match.
I'm currently building a product on top of Google Apps Script [1][2]. 
The pages served on the client side are "cajoled" (processed by a 
deployed Caja before being sent to the browser) by Google. As a 
developer, I'm just coding according to standards. No specific APIs for 
the confined code. I haven't seen any difference besides 
"requestAnimationFrame" and the "performance" object being missing, but 
I believe this is only because they (people of Google App Script who 
installed and deployed their configured Caja) don't keep up with the 
latest browser trends and just forgot to whitelist them.
My point is that Caja offer confinement and the confined code has been 
coded to standards, so I consider the problem of confining 
standard-based code solved. Really, take a look at it.

Caja proves that confinment of malicious widgets within the same page is 
possible (!). I believe a lighter version of Caja aiming at isolating 
well-behaving widgets would be much lighter. Hopefully it wouldn't 
require the whole server-side live rewriting infrastructure (which is 
definitely something that shouldn't be required to run independent 
scripts, I can only agree). Maybe assuming widgets give up a little bit 
on how dynamic their JavaScript can be (maybe not even).
I'm no Caja expert, but this light-Caja might be as simple as picking a 
few Caja libraries and wiring them a bit differently. I'll ask the Caja 
mailing-list.


What about starting with an API à la html at loading and if devs complain 
it's too hard when there are independent scripts, then add a mechanism 
like delayLoadEvent/stopDelayingLoadEvent? (I still believe delaying the 
UA load event is a terrible idea. What will dev tools show? The actual 
load event or the delayed one? And the argument about performanceTiming, 
etc.). The more complex multi-call API can be later retrofitted, but 
please wait for devs to ask for it.


Also, independent scripts loading on a page increase the probably of at 
least one failing.

     document.delayLoadEvent();
     doX(function(){
         doY();
         document.stopDelayingLoadEvent();
     })

First and foremost, let's hope the script that defines doY from your 
automated build process didn't end up in a SyntaxError or you'll be told 
soon enough that "undefined is not a function"
Then maybe doY calls JSON.parse to get info from your localStorage or 
from the network. Too bad, you're parsing "[Object object]" because your 
colleague wrote
     localStorage.set('key', obj)
instead of
     localStorage.set('key', JSON.stringify(obj))
doY throws, document.stopDelayingLoadEvent never gets called.

Maybe doY contains a call to JSON.stringify. Few people know but this 
one can throw too if passed an object with a cycle. Oops, 
document.stopDelayingLoadEvent never gets called.
And hundreds of ECMAScript/Web APIs

Recently, I was working on a WebDocumentary project with lots of 
<video>. All was working fine on FF and Chrome. When testing on iPad, 
some calls to video.play were throwing INVALID_STATE_ERR for no apparent 
reason. Not even reliably. Maybe something due to loading speed. Maybe 
QuickTime was in a bad mood (apparently, on iPad, the <video> elements 
is an embedded QuickTime). Who knows? Anyway, if doY does this kind of 
things, it will throw in some platforms and 
document.stopDelayingLoadEvent never gets called.

There are thousands of ways a you can screw up or one browser can let 
you down and one of your independent widget ends up not calling 
document.stopDelayingLoadEvent.
As I explain below, when that happens, you cannot react at runtime.


>
>     If your scripts are that independent, how do you know if one
>     forgets to call document.stopDelayingLoadEvent()? This is a footgun.
>
>
> The approach I've suggested makes tracking misuse easy; just stash a 
> stack trace when creating the object, and provide a console API to 
> print the stack trace for delays that haven't been finished, or if an 
> object gets collected without being finished.
That's a way to debug, not to react at runtime. If one of your 
independent script forgets to call document.stopDelayingLoadEvent(), how 
does the page recover to guarantee that the "load" event will happen 
eventually anyway? Code isn't always maintained. Even maintained code 
isn't even tested on all platforms it will run on. How does one 
guarantee a load event to be triggered eventually when scripts are 
independent?
Lots of scripts are written with the assumption that the load event will 
be called. You're breaking them if document.stopDelayingLoadEvent() is 
not called enough (one more reason to leave the UA "load" event as it is)
Also, does delaying the "load" of an iframe delays the parent? If yes, 
one more reason not to delay the UA "load" and leave it working as it 
does today.


>
>     This is also additional surface for web browsers to mess up which
>     they already have enough to deal with.
>
>
> The proposal here is trivial as web APIs go, so I don't buy this.
As a web developer, I can totally imagine a web browser forgetting to 
fire "load" because of weird internal conditions like "one 
document.delayLoadEvent call was before DOMContentLoaded and another 
after". Browsers fail us like this *all the time* and this kind of 
feature is very subtle, make very hard to write test cases to reproduce 
reliably when there is a bug.
Allowing several delayLoadEvent/stopDelayingLoadEvent (by opposition to 
one HTML attribute and Mutation events which are *already* in the specs 
and browsers) will require more spec, more spec tests, more 
implementation, more implementation tests.
I'm not saying the feature is complicated, just that it's more 
complication that just an attribute and the value remain to be demonstrated.
What level of testing do you think browsers will provide? I can tell in 
advance that few browsers (none?) will test for conditions like "one 
document.delayLoadEvent call was before DOMContentLoaded and another 
after" and that's where you're in trouble.
Removing an attribute? Mutation events? Already in browsers, already 
used, already tested. That works. That's much less work for just everyone.

>     Give one way to signal that the application is ready. Devs will
>     figure out the rest. One way to signal that the application is
>     ready will serve at least 80% (maybe 90%) of the needs anyway.
>
>
> I think every proposal so far gives exactly one way to signal, so I 
> don't know what this means.
I didn't mean "one way" in that sense, sorry for the confusion. I meant 
"send one signal". If "independent scripts" can all contribute to 
telling when the app is ready, then, there are several signals.

>
>     In this context, trying to support composition of independent
>     scripts is most likely over-engineering. Will ads care to call
>     document.delayLoadEvent()? Will social widgets do that? Where is
>     the concrete need for independent script composition? Are the rare
>     use cases really worth the additional complexity?
>
>
> If I'm making part of a site use this feature, I want it to be 
> self-contained within the code that's actually using the feature, not 
> messing about with document-global attributes.  This is equivalent to 
> why we use addEventListener in modules, rather than event handlers.
How are document.delayLoadEvent and document.stopDelayingLoadEvent any 
less global than an attribute on <html>? That is *exactly* the same 
amount of globalness. The risks and consequences of bugs and malicious 
behavior is equivalent for both features.

"I want it to be self-contained within the code that's actually using 
the feature, not messing about with document-global attributes."
=> The "self-contained" keyword makes me think that you really want Caja 
or some lighter version of it.

David

[1] https://developers.google.com/apps-script/overview
[2] https://script.google.com/


More information about the whatwg mailing list