Giter VIP home page Giter VIP logo

proposal-export-star-default's Introduction

ECMAScript Proposal: Include default export in export * from 'module'

Stage: 0

Author: Guy Bedford

Reviewers: Caridy Patiño

Specification: http://guybedford.github.io/proposal-export-star-default/

Motivation

In the current specification, export * from 'module' will export all named exports, except for the default export.

There are use cases though where it is useful to be able to have the default export defined within an internal private module, and have that exposed through export *.

1. Symmetry with named exports

Consider a module X with both a named export and a default export that is re-exported through another module. We then re-export this module with explicit names in reexport1.js and with export * in reexport2.js:

x.js

export default 'default';
export let name = 'name';

Re-export variations:

reexport1.js

export { name, default } from './x.js';

reexport2.js

export * from './x.js';

In the first variation, we can import the default as it was exported explicitly:

import { name } from './reexport1.js';
import { default } from './reexport1.js';

import * as A from './reexport1.js';
A.default;
// -> 'default'

while in the export * re-export variation, the default is not available:

import { name } from './reexport2.js';
import { default } from './reexport2.js';
// Syntax Error: 'default' is not exported

import * as B from './reexport2.js';
B.default
// -> undefined

This breaks the the user intuition that default is a named export like any other.

2. Creating an index module

In NodeJS it is a convention to have an index.js as the main entry point of the package.

If we want to create this module using export * statements to expose modules from sub-folders, we cannot export the default in this way:

index.js

export * from './lib/package-core.js';
export let extraInfo = 'abc';

If lib/package-core.js contained a default export, we would not be exposing it.

We would need to explicitly export the default with:

index.js

export * from './lib/package-core.js';
export { default } from './lib/package-core.js';
export let extraInfo = 'abc';

in order to ensure we get the expected entry point module value.

The issue here is that if we were ever to remove the default export from lib/package-core.js, we would then get a SyntaxError in index.js that the default export does not exist anymore. The change of removing the default export would need to be made in two separate places.

The above pattern is also already widely seen in index.js modules on npm, of the form:

module.exports = require('./lib/package.js');

where we know that the index.js module will exactly match the internal module.

3. Dynamic wrapping

The case for re-exporting the default can also be extended to use cases where we want to dynamically generate a module wrapper exposing the exports of another module, without knowing in advance its export names.

Consider a use case such as an npm CDN, which allows shortcut URLs like https://npmcdn.com/lodash, which then exposes a module at a full versioned URL like https://npmcdn.com/[email protected]/index.js.

A dynamically generated module for https://npmcdn.com/lodash could look like:

export * from './[email protected]/index.js';

but if there was a default export we would have to provide a different response:

export * from './[email protected]/index.js';
export { default } from './[email protected]/index.js';

If we don't include the default export when it is needed we may miss the default, but if do we include it when it isn't needed we will get an error. This restriction has thus added a new static analysis concern to what would otherwise be a simple server response.

Proposal

The proposal is to remove special-casing of default for export * in the current specification in order to simplify the symmetry of export * as well as to enable easier module wrapping use cases as described above.

The change is backwards-compatible with the existing specification and results in disabling the syntax error for importing a default export through an export *, and making default available as a named export on the module namespace object for this case.

http://guybedford.github.io/proposal-export-star-default/

Handling Ambiguity

One concern with including default in export * is how to handle collisions, but export * is already designed to handle ambiguity well - when two export * statements in a module resolve the same export name, a SyntaxError is thrown as in 15.2.1.16.4 12.d.ii):

x.js

export default 'x';
export let name = 'nameX';

y.js

export default 'y';
export let name = 'nameY';

z.js

export * from './x.js';
export * from './y.ys';

When we try to import name via

import { name } from './z.js';

we will get a SyntaxError that name is ambiguous.

This conflict can be resolved by explicitly indicating a module to export name from:

z.js

export * from './x.js';
export * from './y.ys';
export { name } from './x.js';

Now when we import name from z.js it will be correctly resolved.

With this spec change the same ambiguity resolution process would apply to the default export:

import { default } from './z.js';

would throw a SyntaxError.

z.js

export * from './x.js';
export * from './y.ys';
export { default } from './x.js';

would then resolve that SyntaxError by providing an explicit precedence, providing symmetry between handling conflicts between named exports and default exports via export *.

proposal-export-star-default's People

Contributors

guybedford avatar

Stargazers

Vinson Chuong avatar Josh Wilson avatar ExE Boss avatar Homa Wong avatar Damien Maillard avatar

Watchers

Caridy Patiño avatar Jordan Harband avatar HE Shi-Jun avatar  avatar James Cloos avatar  avatar

proposal-export-star-default's Issues

Potential alternative

I believe the committee rejected this proposal as-is. Perhaps we could introduce a different syntax (maybe export ** from?) which would include the default export if it exists, and people could use whichever was appropriate.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.