Proposal: add more export-from statements in ES7
Latest commit 4258790 Mar 30, 2016 @leebyron micro
Permalink
Failed to load latest commit information.
ESTree.md clarifications Sep 22, 2015
README.md micro Mar 29, 2016
Spec.md Merge branch 'master' of github.com:leebyron/ecmascript-more-export-from Sep 22, 2015

README.md




This spec has been withdrawn in favor of the equivalent micro-proposals: export ns from and export default from.








Additional export-from statements in ES7

ES7 Proposal

Stage: 1

Author: Lee Byron

Specification: Spec.md

AST: ESTree.md

Transpiler: See Babel's es7.exportExtensions option.

Problem statement and rationale

The export ___ from "module" statements are a very useful mechanism for building up "package" modules in a declarative way. In the ES6 spec, we can:

  • export through a single export with export {x} from "mod"
  • ...optionally renaming it with export {x as v} from "mod"
  • We can also spread all exports with export * from "mod".

These three export-from statements are easy to understand if you understand the semantics of the similar looking import statements.

However, there are other import statements which would have very useful export-from forms.

  • Exporting the ModuleNameSpace object as a named export: export * as ns from "mod"
  • Forwarding the default export of the referenced module as a named export of this module: export v from "mod"

Current ES6 Modules:

Import Statement Form [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" "*" "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod";
Export Statement Form [[ModuleRequest]] [[ImportName]] [[LocalName]] [[ExportName]]
export var v; null null "v" "v"
export default function f(){}; null null "f" "default"
export default function(){}; null null "*default*" "default"
export default 42; null null "*default*" "default"
export {x}; null null "x" "x"
export {x as v}; null null "x" "v"
export {x} from "mod"; "mod" "x" null "x"
export {x as v} from "mod"; "mod" "x" null "v"
export * from "mod"; "mod" "*" null null

Proposed additions:

Export Statement Form [[ModuleRequest]] [[ImportName]] [[LocalName]] [[ExportName]]
export * as ns from "mod"; "mod" "*" null "ns"
export v from "mod"; "mod" "default" null "v"

Symmetry between import and export

There's a syntactic symmetry between the export-from statements and the import statements they resemble. There is also a semantic symmetry; where import creates a locally named binding, export-from creates an export entry.

As an example:

export {v} from "mod";

Is symmetric to:

import {v} from "mod";

However, where importing v introduces a name in the local scope, export-from v does not alter the local scope, instead creating an export entry.

The two proposed additions follow this same symmetric pattern:

Exporting a namespace exotic object without altering local scope:

// proposed:
export * as ns from "mod";
// symmetric to:
import * as ns from "mod";

Re-exporting a module's default export with a name:

// proposed:
export v from "mod";
// symmetric to:
import v from "mod";

Using the terminology of Table 42 in ECMA-262 v6 RC4, the export-from form can be created from the symmetric import form by setting export-from's [[ExportName]] to import's [[LocalName]] and export-from's [[LocalName]] to null.

Table showing symmetry

Statement Form [[ModuleRequest]] [[ImportName]] [[LocalName]] [[ExportName]]
import v from "mod"; "mod" "default" "v"
export v from "mod"; "mod" "default" null "v"
import * as ns from "mod"; "mod" "*" "ns"
export * as ns from "mod"; "mod" "*" null "ns"
import {x} from "mod"; "mod" "x" "x"
export {x} from "mod"; "mod" "x" null "x"
import {x as v} from "mod"; "mod" "x" "v"
export {x as v} from "mod"; "mod" "x" null "v"
import * from "mod" "mod" null null (many)
export * from "mod"; "mod" "*" null null (many)

Note: import * from "mod" is only included for illustrative purposes. It is not in existing spec or part of this proposal.

Compound export-from statements

This proposal also includes the symmetric export-from for the compound imports:

// proposed
export v, {x, y as w} from "mod"
// symmetric to
import v, {x, y as w} from "mod"

As well as

// proposed
export v, * as ns from "mod"
// symmetric to
import v, * as ns from "mod"

Export default from

One use case is to take the default export of an inner module and export it as the default export of the outer module. This is written as:

export default from "mod";

This is not additional syntax above what's already proposed. In fact, this is just the export v from "mod" syntax where the export name happens to be default. This nicely mirrors the other export default ____ forms in both syntax and semantics without requiring additional specification. An alteration to an existing lookahead restriction is necessary for supporting this case.