[e-lang] Module loading discussion
Jonathan Rees
jar at mumble.net
Thu Dec 3 05:50:30 PST 2009
I wrote a reply and put it here:
http://odontomachus.wordpress.com/2009/12/03/javascript-modules/
I'm not on google-caja-discuss so did not attempt to cc: there. (maybe
I should be.)
Best
Jonathan
On Nov 19, 2009, at 9:10 PM, ihab.awad at gmail.com wrote:
> Retweeting a message from google-caja-discuss to e-lang.
>
> * * * * *
>
> Caja fans,
>
> A couple days ago, I presented to the Caja group some material that
> I had previously presented to the ECMA TC39 committee, describing
> the module system we have implemented in Caja. The slides are here:
>
> http://sites.google.com/site/ihabawad/Home/es5Modules-2009-11-06.pdf
>
> * * * * *
>
> At the Cajita level, we implement a module loader such that the
> result of calling:
>
> load('foo')
>
> where "foo" is a module ID, returns a "module function". This is a
> closed function (i.e., it has no free variables) and is instantiated
> by calling it with an object literal providing bindings for its free
> variables. So if "foo.js" contained, say:
>
> x + y;
>
> then the following expression:
>
> load('foo')({ x: 3, y: 4 });
>
> would evaluate to 7. So far so good.
>
> One desideratum is that the IDs of modules are "self-relative".
> Let's say module "a/b/c.js" contains the following expression:
>
> load('../d/e');
>
> This should be relative to its _own_ ID; hence, the result of this
> should be to load:
>
> a/d/e.js
>
> This means that a module must "know" its own ID, in some sense, and
> hand it to its own loaders so that they can compute IDs relative to
> that.
>
> The way we did that in Cajita, we just _gave_ the module access to
> its own loader. But Mark Miller pointed out correctly that this was
> a violation of the assumption that module functions are transitively
> immutable -- i.e., powerless. If a module function is connected to
> something that, at the mere utterance of "load()", goes out to the
> internets and fetches guff, that is definitely an ambient authority.
> So, what's to do?
>
> The simplest way to fix this is to allow a module to know its own ID
> (i.e., the ID it was loaded by). Let's say each module function is
> given a well-known constant in its lexical scope; for this
> description, we will call it:
>
> _thisModuleId_
>
> A module can then load something relative to its own ID by saying:
>
> load('foo', _thisModuleId_);
>
> and thus the module function does not have to close over its loader.
> Capability security regained. The specific syntax of this sort of
> thing remains to be hashed out.
>
> * * * * *
>
> Mark Miller made some concrete suggestions as well. He stipulated
> two "load()" forms, which we name for the purposes of this
> discussion only. "loadf" stands for "load function" and is the basic
> "load()" we have now. To load a module function, do:
>
> moduleFunction = loadf('a/b/c');
>
> which will load "a/b/c.js" as before. He also proposed "loadi",
> which stands for "load instance" and actually instantiates the
> module, in addition to loading its module function. To use it, do:
>
> moduleInstance = loadi('a/b/c', { x: 3, y: 4 });
>
> The trick with "loadi" is that it has two conveniences: (a) it loads
> a module function and instantiates it in one shot; and (b) it
> desugars to:
>
> moduleInstance = loadf('a/b/c')({ loadf: loadf.for('a/b/c'), x: 3,
> y: 4});
>
> In other words, it automatically passes down to the module being
> loaded a version of the current loader that is pre-configured to
> search relative to the path "a/b/c".
>
> The reason why conveniences (a) and (b) are mixed together is that I
> may call any given module function with two different loaders, so
> providing a loader is an instantiation time, not a loading time,
> thing. So say I load some module function:
>
> mf = loadf('a/b/c');
>
> I can instantiate this with two different loaders:
>
> mi_1 = mf({ loadf: theFirstLoader, x: 3, y: 4 });
> mi_2 = mf({ loadf: theSecondLoader, x: 3, y: 4 });
>
> and the object graphs created in mi_1 and mi_2, including the code
> they are transitively connected to, may be wildly different because
> -- well -- they were instantiated with different loaders.
>
> There is a final wrinkle in this. Note that we implement synchronous
> "load()" on top of an async loader by stipulating that (i) the
> topmost module loading is always async; and (ii) sync dependencies
> are declared in the Caja module record, and are thus prefetched
> prior to calling the module. Thus the sync dependencies are already
> in the loader's cache when the code is running. Now, what if an
> instantiating entity switches loaders along the way, and the loader
> provided does _not_ have the requested module in the cache? The
> answer is => this is a predictable failure mode. An exception is
> thrown. This is, after all, a fairly uncommon case.
>
> Cheers,
>
> Ihab
>
> --
> Ihab A.B. Awad, Palo Alto, CA
> _______________________________________________
> e-lang mailing list
> e-lang at mail.eros-os.org
> http://www.eros-os.org/mailman/listinfo/e-lang
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.eros-os.org/pipermail/e-lang/attachments/20091203/52472a0e/attachment.html
More information about the e-lang
mailing list