Nested modules clarification

๏̯͡๏ Jasvir Nagra jas at
Thu Jul 19 14:58:58 PDT 2012

On Wed, Jul 18, 2012 at 9:35 PM, David Herman <dherman at> wrote:

> On Jul 18, 2012, at 9:15 AM, ๏̯͡๏ Jasvir Nagra wrote:
> On Wed, Jul 18, 2012 at 4:25 AM, Sam Tobin-Hochstadt <samth at>wrote:
>> Lexical bindings as well as module definitions:
>> module outer {
>>   let x = 1;
>>   export module inner {
>>     export y = x + 2;
>>   }
>> }
> That's a little unexpected.  Would the same hold if the above code was
> refactored so the inner module was a separate file?
> module outer {
>   let x = 1;
>   export module inner = "http://m/inner.js";
> }
> No, an external file only has access to the global scope, so x would not
> be visible to the module in the external file.

Awesome - that avoids one kind of lexical surprise and I agree is the right
design choice.  Given the similarity of semantics, I suspect I'd end up
replacing a lot of code that currently looks like (function() { ...code...
})(); with module $$ { ...code... }. ***

The inlining/outlining issue I was alluding to is because of the deviation
from Tennents correspondence and arises dealing with local vars shadowing
objects in the global scope.  This will affects primodial objects like
Object, Array etc. and those that some environments like the browser cause
to be injected into the global scope (eg getComputedStyle, location,
document, window etc).

Here's the modified test case from earlier:

module outer {
  let Object = {};
  export module inner = "http://m/inner.js";

Object.prototype.myMarker = 3;
assert( ({}).myMarker === 3 )

Presumably, the author of inner.js expects the assertion to hold and it
does in the external module case but does not after inlining of the form
you describe below.  This kind of confusion affects all globals that can be
mentioned by an external module that can be used with them being declared.

This brings me to the question of what globals are in scope in a new
module?  In the case of browsers, there's a lot of globals already.  Is the
expectation that browser module authors will have to do a:

import {document, window, getComputedStyle,location} from browser;

to get to the document object?  How about the window object?

I realize some of this is outside the scope of this standards body but it
will affect globals that es standardizes as well.  Also, more generally I'd
be keen to hear your input on how you think this should even if it's not


*** After writing this, I realized that the module { ... } syntax is (a)
unlike (function() {})() is not generative and (b) can't appear in all the
places that (function(){})(); can so maybe this is not an entirely good
idea.  Just seemed nice to have a simpler syntax for it given how close it
was to the needed semantics.

If not, should a module inliner be doing variable renaming in order to
> maintain semantics?
> It shouldn't be much of an issue if they're only being inlined at top
> level. E.g., transforming module files m1.js, m2.js, m3.js into a single
> file:
>     module m1 { /* contents of m1.js */ }
>     module m2 { /* contents of m2.js */ }
>     module m3 { /* contents of m3.js */ }
> Should be exactly equivalent except for the names m1, m2, and m3. So you'd
> only need to synthesize fresh variable names for the generated modules.
> But maybe I'm missing what kind of inliner you're thinking of?
> Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list