Harmony modules and asynchronous script loading and document.write (oh my)

This is my first post about Harmony modules. I hate to start right out of the gate with a long boring post about timing details, but it seems the few people who might eventually be interested in it are actually interested right now! So let’s dive in.

Once we have modules, running a script will sometimes hit the network.

        module blottr from "blottr.js";

(By the way: you will have to opt in to Harmony syntax somehow—yet to be determined. This post will ignore that consideration.)

When the HTML parser reaches this script, parsing will pause until “blottr.js” is loaded. This matters if “blottr.js” touches the DOM during its initialization, for example. In terms of timing, it behaves just like a <script src=> element.

(As a performance optimization, we plan to change the HTML5 parser to skim ahead, find probable module statements, and pre-fetch the scripts. Again, just like <script src=>.)

But what about this?

    function silly() {
        eval('module blottr from "blottr.js";');

What should happen if silly() is called from an event handler? Should it block until “blottr.js” comes in from the network? That would be a synchronous, blocking call, like synchronous XHR.

That would be gross. So in Harmony, eval will reject such code with a SyntaxError. In short, if a JavaScript caller is waiting, the module X from "url" syntax is banned. If your code needs a module off the network, you’ll just have to run it asynchronously somehow. Two new APIs, SystemLoader.load(urlcallback, errorCallback) and SystemLoader.asyncEval(code, callback, errorCallback), are proposed for that.

Now. Suppose we take the first example above and put it in a document.write call.

            '<script>' +
            '    module blottr from "blottr.js";' +
            '</scr' + 'ipt>');

Now what happens? (Benjamin Smedberg brought this case to my attention about 12 seconds after I described modules to him. It might have been less.)

To me, this particular flavor of document.write() weirdness was something new. I’m still not totally sure how we will handle it. Boris Zbarsky suggested again treating it the same as a <script src=> element: silently make that script load asynchronously, just because document.write() created it. That sounds plausible enough.

There are still a few more special cases to sort through. What happens if you try to load a module by assigning a string to an event handler attribute of a DOM element? I’m not sure yet. Perhaps we will throw a SyntaxError.

Bored to tears? Sorry! I’ll write again in a few days, explaining what Harmony modules are, who’s working on them, and why.

6 Responses to Harmony modules and asynchronous script loading and document.write (oh my)

  1. > silently make that script load asynchronously, just because
    > document.write() created it.

    More precisely, continue execution of the script that executed the document.write call, then once it’s done block the parser waiting for blottr.js to load before running the script that’s using the module.

    > What happens if you try to load a module by assigning a string to an event
    > handler attribute

    Exactly the same thing that happens when you do new Function(“module ….”). Event handler attribute values are just function bodies compiled with a particular list of formal parameters and in a particular scope. What _does_ happen in this case with new Function?

    Note that compile errors in event handler attributes are ignored, by the way (apart from being reported to an error console or whatnot); if they have a SyntaxError you just get no handler.

  2. Thanks, bz. That makes sense.

    Function(“module x from ‘x.js'”) will throw a SyntaxError.

  3. This might be an interesting article … if you remembered to link to somewhere that would tell the reader WTF Harmony is!

  4. Why wouldn’t the nested script case fall into the “JavaScript caller waiting” category of blocked module loads?

  5. pd: Harmony is a code name for the next major edition of the ECMAScript standard. It’s being put together now. You can see what has been proposed here: wiki.ecmascript.org/doku.php?id=harmony:proposals

    As that page says: “Lacking a formal language specification, the following list is not definitive, but it should reflect consensus achieved so far in TC39.”

  6. Blake: Yeah, I didn’t make that clear at all. Sorry. “JavaScript caller waiting” is meant as a rule of thumb. I don’t think we should actually specify examining the stack to see if there’s a JS stack frame. If we went that way, then for consistency, the relevant notion would actually have to be formally specified—currently it is not. (Note that proper tail calls, for example, or self-hosting some APIs, could affect whether there is anything “waiting”.) It sounds hard, and it would make it very difficult for developers to figure out from the spec what to expect.

    Instead, for each case (that is, for each place in the HTML spec and the ES-Harmony spec where a script is compiled), we should specify whether or not a blocking script load is permitted. So blocking script loads will be allowed or not based on the immediate context of the script, not the whole stack.

    The ES-Harmony grammar will note that from "url" is banned in contexts where script loads aren’t allowed.

    We can use the “JavaScript caller waiting” rule of thumb to figure out what to specify for each case. For example, clearly eval typically has a caller waiting, so we’ll ban blocking script loads there (even if eval happens to have been tail-called from setTimeout code, so that nobody is really waiting for the answer at all!) and allow them in evalAsync.

    That’s my intuition. I could be wrong. The relevant parts of the HTML spec are still new to me.

Leave a Reply

Your email address will not be published. Required fields are marked *