Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions crates/oxc_semantic/src/checker/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,37 @@ pub fn check_function_declaration<'a>(
};
}

// It is a Syntax Error if IsLabelledFunction(Statement) is true.
pub fn check_function_declaration_in_labeled_statement<'a>(
body: &Statement<'a>,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
if let Statement::FunctionDeclaration(decl) = body {
if ctx.strict_mode() {
ctx.error(function_declaration_strict(decl.span));
} else {
// skip(1) for `LabeledStatement`
for kind in ctx.nodes.ancestor_kinds(node.id()).skip(1) {
match kind {
// Nested labeled statement
AstKind::LabeledStatement(_) => continue,
AstKind::ForOfStatement(_)
| AstKind::ForInStatement(_)
| AstKind::ForStatement(_)
| AstKind::WhileStatement(_)
| AstKind::DoWhileStatement(_)
| AstKind::WithStatement(_)
| AstKind::IfStatement(_) => break,

_ => return,
}
}
ctx.error(function_declaration_non_strict(decl.span));
}
};
}

// It is a Syntax Error if any element of the LexicallyDeclaredNames of
// StatementList also occurs in the VarDeclaredNames of StatementList.
pub fn check_variable_declarator_redeclaration(
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_semantic/src/checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::ContinueStatement(stmt) => js::check_continue_statement(stmt, node, ctx),
AstKind::LabeledStatement(stmt) => {
js::check_labeled_statement(stmt, node, ctx);
js::check_function_declaration(&stmt.body, true, ctx);
js::check_function_declaration_in_labeled_statement(&stmt.body, node, ctx);
}
AstKind::ForInStatement(stmt) => {
js::check_function_declaration(&stmt.body, false, ctx);
Expand Down
26 changes: 22 additions & 4 deletions tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ commit: 578ac4df
parser_babel Summary:
AST Parsed : 2303/2322 (99.18%)
Positive Passed: 2282/2322 (98.28%)
Negative Passed: 1551/1673 (92.71%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.1-sloppy-labeled-functions-if-body/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-if/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js
Negative Passed: 1554/1673 (92.89%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-and-startcolumn-specified/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-specified/input.js
Expand Down Expand Up @@ -729,6 +726,13 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
32 │ }
╰────

× Invalid function declaration
╭─[babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.1-sloppy-labeled-functions-if-body/input.js:1:11]
1 │ if (0) x: function f() {}
· ───────────────
╰────
help: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement

× Identifier `f` has already been declared
╭─[babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.4-var-redeclaration-catch-binding/input.js:2:17]
1 │ try {} catch (e) { var e; }
Expand Down Expand Up @@ -802,6 +806,20 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement

× Invalid function declaration
╭─[babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-if/input.js:1:18]
1 │ if (1) foo: bar: function foo(){}
· ────────────────
╰────
help: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement

× Invalid function declaration
╭─[babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-loop/input.js:1:21]
1 │ while (1) foo: bar: function foo(){}
· ────────────────
╰────
help: In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement

× Cannot assign to this expression
╭─[babel/packages/babel-parser/test/fixtures/core/categorized/invalid-left-hand-side-in-postfix-operation/input.js:1:1]
1 │ a++ = t
Expand Down
171 changes: 152 additions & 19 deletions tasks/coverage/snapshots/parser_test262.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: bc5c1417
parser_test262 Summary:
AST Parsed : 44293/44293 (100.00%)
Positive Passed: 44293/44293 (100.00%)
Negative Passed: 4487/4519 (99.29%)
Negative Passed: 4505/4519 (99.69%)
Expect Syntax Error: tasks/coverage/test262/test/language/expressions/class/class-name-ident-let-escaped.js
Expect Syntax Error: tasks/coverage/test262/test/language/expressions/class/class-name-ident-let.js
Expect Syntax Error: tasks/coverage/test262/test/language/expressions/class/class-name-ident-static-escaped.js
Expand All @@ -18,24 +18,6 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/class/class
Expect Syntax Error: tasks/coverage/test262/test/language/statements/class/class-name-ident-static.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/class/class-name-ident-yield-escaped.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/class/class-name-ident-yield.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/do-while/labelled-fn-stmt.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for/labelled-fn-stmt-const.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for/labelled-fn-stmt-expr.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for/labelled-fn-stmt-let.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for/labelled-fn-stmt-var.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-in/labelled-fn-stmt-const.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-in/labelled-fn-stmt-let.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-in/labelled-fn-stmt-lhs.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-in/labelled-fn-stmt-var.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-of/labelled-fn-stmt-const.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-of/labelled-fn-stmt-let.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-of/labelled-fn-stmt-lhs.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/for-of/labelled-fn-stmt-var.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/if/labelled-fn-stmt-first.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/if/labelled-fn-stmt-lone.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/if/labelled-fn-stmt-second.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/while/labelled-fn-stmt.js
Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labelled-fn-stmt.js

× '0'-prefixed octal literals and octal escape sequences are deprecated
╭─[test262/test/annexB/language/expressions/template-literal/legacy-octal-escape-sequence-strict.js:19:4]
Expand Down Expand Up @@ -33070,6 +33052,14 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
╰────
help: Try insert a semicolon here

× Invalid function declaration
╭─[test262/test/language/statements/do-while/labelled-fn-stmt.js:19:20]
18 │
19 │ do label1: label2: function f() {} while (false)
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/do-while/let-array-with-newline.js:20:4]
19 │
Expand Down Expand Up @@ -33497,6 +33487,38 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
23 │ }
╰────

× Invalid function declaration
╭─[test262/test/language/statements/for/labelled-fn-stmt-const.js:19:44]
18 │
19 │ for (const x = 0; false; ) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for/labelled-fn-stmt-expr.js:19:34]
18 │
19 │ for ( ; false; ) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for/labelled-fn-stmt-let.js:19:38]
18 │
19 │ for (let x; false; ) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for/labelled-fn-stmt-var.js:19:38]
18 │
19 │ for (var x; false; ) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/for/let-array-with-newline.js:20:17]
19 │
Expand Down Expand Up @@ -34635,6 +34657,38 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
· ────
╰────

