Re: Out of order JS file execution in WebKit
Tristan Seligmann <[email protected]> Thu, 15 Apr 2010 10:45:12 +0200
| Newsgroups | gmane.comp.python.quotient.dev |
|---|---|
| Message-ID | <[email protected]> |
On Thu, Apr 15, 2010 at 8:10 AM, Werner Thie <[email protected]> wrote: > Tristan, can you give me a pointer for attacking this problem, I like Hmm, let's see. In order to serialise a widget for dynamic instantiation, LIveElement._structured() is called. This, in turn, flattens the element to get the markup; it also uses context.call to set up lists, including 'requiredModules', which the liveElement renderer mutates during the course of rendering. This allows it to collect a list of all modules required by the widget and any of its children. The list of dependencies is constructed by calling allDependencies() on the relevant module, and then filtering it with LivePage._shouldInclude(). _shouldInclude keeps a list of all modules it has ever been called with, and returns False if one of those modules is passed in, otherwise True (and adds it to the list); thus, each module will only be imported once. For static instantiation, this is exactly what we want, as modules will be loaded in the correct order, and only once; I'm not sure what the best way to fix this for dynamic instantiation is. One way to do it would be to force the client-side code to load modules serially; this would ensure that they're loaded in the correct order, but this may affect network performance adversely. I think a better solution would actually be something similar to what was already discussed in this thread; although, most of the pieces are already in place. Scripts are loaded in Nevow.Athena.Widget._addChildWidgetFromComponents, using Divmod.Runtime.theRuntime.loadScript(). The implementation differs between runtimes, but in all cases, it returns a Deferred that only fires once the module has actually been loaded. This is used to delay the actual instantiation of the widget until the dependent modules have been loaded. My suggestion would involve adding a loadScript() method on the page widget: the first time it's called, it would fire off the real loadScript() call; if called while the script is still being loaded, it would return another deferred that fires when the script has loaded; if called after the script has loaded, it would return a deferred that fires immediately. The server-side code would be changed to not filter the dependencies list through _shouldInclude in the dynamic instantiation case (by adding a flag parameter to the involved methods, I guess?), so that loadScript() would be called for all of the dependencies, not just the ones that have never been loaded. The page setup code would probably need to pass a list of statically loaded modules to the page widget, so that it knows that they're already loaded. Hope that helps; I wrote this based on a cursory reexamination of the code in question, along with vague recollections from the last time I looked at the code, so I may have some of the details wrong, but hopefully this is enough to point you in the right direction. -- mithrandi, i Ainil en-Balandor, a faer Ambar