Remarks about module import

ihab.awad at ihab.awad at
Mon Aug 18 13:44:40 PDT 2008

Hi folks,

The module system proposals, especially the one here --

are pretty cool; I took the liberty of not following Dave Herman's
advice to not pay it much attention. ;) Here are some comments coming
from where I sit on the Caja team, and thus with a strong emphasis on

== Module naming ==

The declared name of a module, e.g. "A" in --

  module A { ... }

is either meaningful or meaningless. ;) If it is meaningful, it means
that the module itself gets to specify where it lives in the
namespace(s) owned by the importing entity. That is an improper (read:
insecure) inversion of responsibility; what a module, upon being
imported, is called by its importer is properly none of its business.
And if the module name is meaningless, then we don't need it.

By that argument, I would like to propose that a module and a
"compilation unit" (or ES3 <Program>) be merged into one concept. This
has the useful side effect that the loading of a top-level program
(whatever that is, and wherever it comes from) can be re-explained
simply in terms of the loading of a module.

== Exchange of objects ==

I strongly suggest that the importer supply an explicit map giving
symbol bindings for the loaded module, , i.e., I don't think the
imported module should automatically inherit the lexical scope at the
import point. The module's code is typically not under the direct
control of the importer, so allowing it to schlep all its importer's
lexical variables is giving it too much dangerous power.

The module itself can gain access to the symbols supplied by the
caller via some sort of a "require" syntax; that said, our position in
the Caja project has been to simply recognize that certain variables
in a [Caja] module are free, and expect the importer to provide
bindings (and bind them to "undefined" if the importer fails to
provide bindings). I think this is simpler than the "require" syntax
and meshes nicely with the existing way that symbols (like "document"
and "window") are provided to top-level code in ES embeddings.

Finally, the importing code should be in full control of what names
are inserted into its own scope; this again is important for security.
In fact, this point is important enough that I would leave out any
sort of "import *" functionality, relegating to IDEs the task of
helping manage explicit import lists.

== An example ==

Consider a module file located at the URL --

containing the text --

  var isOn = false;
      toggle: function() {
        document.setBackgroundColor(isOn ?
            background : '#ffffff');
        isOn = !isOn;
      set: function() {
        isOn = true;

This code has two free variables, "document" and "background", and
returns the symbols "toggle" and "set" to the importer. The module
also has state, implying that it can be instantiated multiple times.

An importer could use this as follows --

  var doc = ...;
  var bg = ...;

      of fetchModule(''),
      with document: doc, background: bg
      using t: toggle, s: set;

  // "t" and "s" are now in scope

This would desugar to something like --

  var doc = ...;
  var bg = ...;

  var temp___ = importModule(
      { document: doc, background: bg });
  var t = temp___.toggle;
  var s = temp___.set;

Note that I have used "fetchModule" as a shortcut to say that I am
punting on the semantics of how a module is located and the
concurrency semantics whereby its text is retrieved (per Brendan's
points made earlier).

To exchange symbols without renaming them, we could abbreviate to --

  var document = ...;
  var background = ...;

      of fetchModule(''),
      with document, background
      using toggle, set;

  // "toggle" and "set" are now in scope

== Reference to Caja modules ==

We have a preliminary writeup of how we would like to think about
module loading in Caja here --

Hope this helps. Cheers,


Ihab A.B. Awad, Palo Alto, CA

More information about the Es-discuss mailing list