× Invalid function declaration
╭─[test262/test/language/statements/for-in/labelled-fn-stmt-const.js:19:37]
18 │
19 │ for (const x in {}) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for-in/labelled-fn-stmt-let.js:19:35]
18 │
19 │ for (let x in {}) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for-in/labelled-fn-stmt-lhs.js:19:31]
18 │
19 │ for (x in {}) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for-in/labelled-fn-stmt-var.js:19:35]
18 │
19 │ for (var x in {}) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/for-in/let-array-with-newline.js:20:21]
19 │
Expand Down Expand Up @@ -35362,6 +35416,38 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
· ╰── `)` expected
╰────

× Invalid function declaration
╭─[test262/test/language/statements/for-of/labelled-fn-stmt-const.js:19:37]
18 │
19 │ for (const x of []) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for-of/labelled-fn-stmt-let.js:19:35]
18 │
19 │ for (let x of []) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for-of/labelled-fn-stmt-lhs.js:19:31]
18 │
19 │ for (x of []) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/for-of/labelled-fn-stmt-var.js:19:35]
18 │
19 │ for (var x of []) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/for-of/let-array-with-newline.js:20:19]
19 │
Expand Down Expand Up @@ -36634,6 +36720,30 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
╰────
help: Try insert a semicolon here

× Invalid function declaration
╭─[test262/test/language/statements/if/labelled-fn-stmt-first.js:30:28]
29 │
30 │ if (false) label1: label2: function test262() {} else ;
· ─────────────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/if/labelled-fn-stmt-lone.js:30:28]
29 │
30 │ if (false) label1: label2: function test262() {}
· ─────────────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Invalid function declaration
╭─[test262/test/language/statements/if/labelled-fn-stmt-second.js:30:34]
29 │
30 │ if (true) ; else label1: label2: function test262() {}
· ─────────────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/if/let-array-with-newline.js:20:12]
19 │
Expand Down Expand Up @@ -38494,6 +38604,14 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
╰────
help: Try insert a semicolon here

× Invalid function declaration
╭─[test262/test/language/statements/while/labelled-fn-stmt.js:19:31]
18 │
19 │ while (false) label1: label2: function f() {}
· ───────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/while/let-array-with-newline.js:20:15]
19 │
Expand Down Expand Up @@ -38586,6 +38704,21 @@ Expect Syntax Error: tasks/coverage/test262/test/language/statements/with/labell
╰────
help: Try insert a semicolon here

× Invalid function declaration
╭─[test262/test/language/statements/with/labelled-fn-stmt.js:27:27]
26 │
27 │ with ({}) label1: label2: function test262() {}
· ─────────────────────
╰────
help: In strict mode code, functions can only be declared at top level or inside a block

× 'with' statements are not allowed
╭─[test262/test/language/statements/with/labelled-fn-stmt.js:27:1]
26 │
27 │ with ({}) label1: label2: function test262() {}
· ────
╰────

× Lexical declaration cannot appear in a single-statement context
╭─[test262/test/language/statements/with/let-array-with-newline.js:22:15]
21 │ if (false) {
Expand Down
Loading