Quantifying Default Exports

Brian Di Palma offler at gmail.com
Mon Jul 21 13:34:08 PDT 2014


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
>>>
>>
>


More information about the es-discuss mailing list