Composition of Uncoordinated Working Sets of Modules

Sam Tobin-Hochstadt samth at
Mon Jun 7 08:37:09 PDT 2010

On Sun, Jun 6, 2010 at 2:00 PM, Kris Kowal <kris.kowal at> wrote:
> Supposing that aQuery and bQuery are implemented by independent
> uncoordinated authors.
> aQuery.js
>    module $ {
>    }
> bQuery.js
>    module $ {
>    }
> If my interpretation is correct, these cannot be combined in a single
> "Application".
>    <script type="harmony" src="aQuery.js"></script>
>    <script type="harmony" src="bQuery.js"></script>

That's not correct, the second module would simply shadow the first.

> One solution to this problem is to convince A and B to coordinate,
> which I've hitherto inferred was the only solution supported by Simple
> Modules, in which case they share a fault with Java.

That's not the only solution.

> Is this a solution?
>    <script type="harmony">
>        module A_ = load("aQuery.js");
>        module A = A_.$;
>        module B_ = load("bQuery.js");
>        module B = B_.$;
>    </script>

Yes, although it's even simpler to just skip the `A_' bits, and refer
to A.$ and B.$.

> With this example, I am inferring that
> * That the web-browser's loader knows the location of the current
>  page, so it can resolve the MRL based on that location.

We have explicitly avoided any commitment to the semantics of MRLs.
Certainly we don't want to mandate how path lookup or remote fetching
works, since this may not be applicable to all ES host environments.

> * "load" can only be used in the context of an importing module
>  assignment.

'load' is a relative keyword (I'm forgetting the exact term here)
which is specified in the ModuleDeclaration production on the
simple_modules wiki page.

> * conceptually, if not at run-time, "load" returns a module instance
>  that contains the top-level modules of the given script.
> * that the top-level modules of the remote script are not registered
>  as top-level modules of the local application, unlike co-DOM
>  scripts.


module M = load "foo.js";

creates a new module M with foo.js as its contents.

> * for a script to have importable bindings, these must exist in a
>  module block of the loaded script.

I don't know what this means.

> * there is no notation for destructuring a module from a loaded
>  sub-module

If a module is statically bound, you can access its value exports with
'import' or its component modules with 'module M = ...'

> * a script is not a module, so exports cannot be used at the top
>  level.

The ScriptElement production explicitly includes ImportStatement, so
modules can be imported by scripts.

> If that's the case, I would like to refine this approach, such that
> loaded modules can have exports at the top level.  This would permit
> the function export.
> aQuery.js
>    export var $ = function () {
>    };
> bQuery.js
>    export var $ = function () {
>    };
> link.js
>    module A = load("aQuery.js");
>    module B = load("bQuery.js");

This is exactly what the proposal already specifies.

> It would also be good for there to be a way to bind $ without binding
> a module.
>    const A = load("aQuery.js").$;
>    const B = load("bQuery.js").$;

It's possible to use the module loader API to do this, slightly more
verbosely.   But why?  If you say:

module A = load "aQuery.js";

then A.$ is already available for use in expression contexts.

> This obviously breaks a load call outside an import clause, which I
> infer is not possible with the present proposal.

You keep saying 'infer'.  Is the grammar Dave has written on the wiki
page unclear?

> Is it possible to decouple name spaces from loaded modules?

What do you mean by 'name spaces'?

> Another point of interest is transitive loads.  I do not think that
> there is a provision in the specification that would permit load
> directives to be resolved relative to the location or MRL of the
> module from which load call is declared.
> scripts/sazzle.js
>    module Sazzle {
>    }
> scripts/aQuery.js
>    module Sazzle_ = load("sazzle.js"); // relative to
>                                    // "scripts/aQuery.js"
>    module Sazzle = Sazzle_.Sazzle;
>    module aQuery {
>        export $ = function () {
>        };
>    }
> link.js
>    module aQuery_ = load("scripts/aQuery.js");
>    const $ = aQuery_.aQuery.$;

Again, we haven't specified the precise semantics of MRL resolution,
which will depend both on the host environment and the current module
loader.  Your example might point to a need to augment the module
loader api with information on 'load' calls specifying what module the
'load' occurs in.
sam th
samth at

More information about the es-discuss mailing list