Skip to content

Commit 5395308

Browse files
committed
fix scope hoisting for non-hoisted self-references
1 parent e6a0915 commit 5395308

File tree

1 file changed

+60
-53
lines changed

1 file changed

+60
-53
lines changed

turbopack/crates/turbopack-core/src/module_graph/merged_modules.rs

Lines changed: 60 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ pub async fn compute_merged_modules(module_graph: Vc<ModuleGraph>) -> Result<Vc<
167167
.collect::<Result<Vec<_>>>()?,
168168
&mut (),
169169
|parent_info: Option<(ResolvedVc<Box<dyn Module>>, &'_ RefData, _)>,
170-
node: ResolvedVc<Box<dyn Module>>,
170+
module: ResolvedVc<Box<dyn Module>>,
171171
_,
172172
_|
173173
-> Result<GraphTraversalAction> {
@@ -183,63 +183,70 @@ pub async fn compute_merged_modules(module_graph: Vc<ModuleGraph>) -> Result<Vc<
183183
},
184184
)
185185
});
186-
let module = node;
187186

188-
Ok(if parent_module.is_some_and(|p| p == module) {
189-
// A self-reference
190-
GraphTraversalAction::Skip
191-
} else if hoisted
192-
&& let Some(parent_module) = parent_module
193-
&& mergeable.contains(&parent_module)
194-
&& mergeable.contains(&module)
195-
&& !async_module_info.contains(&parent_module)
196-
&& !async_module_info.contains(&module)
197-
{
198-
// ^ TODO technically we could merge a sync child into an async parent
199-
200-
// A hoisted reference from a mergeable module to a non-async mergeable
201-
// module, inherit bitmaps from parent.
202-
module_merged_groups.entry(node).or_default();
203-
let [Some(parent_merged_groups), Some(current_merged_groups)] =
204-
module_merged_groups.get_disjoint_mut([&parent_module, &node])
205-
else {
206-
// All modules are inserted in the previous iteration
207-
bail!("unreachable except for eventual consistency");
208-
};
209-
210-
if current_merged_groups.is_empty() {
211-
// Initial visit, clone instead of merging
212-
*current_merged_groups = parent_merged_groups.clone();
213-
GraphTraversalAction::Continue
214-
} else if parent_merged_groups.is_proper_superset(current_merged_groups) {
215-
// Add bits from parent, and continue traversal because changed
216-
**current_merged_groups |= &**parent_merged_groups;
217-
GraphTraversalAction::Continue
187+
Ok(
188+
if hoisted
189+
&& let Some(parent_module) = parent_module
190+
&& mergeable.contains(&parent_module)
191+
&& mergeable.contains(&module)
192+
&& !async_module_info.contains(&parent_module)
193+
&& !async_module_info.contains(&module)
194+
{
195+
// ^ TODO technically we could merge a sync child into an async parent
196+
if parent_module == module {
197+
// A hoisted self-reference, no need to update bitmaps and don't recurse
198+
GraphTraversalAction::Skip
199+
} else {
200+
// A hoisted reference from a mergeable module to a non-async mergeable
201+
// module, inherit bitmaps from parent.
202+
module_merged_groups.entry(module).or_default();
203+
let [Some(parent_merged_groups), Some(current_merged_groups)] =
204+
module_merged_groups.get_disjoint_mut([&parent_module, &module])
205+
else {
206+
// All modules are inserted in the previous iteration
207+
bail!("unreachable except for eventual consistency");
208+
};
209+
210+
if current_merged_groups.is_empty() {
211+
// Initial visit, clone instead of merging
212+
*current_merged_groups = parent_merged_groups.clone();
213+
GraphTraversalAction::Continue
214+
} else if parent_merged_groups.is_proper_superset(current_merged_groups)
215+
{
216+
// Add bits from parent, and continue traversal because changed
217+
**current_merged_groups |= &**parent_merged_groups;
218+
GraphTraversalAction::Continue
219+
} else {
220+
// Unchanged, no need to forward to children
221+
GraphTraversalAction::Skip
222+
}
223+
}
218224
} else {
219-
// Unchanged, no need to forward to children
220-
GraphTraversalAction::Skip
221-
}
222-
} else {
223-
// Either a non-hoisted reference or an incompatible parent or child module
224-
225-
if entry_modules.insert(module) {
226-
// Not assigned a new group before, create a new one.
227-
let idx = next_index;
228-
next_index += 1;
229-
230-
if module_merged_groups.entry(module).or_default().insert(idx) {
231-
// Mark and continue traversal because modified (or first visit)
232-
GraphTraversalAction::Continue
225+
// Either a non-hoisted reference or an incompatible parent or child module
226+
if entry_modules.insert(module) {
227+
// Not assigned a new group before, create a new one.
228+
let idx = next_index;
229+
next_index += 1;
230+
231+
if module_merged_groups.entry(module).or_default().insert(idx) {
232+
if parent_module.is_some_and(|p| p == module) {
233+
// A hoisted self-reference, don't recurse
234+
GraphTraversalAction::Skip
235+
} else {
236+
// Mark and continue traversal because modified (or first visit)
237+
GraphTraversalAction::Continue
238+
}
239+
} else {
240+
// Unchanged, no need to forward to children
241+
GraphTraversalAction::Skip
242+
}
233243
} else {
234-
// Unchanged, no need to forward to children
244+
// Already visited and assigned a new group, no need to forward to
245+
// children.
235246
GraphTraversalAction::Skip
236247
}
237-
} else {
238-
// Already visited and assigned a new group, no need to forward to
239-
// children.
240-
GraphTraversalAction::Skip
241-
}
242-
})
248+
},
249+
)
243250
},
244251
|successor, _| {
245252
// Invert the ordering here. High priority values get visited first, and we want to

0 commit comments

Comments
 (0)