Re: Out of order JS file execution in WebKit

[email protected] Tue, 13 Apr 2010 01:56:03 -0000
Newsgroups gmane.comp.python.quotient.dev
Message-ID <20100413015603.2779.119455803.divmod.xquotient.398@localhost.localdomain>
On 12 Apr, 06:53 pm, [email protected] wrote:
>This definitely makes sense. I got the sinking feeling that I'm loosing
>this really great and simple extension of JS and the whole nevow/athena
>LivePage ecosystem too when I encountered this WebKit problem first. If
>you could elaborate on where to bring in the wrapper func you proposed 
>I
>would be more than happy.

So, a few tips to get started:

Athena already keeps track of any widget which has been dropped into the 
page somehow but for which the javascript object hasn't yet been 
initialized.  The reasons for this are a bit obscure, but the result is 
Nevow.Athena.Widget._waitingWidgets.   If you search for _waitingWidgets 
in Nevow/nevow/js/Nevow/Athena/__init__.js, you'll find a couple 
functions which interact with this.  One, _widgetNodeAdded, gets called 
from the DOM when a new widget appears in it that needs to be 
initialized.  Then, some time later, _instantiateWidgets gets called and 
goes over _waitingWidgets instantiating the things that need to be 
instantiated.

That's all interesting because it's _sort of_ like what you might want 
to happen with modules.  Keep track of which ones have been loaded but 
are waiting on dependencies before actually being evaluated, and then at 
some later point actually doing the evaluation.

_waitingWidgets triggers the "later point" using a timer event, which 
sucks, but there was probably some reason for it.  Fortunately, for 
module loading, it's not necessary to resort to timing.  Instead, the 
event will be that some /other/ javascript module was finally loaded and 
evaluated.

Next, in Nevow/nevow/athena.py, there's MappingResource.  This is the 
thing that's supposed to be used to actually serve up the source of the 
JavaScript modules.

If you change what its `resourceFactory` method returns, then you're 
changing what javascript is served up when a browser tries to load 
athena modules.  As a first stab, you could try loading up the contents 
of the named file yourself, mangling it somehow, and returning it in a 
static.Data.

Ultimately it would be nice if Athena's javascript weren't tied to files 
on disk, but that's a concern for later on I think.

As for the actual mangling itself, it may be a simple matter of wrapping 
the entire module source in some boilerplate for deferring evaluation 
and setting up the necessary triggers.  As far as the wrapping goes, I'm 
really just talking about simple string manipulation.  Like:

    moduleSource = """
setupSomeState("%(moduleName)s, function() {
%(moduleBody)s
});
""" % {'moduleName': whateverName, 'moduleBody': originalJSSource}

Nothing fancier than that.  I think it should work.  Perhaps the only 
tricky bit is that the module name may not be immediately easily 
accessible, but I'm sure there's a way to deal with that.

Hope this helps,
Jean-Paul