mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 06:39:17 +00:00
fix(semantic): reject jumps across arrow functions (#26357)
Reject labeled and unlabeled `break` and `continue` statements that cross an arrow-function boundary.
For example:
```ts
while (true) {
(() => {
break;
});
}
```
now reports an illegal break, while jumps targeting loops inside the arrow remain valid.
This commit is contained in:
1 parent
5b3e335484
commit
4b89c7bd55
10 files changed
+145
-20
No files matched your search
@@ -797,7 +797,9 @@ pub fn check_break_statement(stmt: &BreakStatement, ctx: &SemanticBuilder<'_>) {
|
||||
},
|
||||
);
|
||||
}
|
||||
AstKind::Function(_) | AstKind::StaticBlock(_) => {
|
||||
AstKind::Function(_)
|
||||
| AstKind::ArrowFunctionExpression(_)
|
||||
| AstKind::StaticBlock(_) => {
|
||||
return stmt.label.as_ref().map_or_else(
|
||||
|| ctx.error(diagnostics::invalid_break(stmt.span)),
|
||||
|label| ctx.error(diagnostics::invalid_label_jump_target(label.span)),
|
||||
@@ -840,7 +842,9 @@ pub fn check_continue_statement(stmt: &ContinueStatement, ctx: &SemanticBuilder<
|
||||
},
|
||||
);
|
||||
}
|
||||
AstKind::Function(_) | AstKind::StaticBlock(_) => {
|
||||
AstKind::Function(_)
|
||||
| AstKind::ArrowFunctionExpression(_)
|
||||
| AstKind::StaticBlock(_) => {
|
||||
return stmt.label.as_ref().map_or_else(
|
||||
|| ctx.error(diagnostics::invalid_continue(stmt.span)),
|
||||
|label| ctx.error(diagnostics::invalid_label_jump_target(label.span)),
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
while (true) { (() => { break; }); }
|
||||
|
||||
outer: while (true) { (() => { break outer; }); }
|
||||
|
||||
while (true) { (() => { continue; }); }
|
||||
|
||||
outer: while (true) { (() => { continue outer; }); }
|
||||
@@ -0,0 +1,6 @@
|
||||
(() => {
|
||||
while (true) { break; }
|
||||
while (true) { continue; }
|
||||
outer: while (true) { break outer; }
|
||||
outer: while (true) { continue outer; }
|
||||
});
|
||||
@@ -1,3 +1,3 @@
|
||||
codegen_misc Summary:
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
AST Parsed : 81/81 (100.00%)
|
||||
Positive Passed: 81/81 (100.00%)
|
||||
@@ -1,3 +1,3 @@
|
||||
formatter_misc Summary:
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
AST Parsed : 81/81 (100.00%)
|
||||
Positive Passed: 81/81 (100.00%)
|
||||
@@ -1,6 +1,6 @@
|
||||
lexer_misc Summary:
|
||||
AST Parsed : 248/248 (100.00%)
|
||||
Positive Passed: 246/248 (99.19%)
|
||||
AST Parsed : 250/250 (100.00%)
|
||||
Positive Passed: 248/250 (99.20%)
|
||||
Tokens: tasks/coverage/misc/pass/oxc-2674.tsx
|
||||
|
||||
Tokens: tasks/coverage/misc/pass/swc-7187.ts
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
parser_misc Summary:
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
Negative Passed: 168/168 (100.00%)
|
||||
AST Parsed : 81/81 (100.00%)
|
||||
Positive Passed: 81/81 (100.00%)
|
||||
Negative Passed: 169/169 (100.00%)
|
||||
|
||||
× Cannot assign to 'arguments' in strict mode
|
||||
╭─[misc/fail/arguments-eval-ambient.ts:2:13]
|
||||
@@ -136,6 +136,38 @@ Negative Passed: 168/168 (100.00%)
|
||||
╰────
|
||||
note: Classes are always strict mode code
|
||||
|
||||
× Illegal break statement
|
||||
╭─[misc/fail/arrow-function-jumps.js:1:25]
|
||||
1 │ while (true) { (() => { break; }); }
|
||||
· ──────
|
||||
2 │
|
||||
╰────
|
||||
help: A `break` statement can only be used within an enclosing iteration or switch statement.
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[misc/fail/arrow-function-jumps.js:3:38]
|
||||
2 │
|
||||
3 │ outer: while (true) { (() => { break outer; }); }
|
||||
· ─────
|
||||
4 │
|
||||
╰────
|
||||
|
||||
× Illegal continue statement: no surrounding iteration statement
|
||||
╭─[misc/fail/arrow-function-jumps.js:5:25]
|
||||
4 │
|
||||
5 │ while (true) { (() => { continue; }); }
|
||||
· ─────────
|
||||
6 │
|
||||
╰────
|
||||
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[misc/fail/arrow-function-jumps.js:7:41]
|
||||
6 │
|
||||
7 │ outer: while (true) { (() => { continue outer; }); }
|
||||
· ─────
|
||||
╰────
|
||||
|
||||
× `await` is only allowed within async functions and at the top levels of modules
|
||||
╭─[misc/fail/auto-accessor-initializer-await.js:3:18]
|
||||
2 │ class C {
|
||||
|
||||
@@ -3,7 +3,7 @@ commit: b465fdbf
|
||||
parser_typescript Summary:
|
||||
AST Parsed : 9783/9783 (100.00%)
|
||||
Positive Passed: 9783/9783 (100.00%)
|
||||
Negative Passed: 1647/2636 (62.48%)
|
||||
Negative Passed: 1649/2636 (62.56%)
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts
|
||||
@@ -174,8 +174,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/contextualTy
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/contextualTypingWithFixedTypeParameters1.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/continueNotInIterationStatement4.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/crashDeclareGlobalTypeofExport.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/crashRegressionTest.ts
|
||||
@@ -1744,8 +1742,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList17.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement4.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserES5ForOfStatement20.ts
|
||||
|
||||
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/Statements/parserForInStatement4.ts
|
||||
@@ -5188,6 +5184,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
╰────
|
||||
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/compiler/continueNotInIterationStatement4.ts:4:14]
|
||||
3 │ var x = () => {
|
||||
4 │ continue TWO;
|
||||
· ───
|
||||
5 │ }
|
||||
╰────
|
||||
|
||||
× A `continue` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement.
|
||||
╭─[typescript/tests/cases/compiler/continueTarget1.ts:1:1]
|
||||
1 │ target:
|
||||
@@ -27440,6 +27444,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
╰────
|
||||
help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while`
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement4.ts:4:14]
|
||||
3 │ var x = () => {
|
||||
4 │ continue TWO;
|
||||
· ───
|
||||
5 │ }
|
||||
╰────
|
||||
|
||||
× A `continue` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement.
|
||||
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget1.ts:1:1]
|
||||
1 │ target:
|
||||
@@ -29087,6 +29099,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidDoWhileBreakStatements.ts:14:15]
|
||||
13 │ var x = () => {
|
||||
14 │ break TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidDoWhileBreakStatements.ts:21:15]
|
||||
20 │ var fn = function () {
|
||||
@@ -29128,6 +29148,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidForBreakStatements.ts:14:15]
|
||||
13 │ var x = () => {
|
||||
14 │ break TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidForBreakStatements.ts:21:15]
|
||||
20 │ var fn = function () {
|
||||
@@ -29169,6 +29197,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidForInBreakStatements.ts:14:15]
|
||||
13 │ var fn = () => {
|
||||
14 │ break TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidForInBreakStatements.ts:21:15]
|
||||
20 │ var fn = function () {
|
||||
@@ -29210,6 +29246,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidWhileBreakStatements.ts:14:15]
|
||||
13 │ var x = () => {
|
||||
14 │ break TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidWhileBreakStatements.ts:21:15]
|
||||
20 │ var fn = function () {
|
||||
@@ -29251,6 +29295,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidDoWhileContinueStatements.ts:14:18]
|
||||
13 │ var x = () => {
|
||||
14 │ continue TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidDoWhileContinueStatements.ts:21:18]
|
||||
20 │ var fn = function () {
|
||||
@@ -29292,6 +29344,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidForContinueStatements.ts:14:18]
|
||||
13 │ var x = () => {
|
||||
14 │ continue TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidForContinueStatements.ts:21:18]
|
||||
20 │ var fn = function () {
|
||||
@@ -29333,6 +29393,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidForInContinueStatements.ts:14:18]
|
||||
13 │ var fn = () => {
|
||||
14 │ continue TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidForInContinueStatements.ts:21:18]
|
||||
20 │ var fn = function () {
|
||||
@@ -29383,6 +29451,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
9 │
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidWhileContinueStatements.ts:14:18]
|
||||
13 │ var x = () => {
|
||||
14 │ continue TWO;
|
||||
· ───
|
||||
15 │ }
|
||||
╰────
|
||||
|
||||
× Jump target cannot cross function boundary.
|
||||
╭─[typescript/tests/cases/conformance/statements/continueStatements/invalidWhileContinueStatements.ts:21:18]
|
||||
20 │ var fn = function () {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
semantic_misc Summary:
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 76/80 (95.00%)
|
||||
AST Parsed : 81/81 (100.00%)
|
||||
Positive Passed: 77/81 (95.06%)
|
||||
semantic Error: tasks/coverage/misc/pass/declare-let-private.ts
|
||||
Bindings mismatch:
|
||||
after transform: ScopeId(0): ["private"]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
transformer_misc Summary:
|
||||
AST Parsed : 80/80 (100.00%)
|
||||
Positive Passed: 80/80 (100.00%)
|
||||
AST Parsed : 81/81 (100.00%)
|
||||
Positive Passed: 81/81 (100.00%)
|
||||
Reference in new issue
Block a user