From 84c43c8282de604aa821524cebd65c19c59d4716 Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 21 Apr 2024 23:53:38 +0800 Subject: [PATCH] fix(semantic): correctly resolve identifiers inside catch parameter initializers (#3050) closes #2499 --- crates/oxc_semantic/src/binder.rs | 38 ++++++++++++----------------- crates/oxc_semantic/src/builder.rs | 7 +++--- crates/oxc_semantic/tests/scopes.rs | 16 ++++++++++++ 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index 3b628a03a..463f00213 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -241,33 +241,27 @@ impl<'a> Binder for FormalParameter<'a> { } } -impl<'a> Binder for CatchClause<'a> { +impl<'a> Binder for CatchParameter<'a> { fn bind(&self, builder: &mut SemanticBuilder) { let current_scope_id = builder.current_scope_id; - if let Some(param) = &self.param { - // https://tc39.es/ecma262/#sec-variablestatements-in-catch-blocks - // It is a Syntax Error if any element of the BoundNames of CatchParameter also occurs in the VarDeclaredNames of Block - // unless CatchParameter is CatchParameter : BindingIdentifier - if let BindingPatternKind::BindingIdentifier(ident) = ¶m.pattern.kind { - let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable; - let symbol_id = builder.declare_shadow_symbol( - &ident.name, + // https://tc39.es/ecma262/#sec-variablestatements-in-catch-blocks + // It is a Syntax Error if any element of the BoundNames of CatchParameter also occurs in the VarDeclaredNames of Block + // unless CatchParameter is CatchParameter : BindingIdentifier + if let BindingPatternKind::BindingIdentifier(ident) = &self.pattern.kind { + let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable; + let symbol_id = + builder.declare_shadow_symbol(&ident.name, ident.span, current_scope_id, includes); + ident.symbol_id.set(Some(symbol_id)); + } else { + self.pattern.bound_names(&mut |ident| { + let symbol_id = builder.declare_symbol( ident.span, - current_scope_id, - includes, + &ident.name, + SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable, + SymbolFlags::BlockScopedVariableExcludes, ); ident.symbol_id.set(Some(symbol_id)); - } else { - param.pattern.bound_names(&mut |ident| { - let symbol_id = builder.declare_symbol( - ident.span, - &ident.name, - SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable, - SymbolFlags::BlockScopedVariableExcludes, - ); - ident.symbol_id.set(Some(symbol_id)); - }); - } + }); } } } diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index c9873149b..50a2e1841 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -1732,8 +1732,9 @@ impl<'a> SemanticBuilder<'a> { AstKind::FormalParameter(param) => { param.bind(self); } - AstKind::CatchClause(clause) => { - clause.bind(self); + AstKind::CatchParameter(param) => { + self.current_node_flags |= NodeFlags::Parameter; + param.bind(self); } AstKind::TSModuleDeclaration(module_declaration) => { module_declaration.bind(self); @@ -1832,7 +1833,7 @@ impl<'a> SemanticBuilder<'a> { AstKind::ArrowFunctionExpression(_) => { self.function_stack.pop(); } - AstKind::FormalParameters(_) => { + AstKind::FormalParameters(_) | AstKind::CatchParameter(_) => { self.current_node_flags -= NodeFlags::Parameter; } AstKind::TSModuleBlock(_) => { diff --git a/crates/oxc_semantic/tests/scopes.rs b/crates/oxc_semantic/tests/scopes.rs index d77f6aa6e..116bcd657 100644 --- a/crates/oxc_semantic/tests/scopes.rs +++ b/crates/oxc_semantic/tests/scopes.rs @@ -121,3 +121,19 @@ fn test_function_parameters() { .has_number_of_references(1) .test(); } + +#[test] +fn test_catch_clause_parameters() { + SemanticTester::js( + " + const a = 0; + try { + } catch ({ [a]: b }) { + const a = 1; + } + ", + ) + .has_root_symbol("a") + .has_number_of_references(1) + .test(); +}