mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:57:35 +00:00
LibJS/Bytecode: Support class field initializers
Fixes 513 test262 tests. :^)
This commit is contained in:
parent
82828ad936
commit
d89e0b36d4
3 changed files with 49 additions and 36 deletions
|
@ -1748,46 +1748,30 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use this class to mimic Initializer : = AssignmentExpression of
|
Completion ClassFieldInitializerStatement::execute(Interpreter& interpreter) const
|
||||||
// 10.2.1.3 Runtime Semantics: EvaluateBody, https://tc39.es/ecma262/#sec-runtime-semantics-evaluatebody
|
{
|
||||||
class ClassFieldInitializerStatement : public Statement {
|
// 1. Assert: argumentsList is empty.
|
||||||
public:
|
VERIFY(interpreter.vm().argument_count() == 0);
|
||||||
ClassFieldInitializerStatement(SourceRange source_range, NonnullRefPtr<Expression const> expression, DeprecatedFlyString field_name)
|
|
||||||
: Statement(source_range)
|
|
||||||
, m_expression(move(expression))
|
|
||||||
, m_class_field_identifier_name(move(field_name))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Completion execute(Interpreter& interpreter) const override
|
// 2. Assert: functionObject.[[ClassFieldInitializerName]] is not empty.
|
||||||
{
|
VERIFY(!m_class_field_identifier_name.is_empty());
|
||||||
// 1. Assert: argumentsList is empty.
|
|
||||||
VERIFY(interpreter.vm().argument_count() == 0);
|
|
||||||
|
|
||||||
// 2. Assert: functionObject.[[ClassFieldInitializerName]] is not empty.
|
// 3. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then
|
||||||
VERIFY(!m_class_field_identifier_name.is_empty());
|
// a. Let value be ? NamedEvaluation of Initializer with argument functionObject.[[ClassFieldInitializerName]].
|
||||||
|
// 4. Else,
|
||||||
|
// a. Let rhs be the result of evaluating AssignmentExpression.
|
||||||
|
// b. Let value be ? GetValue(rhs).
|
||||||
|
auto value = TRY(interpreter.vm().named_evaluation_if_anonymous_function(m_expression, m_class_field_identifier_name));
|
||||||
|
|
||||||
// 3. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then
|
// 5. Return Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
|
||||||
// a. Let value be ? NamedEvaluation of Initializer with argument functionObject.[[ClassFieldInitializerName]].
|
return { Completion::Type::Return, value, {} };
|
||||||
// 4. Else,
|
}
|
||||||
// a. Let rhs be the result of evaluating AssignmentExpression.
|
|
||||||
// b. Let value be ? GetValue(rhs).
|
|
||||||
auto value = TRY(interpreter.vm().named_evaluation_if_anonymous_function(m_expression, m_class_field_identifier_name));
|
|
||||||
|
|
||||||
// 5. Return Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
|
void ClassFieldInitializerStatement::dump(int) const
|
||||||
return { Completion::Type::Return, value, {} };
|
{
|
||||||
}
|
// This should not be dumped as it is never part of an actual AST.
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
void dump(int) const override
|
}
|
||||||
{
|
|
||||||
// This should not be dumped as it is never part of an actual AST.
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
NonnullRefPtr<Expression const> m_expression;
|
|
||||||
DeprecatedFlyString m_class_field_identifier_name; // [[ClassFieldIdentifierName]]
|
|
||||||
};
|
|
||||||
|
|
||||||
// 15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classfielddefinitionevaluation
|
// 15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classfielddefinitionevaluation
|
||||||
ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation(Interpreter& interpreter, Object& target) const
|
ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation(Interpreter& interpreter, Object& target) const
|
||||||
|
|
|
@ -1455,6 +1455,26 @@ private:
|
||||||
NonnullRefPtr<ClassExpression const> m_class_expression;
|
NonnullRefPtr<ClassExpression const> m_class_expression;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We use this class to mimic Initializer : = AssignmentExpression of
|
||||||
|
// 10.2.1.3 Runtime Semantics: EvaluateBody, https://tc39.es/ecma262/#sec-runtime-semantics-evaluatebody
|
||||||
|
class ClassFieldInitializerStatement final : public Statement {
|
||||||
|
public:
|
||||||
|
ClassFieldInitializerStatement(SourceRange source_range, NonnullRefPtr<Expression const> expression, DeprecatedFlyString field_name)
|
||||||
|
: Statement(move(source_range))
|
||||||
|
, m_expression(move(expression))
|
||||||
|
, m_class_field_identifier_name(move(field_name))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Completion execute(Interpreter& interpreter) const override;
|
||||||
|
virtual void dump(int) const override;
|
||||||
|
virtual Bytecode::CodeGenerationErrorOr<void> generate_bytecode(Bytecode::Generator&) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NonnullRefPtr<Expression const> m_expression;
|
||||||
|
DeprecatedFlyString m_class_field_identifier_name; // [[ClassFieldIdentifierName]]
|
||||||
|
};
|
||||||
|
|
||||||
class SpreadExpression final : public Expression {
|
class SpreadExpression final : public Expression {
|
||||||
public:
|
public:
|
||||||
explicit SpreadExpression(SourceRange source_range, NonnullRefPtr<Expression const> target)
|
explicit SpreadExpression(SourceRange source_range, NonnullRefPtr<Expression const> target)
|
||||||
|
|
|
@ -2593,4 +2593,13 @@ Bytecode::CodeGenerationErrorOr<void> MetaProperty::generate_bytecode(Bytecode::
|
||||||
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bytecode::CodeGenerationErrorOr<void> ClassFieldInitializerStatement::generate_bytecode(Bytecode::Generator& generator) const
|
||||||
|
{
|
||||||
|
TRY(m_expression->generate_bytecode(generator));
|
||||||
|
generator.perform_needed_unwinds<Bytecode::Op::Return>();
|
||||||
|
generator.emit<Bytecode::Op::Return>();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue