Skip to content

Commit 4c7f8a4

Browse files
committed
fixup
1 parent eed8e74 commit 4c7f8a4

File tree

3 files changed

+141
-58
lines changed
  • turbopack/crates

3 files changed

+141
-58
lines changed

turbopack/crates/turbopack-core/src/resolve/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::{
77
};
88

99
use anyhow::{Result, bail};
10+
use auto_hash_map::AutoSet;
1011
use rustc_hash::{FxHashMap, FxHashSet};
1112
use serde::{Deserialize, Serialize};
1213
use tracing::{Instrument, Level};
@@ -108,8 +109,22 @@ impl ModuleResolveResultItem {
108109
pub enum ImportUsage {
109110
#[default]
110111
Global,
111-
Exports(Vec<RcStr>),
112+
Exports(AutoSet<RcStr>),
112113
}
114+
impl ImportUsage {
115+
pub fn add_export(&mut self, user: &RcStr) {
116+
match self {
117+
ImportUsage::Exports(set) => {
118+
set.insert(user.clone());
119+
}
120+
ImportUsage::Global => {}
121+
}
122+
}
123+
pub fn make_global(&mut self) {
124+
*self = ImportUsage::Global;
125+
}
126+
}
127+
113128
#[turbo_tasks::value_impl]
114129
impl ImportUsage {
115130
#[turbo_tasks::function]

turbopack/crates/turbopack-ecmascript/src/analyzer/graph.rs

Lines changed: 84 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use super::{
3131
use crate::{
3232
AnalyzeMode, SpecifiedModuleType,
3333
analyzer::{WellKnownObjectKind, is_unresolved},
34-
references::constant_value::parse_single_expr_lit,
34+
references::{constant_value::parse_single_expr_lit, for_each_ident_in_pat},
3535
utils::{AstPathRange, unparen},
3636
};
3737

@@ -308,32 +308,26 @@ impl VarMeta {
308308
}
309309

310310
#[derive(Clone, Debug)]
311-
pub enum ImportUsage {
311+
pub enum DeclUsage {
312312
Global,
313-
OnlyExports(FxHashSet<Id>),
313+
Bindings(FxHashSet<Id>),
314314
}
315-
impl ImportUsage {
316-
fn add_export(&mut self, user: &Id) {
315+
impl Default for DeclUsage {
316+
fn default() -> Self {
317+
DeclUsage::Bindings(Default::default())
318+
}
319+
}
320+
impl DeclUsage {
321+
fn add_usage(&mut self, user: &Id) {
317322
match self {
318-
ImportUsage::OnlyExports(set) => {
323+
Self::Bindings(set) => {
319324
set.insert(user.clone());
320325
}
321-
ImportUsage::Global => {}
326+
Self::Global => {}
322327
}
323328
}
324329
fn make_global(&mut self) {
325-
*self = ImportUsage::Global;
326-
}
327-
}
328-
329-
impl From<ImportUsage> for turbopack_core::resolve::ImportUsage {
330-
fn from(value: ImportUsage) -> Self {
331-
match value {
332-
ImportUsage::OnlyExports(exports) => {
333-
Self::Exports(exports.into_iter().map(|id| RcStr::from(&*id.0)).collect())
334-
}
335-
ImportUsage::Global => Self::Global,
336-
}
330+
*self = Self::Global;
337331
}
338332
}
339333

@@ -347,9 +341,11 @@ pub struct VarGraph {
347341
pub effects: Vec<Effect>,
348342

349343
// ident -> immediate usage (top level decl)
350-
pub top_level_mappings: FxHashMap<Id, FxHashSet<Id>>,
344+
pub decl_usages: FxHashMap<Id, DeclUsage>,
351345
// import -> immediate usage (top level decl)
352-
pub import_usages: FxHashMap<usize, ImportUsage>,
346+
pub import_usages: FxHashMap<usize, DeclUsage>,
347+
// export name -> top level decl
348+
pub exports: FxHashMap<Atom, Id>,
353349
}
354350

355351
impl VarGraph {
@@ -374,8 +370,9 @@ pub fn create_graph(
374370
values: Default::default(),
375371
free_var_ids: Default::default(),
376372
effects: Default::default(),
377-
top_level_mappings: Default::default(),
373+
decl_usages: Default::default(),
378374
import_usages: Default::default(),
375+
exports: Default::default(),
379376
};
380377

381378
m.visit_with_ast_path(
@@ -2263,9 +2260,9 @@ impl VisitAstPath for Analyzer<'_> {
22632260
.data
22642261
.import_usages
22652262
.entry(esm_reference_index)
2266-
.or_insert_with(|| ImportUsage::OnlyExports(Default::default()));
2263+
.or_default();
22672264
if let Some(top_level) = self.state.cur_top_level_decl_name() {
2268-
usage.add_export(top_level);
2265+
usage.add_usage(top_level);
22692266
} else {
22702267
usage.make_global();
22712268
}
@@ -2317,15 +2314,22 @@ impl VisitAstPath for Analyzer<'_> {
23172314
})
23182315
}
23192316

2320-
if !is_unresolved(ident, self.eval_context.unresolved_mark)
2321-
&& let Some(top_level) = self.state.cur_top_level_decl_name()
2322-
&& !(ident.sym == top_level.0 && ident.ctxt == top_level.1)
2323-
{
2324-
self.data
2325-
.top_level_mappings
2326-
.entry(ident.to_id())
2327-
.or_default()
2328-
.insert(top_level.clone());
2317+
if !is_unresolved(ident, self.eval_context.unresolved_mark) {
2318+
if let Some(top_level) = self.state.cur_top_level_decl_name() {
2319+
if !(ident.sym == top_level.0 && ident.ctxt == top_level.1) {
2320+
self.data
2321+
.decl_usages
2322+
.entry(ident.to_id())
2323+
.or_default()
2324+
.add_usage(top_level);
2325+
}
2326+
} else {
2327+
self.data
2328+
.decl_usages
2329+
.entry(ident.to_id())
2330+
.or_default()
2331+
.make_global();
2332+
}
23292333
}
23302334
}
23312335

@@ -2665,6 +2669,53 @@ impl VisitAstPath for Analyzer<'_> {
26652669
self.effects = prev_effects;
26662670
self.early_return_stack = prev_early_return_stack;
26672671
}
2672+
2673+
fn visit_export_decl<'ast: 'r, 'r>(
2674+
&mut self,
2675+
node: &'ast ExportDecl,
2676+
ast_path: &mut swc_core::ecma::visit::AstNodePath<'r>,
2677+
) {
2678+
match &node.decl {
2679+
Decl::Class(node) => {
2680+
self.data
2681+
.exports
2682+
.insert(node.ident.sym.clone(), node.ident.to_id());
2683+
}
2684+
Decl::Fn(node) => {
2685+
self.data
2686+
.exports
2687+
.insert(node.ident.sym.clone(), node.ident.to_id());
2688+
}
2689+
Decl::Var(node) => {
2690+
for VarDeclarator { name, .. } in &node.decls {
2691+
for_each_ident_in_pat(name, &mut |name, ctxt| {
2692+
self.data.exports.insert(name.clone(), (name.clone(), ctxt));
2693+
});
2694+
}
2695+
}
2696+
_ => {}
2697+
};
2698+
node.visit_children_with_ast_path(self, ast_path);
2699+
}
2700+
2701+
fn visit_export_named_specifier<'ast: 'r, 'r>(
2702+
&mut self,
2703+
node: &'ast ExportNamedSpecifier,
2704+
ast_path: &mut swc_core::ecma::visit::AstNodePath<'r>,
2705+
) {
2706+
let export_name = match &node.exported {
2707+
Some(ident) => ident.atom().clone(),
2708+
None => node.orig.atom().clone(),
2709+
};
2710+
self.data.exports.insert(
2711+
export_name,
2712+
match &node.orig {
2713+
ModuleExportName::Ident(ident) => ident.to_id(),
2714+
ModuleExportName::Str(_) => unreachable!("exporting a string should be impossible"),
2715+
},
2716+
);
2717+
node.visit_children_with_ast_path(self, ast_path);
2718+
}
26682719
}
26692720

26702721
fn is_lexically_block_scope(ast_path: &mut AstNodePath<AstParentNodeRef>) -> bool {

turbopack/crates/turbopack-ecmascript/src/references/mod.rs

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use serde::{Deserialize, Serialize};
4141
use swc_core::{
4242
atoms::{Atom, atom},
4343
common::{
44-
GLOBALS, Globals, Span, Spanned,
44+
GLOBALS, Globals, Span, Spanned, SyntaxContext,
4545
comments::{CommentKind, Comments},
4646
errors::{DiagnosticId, HANDLER, Handler},
4747
pass::AstNodePath,
@@ -77,7 +77,7 @@ use turbopack_core::{
7777
reference::{ModuleReference, ModuleReferences},
7878
reference_type::{CommonJsReferenceSubType, ReferenceType},
7979
resolve::{
80-
FindContextFileResult, ModulePart, find_context_file,
80+
FindContextFileResult, ImportUsage, ModulePart, find_context_file,
8181
origin::{PlainResolveOrigin, ResolveOrigin, ResolveOriginExt},
8282
parse::Request,
8383
pattern::Pattern,
@@ -132,7 +132,7 @@ use crate::{
132132
analyzer::{
133133
ConstantNumber, ConstantString, JsValueUrlKind, RequireContextValue,
134134
builtin::early_replace_builtin,
135-
graph::{ConditionalKind, EffectArg, EvalContext, ImportUsage, VarGraph},
135+
graph::{ConditionalKind, DeclUsage, EffectArg, EvalContext, VarGraph},
136136
imports::{ImportAnnotations, ImportAttributes, ImportedSymbol, Reexport},
137137
parse_require_context,
138138
top_level_await::has_top_level_await,
@@ -709,23 +709,44 @@ async fn analyze_ecmascript_module_internal(
709709
FxHashMap::with_capacity_and_hasher(var_graph.import_usages.len(), Default::default());
710710
for (reference, usage) in &var_graph.import_usages {
711711
// TODO make this more efficient, i.e. cache the result?
712-
if let ImportUsage::OnlyExports(ids) = usage {
712+
if let DeclUsage::Bindings(ids) = usage {
713713
// compute transitive closure of `ids` over `top_level_mappings`
714714
let mut visited = ids.clone();
715715
let mut stack = ids.iter().collect::<Vec<_>>();
716-
716+
let mut has_global_usage = false;
717717
while let Some(id) = stack.pop() {
718-
if let Some(callers) = var_graph.top_level_mappings.get(id) {
719-
for caller in callers {
720-
if visited.insert(caller.clone()) {
721-
stack.push(caller);
718+
match var_graph.decl_usages.get(id) {
719+
Some(DeclUsage::Global) => {
720+
has_global_usage = true;
721+
break;
722+
}
723+
Some(DeclUsage::Bindings(callers)) => {
724+
for caller in callers {
725+
if visited.insert(caller.clone()) {
726+
stack.push(caller);
727+
}
722728
}
723729
}
730+
_ => {}
724731
}
725732
}
726733

727-
// TODO filter out the non-export declarations here
728-
import_usage.insert(*reference, ImportUsage::OnlyExports(visited));
734+
// Collect all `visited` declarations which are exported
735+
import_usage.insert(
736+
*reference,
737+
if has_global_usage {
738+
ImportUsage::Global
739+
} else {
740+
ImportUsage::Exports(
741+
var_graph
742+
.exports
743+
.iter()
744+
.filter(|(_, id)| visited.contains(*id))
745+
.map(|(exported, _)| exported.as_str().into())
746+
.collect(),
747+
)
748+
},
749+
);
729750
}
730751
}
731752

@@ -769,11 +790,7 @@ async fn analyze_ecmascript_module_internal(
769790
)
770791
.then(ModulePart::exports),
771792
},
772-
import_usage
773-
.get(&i)
774-
.cloned()
775-
.map(Into::into)
776-
.unwrap_or_default(),
793+
import_usage.get(&i).cloned().unwrap_or_default(),
777794
import_externals,
778795
)
779796
.resolved_cell();
@@ -1413,8 +1430,8 @@ async fn analyze_ecmascript_module_internal(
14131430
original_reference.issue_source,
14141431
original_reference.annotations.clone(),
14151432
Some(ModulePart::export(export.clone())),
1416-
// TODO this rewriting is annoying
1417-
ImportUsage::Global.into(),
1433+
// TODO this reference rewriting is annoying
1434+
ImportUsage::Global,
14181435
original_reference.import_externals,
14191436
)
14201437
.resolved_cell()
@@ -2821,7 +2838,7 @@ async fn handle_free_var_reference(
28212838
) => export.clone().map(ModulePart::export),
28222839
None => None,
28232840
},
2824-
ImportUsage::Global.into(),
2841+
ImportUsage::Global,
28252842
state.import_externals,
28262843
)
28272844
.resolved_cell())
@@ -3448,10 +3465,10 @@ fn as_parent_path(ast_path: &AstNodePath<AstParentNodeRef<'_>>) -> Vec<AstParent
34483465
ast_path.iter().map(|n| n.kind()).collect()
34493466
}
34503467

3451-
fn for_each_ident_in_pat(pat: &Pat, f: &mut impl FnMut(RcStr)) {
3468+
pub(crate) fn for_each_ident_in_pat(pat: &Pat, f: &mut impl FnMut(&Atom, SyntaxContext)) {
34523469
match pat {
34533470
Pat::Ident(BindingIdent { id, .. }) => {
3454-
f(id.sym.as_str().into());
3471+
f(&id.sym, id.ctxt);
34553472
}
34563473
Pat::Array(ArrayPat { elems, .. }) => elems.iter().for_each(|e| {
34573474
if let Some(e) = e {
@@ -3467,7 +3484,7 @@ fn for_each_ident_in_pat(pat: &Pat, f: &mut impl FnMut(RcStr)) {
34673484
for_each_ident_in_pat(value, f);
34683485
}
34693486
ObjectPatProp::Assign(AssignPatProp { key, .. }) => {
3470-
f(key.sym.as_str().into());
3487+
f(&key.sym, key.ctxt);
34713488
}
34723489
ObjectPatProp::Rest(RestPat { arg, .. }) => {
34733490
for_each_ident_in_pat(arg, f);
@@ -3600,8 +3617,8 @@ impl VisitAstPath for ModuleReferencesVisitor<'_> {
36003617
};
36013618
let decls = &*var_decl.decls;
36023619
decls.iter().for_each(|VarDeclarator { name, .. }| {
3603-
for_each_ident_in_pat(name, &mut |name| {
3604-
insert_export_binding(name, liveness)
3620+
for_each_ident_in_pat(name, &mut |name, _| {
3621+
insert_export_binding(name.as_str().into(), liveness)
36053622
})
36063623
});
36073624
}

0 commit comments

Comments
 (0)