Skip to content

Commit

Permalink
feat(linter): resolve ESM star exports (#2682)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Mar 11, 2024
1 parent 8a73d18 commit 366a879
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 9 deletions.
51 changes: 42 additions & 9 deletions crates/oxc_linter/src/service.rs
Expand Up @@ -289,17 +289,50 @@ impl Runtime {
.for_each_with(tx_error, |tx_error, (specifier, resolution)| {
let path = resolution.path();
self.process_path(path, tx_error);
if let Some(target_module_record_ref) = self.module_map.get(path) {
if let ModuleState::Resolved(target_module_record) =
target_module_record_ref.value()
{
module_record
.loaded_modules
.insert(specifier.clone(), Arc::clone(target_module_record));
}
}
let Some(target_module_record_ref) = self.module_map.get(path) else { return };
let ModuleState::Resolved(target_module_record) =
target_module_record_ref.value()
else {
return;
};
// Append target_module to loaded_modules
module_record
.loaded_modules
.insert(specifier.clone(), Arc::clone(target_module_record));
});

// The thread is blocked here until all dependent modules are resolved.

// Resolve and append `star_export_bindings`
for export_entry in &module_record.star_export_entries {
let Some(remote_module_record_ref) =
export_entry.module_request.as_ref().and_then(|module_request| {
module_record.loaded_modules.get(module_request.name())
})
else {
continue;
};
let remote_module_record = remote_module_record_ref.value();

// Append both remote `bindings` and `exported_bindings_from_star_export`
let remote_exported_bindings_from_star_export = remote_module_record
.exported_bindings_from_star_export
.iter()
.flat_map(|r| r.value().clone());
let remote_bindings = remote_module_record
.exported_bindings
.keys()
.cloned()
.chain(remote_exported_bindings_from_star_export)
.collect::<Vec<_>>();
module_record
.exported_bindings_from_star_export
.entry(remote_module_record.resolved_absolute_path.clone())
.or_default()
.value_mut()
.extend(remote_bindings);
}

// Stop if the current module is not marked for lint.
if !self.paths.contains(path) {
return vec![];
Expand Down
12 changes: 12 additions & 0 deletions crates/oxc_syntax/src/module_record.rs
Expand Up @@ -65,10 +65,21 @@ pub struct ModuleRecord {
/// not including export * as namespace declarations.
pub star_export_entries: Vec<ExportEntry>,

/// Local exported bindings
pub exported_bindings: FxHashMap<CompactStr, Span>,

/// Local duplicated exported bindings, for diagnostics
pub exported_bindings_duplicated: Vec<NameSpan>,

/// Reexported bindings from `export * from 'specifier'`
/// Keyed by resolved path
pub exported_bindings_from_star_export: DashMap<PathBuf, Vec<CompactStr>>,

/// `export default name`
/// ^^^^^^^ span
pub export_default: Option<Span>,

/// Duplicated span of `export default` for diagnostics
pub export_default_duplicated: Vec<Span>,
}

Expand Down Expand Up @@ -99,6 +110,7 @@ impl fmt::Debug for ModuleRecord {
.field("star_export_entries", &self.star_export_entries)
.field("exported_bindings", &self.exported_bindings)
.field("exported_bindings_duplicated", &self.exported_bindings_duplicated)
.field("exported_bindings_from_star_export", &self.exported_bindings_from_star_export)
.field("export_default", &self.export_default)
.field("export_default_duplicated", &self.export_default_duplicated)
.finish()
Expand Down

0 comments on commit 366a879

Please sign in to comment.