mirror of
https://github.com/RGBCube/serenity
synced 2025-07-23 05:57:41 +00:00
LibJS: Use Identifier to represent name of ClassExpression
By using Identifier class to represent the name of a class expression, it becomes possible to consistently store information within the identifier object, indicating whether the name refers to a local variable or not.
This commit is contained in:
parent
4a83fb1b12
commit
c734f2b5e6
4 changed files with 20 additions and 14 deletions
|
@ -1852,7 +1852,7 @@ Completion ClassExpression::execute(Interpreter& interpreter) const
|
||||||
|
|
||||||
// 1. Let className be StringValue of BindingIdentifier.
|
// 1. Let className be StringValue of BindingIdentifier.
|
||||||
// 2. Let value be ? ClassDefinitionEvaluation of ClassTail with arguments className and className.
|
// 2. Let value be ? ClassDefinitionEvaluation of ClassTail with arguments className and className.
|
||||||
auto* value = TRY(class_definition_evaluation(interpreter.vm(), m_name, m_name.is_null() ? "" : m_name));
|
auto* value = TRY(class_definition_evaluation(interpreter.vm(), name(), name()));
|
||||||
|
|
||||||
// 3. Set value.[[SourceText]] to the source text matched by ClassExpression.
|
// 3. Set value.[[SourceText]] to the source text matched by ClassExpression.
|
||||||
value->set_source_text(m_source_text);
|
value->set_source_text(m_source_text);
|
||||||
|
@ -2311,7 +2311,7 @@ ThrowCompletionOr<void> ClassDeclaration::for_each_bound_name(ThrowCompletionOrV
|
||||||
void ClassExpression::dump(int indent) const
|
void ClassExpression::dump(int indent) const
|
||||||
{
|
{
|
||||||
print_indent(indent);
|
print_indent(indent);
|
||||||
outln("ClassExpression: \"{}\"", m_name);
|
outln("ClassExpression: \"{}\"", name());
|
||||||
|
|
||||||
print_indent(indent);
|
print_indent(indent);
|
||||||
outln("(Constructor)");
|
outln("(Constructor)");
|
||||||
|
|
|
@ -1405,7 +1405,7 @@ public:
|
||||||
|
|
||||||
class ClassExpression final : public Expression {
|
class ClassExpression final : public Expression {
|
||||||
public:
|
public:
|
||||||
ClassExpression(SourceRange source_range, DeprecatedString name, DeprecatedString source_text, RefPtr<FunctionExpression const> constructor, RefPtr<Expression const> super_class, Vector<NonnullRefPtr<ClassElement const>> elements)
|
ClassExpression(SourceRange source_range, RefPtr<Identifier const> name, DeprecatedString source_text, RefPtr<FunctionExpression const> constructor, RefPtr<Expression const> super_class, Vector<NonnullRefPtr<ClassElement const>> elements)
|
||||||
: Expression(source_range)
|
: Expression(source_range)
|
||||||
, m_name(move(name))
|
, m_name(move(name))
|
||||||
, m_source_text(move(source_text))
|
, m_source_text(move(source_text))
|
||||||
|
@ -1415,7 +1415,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView name() const { return m_name; }
|
StringView name() const { return m_name ? m_name->string().view() : ""sv; }
|
||||||
|
|
||||||
DeprecatedString const& source_text() const { return m_source_text; }
|
DeprecatedString const& source_text() const { return m_source_text; }
|
||||||
RefPtr<FunctionExpression const> constructor() const { return m_constructor; }
|
RefPtr<FunctionExpression const> constructor() const { return m_constructor; }
|
||||||
|
|
||||||
|
@ -1424,7 +1425,7 @@ public:
|
||||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&) const override;
|
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&) const override;
|
||||||
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name) const;
|
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode_with_lhs_name(Bytecode::Generator&, Optional<Bytecode::IdentifierTableIndex> lhs_name) const;
|
||||||
|
|
||||||
bool has_name() const { return !m_name.is_empty(); }
|
bool has_name() const { return m_name; }
|
||||||
|
|
||||||
ThrowCompletionOr<ECMAScriptFunctionObject*> class_definition_evaluation(VM&, DeprecatedFlyString const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
ThrowCompletionOr<ECMAScriptFunctionObject*> class_definition_evaluation(VM&, DeprecatedFlyString const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
||||||
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, DeprecatedFlyString const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
ThrowCompletionOr<ECMAScriptFunctionObject*> create_class_constructor(VM&, Environment* class_environment, Environment* environment, Value super_class, DeprecatedFlyString const& binding_name = {}, DeprecatedFlyString const& class_name = {}) const;
|
||||||
|
@ -1432,7 +1433,7 @@ public:
|
||||||
private:
|
private:
|
||||||
virtual bool is_class_expression() const override { return true; }
|
virtual bool is_class_expression() const override { return true; }
|
||||||
|
|
||||||
DeprecatedString m_name;
|
RefPtr<Identifier const> m_name;
|
||||||
DeprecatedString m_source_text;
|
DeprecatedString m_source_text;
|
||||||
RefPtr<FunctionExpression const> m_constructor;
|
RefPtr<FunctionExpression const> m_constructor;
|
||||||
RefPtr<Expression const> m_super_class;
|
RefPtr<Expression const> m_super_class;
|
||||||
|
|
|
@ -2323,7 +2323,7 @@ Bytecode::CodeGenerationErrorOr<void> ClassExpression::generate_bytecode_with_lh
|
||||||
|
|
||||||
if (has_name() || !lhs_name.has_value()) {
|
if (has_name() || !lhs_name.has_value()) {
|
||||||
// NOTE: Step 3.a is not a part of NewClass instruction because it is assumed to be done before super class expression evaluation
|
// NOTE: Step 3.a is not a part of NewClass instruction because it is assumed to be done before super class expression evaluation
|
||||||
auto interned_index = generator.intern_identifier(m_name);
|
auto interned_index = generator.intern_identifier(name());
|
||||||
generator.emit<Bytecode::Op::CreateVariable>(interned_index, Bytecode::Op::EnvironmentMode::Lexical, true);
|
generator.emit<Bytecode::Op::CreateVariable>(interned_index, Bytecode::Op::EnvironmentMode::Lexical, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1071,12 +1071,17 @@ NonnullRefPtr<ClassExpression const> Parser::parse_class_expression(bool expect_
|
||||||
RefPtr<FunctionExpression const> constructor;
|
RefPtr<FunctionExpression const> constructor;
|
||||||
HashTable<DeprecatedFlyString> found_private_names;
|
HashTable<DeprecatedFlyString> found_private_names;
|
||||||
|
|
||||||
DeprecatedFlyString class_name = expect_class_name || match_identifier() || match(TokenType::Yield) || match(TokenType::Await)
|
RefPtr<Identifier const> class_name { nullptr };
|
||||||
? consume_identifier_reference().DeprecatedFlyString_value()
|
if (expect_class_name || match_identifier() || match(TokenType::Yield) || match(TokenType::Await)) {
|
||||||
: "";
|
class_name = create_ast_node<Identifier const>(
|
||||||
|
{ m_source_code, rule_start.position(), position() },
|
||||||
|
consume_identifier_reference().DeprecatedFlyString_value()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
check_identifier_name_for_assignment_validity(class_name, true);
|
if (class_name)
|
||||||
if (m_state.in_class_static_init_block && class_name == "await"sv)
|
check_identifier_name_for_assignment_validity(class_name->string(), true);
|
||||||
|
if (m_state.in_class_static_init_block && class_name && class_name->string() == "await"sv)
|
||||||
syntax_error("Identifier must not be a reserved word in modules ('await')");
|
syntax_error("Identifier must not be a reserved word in modules ('await')");
|
||||||
|
|
||||||
if (match(TokenType::Extends)) {
|
if (match(TokenType::Extends)) {
|
||||||
|
@ -1365,12 +1370,12 @@ NonnullRefPtr<ClassExpression const> Parser::parse_class_expression(bool expect_
|
||||||
constructor_body->append(create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, move(super_call)));
|
constructor_body->append(create_ast_node<ReturnStatement>({ m_source_code, rule_start.position(), position() }, move(super_call)));
|
||||||
|
|
||||||
constructor = create_ast_node<FunctionExpression>(
|
constructor = create_ast_node<FunctionExpression>(
|
||||||
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
{ m_source_code, rule_start.position(), position() }, class_name ? class_name->string() : "", "",
|
||||||
move(constructor_body), Vector { FunctionParameter { move(argument_name), nullptr, true } }, 0, FunctionKind::Normal,
|
move(constructor_body), Vector { FunctionParameter { move(argument_name), nullptr, true } }, 0, FunctionKind::Normal,
|
||||||
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
|
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
|
||||||
} else {
|
} else {
|
||||||
constructor = create_ast_node<FunctionExpression>(
|
constructor = create_ast_node<FunctionExpression>(
|
||||||
{ m_source_code, rule_start.position(), position() }, class_name, "",
|
{ m_source_code, rule_start.position(), position() }, class_name ? class_name->string() : "", "",
|
||||||
move(constructor_body), Vector<FunctionParameter> {}, 0, FunctionKind::Normal,
|
move(constructor_body), Vector<FunctionParameter> {}, 0, FunctionKind::Normal,
|
||||||
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
|
/* is_strict_mode */ true, /* might_need_arguments_object */ false, /* contains_direct_call_to_eval */ false);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue