From 26387c0660c3de32a8d5d26ca2a907b7ccc4818f Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 9 Mar 2023 13:45:07 +0800 Subject: [PATCH] feat(linter): check `ContinueStatement` in javascript --- .../src/rules/early_error/javascript.rs | 114 +++++-- tasks/coverage/babel.snap | 100 +++++- tasks/coverage/test262.snap | 190 ++++++++++-- tasks/coverage/typescript.snap | 290 +++++++++++++++++- 4 files changed, 611 insertions(+), 83 deletions(-) diff --git a/crates/oxc_linter/src/rules/early_error/javascript.rs b/crates/oxc_linter/src/rules/early_error/javascript.rs index 66ab7027d..f63f22755 100644 --- a/crates/oxc_linter/src/rules/early_error/javascript.rs +++ b/crates/oxc_linter/src/rules/early_error/javascript.rs @@ -19,6 +19,7 @@ impl Rule for EarlyErrorJavaScript { AstKind::StringLiteral(lit) => check_string_literal(lit, node, ctx), AstKind::RegExpLiteral(lit) => check_regexp_literal(lit, ctx), AstKind::BreakStatement(lit) => check_break_statement(lit, node, ctx), + AstKind::ContinueStatement(lit) => check_continue_statement(lit, node, ctx), _ => {} } } @@ -54,8 +55,7 @@ fn check_private_identifier<'a>( #[error("Private identifier '#{0:?}' is not allowed outside class bodies")] #[diagnostic()] struct PrivateNotInClass(Atom, #[label] Span); - ctx.diagnostic(PrivateNotInClass(ident.name.clone(), ident.span)); - return; + return ctx.diagnostic(PrivateNotInClass(ident.name.clone(), ident.span)); }; // Check private identifier declarations in class. @@ -115,7 +115,6 @@ fn check_number_literal(lit: &NumberLiteral, node: &AstNode, ctx: &LintContext) #[error("Decimals with leading zeros are not allowed in strict mode")] #[diagnostic(help("remove the leading zero"))] struct LeadingZeroDecimal(#[label] Span); - ctx.diagnostic(LeadingZeroDecimal(lit.span)); } _ => {} @@ -137,21 +136,18 @@ fn check_string_literal<'a>(lit: &StringLiteral, node: &AstNode<'a>, ctx: &LintC match chars.next() { Some('0') => { if chars.peek().is_some_and(|c| ('1'..='9').contains(c)) { - ctx.diagnostic(LegacyOctal(lit.span)); - return; + return ctx.diagnostic(LegacyOctal(lit.span)); } } Some('1'..='7') => { - ctx.diagnostic(LegacyOctal(lit.span)); - return; + return ctx.diagnostic(LegacyOctal(lit.span)); } Some('8'..='9') => { #[derive(Debug, Error, Diagnostic)] #[error("Invalid escape sequence")] #[diagnostic(help("\\8 and \\9 are not allowed in strict mode"))] struct NonOctalDecimalEscapeSequence(#[label] Span); - ctx.diagnostic(NonOctalDecimalEscapeSequence(lit.span)); - return; + return ctx.diagnostic(NonOctalDecimalEscapeSequence(lit.span)); } _ => {} } @@ -172,6 +168,16 @@ fn check_regexp_literal(lit: &RegExpLiteral, ctx: &LintContext) { } } +#[derive(Debug, Error, Diagnostic)] +#[error("Jump target cannot cross function boundary.")] +#[diagnostic()] +struct InvalidLabelJumpTarget(#[label] Span); + +#[derive(Debug, Error, Diagnostic)] +#[error("Use of undefined label")] +#[diagnostic()] +struct InvalidLabelTarget(#[label("This label is used, but not defined")] Span); + fn check_break_statement<'a>(stmt: &BreakStatement, node: &AstNode<'a>, ctx: &LintContext<'a>) { #[derive(Debug, Error, Diagnostic)] #[error("Illegal break statement")] @@ -180,39 +186,20 @@ fn check_break_statement<'a>(stmt: &BreakStatement, node: &AstNode<'a>, ctx: &Li ))] struct InvalidBreak(#[label] Span); - #[derive(Debug, Error, Diagnostic)] - #[error("Illegal continue statement: no surrounding iteration statement")] - #[diagnostic(help( - "A `continue` statement can only be used within an enclosing `for`, `while` or `do while` " - ))] - struct InvalidContinue(#[label] Span); - - #[derive(Debug, Error, Diagnostic)] - #[error("Use of undefined label")] - #[diagnostic()] - struct InvalidLabelTarget(#[label("This label is used, but not defined")] Span); - - #[derive(Debug, Error, Diagnostic)] - #[error("Jump target cannot cross function boundary.")] - #[diagnostic()] - struct InvalidLabelJumpTarget(#[label] Span); - // It is a Syntax Error if this BreakStatement is not nested, directly or indirectly (but not crossing function or static initialization block boundaries), within an IterationStatement or a SwitchStatement. for node_id in ctx.ancestors(node).skip(1) { match ctx.kind(node_id) { AstKind::Program(_) => { - stmt.label.as_ref().map_or_else( + return stmt.label.as_ref().map_or_else( || ctx.diagnostic(InvalidBreak(stmt.span)), |label| ctx.diagnostic(InvalidLabelTarget(label.span)), ); - return; } AstKind::Function(_) | AstKind::StaticBlock(_) => { - stmt.label.as_ref().map_or_else( - || ctx.diagnostic(InvalidContinue(stmt.span)), + return stmt.label.as_ref().map_or_else( + || ctx.diagnostic(InvalidBreak(stmt.span)), |label| ctx.diagnostic(InvalidLabelJumpTarget(label.span)), ); - return; } AstKind::LabeledStatement(labeled_statement) => { if let Some(label) = &stmt.label @@ -230,3 +217,68 @@ fn check_break_statement<'a>(stmt: &BreakStatement, node: &AstNode<'a>, ctx: &Li } } } + +fn check_continue_statement<'a>( + stmt: &ContinueStatement, + node: &AstNode<'a>, + ctx: &LintContext<'a>, +) { + #[derive(Debug, Error, Diagnostic)] + #[error("Illegal continue statement: no surrounding iteration statement")] + #[diagnostic(help( + "A `continue` statement can only be used within an enclosing `for`, `while` or `do while` " + ))] + struct InvalidContinue(#[label] Span); + + #[derive(Debug, Error, Diagnostic)] + #[error( + "A `{0:?}` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement." + )] + #[diagnostic()] + struct InvalidLabelNonIteration( + &'static str, + #[label("This is an non-iteration statement")] Span, + #[label("for this label")] Span, + ); + + // It is a Syntax Error if this ContinueStatement is not nested, directly or indirectly (but not crossing function or static initialization block boundaries), within an IterationStatement. + for node_id in ctx.ancestors(node).skip(1) { + match ctx.kind(node_id) { + AstKind::Program(_) => { + return stmt.label.as_ref().map_or_else( + || ctx.diagnostic(InvalidContinue(stmt.span)), + |label| ctx.diagnostic(InvalidLabelTarget(label.span)), + ); + } + AstKind::Function(_) | AstKind::StaticBlock(_) => { + return stmt.label.as_ref().map_or_else( + || ctx.diagnostic(InvalidContinue(stmt.span)), + |label| ctx.diagnostic(InvalidLabelJumpTarget(label.span)), + ); + } + AstKind::LabeledStatement(labeled_statement) => { + if let Some(label) = &stmt.label + && label.name == labeled_statement.label.name { + if matches!( + labeled_statement.body, + Statement::LabeledStatement(_) + | Statement::DoWhileStatement(_) + | Statement::WhileStatement(_) + | Statement::ForStatement(_) + | Statement::ForInStatement(_) + | Statement::ForOfStatement(_) + ) { + break; + } + return ctx.diagnostic(InvalidLabelNonIteration( + "continue", + labeled_statement.label.span, + label.span, + )); + } + } + kind if kind.is_iteration_statement() && stmt.label.is_none() => break, + _ => {} + } + } +} diff --git a/tasks/coverage/babel.snap b/tasks/coverage/babel.snap index 18cf72096..f7d5baa45 100644 --- a/tasks/coverage/babel.snap +++ b/tasks/coverage/babel.snap @@ -1,7 +1,7 @@ Babel Summary: AST Parsed : 2056/2069 (99.37%) Positive Passed: 2056/2069 (99.37%) -Negative Passed: 896/1502 (59.65%) +Negative Passed: 908/1502 (60.45%) Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js" Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-multiple-labels/input.js" @@ -58,15 +58,9 @@ Expect Syntax Error: "core/scope/undecl-export-builtin-as/input.js" Expect Syntax Error: "core/scope/undecl-export-builtin/input.js" Expect Syntax Error: "core/scope/undecl-export-if/input.js" Expect Syntax Error: "core/scope/undecl-export/input.js" -Expect Syntax Error: "core/uncategorised/411/input.js" Expect Syntax Error: "core/uncategorised/415/input.js" Expect Syntax Error: "core/uncategorised/427/input.js" Expect Syntax Error: "core/uncategorised/454/input.js" -Expect Syntax Error: "core/uncategorised/456/input.js" -Expect Syntax Error: "core/uncategorised/457/input.js" -Expect Syntax Error: "core/uncategorised/460/input.js" -Expect Syntax Error: "core/uncategorised/462/input.js" -Expect Syntax Error: "core/uncategorised/464/input.js" Expect Syntax Error: "core/uncategorised/465/input.js" Expect Syntax Error: "core/uncategorised/466/input.js" Expect Syntax Error: "core/uncategorised/467/input.js" @@ -392,15 +386,9 @@ Expect Syntax Error: "esprima/invalid-syntax/migrated_0093/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0094/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0100/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0101/input.js" -Expect Syntax Error: "esprima/invalid-syntax/migrated_0118/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0123/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0143/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0171/input.js" -Expect Syntax Error: "esprima/invalid-syntax/migrated_0173/input.js" -Expect Syntax Error: "esprima/invalid-syntax/migrated_0174/input.js" -Expect Syntax Error: "esprima/invalid-syntax/migrated_0177/input.js" -Expect Syntax Error: "esprima/invalid-syntax/migrated_0179/input.js" -Expect Syntax Error: "esprima/invalid-syntax/migrated_0181/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0182/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0183/input.js" Expect Syntax Error: "esprima/invalid-syntax/migrated_0184/input.js" @@ -1427,6 +1415,13 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ─ ╰──── + × Illegal continue statement: no surrounding iteration statement + ╭─[core/uncategorised/411/input.js:1:1] + 1 │ continue + · ──────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Unexpected token ╭─[core/uncategorised/412/input.js:1:1] 1 │ continue 2; @@ -1709,6 +1704,20 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" ╰──── help: A `break` statement can only be used within an enclosing iteration or switch statement. + × Illegal continue statement: no surrounding iteration statement + ╭─[core/uncategorised/456/input.js:1:1] + 1 │ continue + · ──────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Illegal continue statement: no surrounding iteration statement + ╭─[core/uncategorised/457/input.js:1:1] + 1 │ switch (x) { default: continue; } + · ───────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Expect token ╭─[core/uncategorised/458/input.js:1:1] 1 │ do { x } * @@ -1723,17 +1732,37 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ╰── This label is used, but not defined ╰──── + × Use of undefined label + ╭─[core/uncategorised/460/input.js:1:1] + 1 │ while (true) { continue x; } + · ┬ + · ╰── This label is used, but not defined + ╰──── + × Jump target cannot cross function boundary. ╭─[core/uncategorised/461/input.js:1:1] 1 │ x: while (true) { (function () { break x; }); } · ─ ╰──── - × Illegal continue statement: no surrounding iteration statement + × Jump target cannot cross function boundary. + ╭─[core/uncategorised/462/input.js:1:1] + 1 │ x: while (true) { (function () { continue x; }); } + · ─ + ╰──── + + × Illegal break statement ╭─[core/uncategorised/463/input.js:1:1] 1 │ x: while (true) { (function () { break; }); } · ────── ╰──── + help: A `break` statement can only be used within an enclosing iteration or switch statement. + + × Illegal continue statement: no surrounding iteration statement + ╭─[core/uncategorised/464/input.js:1:1] + 1 │ x: while (true) { (function () { continue; }); } + · ───────── + ╰──── help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` × Unexpected token @@ -6399,6 +6428,13 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ─ ╰──── + × Illegal continue statement: no surrounding iteration statement + ╭─[esprima/invalid-syntax/migrated_0118/input.js:1:1] + 1 │ continue + · ──────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Unexpected token ╭─[esprima/invalid-syntax/migrated_0119/input.js:1:1] 1 │ continue 2; @@ -6759,6 +6795,20 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" ╰──── help: A `break` statement can only be used within an enclosing iteration or switch statement. + × Illegal continue statement: no surrounding iteration statement + ╭─[esprima/invalid-syntax/migrated_0173/input.js:1:1] + 1 │ continue + · ──────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Illegal continue statement: no surrounding iteration statement + ╭─[esprima/invalid-syntax/migrated_0174/input.js:1:1] + 1 │ switch (x) { default: continue; } + · ───────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Expect token ╭─[esprima/invalid-syntax/migrated_0175/input.js:1:1] 1 │ do { x } * @@ -6773,17 +6823,37 @@ Expect to Parse: "typescript/types/const-type-parameters/input.ts" · ╰── This label is used, but not defined ╰──── + × Use of undefined label + ╭─[esprima/invalid-syntax/migrated_0177/input.js:1:1] + 1 │ while (true) { continue x; } + · ┬ + · ╰── This label is used, but not defined + ╰──── + × Jump target cannot cross function boundary. ╭─[esprima/invalid-syntax/migrated_0178/input.js:1:1] 1 │ x: while (true) { (function () { break x; }); } · ─ ╰──── - × Illegal continue statement: no surrounding iteration statement + × Jump target cannot cross function boundary. + ╭─[esprima/invalid-syntax/migrated_0179/input.js:1:1] + 1 │ x: while (true) { (function () { continue x; }); } + · ─ + ╰──── + + × Illegal break statement ╭─[esprima/invalid-syntax/migrated_0180/input.js:1:1] 1 │ x: while (true) { (function () { break; }); } · ────── ╰──── + help: A `break` statement can only be used within an enclosing iteration or switch statement. + + × Illegal continue statement: no surrounding iteration statement + ╭─[esprima/invalid-syntax/migrated_0181/input.js:1:1] + 1 │ x: while (true) { (function () { continue; }); } + · ───────── + ╰──── help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` × Unexpected token diff --git a/tasks/coverage/test262.snap b/tasks/coverage/test262.snap index dde150ed5..ec19d7708 100644 --- a/tasks/coverage/test262.snap +++ b/tasks/coverage/test262.snap @@ -1,7 +1,7 @@ Test262 Summary: AST Parsed : 44000/44009 (99.98%) Positive Passed: 44000/44009 (99.98%) -Negative Passed: 2205/3917 (56.29%) +Negative Passed: 2223/3917 (56.75%) Expect Syntax Error: "annexB/language/statements/for-in/const-initializer.js" Expect Syntax Error: "annexB/language/statements/for-in/let-initializer.js" Expect Syntax Error: "annexB/language/statements/for-in/strict-initializer.js" @@ -866,7 +866,6 @@ Expect Syntax Error: "language/module-code/early-import-eval.js" Expect Syntax Error: "language/module-code/early-lex-and-var.js" Expect Syntax Error: "language/module-code/early-new-target.js" Expect Syntax Error: "language/module-code/early-strict-mode.js" -Expect Syntax Error: "language/module-code/early-undef-continue.js" Expect Syntax Error: "language/module-code/export-default-asyncfunction-declaration-binding-exists.js" Expect Syntax Error: "language/module-code/export-default-asyncgenerator-declaration-binding-exists.js" Expect Syntax Error: "language/module-code/export-default-function-declaration-binding-exists.js" @@ -1005,7 +1004,6 @@ Expect Syntax Error: "language/statements/async-generator/yield-as-identifier-re Expect Syntax Error: "language/statements/async-generator/yield-as-identifier-reference.js" Expect Syntax Error: "language/statements/async-generator/yield-identifier-spread-strict.js" Expect Syntax Error: "language/statements/async-generator/yield-identifier-strict.js" -Expect Syntax Error: "language/statements/block/labeled-continue.js" Expect Syntax Error: "language/statements/class/async-gen-method-static/array-destructuring-param-strict-body.js" Expect Syntax Error: "language/statements/class/async-gen-method-static/await-as-binding-identifier-escaped.js" Expect Syntax Error: "language/statements/class/async-gen-method-static/await-as-binding-identifier.js" @@ -1324,7 +1322,6 @@ Expect Syntax Error: "language/statements/class/static-init-invalid-lex-dup.js" Expect Syntax Error: "language/statements/class/static-init-invalid-lex-var.js" Expect Syntax Error: "language/statements/class/static-init-invalid-return.js" Expect Syntax Error: "language/statements/class/static-init-invalid-super-call.js" -Expect Syntax Error: "language/statements/class/static-init-invalid-undefined-continue-target.js" Expect Syntax Error: "language/statements/class/static-init-invalid-yield.js" Expect Syntax Error: "language/statements/class/static-method-param-yield.js" Expect Syntax Error: "language/statements/class/strict-mode/with.js" @@ -1336,18 +1333,6 @@ Expect Syntax Error: "language/statements/const/dstr/ary-ptrn-rest-init-obj.js" Expect Syntax Error: "language/statements/const/redeclaration-error-from-within-strict-mode-function-const.js" Expect Syntax Error: "language/statements/const/static-init-await-binding-invalid.js" Expect Syntax Error: "language/statements/const/syntax/const-declaring-let-split-across-two-lines.js" -Expect Syntax Error: "language/statements/continue/S12.7_A1_T1.js" -Expect Syntax Error: "language/statements/continue/S12.7_A1_T2.js" -Expect Syntax Error: "language/statements/continue/S12.7_A1_T3.js" -Expect Syntax Error: "language/statements/continue/S12.7_A1_T4.js" -Expect Syntax Error: "language/statements/continue/S12.7_A5_T1.js" -Expect Syntax Error: "language/statements/continue/S12.7_A5_T2.js" -Expect Syntax Error: "language/statements/continue/S12.7_A5_T3.js" -Expect Syntax Error: "language/statements/continue/S12.7_A6.js" -Expect Syntax Error: "language/statements/continue/S12.7_A8_T1.js" -Expect Syntax Error: "language/statements/continue/S12.7_A8_T2.js" -Expect Syntax Error: "language/statements/continue/static-init-with-label.js" -Expect Syntax Error: "language/statements/continue/static-init-without-label.js" Expect Syntax Error: "language/statements/do-while/decl-fun.js" Expect Syntax Error: "language/statements/do-while/labelled-fn-stmt.js" Expect Syntax Error: "language/statements/for-await-of/async-func-decl-dstr-array-elem-init-yield-ident-invalid.js" @@ -1480,8 +1465,6 @@ Expect Syntax Error: "language/statements/for-of/labelled-fn-stmt-const.js" Expect Syntax Error: "language/statements/for-of/labelled-fn-stmt-let.js" Expect Syntax Error: "language/statements/for-of/labelled-fn-stmt-lhs.js" Expect Syntax Error: "language/statements/for-of/labelled-fn-stmt-var.js" -Expect Syntax Error: "language/statements/for/S12.6.3_A11.1_T3.js" -Expect Syntax Error: "language/statements/for/S12.6.3_A11_T3.js" Expect Syntax Error: "language/statements/for/decl-fun.js" Expect Syntax Error: "language/statements/for/dstr/const-ary-ptrn-rest-init-ary.js" Expect Syntax Error: "language/statements/for/dstr/const-ary-ptrn-rest-init-id.js" @@ -1570,7 +1553,6 @@ Expect Syntax Error: "language/statements/if/if-stmt-else-fun-strict.js" Expect Syntax Error: "language/statements/if/labelled-fn-stmt-first.js" Expect Syntax Error: "language/statements/if/labelled-fn-stmt-lone.js" Expect Syntax Error: "language/statements/if/labelled-fn-stmt-second.js" -Expect Syntax Error: "language/statements/labeled/continue.js" Expect Syntax Error: "language/statements/labeled/decl-fun-strict.js" Expect Syntax Error: "language/statements/labeled/value-yield-strict-escaped.js" Expect Syntax Error: "language/statements/labeled/value-yield-strict.js" @@ -14155,6 +14137,15 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat 18 │ } ╰──── + × Use of undefined label + ╭─[language/module-code/early-undef-continue.js:16:1] + 16 │ while (false) { + 17 │ continue undef; + · ──┬── + · ╰── This label is used, but not defined + 18 │ } + ╰──── + × An export name cannot include a unicode lone surrogate ╭─[language/module-code/export-expname-from-as-unpaired-surrogate.js:20:1] 20 │ @@ -15093,6 +15084,19 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat · ── ╰──── + × A `"continue"` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement. + ╭─[language/statements/block/labeled-continue.js:19:1] + 19 │ + 20 │ label: { + · ──┬── + · ╰── This is an non-iteration statement + 21 │ for ( ;; ) { + 22 │ continue label; + · ──┬── + · ╰── for this label + 23 │ } + ╰──── + × Illegal break statement ╭─[language/statements/break/S12.8_A1_T1.js:17:1] 17 │ var x=1; @@ -15179,14 +15183,14 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat ╰──── help: A `break` statement can only be used within an enclosing iteration or switch statement. - × Illegal continue statement: no surrounding iteration statement + × Illegal break statement ╭─[language/statements/break/static-init-without-label.js:23:1] 23 │ static { 24 │ break; · ────── 25 │ } ╰──── - help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + help: A `break` statement can only be used within an enclosing iteration or switch statement. × Keywords cannot contain escape characters ╭─[language/statements/class/async-gen-meth-escaped-async.js:24:1] @@ -18429,6 +18433,14 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat 23 │ } ╰──── + × Jump target cannot cross function boundary. + ╭─[language/statements/class/static-init-invalid-undefined-continue-target.js:21:1] + 21 │ x: while (false) { + 22 │ continue y; + · ─ + 23 │ } + ╰──── + × Keywords cannot contain escape characters ╭─[language/statements/class/syntax/escaped-static.js:23:1] 23 │ class C { @@ -18664,6 +18676,112 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat ╰──── help: Wrap this declaration in a block statement + × Illegal continue statement: no surrounding iteration statement + ╭─[language/statements/continue/S12.7_A1_T1.js:19:1] + 19 │ var x=1; + 20 │ continue; + · ───────── + 21 │ var y=2; + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Use of undefined label + ╭─[language/statements/continue/S12.7_A1_T2.js:21:1] + 21 │ var x=1; + 22 │ continue LABEL; + · ──┬── + · ╰── This label is used, but not defined + 23 │ var y=2; + ╰──── + + × Use of undefined label + ╭─[language/statements/continue/S12.7_A1_T3.js:22:1] + 22 │ var x=1; + 23 │ continue LABEL; + · ──┬── + · ╰── This label is used, but not defined + 24 │ var y=2; + ╰──── + + × Illegal continue statement: no surrounding iteration statement + ╭─[language/statements/continue/S12.7_A1_T4.js:20:1] + 20 │ var x=1; + 21 │ continue; + · ───────── + 22 │ var y=2; + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Use of undefined label + ╭─[language/statements/continue/S12.7_A5_T1.js:21:1] + 21 │ if(x===10)break; + 22 │ continue LABEL_ANOTHER_LOOP; + · ─────────┬──────── + · ╰── This label is used, but not defined + 23 │ LABEL_IN_2 : y++; + ╰──── + + × Use of undefined label + ╭─[language/statements/continue/S12.7_A5_T2.js:21:1] + 21 │ if(x===10)break; + 22 │ continue IN_DO_FUNC; + · ─────┬──── + · ╰── This label is used, but not defined + 23 │ LABEL_IN_2 : y++; + ╰──── + + × Use of undefined label + ╭─[language/statements/continue/S12.7_A5_T3.js:22:1] + 22 │ if(x===10)break; + 23 │ continue LABEL_IN; + · ────┬─── + · ╰── This label is used, but not defined + 24 │ LABEL_IN_2 : y++; + ╰──── + + × Jump target cannot cross function boundary. + ╭─[language/statements/continue/S12.7_A6.js:20:1] + 20 │ x++; + 21 │ (function(){continue LABEL1;})(); + · ────── + 22 │ y++; + ╰──── + + × Use of undefined label + ╭─[language/statements/continue/S12.7_A8_T1.js:18:1] + 18 │ } catch(e){ + 19 │ continue LABEL2; + · ───┬── + · ╰── This label is used, but not defined + 20 │ LABEL2 : do { + ╰──── + + × Illegal continue statement: no surrounding iteration statement + ╭─[language/statements/continue/S12.7_A8_T2.js:16:1] + 16 │ } catch(e){ + 17 │ continue; + · ───────── + 18 │ }; + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Jump target cannot cross function boundary. + ╭─[language/statements/continue/static-init-with-label.js:24:1] + 24 │ static { + 25 │ continue label; + · ───── + 26 │ } + ╰──── + + × Illegal continue statement: no surrounding iteration statement + ╭─[language/statements/continue/static-init-without-label.js:24:1] + 24 │ static { + 25 │ continue; + · ───────── + 26 │ } + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Unexpected token ╭─[language/statements/debugger/expression.js:13:1] 13 │ @@ -19732,6 +19850,24 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat ╰──── help: Wrap this declaration in a block statement + × Use of undefined label + ╭─[language/statements/for/S12.6.3_A11.1_T3.js:23:1] + 23 │ nested:for(var index_n=0;index_n<=index;index_n++){ + 24 │ if(index*index_n == 6)continue nonexist; + · ────┬─── + · ╰── This label is used, but not defined + 25 │ __str+=""+index+index_n; + ╰──── + + × Use of undefined label + ╭─[language/statements/for/S12.6.3_A11_T3.js:23:1] + 23 │ nested:for(index_n=0;index_n<=index;index_n++){ + 24 │ if(index*index_n == 6)continue nonexist; + · ────┬─── + · ╰── This label is used, but not defined + 25 │ __str+=""+index+index_n; + ╰──── + × Use of undefined label ╭─[language/statements/for/S12.6.3_A12.1_T3.js:23:1] 23 │ nested:for(var index_n=0;index_n<=index;index_n++){ @@ -20576,6 +20712,18 @@ Expect to Parse: "language/statements/class/decorator/syntax/class-valid/decorat ╰──── help: Wrap this declaration in a block statement + × A `"continue"` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement. + ╭─[language/statements/labeled/continue.js:23:1] + 23 │ do { + 24 │ test262: { + · ───┬─── + · ╰── This is an non-iteration statement + 25 │ continue test262; + · ───┬─── + · ╰── for this label + 26 │ } + ╰──── + × Async functions can only be declared at the top level or inside a block ╭─[language/statements/labeled/decl-async-function.js:19:1] 19 │ diff --git a/tasks/coverage/typescript.snap b/tasks/coverage/typescript.snap index 9dfb513fc..8b1470906 100644 --- a/tasks/coverage/typescript.snap +++ b/tasks/coverage/typescript.snap @@ -1,7 +1,7 @@ TypeScript Summary: AST Parsed : 2310/2338 (98.80%) Positive Passed: 2310/2338 (98.80%) -Negative Passed: 546/2531 (21.57%) +Negative Passed: 558/2531 (22.05%) Expect Syntax Error: "Symbols/ES5SymbolProperty2.ts" Expect Syntax Error: "Symbols/ES5SymbolProperty6.ts" Expect Syntax Error: "additionalChecks/noPropertyAccessFromIndexSignature1.ts" @@ -1336,19 +1336,12 @@ Expect Syntax Error: "parser/ecmascript5/RegularExpressions/parserRegularExpress Expect Syntax Error: "parser/ecmascript5/RegularExpressions/parserRegularExpressionDivideAmbiguity5.ts" Expect Syntax Error: "parser/ecmascript5/Statements/BreakStatements/parser_breakInIterationOrSwitchStatement4.ts" Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueInIterationStatement4.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement1.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement2.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement3.ts" Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement4.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget1.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget5.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget6.ts" Expect Syntax Error: "parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel1.ts" Expect Syntax Error: "parser/ecmascript5/Statements/LabeledStatements/parser_duplicateLabel2.ts" Expect Syntax Error: "parser/ecmascript5/Statements/ReturnStatements/parserReturnStatement1.ts" Expect Syntax Error: "parser/ecmascript5/Statements/ReturnStatements/parserReturnStatement2.ts" Expect Syntax Error: "parser/ecmascript5/Statements/parserBlockStatement1.d.ts" -Expect Syntax Error: "parser/ecmascript5/Statements/parserContinueStatement1.d.ts" Expect Syntax Error: "parser/ecmascript5/Statements/parserDebuggerStatement1.d.ts" Expect Syntax Error: "parser/ecmascript5/Statements/parserDoStatement1.d.ts" Expect Syntax Error: "parser/ecmascript5/Statements/parserES5ForOfStatement1.d.ts" @@ -1561,11 +1554,6 @@ Expect Syntax Error: "statements/VariableStatements/everyTypeWithAnnotationAndIn Expect Syntax Error: "statements/VariableStatements/invalidMultipleVariableDeclarations.ts" Expect Syntax Error: "statements/breakStatements/invalidSwitchBreakStatement.ts" Expect Syntax Error: "statements/breakStatements/switchBreakStatements.ts" -Expect Syntax Error: "statements/continueStatements/invalidDoWhileContinueStatements.ts" -Expect Syntax Error: "statements/continueStatements/invalidForContinueStatements.ts" -Expect Syntax Error: "statements/continueStatements/invalidForInContinueStatements.ts" -Expect Syntax Error: "statements/continueStatements/invalidSwitchContinueStatement.ts" -Expect Syntax Error: "statements/continueStatements/invalidWhileContinueStatements.ts" Expect Syntax Error: "statements/for-inStatements/for-inStatements.ts" Expect Syntax Error: "statements/for-inStatements/for-inStatementsArrayErrors.ts" Expect Syntax Error: "statements/for-inStatements/for-inStatementsDestructuring.ts" @@ -2623,13 +2611,30 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 7 │ } ╰──── - × Illegal continue statement: no surrounding iteration statement + × Jump target cannot cross function boundary. + ╭─[classes/classStaticBlock/classStaticBlock8.ts:8:1] + 8 │ if (v === 2) { + 9 │ continue label; + · ───── + 10 │ } + ╰──── + + × Illegal break statement ╭─[classes/classStaticBlock/classStaticBlock8.ts:11:1] 11 │ if (v === 3) { 12 │ break · ───── 13 │ } ╰──── + help: A `break` statement can only be used within an enclosing iteration or switch statement. + + × Illegal continue statement: no surrounding iteration statement + ╭─[classes/classStaticBlock/classStaticBlock8.ts:14:1] + 14 │ if (v === 4) { + 15 │ continue + · ──────── + 16 │ } + ╰──── help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` × Automatic Semicolon Insertion @@ -5834,6 +5839,15 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" ╰──── help: A `break` statement can only be used within an enclosing iteration or switch statement. + × Illegal continue statement: no surrounding iteration statement + ╭─[jsdoc/typedefOnStatements.ts:36:1] + 36 │ /** @typedef {{ l: string }} L */ + 37 │ continue; + · ───────── + 38 │ /** @typedef {{ m: string }} M */ + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Unexpected token ╭─[jsx/checkJsxNamespaceNamesQuestionableForms.tsx:12:1] 12 │ ; @@ -7353,14 +7367,14 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" ╰──── help: A `break` statement can only be used within an enclosing iteration or switch statement. - × Illegal continue statement: no surrounding iteration statement + × Illegal break statement ╭─[parser/ecmascript5/Statements/BreakStatements/parser_breakNotInIterationOrSwitchStatement2.ts:2:1] 2 │ function f() { 3 │ break; · ────── 4 │ } ╰──── - help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + help: A `break` statement can only be used within an enclosing iteration or switch statement. × Jump target cannot cross function boundary. ╭─[parser/ecmascript5/Statements/BreakStatements/parser_breakTarget5.ts:4:1] @@ -7379,6 +7393,58 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 3 │ } ╰──── + × Illegal continue statement: no surrounding iteration statement + ╭─[parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement1.ts:1:1] + 1 │ continue; + · ───────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Illegal continue statement: no surrounding iteration statement + ╭─[parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement2.ts:2:1] + 2 │ function f() { + 3 │ continue; + · ───────── + 4 │ } + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Illegal continue statement: no surrounding iteration statement + ╭─[parser/ecmascript5/Statements/ContinueStatements/parser_continueNotInIterationStatement3.ts:2:1] + 2 │ default: + 3 │ continue; + · ───────── + 4 │ } + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × A `"continue"` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement. + ╭─[parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget1.ts:1:1] + 1 │ target: + · ───┬── + · ╰── This is an non-iteration statement + 2 │ continue target; + · ───┬── + · ╰── for this label + ╰──── + + × Jump target cannot cross function boundary. + ╭─[parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget5.ts:4:1] + 4 │ while (true) { + 5 │ continue target; + · ────── + 6 │ } + ╰──── + + × Use of undefined label + ╭─[parser/ecmascript5/Statements/ContinueStatements/parser_continueTarget6.ts:1:1] + 1 │ while (true) { + 2 │ continue target; + · ───┬── + · ╰── This label is used, but not defined + 3 │ } + ╰──── + × Illegal break statement ╭─[parser/ecmascript5/Statements/parserBreakStatement1.d.ts:1:1] 1 │ break; @@ -7386,6 +7452,13 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" ╰──── help: A `break` statement can only be used within an enclosing iteration or switch statement. + × Illegal continue statement: no surrounding iteration statement + ╭─[parser/ecmascript5/Statements/parserContinueStatement1.d.ts:1:1] + 1 │ continue; + · ───────── + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + × Expect token ╭─[parser/ecmascript5/Statements/parserES5ForOfStatement2.ts:1:1] 1 │ //@target: ES5 @@ -8067,6 +8140,191 @@ Expect to Parse: "salsa/privateIdentifierExpando.ts" 38 │ } ╰──── + × Illegal continue statement: no surrounding iteration statement + ╭─[statements/continueStatements/invalidDoWhileContinueStatements.ts:6:1] + 6 │ // naked continue not allowed + 7 │ continue; + · ───────── + 8 │ + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Use of undefined label + ╭─[statements/continueStatements/invalidDoWhileContinueStatements.ts:10:1] + 10 │ ONE: + 11 │ do continue TWO; while (true) + · ─┬─ + · ╰── This label is used, but not defined + 12 │ + ╰──── + + × Jump target cannot cross function boundary. + ╭─[statements/continueStatements/invalidDoWhileContinueStatements.ts:23:1] + 23 │ var fn = function () { + 24 │ continue THREE; + · ───── + 25 │ } + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidDoWhileContinueStatements.ts:29:1] + 29 │ do { + 30 │ continue FIVE; + · ──┬─ + · ╰── This label is used, but not defined + 31 │ FIVE: + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidDoWhileContinueStatements.ts:39:1] + 39 │ do { + 40 │ continue NINE; + · ──┬─ + · ╰── This label is used, but not defined + 41 │ }while (true) + ╰──── + + × Illegal continue statement: no surrounding iteration statement + ╭─[statements/continueStatements/invalidForContinueStatements.ts:6:1] + 6 │ // naked continue not allowed + 7 │ continue; + · ───────── + 8 │ + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Use of undefined label + ╭─[statements/continueStatements/invalidForContinueStatements.ts:10:1] + 10 │ ONE: + 11 │ for(;;) continue TWO; + · ─┬─ + · ╰── This label is used, but not defined + 12 │ + ╰──── + + × Jump target cannot cross function boundary. + ╭─[statements/continueStatements/invalidForContinueStatements.ts:23:1] + 23 │ var fn = function () { + 24 │ continue THREE; + · ───── + 25 │ } + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidForContinueStatements.ts:29:1] + 29 │ for(;;) { + 30 │ continue FIVE; + · ──┬─ + · ╰── This label is used, but not defined + 31 │ FIVE: + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidForContinueStatements.ts:38:1] + 38 │ for(;;) { + 39 │ continue NINE; + · ──┬─ + · ╰── This label is used, but not defined + 40 │ } + ╰──── + + × Illegal continue statement: no surrounding iteration statement + ╭─[statements/continueStatements/invalidForInContinueStatements.ts:6:1] + 6 │ // naked continue not allowed + 7 │ continue; + · ───────── + 8 │ + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Use of undefined label + ╭─[statements/continueStatements/invalidForInContinueStatements.ts:10:1] + 10 │ ONE: + 11 │ for (var x in {}) continue TWO; + · ─┬─ + · ╰── This label is used, but not defined + 12 │ + ╰──── + + × Jump target cannot cross function boundary. + ╭─[statements/continueStatements/invalidForInContinueStatements.ts:23:1] + 23 │ var fn = function () { + 24 │ continue THREE; + · ───── + 25 │ } + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidForInContinueStatements.ts:29:1] + 29 │ for (var x in {}) { + 30 │ continue FIVE; + · ──┬─ + · ╰── This label is used, but not defined + 31 │ FIVE: + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidForInContinueStatements.ts:39:1] + 39 │ for (var x in {}) { + 40 │ continue NINE; + · ──┬─ + · ╰── This label is used, but not defined + 41 │ } + ╰──── + + × Illegal continue statement: no surrounding iteration statement + ╭─[statements/continueStatements/invalidSwitchContinueStatement.ts:4:1] + 4 │ case 5: + 5 │ continue; + · ───────── + 6 │ } + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Illegal continue statement: no surrounding iteration statement + ╭─[statements/continueStatements/invalidWhileContinueStatements.ts:6:1] + 6 │ // naked continue not allowed + 7 │ continue; + · ───────── + 8 │ + ╰──── + help: A `continue` statement can only be used within an enclosing `for`, `while` or `do while` + + × Use of undefined label + ╭─[statements/continueStatements/invalidWhileContinueStatements.ts:10:1] + 10 │ ONE: + 11 │ while (true) continue TWO; + · ─┬─ + · ╰── This label is used, but not defined + 12 │ + ╰──── + + × Jump target cannot cross function boundary. + ╭─[statements/continueStatements/invalidWhileContinueStatements.ts:23:1] + 23 │ var fn = function () { + 24 │ continue THREE; + · ───── + 25 │ } + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidWhileContinueStatements.ts:29:1] + 29 │ while (true) { + 30 │ continue FIVE; + · ──┬─ + · ╰── This label is used, but not defined + 31 │ FIVE: + ╰──── + + × Use of undefined label + ╭─[statements/continueStatements/invalidWhileContinueStatements.ts:39:1] + 39 │ while (true) { + 40 │ continue NINE; + · ──┬─ + · ╰── This label is used, but not defined + 41 │ } + ╰──── + × Unexpected token ╭─[statements/for-ofStatements/ES5For-of12.ts:1:1] 1 │ for ([""] of [[""]]) { }