mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +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()
|
||||
.map(|(name, span)| (CompactStr::from(name.as_str()), *span))
|
||||
.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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,9 +49,6 @@ impl Rule for NoDefaultExport {
|
|||
if let Some(span) = module_record.export_default {
|
||||
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);
|
||||
}
|
||||
}
|
||||
let (module_record, module_record_errors) = self.module_record_builder.build();
|
||||
if errors.len() != 1 {
|
||||
errors.reserve(self.lexer.errors.len() + self.errors.len());
|
||||
errors.extend(self.lexer.errors);
|
||||
errors.extend(self.errors);
|
||||
// Skip checking for exports in TypeScript {
|
||||
if !self.source_type.is_typescript() {
|
||||
errors.extend(self.module_record_builder.errors());
|
||||
errors.extend(module_record_errors);
|
||||
}
|
||||
}
|
||||
let irregular_whitespaces =
|
||||
self.lexer.trivia_builder.irregular_whitespaces.into_boxed_slice();
|
||||
ParserReturn {
|
||||
program,
|
||||
module_record: self.module_record_builder.build(),
|
||||
module_record,
|
||||
errors,
|
||||
irregular_whitespaces,
|
||||
panicked,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ pub struct ModuleRecordBuilder<'a> {
|
|||
allocator: &'a Allocator,
|
||||
module_record: ModuleRecord<'a>,
|
||||
export_entries: Vec<ExportEntry<'a>>,
|
||||
export_default_duplicated: Vec<Span>,
|
||||
exported_bindings_duplicated: Vec<NameSpan<'a>>,
|
||||
}
|
||||
|
||||
|
|
@ -21,16 +20,16 @@ impl<'a> ModuleRecordBuilder<'a> {
|
|||
allocator,
|
||||
module_record: ModuleRecord::new(allocator),
|
||||
export_entries: vec![],
|
||||
export_default_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
|
||||
// resolved before resolving export entries.
|
||||
self.resolve_export_entries();
|
||||
self.module_record
|
||||
let errors = self.errors();
|
||||
(self.module_record, errors)
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
for span in &self.export_default_duplicated {
|
||||
let old_span = module_record.export_default.unwrap();
|
||||
errors.push(diagnostics::duplicate_export("default", *span, old_span));
|
||||
// Multiple default exports
|
||||
// `export default foo`
|
||||
// `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
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
/// Step 10.
|
||||
fn resolve_export_entries(&mut self) {
|
||||
|
|
@ -264,8 +263,6 @@ impl<'a> ModuleRecordBuilder<'a> {
|
|||
return;
|
||||
}
|
||||
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 {
|
||||
ExportDefaultDeclarationKind::Identifier(ident) => {
|
||||
|
|
|
|||
|
|
@ -55,10 +55,6 @@ pub struct ModuleRecord<'a> {
|
|||
|
||||
/// Local exported bindings
|
||||
pub exported_bindings: FxHashMap<Atom<'a>, Span>,
|
||||
|
||||
/// `export default name`
|
||||
/// ^^^^^^^ span
|
||||
pub export_default: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'a> ModuleRecord<'a> {
|
||||
|
|
@ -72,7 +68,6 @@ impl<'a> ModuleRecord<'a> {
|
|||
indirect_export_entries: Vec::new_in(allocator),
|
||||
star_export_entries: Vec::new_in(allocator),
|
||||
exported_bindings: FxHashMap::default(),
|
||||
export_default: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -287,6 +282,17 @@ impl ExportExportName<'_> {
|
|||
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`
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
1 │ export default {};
|
||||
· ───┬───
|
||||
· ╰── Export has already been declared here
|
||||
· ───────
|
||||
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]
|
||||
1 │ export default function() {};
|
||||
· ───┬───
|
||||
· ╰── Export has already been declared here
|
||||
· ───────
|
||||
2 │ export { foo as default };
|
||||
· ───┬───
|
||||
· ╰── It cannot be redeclared here
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× 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
|
||||
╰────
|
||||
|
||||
× Duplicated export 'default'
|
||||
× Duplicated default export
|
||||
╭─[test262/test/language/module-code/early-dup-export-dflt-id.js:18:8]
|
||||
17 │ var x, y;
|
||||
18 │ export default x;
|
||||
· ───┬───
|
||||
· ╰── Export has already been declared here
|
||||
· ───────
|
||||
19 │ export { y as default };
|
||||
· ───┬───
|
||||
· ╰── It cannot be redeclared here
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× Unexpected token
|
||||
|
|
@ -22199,15 +22197,13 @@ Expect Syntax Error: tasks/coverage/test262/test/language/import/import-attribut
|
|||
· ╰── 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]
|
||||
17 │ var x;
|
||||
18 │ export default x;
|
||||
· ───┬───
|
||||
· ╰── Export has already been declared here
|
||||
· ───────
|
||||
19 │ export * as default from './early-dup-export-start-as-dflt.js';
|
||||
· ───┬───
|
||||
· ╰── It cannot be redeclared here
|
||||
· ───────
|
||||
╰────
|
||||
|
||||
× Label `label` has already been declared
|
||||
|
|
|
|||
|
|
@ -22418,14 +22418,12 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
|
|||
13 │ deleted() {
|
||||
╰────
|
||||
|
||||
× Duplicated export 'default'
|
||||
× Duplicated default export
|
||||
╭─[typescript/tests/cases/conformance/salsa/plainJSBinderErrors.ts:1:8]
|
||||
1 │ export default 12
|
||||
· ───┬───
|
||||
· ╰── Export has already been declared here
|
||||
· ───────
|
||||
2 │ export default 13
|
||||
· ───┬───
|
||||
· ╰── It cannot be redeclared here
|
||||
· ───────
|
||||
3 │ const await = 1
|
||||
╰────
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue