Modules, Concatenation, and Better Solutions

John J Barton johnjbarton at
Tue Oct 16 16:51:56 PDT 2012

On Tue, Oct 16, 2012 at 2:58 PM, David Herman <dherman at> wrote:
> On Oct 15, 2012, at 6:45 AM, Kevin Smith <khs4473 at> wrote:
>> OK, so:
>>     module A {
>>       console.log("a");
>>       export var x;
>>     }
>>     console.log("$");
>>     import x from A;
>> Does this print:
> Good question. The way we have it currently specified isn't ideal for concatenation, I think. The code executes eagerly, from top to bottom, but if it encounters an external load, it executes that external module on demand (i.e., on first import). This means that this:
>     // a.js
>     import b from "b.js";
>     console.log("a");
>     export let a = "a";
>     // b.js
>     console.log("b");
>     export let b = "b";
>     // main.js
>     import a from "a.js";
>     console.log("main");
> prints "b" then "a" then "main", whereas this:
>     module a {
>         import b from b;
>         console.log("a");
>         export let a = "a";
>     }
>     module b {
>         console.log("b");
>         export let b = "b";
>     }
>     import a from "a".js";
>     console.log("main");
> prints "a" then "b" then "main". That's clearly a problem for simple concatenation. On the one hand, the point of eager execution was to make the execution model simple and consistent with corresponding IIFE code.

(I know this is obvious, but the eager execution model is simple and
IIFE-like only if you imagine that "module execute eagerly".)

> On the other hand, executing external modules by need is good for usually (except in some cases with cyclic dependencies) ensuring that the module you're importing from is fully initialized by the time you import from it.
> I see two coherent alternatives:
> (a) execute inline modules by need (i.e., on first import) rather than eagerly
> (b) execute external modules "transactionally", trying to order them by dependency so that imported modules have fully initialized before the code that depends on them runs
> The weird thing about (a) is that code that appears to be straight-line actually executes in somewhat more unpredictable (although deterministic) order.

I guess if we can handle deeply nested callbacks, event handlers, and
promises, then this is a pretty tame as weird things go.  Are you are
saying is that the body of the module does not run until we need its
content? So dependents pull in their dependencies and modules that are
not needed are not executed. That's what we want right?

> The downside of (b) is that when you have cyclic dependencies, one module won't even be *partly* initialized before the other module starts running. (Although usually, when you have cyclic dependencies, you probably don't want to be evaluating exports from each other in top-level code -- you want all those mutual references to be happening under functions.)

I don't understand b, but dependency on internal vs external sounds bad.

jjb ... eager to see modules happen!

> Dave
> _______________________________________________
> es-discuss mailing list
> es-discuss at

More information about the es-discuss mailing list