mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 22:59:17 +00:00
fix(minifier): avoid unsafe return removal in labeled blocks (#25406)
revert #24813 currently there is no way to validate if stmt can be removed if its inside a block correct issue with incorrect removal of `return` stmt not at termination points ```js (function() { label: { console.log('before return'); return; } console.log('unreachable!'); })(); ``` ref: https://github.com/rolldown/rolldown/issues/10555
This commit is contained in:
1 parent
17037390ed
commit
e0fb2d782a
4 files changed
+52
-56
No files matched your search
@@ -374,9 +374,6 @@ impl<'a> PeepholeOptimizations {
|
||||
Statement::ForOfStatement(for_of_stmt) => {
|
||||
Self::handle_for_of_statement(for_of_stmt, result, ctx);
|
||||
}
|
||||
Statement::LabeledStatement(label_stmt) => {
|
||||
Self::handle_labeled_statement(label_stmt, result, ctx);
|
||||
}
|
||||
Statement::BlockStatement(block_stmt) => Self::handle_block(result, block_stmt, ctx),
|
||||
stmt => result.push(stmt),
|
||||
}
|
||||
@@ -1238,33 +1235,6 @@ impl<'a> PeepholeOptimizations {
|
||||
result.push(Statement::ForOfStatement(for_of_stmt));
|
||||
}
|
||||
|
||||
fn handle_labeled_statement(
|
||||
mut labeled_stmt: ArenaBox<'a, LabeledStatement<'a>>,
|
||||
result: &mut ArenaVec<'a, Statement<'a>>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) {
|
||||
if let Statement::BlockStatement(block_stmt) = &mut labeled_stmt.body {
|
||||
Self::minimize_statements(&mut block_stmt.body, ctx);
|
||||
} else if !Self::statement_cares_about_scope(&labeled_stmt.body) {
|
||||
let mut stmts = ArenaVec::from_value_in(labeled_stmt.body.take_in(ctx), ctx);
|
||||
Self::minimize_statements(&mut stmts, ctx);
|
||||
labeled_stmt.body = match stmts.len() {
|
||||
0 => Statement::new_empty_statement(labeled_stmt.body.span(), ctx),
|
||||
1 => stmts[0].take_in(ctx),
|
||||
_ => {
|
||||
ctx.notice_change();
|
||||
Statement::new_block_statement_with_scope_id(
|
||||
labeled_stmt.span,
|
||||
stmts,
|
||||
ctx.create_child_scope_of_current(ScopeFlags::empty()),
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
result.push(Statement::LabeledStatement(labeled_stmt));
|
||||
}
|
||||
|
||||
/// `appendIfOrLabelBodyPreservingScope`: <https://github.com/evanw/esbuild/blob/v0.24.2/internal/js_parser/js_parser.go#L9839>
|
||||
fn handle_block(
|
||||
result: &mut ArenaVec<'a, Statement<'a>>,
|
||||
|
||||
@@ -25,6 +25,8 @@ fn test_break_optimization() {
|
||||
test("f:g:{if(a()){break f;}else{break f;} break f;}", "f:g:{if(a())break f;break f}"); // f:g:a();
|
||||
test("function f() { a: break a; }", "function f() {}");
|
||||
test("function f() { a: { break a; } }", "function f() {}");
|
||||
test_same("function f() { a: { b(); break a; } c(); }");
|
||||
test_same("function f() { a: { b(); return; } c(); }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -78,11 +80,20 @@ fn test_function_return_optimization() {
|
||||
"function f(){try{a();return}catch{}}",
|
||||
); // function f(){try{a()}catch{}}
|
||||
|
||||
test("function f(){g:return}", "function f(){}");
|
||||
test("function f(){g:{return}}", "function f(){}");
|
||||
test("function f(){g:if(a()){return;}else{return;} return;}", "function f(){g:a()}");
|
||||
test("function f(){g:{if(a()){return;}else{return;} return;}}", "function f(){g:a()}");
|
||||
test("function f(){g:{a();if(b()){return;}else{return;} return;}}", "function f(){g:a(),b()}");
|
||||
test_same("function f(){g:return}"); // function f(){}
|
||||
test("function f(){g:{return}}", "function f(){g:return}"); // function f(){}
|
||||
test(
|
||||
"function f(){g:if(a()){return;}else{return;} return;}",
|
||||
"function f(){g:if(a())return;else return}",
|
||||
); // function f(){g:a()}
|
||||
test(
|
||||
"function f(){g:{if(a()){return;}else{return;} return;}}",
|
||||
"function f(){g:return a(),void 0}",
|
||||
); // function f(){g:a()}
|
||||
test(
|
||||
"function f(){g:{a();if(b()){return;}else{return;} return;}}",
|
||||
"function f(){g:return a(),b(),void 0}",
|
||||
); // function f(){g:a(),b()}
|
||||
test(
|
||||
"function f(){try{g:if(a()){throw 9;} return;}finally{return}}",
|
||||
"function f(){try{g:if(a())throw 9; return}finally{return}}",
|
||||
@@ -143,12 +154,21 @@ fn test_while_continue_optimization() {
|
||||
"for(;;)try{if(a())continue;continue}catch{}",
|
||||
); // for(;;)try{a()}catch{}
|
||||
|
||||
test("while(true){g:continue}", "for(;;);");
|
||||
test("while(true){g:{continue}}", "for(;;);");
|
||||
test("while(true){g:continue}", "for(;;) g:continue;"); // for(;;);
|
||||
test("while(true){g:{continue}}", "for(;;) g:continue;"); // for(;;);
|
||||
// This case could be improved.
|
||||
test("while(true){g:if(a()){continue;}else{continue;} continue;}", "for (;;)g:a();");
|
||||
test("while(true){g:{if(a()){continue;}else{continue;} continue;}}", "for(;;)g:a();");
|
||||
test("while(true){g:{a();if(b()){continue;}else{continue;} continue;}}", "for(;;)g:a(),b();");
|
||||
test(
|
||||
"while(true){g:if(a()){continue;}else{continue;} continue;}",
|
||||
"for(;;)g:if(a())continue;else continue;",
|
||||
); // for (;;)g:a();
|
||||
test(
|
||||
"while(true){g:{if(a()){continue;}else{continue;} continue;}}",
|
||||
"for(;;)g:{if(a())continue;continue}",
|
||||
); // for(;;)g:a();
|
||||
test(
|
||||
"while(true){g:{a();if(b()){continue;}else{continue;} continue;}}",
|
||||
"for(;;)g:{if(a(),b())continue;continue}",
|
||||
); // for(;;)g:a(),b();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -184,9 +204,12 @@ fn test_do_continue_optimization() {
|
||||
"do try{if(a())continue;continue}catch{}while(!0);",
|
||||
); // do try{a()}catch{}while(!0);
|
||||
|
||||
test("do{g:continue}while(true)", "do;while(!0);");
|
||||
test("do{g:continue}while(true)", "do g:continue;while(!0);"); // do;while(!0);
|
||||
// This case could be improved.
|
||||
test("do{g:if(a()){continue;}else{continue;} continue;}while(true)", "do g:a();while(!0);");
|
||||
test(
|
||||
"do{g:if(a()){continue;}else{continue;} continue;}while(true)",
|
||||
"do g:if(a())continue;else continue;while(!0);",
|
||||
); // do g:a();while(!0);
|
||||
|
||||
test("do { foo(); continue; } while(false)", "do foo();while(!1)");
|
||||
test("do { foo(); break; } while(false)", "do foo();while(!1)");
|
||||
@@ -267,19 +290,19 @@ fn test_for_continue_optimization() {
|
||||
"for(x=0;x<y;x++)try{if(a())continue;continue}catch{}",
|
||||
); // for(x=0;x<y;x++)try{a()}catch{}
|
||||
|
||||
test("for(x=0;x<y;x++){g:continue}", "for(x=0;x<y;x++);");
|
||||
test("for(x=0;x<y;x++){g:{continue}}", "for(x=0;x<y;x++);");
|
||||
test("for(x=0;x<y;x++){g:continue}", "for(x=0;x<y;x++)g:continue;"); // for(x=0;x<y;x++);
|
||||
test("for(x=0;x<y;x++){g:{continue}}", "for(x=0;x<y;x++)g:continue;"); // for(x=0;x<y;x++);
|
||||
test(
|
||||
"for(x=0;x<y;x++){g:if(a()){continue;}else{continue;} continue;}",
|
||||
"for(x=0;x<y;x++)g:a();",
|
||||
);
|
||||
"for(x=0;x<y;x++)g:if(a())continue;else continue;",
|
||||
); // for(x=0;x<y;x++)g:a();
|
||||
test(
|
||||
"for(x=0;x<y;x++){g:{if(a()){continue;}else{continue;} continue;}}",
|
||||
"for(x=0;x<y;x++)g:a();",
|
||||
);
|
||||
"for(x=0;x<y;x++)g:{if(a())continue;continue;}",
|
||||
); // for(x=0;x<y;x++)g:a();
|
||||
test(
|
||||
"for(x=0;x<y;x++){g:{a();if(b()){continue;}else{continue;} continue;}}",
|
||||
"for(x=0;x<y;x++)g:a(),b();",
|
||||
"for(x=0;x<y;x++)g:{if(a(),b())continue;continue}",
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -205,14 +205,17 @@ fn test_handle_switch_statement() {
|
||||
test("switch (a) { case 1: if(a) {b();}c();}", "a === 1 && (a && b(), c());");
|
||||
test("switch ('\\v') { case '\\u000B': foo();}", "foo();");
|
||||
|
||||
test("x: switch (a) { case 1: break x;}", "x: if (a === 1) break x;");
|
||||
test("x: switch (a) { case 1: break x;}", "x: switch (a) { case 1: break x; }"); // x: if (a === 1) break x;
|
||||
test_same("x: switch (a) { case 2: break x; case 1: break x;}"); // x: { a; break x; }
|
||||
test("x: switch (2) { case 2: f(); break outer; }", "x: { f(); break outer; }");
|
||||
test("x: switch (2) { case 2: f(); break outer; }", "x:switch(2){case 2:f();break outer}"); // x: { f(); break outer; }
|
||||
test(
|
||||
"x: switch (x) { case 2: f(); for (;;){break outer;}}",
|
||||
"x: if (x === 2) for (f();;) break outer;",
|
||||
);
|
||||
test("x: switch (a) { case 2: if(b) { break outer; } }", "x: if (a === 2 && b) break outer;");
|
||||
"x: switch (x) { case 2: for (f();;)break outer}",
|
||||
); // x: if (x === 2) for (f();;) break outer;
|
||||
test(
|
||||
"x: switch (a) { case 2: if(b) { break outer; } }",
|
||||
"x: switch (a) { case 2: if(b) break outer; }",
|
||||
); // x: if (a === 2 && b) break outer;
|
||||
|
||||
test(
|
||||
"switch ('r') { case 'r': a();break; case 'r': var x=0;break;}",
|
||||
|
||||
@@ -5,7 +5,7 @@ checker.ts:
|
||||
sys deallocs: 152
|
||||
sys alloc bytes: 14996600 # 15.00 MB
|
||||
sys peak growth: 10169560 # 10.17 MB
|
||||
arena allocs: 148493
|
||||
arena allocs: 148428
|
||||
arena reallocs: 28468
|
||||
arena size: 19205776 # 19.21 MB
|
||||
|
||||
@@ -71,6 +71,6 @@ kitchen-sink.tsx:
|
||||
sys deallocs: 1858
|
||||
sys alloc bytes: 5307512 # 5.31 MB
|
||||
sys peak growth: 3707425 # 3.71 MB
|
||||
arena allocs: 66806
|
||||
arena allocs: 66771
|
||||
arena reallocs: 12252
|
||||
arena size: 9424360 # 9.42 MB
|
||||
Reference in new issue
Block a user