domenic at domenicdenicola.com (2013-11-02T19:22:55.016Z)
On Thu, Oct 31, 2013 at 12:40 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:
> You have to wait for "stickers" to load to validate the imports anyway.
Right. Validating imports doesn't block compilation though. As long as
you know at compile time that a given identifier *is* an import, you
can just emit a load, and patch that load's target address at link
time.
Or, if it's not an import: in the absence of `import * from`, the use
of the identifier "Math" above could be compiled to code that does
`global.[[Get]]("Math")`. SpiderMonkey does this today, when all
enclosing non-global scopes are static, which is most of the time.
With `import * from`, we have dynamic scoping until link time—which is
not the end of the world, but it sucks. Dynamic scoping sucks.
But all that is me speaking as an implementer. Humans looking at
modules in isolation also benefit from being able to tell what names
refer to.
> [regarding export * from]
> But it has a similar issue. You cannot look at a module in isolation and
> know what it exports.
The issues are abstractly similar, but very different in practice. The
effect of `import * from` on scoping depends on the version of the
module you're importing. Collisions can occur in the future, as your
code, the global object, and the imported module evolve. There's no
way to mitigate.
The effect of `export * from` has no effect on scoping and no
analogous risk of future collisions.
Now... good use cases could be a sufficient counterargument to all
this. Maybe we should add `import * from` in 2014. I just want to make
it totally clear why it's designed this way for ES6. `import * from`
poses significant problems, both for users and implementations, that
`export * from` doesn't.
On Thu, Oct 31, 2013 at 12:40 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote: > On Thu, Oct 31, 2013 at 1:22 PM, Jason Orendorff <jason.orendorff at gmail.com> > wrote: >> import * from "stickers"; >> ... >> y = r * Math.sin(a); >> ... >> >> It is unclear whether `Math` refers to the global Math or to something >> imported from "stickers" at least until "stickers" is loaded. > > You have to wait for "stickers" to load to validate the imports anyway. Right. Validating imports doesn't block compilation though. As long as you know at compile time that a given identifier *is* an import, you can just emit a load, and patch that load's target address at link time. Or, if it's not an import: in the absence of `import * from`, the use of the identifier "Math" above could be compiled to code that does global.[[Get]]("Math"). SpiderMonkey does this today, when all enclosing non-global scopes are static, which is most of the time. With `import * from`, we have dynamic scoping until link time—which is not the end of the world, but it sucks. Dynamic scoping sucks. But all that is me speaking as an implementer. Humans looking at modules in isolation also benefit from being able to tell what names refer to. [regarding export * from] > But it has a similar issue. You cannot look at a module in isolation and > know what it exports. The issues are abstractly similar, but very different in practice. The effect of `import * from` on scoping depends on the version of the module you're importing. Collisions can occur in the future, as your code, the global object, and the imported module evolve. There's no way to mitigate. The effect of `export * from` has no effect on scoping and no analogous risk of future collisions. Now... good use cases could be a sufficient counterargument to all this. Maybe we should add `import * from` in 2014. I just want to make it totally clear why it's designed this way for ES6. `import * from` poses significant problems, both for users and implementations, that `export * from` doesn't. -j