ModuleImport

John Barton johnjbarton at google.com
Fri Jun 20 15:47:59 PDT 2014


ES6 already has what you want:

_Named Exports_:

export var foo = 1;

_Single Export Object_:

export var moduleName = {

  foo: 1,

  bar: function() {}
};

_Single Export Function_:

export function fName() { }

And even cooler, the syntax for import is uniform,

import {foo} from './namedExport';

import {moduleName} from './singleExportObject';

import {fName} from './singleExportFunction';


On Fri, Jun 20, 2014 at 3:21 PM, Ron Buckton <rbuckton at chronicles.org>
wrote:

>  > -----Original Message-----
>
> > From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of
>
> > Sébastien Cevey
>
> > Sent: Friday, June 20, 2014 3:46 AM
>
> > To: Axel Rauschmayer
>
> > Cc: es-discuss list
>
> > Subject: Re: ModuleImport
>
> >
>
> > On 20 June 2014 11:39, Axel Rauschmayer <axel at rauschma.de> wrote:
>
> > > > The `*' symbol universally represents a glob of "everything", but
>
> > > > when used to import from a module that has multiple exports, you
>
> > > > won't get everything, you will get either the single default export
>
> > > > (if there is
>
> > > > one) or nothing.
>
> > >
>
> > >
>
> > > What gives you that impression? Quoting David’s original email:
>
> > >
>
> > > ```js
>
> > > import * as fs from "fs"; // importing the named exports as an object
>
> > > import Dict from "dict";  // importing a default export, same as ever
>
> > > ```
>
>
>
> With all due respect, why is it that we cannot change the specification to
> allow `import name from "module"` for both the default export (for single
> export modules) and the Module object (for multi-named export modules). The
> same question goes for using `import { name as "name" } from "module"` for
> both. As specified, a default export is equivalent to a Module object with
> a "default" property, and as a result requires special handling with
> respect to how it is bound to the _ImportBinding_ in `import name from
> "module"`. Wouldn't it make sense to simplify the syntax and expand the
> static and runtime semantics for imports? Are we sure that the current
> semantics are the right approach that we should shoehorn the syntax into?
>
>
>
>
> Is it imperative for module authors to be able to provide both a default
> export *and* named exports within the same module? From most of the
> comments in this thread, it seems that expected module use falls into two
> categories:  Single-export modules and Multi-export modules. Is there a
> use-case in the wild (via ES6 module transpilers) where a single module
> today uses both a default export as well as named exports?
>
>
>
> With respect to Node libraries, I often see one of three approaches to
> exporting from a module:
>
>
>
> _Named Exports_:
>
> ```
>
> exports.foo = 1;
>
> // or
>
> module.exports.foo = 1;
>
> ```
>
>
>
> _Single Export Object_:
>
> ```
>
> module.exports = {
>
>   foo: 1,
>
>   bar: function() {}
> }
>
> ```
>
>
>
> _Single Export Function_:
>
> ```
>
> module.exports = function() { }
>
> ```
>
>
>
> In Node, if you wanted to have a default export that is a function, but
> also have additional exports you would most likely add them as data
> properties on the function:
>
> ```
>
> module.exports = function() {}
>
> module.exports.foo = 1;
>
> ```
>
>
>
> Given that, why not simplify the syntax and semantics to just the
> following three forms:
>
> ```
>
> import "module"; // imports the module but does not perform binding
>
> import name from "module"; // imports the module (either the default
> export or a module object with the named exports, see below)
>
> import { name1, name2 as "otherName" } from "module"; // imports members
> of the module.
>
> ```
>
>
>
> Simplifying this requires the following (approximate) changes in semantics:
>
>
>
> * Either (A) a module cannot have *both* a default export and named
> exports, _or_..
>
> * (B) A modules named exports become attached properties of the default
> export if provided.
>
>     * If (B), it becomes an runtime error to add a default export after a
> named export, and a runtime error to add a named export if the default
> export is not an Object.
>
> * The ImportBinding (`name` above) becomes bound to a [[Value]] property
> of an (not part of the current spec) Import exotic object.
>
> * When the Module exotic object is loaded, if it has a property named
> "default", that becomes the value of the [[Value]] property of the Import
> exotic object.
>
> * If the Module exotic object does not have a property named "default",
> the Module itself becomes the value of the [[Value]] property of the Import
> exotic object.
>
> * NamedImports now points to bindings to the [[Value]] property of the
> Import exotic object. If you want both a default export and named exports,
> attach the named exports as properties of the default export.
>
>
>
> With the above changes, whether you're using a default export or named
> exports becomes transparent to the developer.  If the developer _really_
> wants the module object, they could fall back to:
>
> ```
>
> import "module";
>
> var name = System.get("module"); // Returns the Module object without the
> transformations applied from above.
>
> ```
>
>
>
> The above is a rough approximation of the semantics changes. If anyone
> finds merit to this proposal, I'll find some time this weekend to write out
> exactly what kind of changes there would need to be in the static and
> runtime semantics in the current spec. The overall goal is to keep the
> import syntax simple and expand the static and runtime semantics to support
> that simplicity. This includes continuing to support the ability to handle
> cyclic dependencies. Engine authors will need to write the code for the
> import semantics once, while the development community will use the import
> syntax over and over for some time to come. It seems like a simpler syntax
> should win out over possibly changing the semantics.
>
>
>
> Best regards,
>
> Ron
>
>
>
>
>
>
>
>
>
> p.s. Here are some examples of various inputs and outputs based on this
> proposal:
>
>
>
> # Exports
>
>
>
> [named-exports.js]
>
> ```
>
> export var version = "1.0";
>
> export function println(text) { console.log(text); }
>
> ```
>
>
>
> [single-export.js]
>
> ```
>
> function hello (text) { alert("Hello " + text + "!"); }
>
> hello.goodbye = function (text) { alert("Goodbye " + text + "!"); }
>
> export default hello;
>
> ```
>
>
>
> [multi-export-with-default.js]
>
> ```
>
> // if (A) above, this is an early error
>
> // if (B) above, version becomes Person.version
>
> export default class Person {
>
>   jump() { return "How high?"; }
> }
>
> export var version = "2.0";
>
> ```
>
>
>
> [single-export-of-object.js]
>
> ```
>
> export default {
>
>   version: "1.0",
>
>   assert(test) { if (!test) throw new Error("failed!"); }
>
> }
>
> ```
>
>
>
> # Imports
>
>
>
> [import-named-imports.js]
>
> ```
>
> import namedExports from "named-exports"; // namedExports = binding to
> Import.[[Value]] which results in a Module object with properties "version"
> and "println";
>
> import { version, println } from "named-exports"; // version = binding to
> Import.[[Value]].version, println = binding to Import.[[Value]].println
>
> // or...
>
> import namedExports, { version, println } from "named-exports"; // both of
> the above
>
> ```
>
>
>
> [import-single-export.js]
>
> ```
>
> import hello from "single-export"; // hello = binding to Import.[[Value]]
> which results in the "hello" function
>
> import { goodbye } from "single-export"; // goodbye = binding to
> Import.[[Value]].goodbye
>
> // or...
>
> import hello, { goodbye } from "single-export"; // both of the above
>
> ```
>
>
>
> [import-multi-export-with-default.js]
>
> ```
>
> // assumes (B) above
>
> import Person from "multi-export-with-default"; // Person = binding to
> Import.[[Value]] which results in the "Person" class
>
> import { version } from "multi-export-with-default"; // version = binding
> to Import.[[Value]].version
>
> // or...
>
> import Person, { version } from "multi-export-with-default"; // both of
> the above
>
> ```
>
>
>
> [import-single-export-of-object.js]
>
> ```
>
> import test from "single-export-of-object"; // test = binding to
> Import.[[Value]] which results in an Object with properties "version" and
> "assert"
>
> import { version, assert } from "single-export-of-object"; // version =
> binding to Import.[[Value]].version, assert = binding to
> Import.[[Value]].assert
>
> // or...
>
> import test, { version, assert } from "single-export-of-object"; // both
> of the above.
>
> ```
>
>
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140620/d296966d/attachment.html>


More information about the es-discuss mailing list