[e-lang] Module loading discussion
Monty Zukowski
monty at codetransform.com
Thu Dec 3 09:04:42 PST 2009
I like the ability to bind variables during instantiation, seems to
follow along with the philosophy of
http://bracha.org/newspeak-modules.pdf which I found to be helpful in
reasoning about the module system we're developing at Temboo.
Monty
On Thu, Nov 19, 2009 at 6: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
>
>
More information about the e-lang
mailing list