I received an issue on GitHub about my ES2015 module import/export validating plugin for ESLint not recognizing the default
export in the following syntax:
export {
foo as default,
bar
}
where my plugin will lint the following (equivalent?) syntax no problem:
export default foo;
export const bar = ..;
Both Babel and Esprima parse similar syntax without errors, and this works for code using Babel on both ends (import and export).
However, I'm not convinced the spec allows the former export { x as default }
form:
For each
IdentifierName
n
inReferencedBindings
ofExportClause
: It is a Syntax Error if StringValue of n is a ReservedWord or if the StringValue of n is one of: "implements", "interface", "let", "package", "private", "protected", "public", "static", or "yield".
ReservedWord
does include default
, though I think one could argue that ReferencedBindings
is referring specifically to the module-local identifier names that are being exported (i.e. foo
) and not the exported name itself.
It also generally seems like a weird thing to be able to export reserved words; Babel will happily also allow something like
// ./foo.js
export { foo as yield }
// ./mod.js
import { yield as nonReservedIdentifier } from './foo'
So, in summary: is export { foo as default }
a valid way to export a default in ES2015?
Yes, ReferencedBindings refers only to the first IdentifierName. So
is invalid, but
is not. ESLint will need a fix here.
Yes, it's valid. I'll break it down.
:
This matches the following productions (from least to most specific):
Then you have the early error semantics:
These apply to any productions matching
export ExportClause
, including your example syntax. This invokes theReferencedBindings
algorithm.The
ReferencedBindings
algorithm that applies to that most specific production matched by this syntax is:So you see that the restriction regarding
ReservedWord
and the other listed values is only applied to thefoo
part of the syntax in your example.