fix(semantic): correctly resolve identifiers inside catch parameter initializers (#3050)

closes #2499
This commit is contained in:
Boshen 2024-04-21 23:53:38 +08:00 committed by GitHub
parent 92d709bf21
commit 84c43c8282
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 25 deletions

View file

@ -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) { fn bind(&self, builder: &mut SemanticBuilder) {
let current_scope_id = builder.current_scope_id; let current_scope_id = builder.current_scope_id;
if let Some(param) = &self.param { // https://tc39.es/ecma262/#sec-variablestatements-in-catch-blocks
// 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
// 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
// unless CatchParameter is CatchParameter : BindingIdentifier if let BindingPatternKind::BindingIdentifier(ident) = &self.pattern.kind {
if let BindingPatternKind::BindingIdentifier(ident) = &param.pattern.kind { let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable;
let includes = SymbolFlags::FunctionScopedVariable | SymbolFlags::CatchVariable; let symbol_id =
let symbol_id = builder.declare_shadow_symbol( builder.declare_shadow_symbol(&ident.name, ident.span, current_scope_id, includes);
&ident.name, ident.symbol_id.set(Some(symbol_id));
} else {
self.pattern.bound_names(&mut |ident| {
let symbol_id = builder.declare_symbol(
ident.span, ident.span,
current_scope_id, &ident.name,
includes, SymbolFlags::BlockScopedVariable | SymbolFlags::CatchVariable,
SymbolFlags::BlockScopedVariableExcludes,
); );
ident.symbol_id.set(Some(symbol_id)); 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));
});
}
} }
} }
} }

View file

@ -1732,8 +1732,9 @@ impl<'a> SemanticBuilder<'a> {
AstKind::FormalParameter(param) => { AstKind::FormalParameter(param) => {
param.bind(self); param.bind(self);
} }
AstKind::CatchClause(clause) => { AstKind::CatchParameter(param) => {
clause.bind(self); self.current_node_flags |= NodeFlags::Parameter;
param.bind(self);
} }
AstKind::TSModuleDeclaration(module_declaration) => { AstKind::TSModuleDeclaration(module_declaration) => {
module_declaration.bind(self); module_declaration.bind(self);
@ -1832,7 +1833,7 @@ impl<'a> SemanticBuilder<'a> {
AstKind::ArrowFunctionExpression(_) => { AstKind::ArrowFunctionExpression(_) => {
self.function_stack.pop(); self.function_stack.pop();
} }
AstKind::FormalParameters(_) => { AstKind::FormalParameters(_) | AstKind::CatchParameter(_) => {
self.current_node_flags -= NodeFlags::Parameter; self.current_node_flags -= NodeFlags::Parameter;
} }
AstKind::TSModuleBlock(_) => { AstKind::TSModuleBlock(_) => {

View file

@ -121,3 +121,19 @@ fn test_function_parameters() {
.has_number_of_references(1) .has_number_of_references(1)
.test(); .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();
}