diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index b5e99e34baa35..2f0ca06d0486d 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -105,6 +105,13 @@ fn invalid_let_declaration(x0: &str, span1: Span) -> OxcDiagnostic { .with_label(span1) } +fn invalid_let_catch_param(span1: Span) -> OxcDiagnostic { + OxcDiagnostic::error( + "`let` cannot be declared as a variable name inside of a destructured catch parameter", + ) + .with_label(span1) +} + pub fn check_binding_identifier(ident: &BindingIdentifier, ctx: &SemanticBuilder<'_>) { if ctx.strict_mode() { // In strict mode, `eval` and `arguments` are banned as identifiers. @@ -161,6 +168,7 @@ pub fn check_binding_identifier(ident: &BindingIdentifier, ctx: &SemanticBuilder // LexicalDeclaration : LetOrConst BindingList ; // * It is a Syntax Error if the BoundNames of BindingList contains "let". if ident.name == "let" { + let mut is_grandparent_or_above = false; for node_kind in ctx.nodes.ancestor_kinds(ctx.current_node_id) { match node_kind { AstKind::VariableDeclarator(decl) => { @@ -171,8 +179,17 @@ pub fn check_binding_identifier(ident: &BindingIdentifier, ctx: &SemanticBuilder } // `let` is permitted as function name or function param (including arrow functions) AstKind::Function(_) | AstKind::FormalParameter(_) => break, + // `try {} catch (let) {}` is permitted. + // `try {} catch ({let}) {}` and `try {} catch ([let]) {}` are not. + AstKind::CatchParameter(_) => { + if is_grandparent_or_above { + ctx.error(invalid_let_catch_param(ident.span)); + } + break; + } _ => {} } + is_grandparent_or_above = true; } } } diff --git a/tasks/coverage/misc/fail/oxc-12306.cjs b/tasks/coverage/misc/fail/oxc-12306.cjs new file mode 100644 index 0000000000000..32ec85caee428 --- /dev/null +++ b/tasks/coverage/misc/fail/oxc-12306.cjs @@ -0,0 +1,8 @@ +// Sloppy mode + +try {} catch ({let}) {} +try {} catch ([let]) {} +try {} catch ({x: let}) {} +try {} catch ({...let}) {} +try {} catch ([...let]) {} +try {} catch ({x: {y: [{...let}]}}) {} diff --git a/tasks/coverage/misc/pass/oxc-12306.cjs b/tasks/coverage/misc/pass/oxc-12306.cjs new file mode 100644 index 0000000000000..e534f42e92d27 --- /dev/null +++ b/tasks/coverage/misc/pass/oxc-12306.cjs @@ -0,0 +1,3 @@ +// Sloppy mode + +try {} catch (let) {} diff --git a/tasks/coverage/snapshots/codegen_misc.snap b/tasks/coverage/snapshots/codegen_misc.snap index cd0e4486cbd1e..1386b5231b2fc 100644 --- a/tasks/coverage/snapshots/codegen_misc.snap +++ b/tasks/coverage/snapshots/codegen_misc.snap @@ -1,3 +1,3 @@ codegen_misc Summary: -AST Parsed : 45/45 (100.00%) -Positive Passed: 45/45 (100.00%) +AST Parsed : 46/46 (100.00%) +Positive Passed: 46/46 (100.00%) diff --git a/tasks/coverage/snapshots/parser_misc.snap b/tasks/coverage/snapshots/parser_misc.snap index 976b37f860167..c2b8b1fe73d37 100644 --- a/tasks/coverage/snapshots/parser_misc.snap +++ b/tasks/coverage/snapshots/parser_misc.snap @@ -1,7 +1,7 @@ parser_misc Summary: -AST Parsed : 45/45 (100.00%) -Positive Passed: 45/45 (100.00%) -Negative Passed: 48/48 (100.00%) +AST Parsed : 46/46 (100.00%) +Positive Passed: 46/46 (100.00%) +Negative Passed: 49/49 (100.00%) × Cannot assign to 'arguments' in strict mode ╭─[misc/fail/arguments-eval.ts:1:10] @@ -188,6 +188,53 @@ Negative Passed: 48/48 (100.00%) · ────────── ╰──── + × `let` cannot be declared as a variable name inside of a destructured catch parameter + ╭─[misc/fail/oxc-12306.cjs:3:16] + 2 │ + 3 │ try {} catch ({let}) {} + · ─── + 4 │ try {} catch ([let]) {} + ╰──── + + × `let` cannot be declared as a variable name inside of a destructured catch parameter + ╭─[misc/fail/oxc-12306.cjs:4:16] + 3 │ try {} catch ({let}) {} + 4 │ try {} catch ([let]) {} + · ─── + 5 │ try {} catch ({x: let}) {} + ╰──── + + × `let` cannot be declared as a variable name inside of a destructured catch parameter + ╭─[misc/fail/oxc-12306.cjs:5:19] + 4 │ try {} catch ([let]) {} + 5 │ try {} catch ({x: let}) {} + · ─── + 6 │ try {} catch ({...let}) {} + ╰──── + + × `let` cannot be declared as a variable name inside of a destructured catch parameter + ╭─[misc/fail/oxc-12306.cjs:6:19] + 5 │ try {} catch ({x: let}) {} + 6 │ try {} catch ({...let}) {} + · ─── + 7 │ try {} catch ([...let]) {} + ╰──── + + × `let` cannot be declared as a variable name inside of a destructured catch parameter + ╭─[misc/fail/oxc-12306.cjs:7:19] + 6 │ try {} catch ({...let}) {} + 7 │ try {} catch ([...let]) {} + · ─── + 8 │ try {} catch ({x: {y: [{...let}]}}) {} + ╰──── + + × `let` cannot be declared as a variable name inside of a destructured catch parameter + ╭─[misc/fail/oxc-12306.cjs:8:28] + 7 │ try {} catch ([...let]) {} + 8 │ try {} catch ({x: {y: [{...let}]}}) {} + · ─── + ╰──── + × Unexpected token ╭─[misc/fail/oxc-169.js:2:1] 1 │ 1<(V=82< diff --git a/tasks/coverage/snapshots/semantic_misc.snap b/tasks/coverage/snapshots/semantic_misc.snap index b2f6b1f224c88..5f4759eeb025d 100644 --- a/tasks/coverage/snapshots/semantic_misc.snap +++ b/tasks/coverage/snapshots/semantic_misc.snap @@ -1,6 +1,6 @@ semantic_misc Summary: -AST Parsed : 45/45 (100.00%) -Positive Passed: 29/45 (64.44%) +AST Parsed : 46/46 (100.00%) +Positive Passed: 30/46 (65.22%) semantic Error: tasks/coverage/misc/pass/oxc-11593.ts Scope children mismatch: after transform: ScopeId(0): [ScopeId(1)] diff --git a/tasks/coverage/snapshots/transformer_misc.snap b/tasks/coverage/snapshots/transformer_misc.snap index 4eca041a91319..d79d4849e5c24 100644 --- a/tasks/coverage/snapshots/transformer_misc.snap +++ b/tasks/coverage/snapshots/transformer_misc.snap @@ -1,3 +1,3 @@ transformer_misc Summary: -AST Parsed : 45/45 (100.00%) -Positive Passed: 45/45 (100.00%) +AST Parsed : 46/46 (100.00%) +Positive Passed: 46/46 (100.00%)