Quantifying Default Exports

John Barton johnjbarton at google.com
Mon Jul 21 14:48:59 PDT 2014


There are two issues here:
  1) Is 'default' essential?
  2) Should the spec. explicitly define commonjs loading?

Brian is claiming 1) no and 2) no.  More important for me: does 2) require
1). Evidently not.

jjb


On Mon, Jul 21, 2014 at 1:34 PM, Brian Di Palma <offler at gmail.com> wrote:

> It doesn't seem an issue that requires the ES6 module spec to have
> something like default imports though.
>
> The compiler could output
>
> `
> newModule({
>   default: require('minimist')
> })
> `
>
> and importers could do
>
> `import {default as minimist} from 'minimist';`
>
> Or you could have
>
> `
> newModule({
>   minimist: require('minimist');
> })
> `
>
> and
>
> `import {minimist} from 'minimist';`
>
> depending on how the compiler is configured/written.
>
> This is implementation detail of compilers and loaders of legacy
> systems as opposed to spec concerns.
>
> On Mon, Jul 21, 2014 at 6:50 PM, Guy Bedford <guybedford at gmail.com> wrote:
> > Yes this is a bug that can be fixed at the compiler level. As you say we
> can
> > generate a wrapper when loading a non-ES6 module in ES6:
> >
> > newModule({
> >   default: require('minimist')
> > })
> >
> > We then conditionally add this wrapper based on detecting if the import
> is
> > an ES6 module. This is the same method we have for AMD compilations at
> the
> > moment, which seems to have been working well.
> >
> >
> > On 21 July 2014 10:17, John Barton <johnjbarton at google.com> wrote:
> >>
> >>
> >>
> >>
> >> On Mon, Jul 21, 2014 at 10:06 AM, Guy Bedford <guybedford at gmail.com>
> >> wrote:
> >>>
> >>> In Brian's case we actually need default exports. This is because the
> >>> dynamic loader can't pick up the code he has written right now in ES6.
> >>>
> >>> This is how he is loading a NodeJS module in ES6:
> >>>
> >>> module minimist from 'minimist';
> >>>
> >>> In ES6 this means "give me the Module object with getters to the
> >>> exports".
> >>>
> >>> But unfortunately in Traceur this is compiling into:
> >>>
> >>> var minimist = require('minimist');
> >>>
> >>> As a result the `module` syntax can possibly return him a 'function' or
> >>> other non-Module object.
> >>
> >>
> >> You seem to be saying "The traceur implementation of 'module' fails in
> >> this case".  It seems to me that Traceur could generate code which would
> >> wrap functions in Module objects.  That is, this is not a fundamental
> limit,
> >> just an unreported bug.
> >>
> >>>
> >>> Thus we have broken the ability to parse his code in the ES6 dynamic
> >>> loader, as it is not capable of returning a non-Module object for a
> module
> >>> import, which is pretty critical.
> >>>
> >>> Thus default export properties are critical to enabling this support
> >>> path.
> >>
> >>
> >> I believe that Caridy's point is: "fine, use dynamic linking".
> >>
> >>>
> >>>
> >>>
> >>> On 21 July 2014 09:51, Caridy Patino <caridy at gmail.com> wrote:
> >>>>
> >>>> Interoperability should not be a decisive factor here, we have fallen
> >>>> into that trap before, the conclusion was to let Loader to handle
> those
> >>>> cases rather than trying to drive it from the perspective of the
> module
> >>>> syntax. Let's focus on what is best and what makes sense for the ES
> Modules,
> >>>> and keep the dynamic module systems out of the picture since we know
> we have
> >>>> a lot of flexibility with the loader to deal with those dynamic
> modules.
> >>>>
> >>>> /caridy
> >>>>
> >>>>
> >>>> On Mon, Jul 21, 2014 at 12:37 PM, Brian Di Palma <offler at gmail.com>
> >>>> wrote:
> >>>>>
> >>>>> Yep, that makes sense. Highly unlikely but still possible and could
> >>>>> cause issues.
> >>>>> No doubt you could complicate your compiler to deal with these edge
> >>>>> cases but why force that?
> >>>>>
> >>>>> Yet more problems with default imports/exports. This feature doesn't
> >>>>> seem worth its cost.
> >>>>>
> >>>>>
> >>>>> On Mon, Jul 21, 2014 at 5:21 PM, Calvin Metcalf
> >>>>> <calvin.metcalf at gmail.com> wrote:
> >>>>> > (woops hit reply instead of reply all)
> >>>>> >
> >>>>> > Because the `function mainThing(){}` might already have a method
> >>>>> > named
> >>>>> > helper or, more likely, the named export is something like call or
> >>>>> > bind.
> >>>>> >
> >>>>> >
> >>>>> >
> >>>>> >
> >>>>> > On Mon, Jul 21, 2014 at 12:06 PM, Brian Di Palma <offler at gmail.com
> >
> >>>>> > wrote:
> >>>>> >>
> >>>>> >> On Mon, Jul 21, 2014 at 4:16 PM, Calvin Metcalf
> >>>>> >> <calvin.metcalf at gmail.com> wrote:
> >>>>> >> > I have a CommonJS module which exports a single function
> >>>>> >> > ```js
> >>>>> >> > //cj.js
> >>>>> >> > module.exports = function (){}
> >>>>> >> > ```
> >>>>> >> >
> >>>>> >> > If I was to transform it into an ES6 module the best way to do
> so
> >>>>> >> > currently
> >>>>> >> > it so use a default export
> >>>>> >> >
> >>>>> >> > ```js
> >>>>> >> > //cj2es6.js
> >>>>> >> > export default function () {}
> >>>>> >> > ```
> >>>>> >> >
> >>>>> >> > now say I want to import those from another commonjs module,
> >>>>> >> > importing
> >>>>> >> > the
> >>>>> >> > first one is easy, but when importing the second one slightly
> less
> >>>>> >> > so,
> >>>>> >> > how
> >>>>> >> > should the loader treat that default export, a easy solution for
> >>>>> >> > this
> >>>>> >> > case
> >>>>> >> > is to simply have default exports act the same as a
> module.exports
> >>>>> >> >
> >>>>> >> > But then what would you do about es6 modules that use default
> and
> >>>>> >> > named
> >>>>> >> > exports like the example at http://jsmodules.io/ which can be
> >>>>> >> > sumerized
> >>>>> >> > as
> >>>>> >> >
> >>>>> >> > ```js
> >>>>> >> >
> >>>>> >> > export default function mainThing(){}
> >>>>> >> > export function helper (){};
> >>>>> >> >
> >>>>> >> > , if we return a default export if it exists then there is no
> way
> >>>>> >> > to
> >>>>> >> > access
> >>>>> >> > the named exports.
> >>>>> >>
> >>>>> >> As mentioned in the GitHub issue I don't see why you couldn't
> >>>>> >> compile to
> >>>>> >>
> >>>>> >> `
> >>>>> >> module.export = function mainThing(){};
> >>>>> >>
> >>>>> >> module.export.helper = function(){};
> >>>>> >> `
> >>>>> >>
> >>>>> >> Allowing access to the default and named.
> >>>>> >>
> >>>>> >> >
> >>>>> >> > So in that case it would make more sense to treat default as
> just
> >>>>> >> > another
> >>>>> >> > export name.  But if we do that then that means that if we go
> back
> >>>>> >> > to
> >>>>> >> > our
> >>>>> >> > second example
> >>>>> >> >
> >>>>> >> > ```js
> >>>>> >> > //cj2es6.js
> >>>>> >> > export default function () {}
> >>>>> >> > ```
> >>>>> >> >
> >>>>> >> > if that was to be treated that way then importing it from
> another
> >>>>> >> > commonjs
> >>>>> >> > module would be make it be equivalent to
> >>>>> >> >
> >>>>> >> > ```js
> >>>>> >> > //cj2es62cj.js
> >>>>> >> > exports.default = function (){}
> >>>>> >> > ```
> >>>>> >> >
> >>>>> >> > In other words treating default as a regular name prevents you
> >>>>> >> > from
> >>>>> >> > losslessly converting commonjs in a backwards compatible way.
> >>>>> >> >
> >>>>> >> > Making named and default exports be mutually exclusive would
> mean
> >>>>> >> > that
> >>>>> >> > you
> >>>>> >> > could treat default export like module.exports.
> >>>>> >> >
> >>>>> >> >
> >>>>> >> >
> >>>>> >> > On Mon, Jul 21, 2014 at 10:45 AM, Brian Di Palma
> >>>>> >> > <offler at gmail.com>
> >>>>> >> > wrote:
> >>>>> >> >>
> >>>>> >> >> On Mon, Jul 21, 2014 at 3:31 PM, Calvin Metcalf
> >>>>> >> >> <calvin.metcalf at gmail.com> wrote:
> >>>>> >> >> > that won't help if module.exports is a function
> >>>>> >> >>
> >>>>> >> >> That's exactly what `minimist` is, works just fine.
> >>>>> >> >>
> >>>>> >> >> https://github.com/substack/minimist/blob/master/index.js
> >>>>> >> >>
> >>>>> >> >> >
> >>>>> >> >> > Overall the import/exports semantics of es6 and cjs modules
> >>>>> >> >> > would be
> >>>>> >> >> > compatible if mixing named and default exports was
> prohibited,
> >>>>> >> >> > but
> >>>>> >> >> > the
> >>>>> >> >> > ability to have both is hard to represent in cjs modules.
> >>>>> >> >>
> >>>>> >> >> Don't understand this, do you have some code examples? I can't
> >>>>> >> >> see why
> >>>>> >> >> that would be the case.
> >>>>> >> >>
> >>>>> >> >> >
> >>>>> >> >> >
> >>>>> >> >> > On Mon, Jul 21, 2014 at 10:24 AM, Brian Di Palma
> >>>>> >> >> > <offler at gmail.com>
> >>>>> >> >> > wrote:
> >>>>> >> >> >>
> >>>>> >> >> >> Which shows the how the backward compatability argument for
> >>>>> >> >> >> default
> >>>>> >> >> >> export/imports doesn't stand up.
> >>>>> >> >> >>
> >>>>> >> >> >> If you want to import `module.exports` then use the the
> >>>>> >> >> >> `module`
> >>>>> >> >> >> form
> >>>>> >> >> >> if you want named imports use the named form.
> >>>>> >> >> >> Default import/exports are generating nothing more then
> >>>>> >> >> >> complexity,
> >>>>> >> >> >> confusion and not serving their intended goals.
> >>>>> >> >> >>
> >>>>> >> >> >> On Mon, Jul 21, 2014 at 3:18 PM, Calvin Metcalf
> >>>>> >> >> >> <calvin.metcalf at gmail.com> wrote:
> >>>>> >> >> >> > similar discussion at systemjs
> >>>>> >> >> >> > https://github.com/systemjs/systemjs/issues/131 which
> boils
> >>>>> >> >> >> > down
> >>>>> >> >> >> > to
> >>>>> >> >> >> > if a
> >>>>> >> >> >> > CJS
> >>>>> >> >> >> > module imports an ES6 module that has a key named default,
> >>>>> >> >> >> > what
> >>>>> >> >> >> > should
> >>>>> >> >> >> > the
> >>>>> >> >> >> > default behavior be.
> >>>>> >> >> >> >
> >>>>> >> >> >> >
> >>>>> >> >> >> > On Mon, Jul 21, 2014 at 10:05 AM, Brian Di Palma
> >>>>> >> >> >> > <offler at gmail.com>
> >>>>> >> >> >> > wrote:
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> It's using traceur and building the modules to CJS, the
> >>>>> >> >> >> >> project
> >>>>> >> >> >> >> uses
> >>>>> >> >> >> >> other non transpiled CJS modules.
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> The only thing traceur could do here is compile the
> imports
> >>>>> >> >> >> >> into
> >>>>> >> >> >> >> a
> >>>>> >> >> >> >> check for the named export `default` and use that if it
> >>>>> >> >> >> >> exists.
> >>>>> >> >> >> >> If it doesn't then simply return the CJS module object.
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> Here is the output from traceur
> >>>>> >> >> >> >>
> >>>>> >> >> >> >>
> >>>>> >> >> >> >>
> >>>>> >> >> >> >>
> >>>>> >> >> >> >>
> >>>>> >> >> >> >>
> https://github.com/briandipalma/global-compiler/blob/master/out/index.js
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> The relevant line would be
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> `var minimist = require('minimist');`
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> For default import from a CJS module you'd need to output
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> `
> >>>>> >> >> >> >> var minimist = require('minimist');
> >>>>> >> >> >> >> if (minimist.default) {
> >>>>> >> >> >> >>  minimist = minimist.default;
> >>>>> >> >> >> >> }
> >>>>> >> >> >> >> `
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> Is that what you think traceur should do?
> >>>>> >> >> >> >>
> >>>>> >> >> >> >> On Mon, Jul 21, 2014 at 2:34 PM, Juan Ignacio Dopazo
> >>>>> >> >> >> >> <jdopazo at yahoo-inc.com> wrote:
> >>>>> >> >> >> >> >
> >>>>> >> >> >> >> >> On Saturday, July 19, 2014 1:53 PM, Brian Di Palma
> >>>>> >> >> >> >> >> <offler at gmail.com>
> >>>>> >> >> >> >> >> wrote:
> >>>>> >> >> >> >> >
> >>>>> >> >> >> >> >> When an npm package exports a named identifier it's
> >>>>> >> >> >> >> >> trivial to
> >>>>> >> >> >> >> >> use
> >>>>> >> >> >> >> >> it
> >>>>> >> >> >> >> > in an ES6 module.
> >>>>> >> >> >> >> >
> >>>>> >> >> >> >> > import {
> >>>>> >> >> >> >> >     parse,
> >>>>> >> >> >> >> >     print
> >>>>> >> >> >> >> > } from 'recast';
> >>>>> >> >> >> >> >
> >>>>> >> >> >> >> >> When on the other hand it sets its export on
> >>>>> >> >> >> >> >> `module.exports`
> >>>>> >> >> >> >> >> default
> >>>>> >> >> >> >> > exports provide no help at all.
> >>>>> >> >> >> >> >
> >>>>> >> >> >> >> > This sounds like an issue in your transpiler. Ideally
> CJS
> >>>>> >> >> >> >> > modules
> >>>>> >> >> >> >> > inside
> >>>>> >> >> >> >> > projects written using ES6 modules should be treated as
> >>>>> >> >> >> >> > modules
> >>>>> >> >> >> >> > that
> >>>>> >> >> >> >> > default
> >>>>> >> >> >> >> > export an object. CJS modules don't have the same
> static
> >>>>> >> >> >> >> > semantics
> >>>>> >> >> >> >> > as
> >>>>> >> >> >> >> > their
> >>>>> >> >> >> >> > ES6 counterpart, so they should be treated as mutable
> >>>>> >> >> >> >> > objects.
> >>>>> >> >> >> >> > An
> >>>>> >> >> >> >> > ES6
> >>>>> >> >> >> >> > Loader
> >>>>> >> >> >> >> > would do the same when loading CJS modules.
> >>>>> >> >> >> >> >
> >>>>> >> >> >> >> > Juan
> >>>>> >> >> >> >> _______________________________________________
> >>>>> >> >> >> >> es-discuss mailing list
> >>>>> >> >> >> >> es-discuss at mozilla.org
> >>>>> >> >> >> >> https://mail.mozilla.org/listinfo/es-discuss
> >>>>> >> >> >> >
> >>>>> >> >> >> >
> >>>>> >> >> >> >
> >>>>> >> >> >> >
> >>>>> >> >> >> > --
> >>>>> >> >> >> > -Calvin W. Metcalf
> >>>>> >> >> >
> >>>>> >> >> >
> >>>>> >> >> >
> >>>>> >> >> >
> >>>>> >> >> > --
> >>>>> >> >> > -Calvin W. Metcalf
> >>>>> >> >
> >>>>> >> >
> >>>>> >> >
> >>>>> >> >
> >>>>> >> > --
> >>>>> >> > -Calvin W. Metcalf
> >>>>> >
> >>>>> >
> >>>>> >
> >>>>> >
> >>>>> > --
> >>>>> > -Calvin W. Metcalf
> >>>>> _______________________________________________
> >>>>> es-discuss mailing list
> >>>>> es-discuss at mozilla.org
> >>>>> https://mail.mozilla.org/listinfo/es-discuss
> >>>>
> >>>>
> >>>>
> >>>> _______________________________________________
> >>>> es-discuss mailing list
> >>>> es-discuss at mozilla.org
> >>>> https://mail.mozilla.org/listinfo/es-discuss
> >>>>
> >>>
> >>>
> >>> _______________________________________________
> >>> 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/20140721/ad3abf04/attachment-0001.html>


More information about the es-discuss mailing list