ES Modules: suggestions for improvement

Isaac Schlueter i at izs.me
Wed Jun 27 11:15:59 PDT 2012


> Well, this was a relatively high-profile example:
>
>     http://blog.safeshepherd.com/23/how-one-missing-var-ruined-our-launch/

That was a bug caused by a lack of global isolation, which current
module systems cannot fix.  (Well, node *can* fix it with separate
contexts, but only by harshly penalizing performance and breaking
typeof, which we're not willing to do.)

I think we all agree that global isolation is the core purpose of a
module system.  (Is that incorrect?)

The question was whether there are in-the-wild bugs caused by typo-ing
export names in current module systems.


> The client chose to use *. You don't have to use * if you don't want to.
> It's a convenience.

It's unnecessary, afaict, and causes demonstrable harm in languages
that have it.  If it's just a convenience, then it should be cut out.


> Clients are disallowed from mutating another module's exports. (That's one
> of the things we're able to accomplish by making modules declarative rather
> than totally dynamic.)

Mutating *at all*?  Ie, they're frozen?  If I export an object, you
can't decorate it?  (If so, what does that restriction buy us?  It
seems kind of harsh.)


> Here I have no idea what you're talking about. Nothing about ES6 modules
> prevents you from locally controlling names. Local control over scope has
> always been one of the foremost principles of the entire design.

It's not exactly clear to me how I'd import foo's "x" as something
other than "x", from reading
http://wiki.ecmascript.org/doku.php?id=harmony:modules  (Admittedly,
I'm a lot better at parsing JavaScript than parsing JavaScript parsing
rules.)

Something like this?

import {myX: x, myY: y, z} from "foo"
// comparable to:
let {myX: x, myY: y, z} = require("foo")


Does this allow any way for the "foo" module to export *just* a single
thing, as the top level result?  How would this be expressed?

var Foo = require("foo")
var f = new Foo()

If the answer is "that's not supported", then I think that's a
significant gap.  It encourages a "one module = one thing" style and
is very easy to reason about.  It would be better to give up
multi-exporting in favor of exporting one thing, only.  If I could get
away with making that change in Node, I would have by now.


How does this proposal address transitive dependency cycles?
Unfinished export objects?

// a.js
import b from "b"
export a = b

// b.js
import c from "c"
export b = c

// c.js
import a from "a"
export c_a = a
export c = 10
// does c_a === c?

This was one area where I mentioned in my blog post that new syntax
for exporting seems like it might be warranted.  With require()
systems today, c_a is undefined, because the "c" export wasn't set
yet.  It's of course much worse when these are functions that call one
another.

All of the problems that I'm bringing up, which you're saying are
solved by the Harmony:Modules proposal, is it possible to solve them
with less new syntax and boilerplate?


More information about the es-discuss mailing list