LibJS: Use Identifier to represent CatchClause parameter names

By doing that we consistently use Identifier node for identifiers and
also enable mechanism that registers identifiers in a corresponding
ScopePusher for catch parameters, which is necessary for work in the
upcoming changes.
This commit is contained in:
Aliaksandr Kalenik 2025-04-21 19:49:38 +02:00 committed by Alexander Kalenik
commit 0f14c70252
Notes: github-actions[bot] 2025-04-22 19:58:36 +00:00
4 changed files with 43 additions and 30 deletions

View file

@ -1378,19 +1378,17 @@ void TryStatement::dump(int indent) const
void CatchClause::dump(int indent) const void CatchClause::dump(int indent) const
{ {
print_indent(indent); print_indent(indent);
m_parameter.visit(
[&](FlyString const& parameter) {
if (parameter.is_empty())
outln("CatchClause"); outln("CatchClause");
else m_parameter.visit(
outln("CatchClause ({})", parameter); [&](NonnullRefPtr<Identifier const> const& parameter) {
parameter->dump(indent + 1);
}, },
[&](NonnullRefPtr<BindingPattern const> const& pattern) { [&](NonnullRefPtr<BindingPattern const> const& pattern) {
outln("CatchClause");
print_indent(indent); print_indent(indent);
outln("(Parameter)"); outln("(Parameter)");
pattern->dump(indent + 2); pattern->dump(indent + 2);
}); },
[&](Empty) {});
body().dump(indent + 1); body().dump(indent + 1);
} }

View file

@ -2075,7 +2075,7 @@ private:
class CatchClause final : public ASTNode { class CatchClause final : public ASTNode {
public: public:
CatchClause(SourceRange source_range, FlyString parameter, NonnullRefPtr<BlockStatement const> body) CatchClause(SourceRange source_range, NonnullRefPtr<Identifier const> parameter, NonnullRefPtr<BlockStatement const> body)
: ASTNode(move(source_range)) : ASTNode(move(source_range))
, m_parameter(move(parameter)) , m_parameter(move(parameter))
, m_body(move(body)) , m_body(move(body))
@ -2089,13 +2089,20 @@ public:
{ {
} }
CatchClause(SourceRange source_range, NonnullRefPtr<BlockStatement const> body)
: ASTNode(move(source_range))
, m_parameter(Empty {})
, m_body(move(body))
{
}
auto& parameter() const { return m_parameter; } auto& parameter() const { return m_parameter; }
BlockStatement const& body() const { return m_body; } BlockStatement const& body() const { return m_body; }
virtual void dump(int indent) const override; virtual void dump(int indent) const override;
private: private:
Variant<FlyString, NonnullRefPtr<BindingPattern const>> m_parameter; Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>, Empty> m_parameter;
NonnullRefPtr<BlockStatement const> m_body; NonnullRefPtr<BlockStatement const> m_body;
}; };

View file

@ -2660,14 +2660,12 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TryStatement::generate_
bool did_create_variable_scope_for_catch_clause = false; bool did_create_variable_scope_for_catch_clause = false;
TRY(m_handler->parameter().visit( TRY(m_handler->parameter().visit(
[&](FlyString const& parameter) -> Bytecode::CodeGenerationErrorOr<void> { [&](NonnullRefPtr<Identifier const> const& parameter) -> Bytecode::CodeGenerationErrorOr<void> {
if (!parameter.is_empty()) {
generator.begin_variable_scope(); generator.begin_variable_scope();
did_create_variable_scope_for_catch_clause = true; did_create_variable_scope_for_catch_clause = true;
auto parameter_identifier = generator.intern_identifier(parameter); auto parameter_identifier = generator.intern_identifier(parameter->string());
generator.emit<Bytecode::Op::CreateVariable>(parameter_identifier, Bytecode::Op::EnvironmentMode::Lexical, false); generator.emit<Bytecode::Op::CreateVariable>(parameter_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
generator.emit<Bytecode::Op::InitializeLexicalBinding>(parameter_identifier, caught_value); generator.emit<Bytecode::Op::InitializeLexicalBinding>(parameter_identifier, caught_value);
}
return {}; return {};
}, },
[&](NonnullRefPtr<BindingPattern const> const& binding_pattern) -> Bytecode::CodeGenerationErrorOr<void> { [&](NonnullRefPtr<BindingPattern const> const& binding_pattern) -> Bytecode::CodeGenerationErrorOr<void> {
@ -2675,6 +2673,9 @@ Bytecode::CodeGenerationErrorOr<Optional<ScopedOperand>> TryStatement::generate_
did_create_variable_scope_for_catch_clause = true; did_create_variable_scope_for_catch_clause = true;
TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::BindingInitializationMode::Initialize, caught_value, true)); TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::BindingInitializationMode::Initialize, caught_value, true));
return {}; return {};
},
[](Empty) -> Bytecode::CodeGenerationErrorOr<void> {
return {};
})); }));
auto handler_result = TRY(m_handler->body().generate_bytecode(generator)); auto handler_result = TRY(m_handler->body().generate_bytecode(generator));

View file

@ -105,7 +105,7 @@ public:
return scope_pusher; return scope_pusher;
} }
static ScopePusher catch_scope(Parser& parser, RefPtr<BindingPattern const> const& pattern, FlyString const& parameter) static ScopePusher catch_scope(Parser& parser, RefPtr<BindingPattern const> const& pattern, RefPtr<Identifier const> const& parameter)
{ {
ScopePusher scope_pusher(parser, nullptr, ScopeLevel::NotTopLevel, ScopeType::Catch); ScopePusher scope_pusher(parser, nullptr, ScopeLevel::NotTopLevel, ScopeType::Catch);
if (pattern) { if (pattern) {
@ -114,9 +114,9 @@ public:
scope_pusher.m_forbidden_var_names.set(identifier.string()); scope_pusher.m_forbidden_var_names.set(identifier.string());
scope_pusher.m_bound_names.set(identifier.string()); scope_pusher.m_bound_names.set(identifier.string());
})); }));
} else if (!parameter.is_empty()) { } else if (parameter) {
scope_pusher.m_var_names.set(parameter); scope_pusher.m_var_names.set(parameter->string());
scope_pusher.m_bound_names.set(parameter); scope_pusher.m_bound_names.set(parameter->string());
} }
return scope_pusher; return scope_pusher;
@ -3777,7 +3777,7 @@ NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
auto rule_start = push_start(); auto rule_start = push_start();
consume(TokenType::Catch); consume(TokenType::Catch);
FlyString parameter; RefPtr<Identifier const> parameter;
RefPtr<BindingPattern const> pattern_parameter; RefPtr<BindingPattern const> pattern_parameter;
auto should_expect_parameter = false; auto should_expect_parameter = false;
if (match(TokenType::ParenOpen)) { if (match(TokenType::ParenOpen)) {
@ -3787,14 +3787,15 @@ NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
if (match_identifier_name() if (match_identifier_name()
&& (!match(TokenType::Yield) || !m_state.in_generator_function_context) && (!match(TokenType::Yield) || !m_state.in_generator_function_context)
&& (!match(TokenType::Async) || !m_state.await_expression_is_valid) && (!match(TokenType::Async) || !m_state.await_expression_is_valid)
&& (!match(TokenType::Await) || !m_state.in_class_static_init_block)) && (!match(TokenType::Await) || !m_state.in_class_static_init_block)) {
parameter = consume().fly_string_value(); parameter = parse_identifier();
else } else {
pattern_parameter = parse_binding_pattern(AllowDuplicates::No, AllowMemberExpressions::No); pattern_parameter = parse_binding_pattern(AllowDuplicates::No, AllowMemberExpressions::No);
}
consume(TokenType::ParenClose); consume(TokenType::ParenClose);
} }
if (should_expect_parameter && parameter.is_empty() && !pattern_parameter) if (should_expect_parameter && !parameter && !pattern_parameter)
expected("an identifier or a binding pattern"); expected("an identifier or a binding pattern");
HashTable<FlyString> bound_names; HashTable<FlyString> bound_names;
@ -3808,9 +3809,9 @@ NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
})); }));
} }
if (!parameter.is_empty()) { if (parameter) {
check_identifier_name_for_assignment_validity(parameter); check_identifier_name_for_assignment_validity(parameter->string());
bound_names.set(parameter); bound_names.set(parameter->string());
} }
ScopePusher catch_scope = ScopePusher::catch_scope(*this, pattern_parameter, parameter); ScopePusher catch_scope = ScopePusher::catch_scope(*this, pattern_parameter, parameter);
@ -3829,9 +3830,15 @@ NonnullRefPtr<CatchClause const> Parser::parse_catch_clause()
move(body)); move(body));
} }
if (parameter) {
return create_ast_node<CatchClause>(
{ m_source_code, rule_start.position(), position() },
parameter.release_nonnull(),
move(body));
}
return create_ast_node<CatchClause>( return create_ast_node<CatchClause>(
{ m_source_code, rule_start.position(), position() }, { m_source_code, rule_start.position(), position() },
move(parameter),
move(body)); move(body));
} }