restrictions on module import export names

# John Lenz (11 years ago)

I'm wondering if this is valid (or should be):

// a.js

var foo = 1;
export foo as 'a.b.c';

// b.js

import 'a.b.c' as foo from "a.js"

The reason I ask is Modules appear to support have any valid property name (anything) as an export if the Module is defined directly using "newModule".

# Kevin Smith (11 years ago)
// a.js

var foo = 1;
export foo as 'a.b.c';

// b.js

import 'a.b.c' as foo from "a.js"

That is not valid. Export binding names (where you have 'a.b.c') must be IdentifierName.

# John Lenz (11 years ago)

I assume that I can access this like so:

var mod = newModule({'a.b.c':1})
use(mod['a.b.c']);

It isn't clear to me why imports and export names are restricted.

# Allen Wirfs-Brock (11 years ago)

There are still unresolved issues in the Rev22 spec. with the newModule (or possibly new Module) API. t probably needs to say that any property names must conform to IdentifierName.

The grammar requirement of IdentifierName is intentional and I don't believe there is any intent to allow that restriction to be circumvented via the Module API.

# Calvin Metcalf (11 years ago)

related, is it possible to export anonymous objects?

from looking at the spec it would seem that

let foo = 1;
export foo as default;

would be allowed but

export 1 as default;

would not

so to export an object that doesn't already have a name you'd have to something like:

export let default = 1;

less contrived examples of this in practice are exporting the results of a function (extremely common in node, for me at least) and exporting an array:

export let default = foo();
export let default = [thing1, thing2];

is there a reason

export expression;

doesn't desuger to

export const default = expression;

or am I missing something?

# Erik Arvidsson (11 years ago)

export default 1 works.

people.mozilla.org/~jorendorff/es6-draft.html#sec-exports

ExportDeclaration : ... export default AssignmentExpression ;

# Jason Orendorff (11 years ago)

On Wed, Jan 29, 2014 at 2:00 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:

export default 1 works.

people.mozilla.org/~jorendorff/es6-draft.html#sec-exports

ExportDeclaration : export default AssignmentExpression ;

I think that just exports the value 1 with the name "default".

# Calvin Metcalf (11 years ago)

So the following are equivalent?

export default foo();
export let default = foo();
# Domenic Denicola (11 years ago)

You cannot have a declaration with "default" as the IdentifierName, since that is a reserved word. So export let default = foo(); is not possible.

# Calvin Metcalf (11 years ago)

*would be equivalent of it was allowed

# Jason Orendorff (11 years ago)

Yes.

# Calvin Metcalf (11 years ago)

ok so would this be accurate gist.github.com/calvinmetcalf/8701624 ?

the syntax does make it impossible to write something equivalent to

let app = module.exports = require('express')();
# Domenic Denicola (11 years ago)

I would really encourage you to read the spec grammar.

export foo();

This is not allowed by the grammar; there is no form export <expression>

export default let a = [thing1, thing2];

This is not allowed by the grammar; let a = [thing1, thing2] is not an AssignmentExpression.

let app = module.exports = require('express')();

Try

import express from "express";
let app = express();
export default app;
# Kevin Smith (11 years ago)
let app = module.exports = require('express')();

Not impossible. Possibly:

import express from "express";
let app = express();
export { app as default };

I think you're attempting to optimize edge cases.

Also, I agree with Domenic. Read the grammar for the current spec and try not to post syntax errors that might lead others astray : )

# Calvin Metcalf (11 years ago)

sorry guys, was getting confused on VariableStatement vs AssignmentExpression, gist is updated with correct examples, I guess it seems somewhat overly complicated having 4 different ways to export things each with their own arbitrary restrictions which leads to weirdness, e.g. if you want to export an array as foo you could do

export let foo = [stuff];

but if foo was already defined you probably wouldn't want to do that, but you wouldn't be able to do this (I believe).

//bad
export { [stuff] as foo}

as you can only use identifierNames or identifierReferences here even though they are going to be discarded, so

let _foo = [stuff];
export { _foo as foo };

would be the only way

the other thing is on second thought more of an issue with imports not being expressions, yes this code might be an edge case

let app = module.exports = require('express')();

but it's from in the wild code, slightly less ridicules example would be


var projs = [
  require('./projections/merc'),
  require('./projections/longlat')
];

is there a reason import ModuleSpecifier can't be an expression which evaluates to either an object with all the imports or the default export when it's used as an AssignmentExpression (I think I'm using that one right).

# Kevin Smith (11 years ago)
var projs = [
  require('./projections/merc'),

  require('./projections/longlat')
];

With ES6 modules, you might do something like this:

import merc from "./projections/merc";
import longlat from "./projections/longlat";

var projs = [merc, longlat];

Or if you're importing the modules themselves:

module merc from "./projectsions/merc";
module longlat from "./projectsions/longlat";

var projs = [merc, longlat];

is there a reason [import] can't be an expression which evaluates to either an object with all the [exports] or the default export when it's used as an AssignmentExpression (I think I'm using that one right).

Yes. ES6 modules are "statically linked", meaning that all of the non-local (imported) bindings are resolved before the module begins executing. It's an important distinction.

Because of this difference, you can expect usage patterns to turn out somewhat different from the "require" patterns we are used to seeing in node.

# Calvin Metcalf (11 years ago)

forgot to hit replay all

On Thu, Jan 30, 2014 at 10:25 AM, Kevin Smith <zenparsing at gmail.com> wrote:

[Did you mean to reply all?]

var projs = [
    import "./projections/merc",
    import "./projections/longlat"
];

That idea was last discussed on the list two or three years ago. The problem is that you are placing strange and novel placement restrictions on expression forms, which is sure to cause more confusion than it's worth. What about cases like:

var x = f || import "blah";

Should that be different than this?

var x = import "blah" || f;

The current module design is straightforward and clean. Have you tried doing any coding with them?

yes I've coded with them via ember app kit's grunt es6 module transpiler thingy, the syntax was significantly more complex and verbose than commonjs and we ended up switching over to browserify/commonjs.

var x = f || import "blah";

Should that be different than this?

var x = import "blah" || f;

if we have static linking (which imho is great, not complaining about it, seriously good work guys) then those should act in the same way, what I'm really suggesting is probably more like sugar for,

var x = f || import "blah";
//becomes ->

import "blah" as _temp;
var x = f || _temp;

similar to export default which didn't change anything behind the scenes.