mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
fix(semantic): ModuleRecord's indirect_export_entires missing reexported imports (#2792)
local_name has `name` and `span`. We can't directly compare ExportEntry's local_name and ImportEntry's local_name. because the span is never equal.
This commit is contained in:
parent
7b6a4d0690
commit
b6e493bd78
3 changed files with 45 additions and 16 deletions
|
|
@ -7,7 +7,7 @@ use oxc_ast::{ast::*, AstKind, Trivias, Visit};
|
||||||
use oxc_diagnostics::Error;
|
use oxc_diagnostics::Error;
|
||||||
use oxc_span::{CompactStr, SourceType, Span};
|
use oxc_span::{CompactStr, SourceType, Span};
|
||||||
use oxc_syntax::{
|
use oxc_syntax::{
|
||||||
module_record::{ExportLocalName, ModuleRecord},
|
module_record::{ExportImportName, ExportLocalName, ModuleRecord},
|
||||||
operator::AssignmentOperator,
|
operator::AssignmentOperator,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -324,18 +324,20 @@ impl<'a> SemanticBuilder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_export_flag_for_export_identifier(&mut self) {
|
fn add_export_flag_for_export_identifier(&mut self) {
|
||||||
self.module_record.local_export_entries.iter().for_each(|entry| match &entry.local_name {
|
self.module_record.indirect_export_entries.iter().for_each(|entry| {
|
||||||
ExportLocalName::Name(name_span) => {
|
if let ExportImportName::Name(name) = &entry.import_name {
|
||||||
|
if let Some(symbol_id) = self.symbols.get_symbol_id_from_name(name.name()) {
|
||||||
|
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.module_record.local_export_entries.iter().for_each(|entry| {
|
||||||
|
if let ExportLocalName::Name(name_span) = &entry.local_name {
|
||||||
if let Some(symbol_id) = self.scope.get_root_binding(name_span.name()) {
|
if let Some(symbol_id) = self.scope.get_root_binding(name_span.name()) {
|
||||||
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExportLocalName::Default(span) => {
|
|
||||||
if let Some(symbol_id) = self.symbols.get_symbol_id_from_span(span) {
|
|
||||||
self.symbols.union_flag(symbol_id, SymbolFlags::Export);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ExportLocalName::Null => {}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,15 +85,14 @@ impl ModuleRecordBuilder {
|
||||||
for ee in export_entries {
|
for ee in export_entries {
|
||||||
// a. If ee.[[ModuleRequest]] is null, then
|
// a. If ee.[[ModuleRequest]] is null, then
|
||||||
if ee.module_request.is_none() {
|
if ee.module_request.is_none() {
|
||||||
let local_name = match &ee.local_name {
|
let found_import_entry = match &ee.local_name {
|
||||||
ExportLocalName::Name(name) => Some(name),
|
ExportLocalName::Name(name) => self
|
||||||
|
.module_record
|
||||||
|
.import_entries
|
||||||
|
.iter()
|
||||||
|
.find(|entry| entry.local_name.name() == name.name()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let found_import_entry = self
|
|
||||||
.module_record
|
|
||||||
.import_entries
|
|
||||||
.iter()
|
|
||||||
.find(|import_entry| Some(&import_entry.local_name) == local_name);
|
|
||||||
match found_import_entry {
|
match found_import_entry {
|
||||||
// i. If ee.[[LocalName]] is not an element of importedBoundNames, then
|
// i. If ee.[[LocalName]] is not an element of importedBoundNames, then
|
||||||
None => {
|
None => {
|
||||||
|
|
@ -130,6 +129,7 @@ impl ModuleRecordBuilder {
|
||||||
ImportImportName::NamespaceObject => unreachable!(),
|
ImportImportName::NamespaceObject => unreachable!(),
|
||||||
},
|
},
|
||||||
export_name: ee.export_name.clone(),
|
export_name: ee.export_name.clone(),
|
||||||
|
span: ee.span,
|
||||||
..ExportEntry::default()
|
..ExportEntry::default()
|
||||||
};
|
};
|
||||||
self.append_indirect_export_entry(export_entry);
|
self.append_indirect_export_entry(export_entry);
|
||||||
|
|
|
||||||
|
|
@ -248,4 +248,31 @@ mod module_record_tests {
|
||||||
assert_eq!(module_record.local_export_entries.len(), 1);
|
assert_eq!(module_record.local_export_entries.len(), 1);
|
||||||
assert_eq!(module_record.local_export_entries[0], export_entry);
|
assert_eq!(module_record.local_export_entries[0], export_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn indirect_export_entries() {
|
||||||
|
let module_record =
|
||||||
|
build("import { x } from 'mod';export { x };export * as ns from 'mod';");
|
||||||
|
assert_eq!(module_record.indirect_export_entries.len(), 2);
|
||||||
|
assert_eq!(
|
||||||
|
module_record.indirect_export_entries[0],
|
||||||
|
ExportEntry {
|
||||||
|
module_request: Some(NameSpan::new("mod".into(), Span::new(18, 23))),
|
||||||
|
span: Span::new(33, 34),
|
||||||
|
import_name: ExportImportName::Name(NameSpan::new("x".into(), Span::new(9, 10))),
|
||||||
|
export_name: ExportExportName::Name(NameSpan::new("x".into(), Span::new(33, 34))),
|
||||||
|
local_name: ExportLocalName::Null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
module_record.indirect_export_entries[1],
|
||||||
|
ExportEntry {
|
||||||
|
module_request: Some(NameSpan::new("mod".into(), Span::new(57, 62))),
|
||||||
|
span: Span::new(0, 0),
|
||||||
|
import_name: ExportImportName::All,
|
||||||
|
export_name: ExportExportName::Name(NameSpan::new("ns".into(), Span::new(49, 51))),
|
||||||
|
local_name: ExportLocalName::Null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue