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) {
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) = &param.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));
});
}
});
}
}
}

View file

@ -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(_) => {

View file

@ -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();
}