mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(syntax): remove ModuleRecord::export_default (#7578)
This value can be derived.
This commit is contained in:
parent
d476660b0b
commit
18519dea33
8 changed files with 61 additions and 60 deletions
|
|
@ -464,7 +464,17 @@ impl ModuleRecord {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, span)| (CompactStr::from(name.as_str()), *span))
|
.map(|(name, span)| (CompactStr::from(name.as_str()), *span))
|
||||||
.collect(),
|
.collect(),
|
||||||
export_default: other.export_default,
|
export_default: other
|
||||||
|
.local_export_entries
|
||||||
|
.iter()
|
||||||
|
.filter_map(|export_entry| export_entry.export_name.default_export_span())
|
||||||
|
.chain(
|
||||||
|
other
|
||||||
|
.indirect_export_entries
|
||||||
|
.iter()
|
||||||
|
.filter_map(|export_entry| export_entry.export_name.default_export_span()),
|
||||||
|
)
|
||||||
|
.next(),
|
||||||
..ModuleRecord::default()
|
..ModuleRecord::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,9 +49,6 @@ impl Rule for NoDefaultExport {
|
||||||
if let Some(span) = module_record.export_default {
|
if let Some(span) = module_record.export_default {
|
||||||
ctx.diagnostic(no_default_export_diagnostic(span));
|
ctx.diagnostic(no_default_export_diagnostic(span));
|
||||||
}
|
}
|
||||||
if let Some(span) = module_record.exported_bindings.get("default") {
|
|
||||||
ctx.diagnostic(no_default_export_diagnostic(*span));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -438,20 +438,21 @@ impl<'a> ParserImpl<'a> {
|
||||||
errors.push(error);
|
errors.push(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let (module_record, module_record_errors) = self.module_record_builder.build();
|
||||||
if errors.len() != 1 {
|
if errors.len() != 1 {
|
||||||
errors.reserve(self.lexer.errors.len() + self.errors.len());
|
errors.reserve(self.lexer.errors.len() + self.errors.len());
|
||||||
errors.extend(self.lexer.errors);
|
errors.extend(self.lexer.errors);
|
||||||
errors.extend(self.errors);
|
errors.extend(self.errors);
|
||||||
// Skip checking for exports in TypeScript {
|
// Skip checking for exports in TypeScript {
|
||||||
if !self.source_type.is_typescript() {
|
if !self.source_type.is_typescript() {
|
||||||
errors.extend(self.module_record_builder.errors());
|
errors.extend(module_record_errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let irregular_whitespaces =
|
let irregular_whitespaces =
|
||||||
self.lexer.trivia_builder.irregular_whitespaces.into_boxed_slice();
|
self.lexer.trivia_builder.irregular_whitespaces.into_boxed_slice();
|
||||||
ParserReturn {
|
ParserReturn {
|
||||||
program,
|
program,
|
||||||
module_record: self.module_record_builder.build(),
|
module_record,
|
||||||
errors,
|
errors,
|
||||||
irregular_whitespaces,
|
irregular_whitespaces,
|
||||||
panicked,
|
panicked,
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ pub struct ModuleRecordBuilder<'a> {
|
||||||
allocator: &'a Allocator,
|
allocator: &'a Allocator,
|
||||||
module_record: ModuleRecord<'a>,
|
module_record: ModuleRecord<'a>,
|
||||||
export_entries: Vec<ExportEntry<'a>>,
|
export_entries: Vec<ExportEntry<'a>>,
|
||||||
export_default_duplicated: Vec<Span>,
|
|
||||||
exported_bindings_duplicated: Vec<NameSpan<'a>>,
|
exported_bindings_duplicated: Vec<NameSpan<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -21,16 +20,16 @@ impl<'a> ModuleRecordBuilder<'a> {
|
||||||
allocator,
|
allocator,
|
||||||
module_record: ModuleRecord::new(allocator),
|
module_record: ModuleRecord::new(allocator),
|
||||||
export_entries: vec![],
|
export_entries: vec![],
|
||||||
export_default_duplicated: vec![],
|
|
||||||
exported_bindings_duplicated: vec![],
|
exported_bindings_duplicated: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(mut self) -> ModuleRecord<'a> {
|
pub fn build(mut self) -> (ModuleRecord<'a>, Vec<OxcDiagnostic>) {
|
||||||
// The `ParseModule` algorithm requires `importedBoundNames` (import entries) to be
|
// The `ParseModule` algorithm requires `importedBoundNames` (import entries) to be
|
||||||
// resolved before resolving export entries.
|
// resolved before resolving export entries.
|
||||||
self.resolve_export_entries();
|
self.resolve_export_entries();
|
||||||
self.module_record
|
let errors = self.errors();
|
||||||
|
(self.module_record, errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn errors(&self) -> Vec<OxcDiagnostic> {
|
pub fn errors(&self) -> Vec<OxcDiagnostic> {
|
||||||
|
|
@ -44,19 +43,25 @@ impl<'a> ModuleRecordBuilder<'a> {
|
||||||
errors.push(diagnostics::duplicate_export(&name_span.name, name_span.span, old_span));
|
errors.push(diagnostics::duplicate_export(&name_span.name, name_span.span, old_span));
|
||||||
}
|
}
|
||||||
|
|
||||||
for span in &self.export_default_duplicated {
|
// Multiple default exports
|
||||||
let old_span = module_record.export_default.unwrap();
|
// `export default foo`
|
||||||
errors.push(diagnostics::duplicate_export("default", *span, old_span));
|
// `export { default }`
|
||||||
|
let default_exports = module_record
|
||||||
|
.local_export_entries
|
||||||
|
.iter()
|
||||||
|
.filter_map(|export_entry| export_entry.export_name.default_export_span())
|
||||||
|
.chain(
|
||||||
|
module_record
|
||||||
|
.indirect_export_entries
|
||||||
|
.iter()
|
||||||
|
.filter_map(|export_entry| export_entry.export_name.default_export_span()),
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if default_exports.len() > 1 {
|
||||||
|
errors.push(
|
||||||
|
OxcDiagnostic::error("Duplicated default export").with_labels(default_exports),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `export default x;`
|
|
||||||
// `export { y as default };`
|
|
||||||
if let (Some(span), Some(default_span)) =
|
|
||||||
(module_record.exported_bindings.get("default"), &module_record.export_default)
|
|
||||||
{
|
|
||||||
errors.push(diagnostics::duplicate_export("default", *default_span, *span));
|
|
||||||
}
|
|
||||||
|
|
||||||
errors
|
errors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,12 +99,6 @@ impl<'a> ModuleRecordBuilder<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_default_export(&mut self, span: Span) {
|
|
||||||
if let Some(old_node) = self.module_record.export_default.replace(span) {
|
|
||||||
self.export_default_duplicated.push(old_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// [ParseModule](https://tc39.es/ecma262/#sec-parsemodule)
|
/// [ParseModule](https://tc39.es/ecma262/#sec-parsemodule)
|
||||||
/// Step 10.
|
/// Step 10.
|
||||||
fn resolve_export_entries(&mut self) {
|
fn resolve_export_entries(&mut self) {
|
||||||
|
|
@ -264,8 +263,6 @@ impl<'a> ModuleRecordBuilder<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let exported_name = &decl.exported;
|
let exported_name = &decl.exported;
|
||||||
let exported_name_span = decl.exported.span();
|
|
||||||
self.add_default_export(exported_name_span);
|
|
||||||
|
|
||||||
let local_name = match &decl.declaration {
|
let local_name = match &decl.declaration {
|
||||||
ExportDefaultDeclarationKind::Identifier(ident) => {
|
ExportDefaultDeclarationKind::Identifier(ident) => {
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,6 @@ pub struct ModuleRecord<'a> {
|
||||||
|
|
||||||
/// Local exported bindings
|
/// Local exported bindings
|
||||||
pub exported_bindings: FxHashMap<Atom<'a>, Span>,
|
pub exported_bindings: FxHashMap<Atom<'a>, Span>,
|
||||||
|
|
||||||
/// `export default name`
|
|
||||||
/// ^^^^^^^ span
|
|
||||||
pub export_default: Option<Span>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ModuleRecord<'a> {
|
impl<'a> ModuleRecord<'a> {
|
||||||
|
|
@ -72,7 +68,6 @@ impl<'a> ModuleRecord<'a> {
|
||||||
indirect_export_entries: Vec::new_in(allocator),
|
indirect_export_entries: Vec::new_in(allocator),
|
||||||
star_export_entries: Vec::new_in(allocator),
|
star_export_entries: Vec::new_in(allocator),
|
||||||
exported_bindings: FxHashMap::default(),
|
exported_bindings: FxHashMap::default(),
|
||||||
export_default: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -287,6 +282,17 @@ impl ExportExportName<'_> {
|
||||||
Self::Null => None,
|
Self::Null => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get default export span
|
||||||
|
/// `export default foo`
|
||||||
|
/// `export { default }`
|
||||||
|
pub fn default_export_span(&self) -> Option<Span> {
|
||||||
|
match self {
|
||||||
|
Self::Default(span) => Some(*span),
|
||||||
|
Self::Name(name_span) if name_span.name == "default" => Some(name_span.span),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `LocalName` for `ExportEntry`
|
/// `LocalName` for `ExportEntry`
|
||||||
|
|
|
||||||
|
|
@ -3031,24 +3031,20 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
||||||
· ───────────
|
· ───────────
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Duplicated export 'default'
|
× Duplicated default export
|
||||||
╭─[babel/packages/babel-parser/test/fixtures/es2015/modules/duplicate-export-default/input.js:1:8]
|
╭─[babel/packages/babel-parser/test/fixtures/es2015/modules/duplicate-export-default/input.js:1:8]
|
||||||
1 │ export default {};
|
1 │ export default {};
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── Export has already been declared here
|
|
||||||
2 │ export default function() {};
|
2 │ export default function() {};
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── It cannot be redeclared here
|
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Duplicated export 'default'
|
× Duplicated default export
|
||||||
╭─[babel/packages/babel-parser/test/fixtures/es2015/modules/duplicate-export-default-and-export-as-default/input.js:1:8]
|
╭─[babel/packages/babel-parser/test/fixtures/es2015/modules/duplicate-export-default-and-export-as-default/input.js:1:8]
|
||||||
1 │ export default function() {};
|
1 │ export default function() {};
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── Export has already been declared here
|
|
||||||
2 │ export { foo as default };
|
2 │ export { foo as default };
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── It cannot be redeclared here
|
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Export 'foo' is not defined
|
× Export 'foo' is not defined
|
||||||
|
|
|
||||||
|
|
@ -22158,15 +22158,13 @@ Expect Syntax Error: tasks/coverage/test262/test/language/import/import-attribut
|
||||||
· ╰── It can not be redeclared here
|
· ╰── It can not be redeclared here
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Duplicated export 'default'
|
× Duplicated default export
|
||||||
╭─[test262/test/language/module-code/early-dup-export-dflt-id.js:18:8]
|
╭─[test262/test/language/module-code/early-dup-export-dflt-id.js:18:8]
|
||||||
17 │ var x, y;
|
17 │ var x, y;
|
||||||
18 │ export default x;
|
18 │ export default x;
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── Export has already been declared here
|
|
||||||
19 │ export { y as default };
|
19 │ export { y as default };
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── It cannot be redeclared here
|
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Unexpected token
|
× Unexpected token
|
||||||
|
|
@ -22199,15 +22197,13 @@ Expect Syntax Error: tasks/coverage/test262/test/language/import/import-attribut
|
||||||
· ╰── It cannot be redeclared here
|
· ╰── It cannot be redeclared here
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Duplicated export 'default'
|
× Duplicated default export
|
||||||
╭─[test262/test/language/module-code/early-dup-export-star-as-dflt.js:18:8]
|
╭─[test262/test/language/module-code/early-dup-export-star-as-dflt.js:18:8]
|
||||||
17 │ var x;
|
17 │ var x;
|
||||||
18 │ export default x;
|
18 │ export default x;
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── Export has already been declared here
|
|
||||||
19 │ export * as default from './early-dup-export-start-as-dflt.js';
|
19 │ export * as default from './early-dup-export-start-as-dflt.js';
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── It cannot be redeclared here
|
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Label `label` has already been declared
|
× Label `label` has already been declared
|
||||||
|
|
|
||||||
|
|
@ -22418,14 +22418,12 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
|
||||||
13 │ deleted() {
|
13 │ deleted() {
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
× Duplicated export 'default'
|
× Duplicated default export
|
||||||
╭─[typescript/tests/cases/conformance/salsa/plainJSBinderErrors.ts:1:8]
|
╭─[typescript/tests/cases/conformance/salsa/plainJSBinderErrors.ts:1:8]
|
||||||
1 │ export default 12
|
1 │ export default 12
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── Export has already been declared here
|
|
||||||
2 │ export default 13
|
2 │ export default 13
|
||||||
· ───┬───
|
· ───────
|
||||||
· ╰── It cannot be redeclared here
|
|
||||||
3 │ const await = 1
|
3 │ const await = 1
|
||||||
╰────
|
╰────
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue