Conflicts using export *

# Kevin Smith (12 years ago)

Take the following situation:

// M.js
export * from "foo";
export * from "bar";

// "foo"
export var x = 1;

// "bar"
export var x = 2;

What is M.x bound to? foo.x (1), bar.x (2), or is this an error? What is our current thinking?

# Sam Tobin-Hochstadt (12 years ago)

This is a static error.

# Kevin Smith (12 years ago)

Woot! That's what I was hoping.

Thanks,

# Kevin Smith (12 years ago)

What about the following case?

// M
export * from "foo";
export var x = 1;

// foo
export var x = 2;

Would M.x be bound to the local variable, or would this be an error as well?

# Sam Tobin-Hochstadt (12 years ago)

M.x is the local variable, because otherwise changes in the exports of "foo" could, unbenknownst to M, cause an error.

Also, I misspoke earlier. The error is only if you use M.x, for the same reason.

# Kevin Smith (12 years ago)

M.x is the local variable, because otherwise changes in the exports of "foo" could, unbenknownst to M, cause an error.

I agree.

Also, I misspoke earlier. The error is only if you use M.x, for the same reason.

Ah - subtle but important point.

# Brendan Eich (12 years ago)

Kevin Smith wrote:

Also, I misspoke earlier.  The error is only if you *use* M.x, for the
same reason.

Ah - subtle but important point.

Yes, super-important in a growing independently-owned modules setting. I.e., reality.

# Andreas Rossberg (12 years ago)

What about:

// M.js
export * from "foo";
export * from "foo";

// foo.js
export var x = 1;

Or:

// M.js
export * from "foo";
export * from "bar";

// foo.js
export * from "foobar";

// bar.js
export * from "foobar";

// foobar.js
export var x = 1;

I just want to make sure that using M.x in any of these cases is an error likewise.

# Claus Reinke (12 years ago)

This is a static error.

On Thu, Jun 13, 2013 at 3:37 PM, Kevin Smith <zenparsing at gmail.com> wrote:

Take the following situation:

// M.js
export * from "foo";
export * from "bar";

I am confused: I thought "import *" was removed because, in the presence of dynamically configured loaders, it would leave tools (and programmers) unable to infer the local scope without executing code. Now we have the same issue back via "export *", just need a re-exporting intermediate module?

Explicit import/export includes hard-coded interfaces that decouple the importer of such dynamic export changes. Selecting properties from a module object allows for dynamic import without going via static scoping. Without the ability to specify static module interfaces, "export/import *" are different beasts, however, and do not fit into the statically checked import into static scope picture.

Claus

# Sam Tobin-Hochstadt (12 years ago)

On Fri, Jun 14, 2013 at 3:48 AM, Andreas Rossberg <rossberg at google.com> wrote:

What about:

// M.js
export * from "foo";
export * from "foo";

// foo.js
export var x = 1;

Or:

// M.js
export * from "foo";
export * from "bar";

// foo.js
export * from "foobar";

// bar.js
export * from "foobar";

// foobar.js
export var x = 1;

I just want to make sure that using M.x in any of these cases is an error likewise.

In principle, I think it's better to allow these cases (think macros), but I don't have strong feelings about it, so I'm fine with disallowing them.

# Sam Tobin-Hochstadt (12 years ago)

On Fri, Jun 14, 2013 at 4:57 AM, Claus Reinke <claus.reinke at talk21.com> wrote:

I am confused: I thought import * was removed because, in the presence of dynamically configured loaders, it would leave tools (and programmers) unable to infer the local scope without executing code. Now we have the same issue back via export *, just need a re-exporting intermediate module?

No, you don't. import * affects the names bound in a module. export * doesn't. You still can't import a name without listing it explicitly, meaning that it's always easy to determine the local scope.

# Kevin Smith (12 years ago)
// M.js
export * from "foo";
export * from "bar";

// foo.js
export * from "foobar";

// bar.js
export * from "foobar";

// foobar.js
export var x = 1;

I just want to make sure that using M.x in any of these cases is an error likewise.

Is there a particular reason? I feel indifferent so far, and it wouldn't be difficult to put an additional check on the binding target during linking.

# Claus Reinke (12 years ago)

No, you don't. import * affects the names bound in a module. export * doesn't. You still can't import a name without listing it explicitly, meaning that it's always easy to determine the local scope.

Sam

Ah, thanks. That makes sense.

# Andreas Rossberg (12 years ago)

On 14 June 2013 15:00, Kevin Smith <zenparsing at gmail.com> wrote:

// M.js
export * from "foo";
export * from "bar";

// foo.js
export * from "foobar";

// bar.js
export * from "foobar";

// foobar.js
export var x = 1;

I just want to make sure that using M.x in any of these cases is an error likewise.

Is there a particular reason? I feel indifferent so far, and it wouldn't be difficult to put an additional check on the binding target during linking.

It would introduce an observable difference between

export * from "foo" // where foo exports x, y, z

and

import {x, y, z} from "foo" export {x, y, z}

which I think is bad for modularity and refactoring.

Also, it would require name resolution to keep track of where every export is originally coming from, which is kind of nasty. I'm not sure, but it might even make resolution somewhat harder, because you need more (potentially recursive) information to distinguish errors from non-errors -- i.e., you might have to delay certain checks to a separate pass.

# Kevin Smith (12 years ago)

Related: is it permissible to bind more than one local name to a single remote target?

// foo.js
export var x;

// main.js
import { x as x1, x as x2 } from "foo";
# Sam Tobin-Hochstadt (12 years ago)

Yes, this is fine.

# Kevin Smith (12 years ago)

And are imported bindings writable, if the target binding is non-const?

// foo
export var x;

// main.js
import { x } from "foo";
x = 2; // OK?