Skip to content

Commit 5fc75a3

Browse files
authored
Skip unreachable code when early return can be statically analysed (#8890)
### Description * tracks early returns and their conditions * replaces unreachable code with `"TURBOPACK unreachable"` * finds hoisted declarations in unreachable code and keeps them ### Testing Instructions <!-- Give a quick description of steps to test your changes. -->
1 parent e563d20 commit 5fc75a3

File tree

64 files changed

+34904
-19864
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+34904
-19864
lines changed

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

+362-48
Large diffs are not rendered by default.

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

+23
Original file line numberDiff line numberDiff line change
@@ -3866,6 +3866,11 @@ mod tests {
38663866
queue
38673867
.extend(then.effects.into_iter().rev().map(|e| (i, e)));
38683868
}
3869+
ConditionalKind::Else { r#else } => {
3870+
queue.extend(
3871+
r#else.effects.into_iter().rev().map(|e| (i, e)),
3872+
);
3873+
}
38693874
ConditionalKind::IfElse { then, r#else }
38703875
| ConditionalKind::Ternary { then, r#else } => {
38713876
queue.extend(
@@ -3874,6 +3879,18 @@ mod tests {
38743879
queue
38753880
.extend(then.effects.into_iter().rev().map(|e| (i, e)));
38763881
}
3882+
ConditionalKind::IfElseMultiple { then, r#else } => {
3883+
for then in then {
3884+
queue.extend(
3885+
then.effects.into_iter().rev().map(|e| (i, e)),
3886+
);
3887+
}
3888+
for r#else in r#else {
3889+
queue.extend(
3890+
r#else.effects.into_iter().rev().map(|e| (i, e)),
3891+
);
3892+
}
3893+
}
38773894
ConditionalKind::And { expr }
38783895
| ConditionalKind::Or { expr }
38793896
| ConditionalKind::NullishCoalescing { expr } => {
@@ -3904,6 +3921,12 @@ mod tests {
39043921
JsValue::member_call(Box::new(obj), Box::new(prop), new_args),
39053922
));
39063923
}
3924+
Effect::Unreachable { .. } => {
3925+
resolved.push((
3926+
format!("{parent} -> {i} unreachable"),
3927+
JsValue::unknown_empty(true, "unreachable"),
3928+
));
3929+
}
39073930
_ => {}
39083931
}
39093932
let time = start.elapsed();

crates/turbopack-ecmascript/src/path_visitor.rs

+2
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ impl VisitMutAstPath for ApplyVisitors<'_, '_> {
153153
method!(visit_mut_call_expr, CallExpr);
154154
method!(visit_mut_lit, Lit);
155155
method!(visit_mut_str, Str);
156+
method!(visit_mut_block_stmt, BlockStmt);
157+
method!(visit_mut_switch_case, SwitchCase);
156158
}
157159

158160
#[cfg(test)]

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

+49-1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ use crate::{
134134
type_issue::SpecifiedModuleTypeIssue,
135135
},
136136
tree_shake::{find_turbopack_part_id_in_asserts, part_of_module, split},
137+
utils::AstPathRange,
137138
EcmascriptInputTransforms, EcmascriptModuleAsset, SpecifiedModuleType, TreeShakingMode,
138139
};
139140

@@ -861,6 +862,11 @@ pub(crate) async fn analyse_ecmascript_module_internal(
861862
};
862863

863864
match effect {
865+
Effect::Unreachable { start_ast_path } => {
866+
analysis.add_code_gen(Unreachable::new(
867+
AstPathRange::StartAfter(start_ast_path.to_vec()).cell(),
868+
));
869+
}
864870
Effect::Conditional {
865871
condition,
866872
kind,
@@ -872,7 +878,7 @@ pub(crate) async fn analyse_ecmascript_module_internal(
872878

873879
macro_rules! inactive {
874880
($block:ident) => {
875-
analysis.add_code_gen(Unreachable::new(Vc::cell($block.ast_path.to_vec())));
881+
analysis.add_code_gen(Unreachable::new($block.range.clone().cell()));
876882
};
877883
}
878884
macro_rules! condition {
@@ -904,6 +910,19 @@ pub(crate) async fn analyse_ecmascript_module_internal(
904910
active!(then);
905911
}
906912
},
913+
ConditionalKind::Else { r#else } => match condition.is_truthy() {
914+
Some(true) => {
915+
condition!(ConstantConditionValue::Truthy);
916+
inactive!(r#else);
917+
}
918+
Some(false) => {
919+
condition!(ConstantConditionValue::Falsy);
920+
active!(r#else);
921+
}
922+
None => {
923+
active!(r#else);
924+
}
925+
},
907926
ConditionalKind::IfElse { then, r#else }
908927
| ConditionalKind::Ternary { then, r#else } => match condition.is_truthy() {
909928
Some(true) => {
@@ -921,6 +940,35 @@ pub(crate) async fn analyse_ecmascript_module_internal(
921940
active!(r#else);
922941
}
923942
},
943+
ConditionalKind::IfElseMultiple { then, r#else } => match condition.is_truthy()
944+
{
945+
Some(true) => {
946+
condition!(ConstantConditionValue::Truthy);
947+
for then in then {
948+
active!(then);
949+
}
950+
for r#else in r#else {
951+
inactive!(r#else);
952+
}
953+
}
954+
Some(false) => {
955+
condition!(ConstantConditionValue::Falsy);
956+
for then in then {
957+
inactive!(then);
958+
}
959+
for r#else in r#else {
960+
active!(r#else);
961+
}
962+
}
963+
None => {
964+
for then in then {
965+
active!(then);
966+
}
967+
for r#else in r#else {
968+
active!(r#else);
969+
}
970+
}
971+
},
924972
ConditionalKind::And { expr } => match condition.is_truthy() {
925973
Some(true) => {
926974
condition!(ConstantConditionValue::Truthy);

0 commit comments

Comments
 (0)