Skip to content

Commit 2694253

Browse files
committed
remove another case of AST path inspection
1 parent 8b346bd commit 2694253

File tree

1 file changed

+47
-40
lines changed
  • turbopack/crates/turbopack-ecmascript/src/analyzer

1 file changed

+47
-40
lines changed

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

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -946,9 +946,10 @@ impl FunctionLike for SetterProp {
946946
enum BlockContext {
947947
// In the root of a function scope
948948
Function { id: u32, binds_this: bool },
949-
FunctionRoot,
950-
// In the root of the module scope
951-
Module,
949+
// A placeholder for identify anonymous blocks
950+
// If we have Block->Block then we are in an anonymous block
951+
// If we have Function->Block or ControlFlow->Block then we are just in a function root
952+
Block,
952953
// In some kind of control flow
953954
ControlFlow { is_try: bool },
954955
}
@@ -1004,12 +1005,17 @@ mod analyzer_state {
10041005
/// Returns true if we are currently in a block scope that isn't at the root of a function
10051006
/// or a module.
10061007
pub(super) fn is_in_nested_block_scope(&self) -> bool {
1007-
match self.state.block_context_stack.last().unwrap() {
1008-
BlockContext::Module
1009-
| BlockContext::FunctionRoot
1010-
| BlockContext::Function { .. } => false,
1008+
match &self.state.block_context_stack
1009+
[self.state.block_context_stack.len().saturating_sub(2)..]
1010+
{
1011+
[BlockContext::Block] | [BlockContext::Function { .. }, BlockContext::Block] => {
1012+
false
1013+
}
1014+
[] => {
1015+
unreachable!()
1016+
}
10111017

1012-
BlockContext::ControlFlow { .. } => true,
1018+
_ => true,
10131019
}
10141020
}
10151021

@@ -1110,7 +1116,7 @@ mod analyzer_state {
11101116
let fn_id = function.span().lo.0;
11111117
let prev_return_values = self.state.cur_fn_return_values.replace(vec![]);
11121118

1113-
self.enter_block(
1119+
self.with_block(
11141120
BlockContext::Function {
11151121
id: fn_id,
11161122
binds_this: function.binds_this(),
@@ -1180,14 +1186,25 @@ mod analyzer_state {
11801186
func: impl FnOnce(&mut Self) -> T,
11811187
) -> (T, bool) {
11821188
let prev_early_return_stack = take(&mut self.state.early_return_stack);
1183-
self.state.block_context_stack.push(block_kind);
1184-
let result = func(self);
1189+
let result = self.with_block(block_kind, func);
11851190
let always_returns = self.end_early_return_block();
11861191
self.state.early_return_stack = prev_early_return_stack;
1192+
(result, always_returns)
1193+
}
1194+
1195+
/// Pushes a block onto the stack without performing early return logic.
1196+
pub(super) fn with_block<T>(
1197+
&mut self,
1198+
block_kind: BlockContext,
1199+
func: impl FnOnce(&mut Self) -> T,
1200+
) -> T {
1201+
self.state.block_context_stack.push(block_kind);
1202+
let result = func(self);
11871203
let old = self.state.block_context_stack.pop();
11881204
debug_assert_eq!(old, Some(block_kind));
1189-
(result, always_returns)
1205+
result
11901206
}
1207+
11911208
/// Ends a conditional block. All early returns are integrated into the
11921209
/// effects. Returns true if the whole block always early returns.
11931210
fn end_early_return_block(&mut self) -> bool {
@@ -2449,7 +2466,7 @@ impl VisitAstPath for Analyzer<'_> {
24492466
ast_path: &mut AstNodePath<AstParentNodeRef<'r>>,
24502467
) {
24512468
self.effects = take(&mut self.data.effects);
2452-
self.enter_block(BlockContext::Module, |this| {
2469+
self.enter_block(BlockContext::Block, |this| {
24532470
program.visit_children_with_ast_path(this, ast_path);
24542471
});
24552472
self.effects.append(&mut self.hoisted_effects);
@@ -2664,10 +2681,9 @@ impl VisitAstPath for Analyzer<'_> {
26642681
let mut effects = take(&mut self.effects);
26652682
let hoisted_effects = take(&mut self.hoisted_effects);
26662683

2667-
let (_, returns_unconditionally) =
2668-
self.enter_block(BlockContext::FunctionRoot, |this| {
2669-
n.visit_children_with_ast_path(this, ast_path);
2670-
});
2684+
let (_, returns_unconditionally) = self.enter_block(BlockContext::Block, |this| {
2685+
n.visit_children_with_ast_path(this, ast_path);
2686+
});
26712687
// By handling this logic here instead of in enter_fn, we naturally skip it
26722688
// for arrow functions with single expression bodies, since they just don't hit this
26732689
// path.
@@ -2679,29 +2695,20 @@ impl VisitAstPath for Analyzer<'_> {
26792695
self.hoisted_effects = hoisted_effects;
26802696
self.effects = effects;
26812697
}
2682-
BlockContext::ControlFlow { .. }
2683-
| BlockContext::Module
2684-
| BlockContext::FunctionRoot => {
2685-
// A block is anonymous if its parent is also a block (rather than a
2686-
// loop/function/if-stmt)
2687-
let is_anonymous_block = matches!(
2688-
ast_path.get(ast_path.len() - 2),
2689-
Some(AstParentNodeRef::BlockStmt(_, BlockStmtField::Stmts(_)))
2690-
);
2691-
2692-
if is_anonymous_block {
2693-
// Handle anonymous block statement
2694-
// e.g., enter a new control flow context and because it is 'unconditiona' we
2695-
// need to propagate early returns
2696-
let (_, returns_early) = self.enter_control_flow(|this| {
2697-
n.visit_children_with_ast_path(this, ast_path);
2698-
});
2699-
if returns_early {
2700-
self.add_early_return_always(ast_path);
2701-
}
2702-
} else {
2703-
// Regular block (part of if/loop/function/etc)
2704-
n.visit_children_with_ast_path(self, ast_path);
2698+
BlockContext::ControlFlow { .. } => {
2699+
self.with_block(BlockContext::Block, |this| {
2700+
n.visit_children_with_ast_path(this, ast_path)
2701+
});
2702+
}
2703+
BlockContext::Block => {
2704+
// Handle anonymous block statement
2705+
// e.g., enter a new control flow context and because it is 'unconditiona' we
2706+
// need to propagate early returns
2707+
let (_, returns_early) = self.enter_control_flow(|this| {
2708+
n.visit_children_with_ast_path(this, ast_path);
2709+
});
2710+
if returns_early {
2711+
self.add_early_return_always(ast_path);
27052712
}
27062713
}
27072714
}

0 commit comments

Comments
 (0)