diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 1f5fe5054b..e84ffb8449 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -1748,46 +1748,30 @@ ThrowCompletionOr ClassMethod::class_element_evaluatio } } -// 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 : public Statement { -public: - ClassFieldInitializerStatement(SourceRange source_range, NonnullRefPtr expression, DeprecatedFlyString field_name) - : Statement(source_range) - , m_expression(move(expression)) - , m_class_field_identifier_name(move(field_name)) - { - } +Completion ClassFieldInitializerStatement::execute(Interpreter& interpreter) const +{ + // 1. Assert: argumentsList is empty. + VERIFY(interpreter.vm().argument_count() == 0); - Completion execute(Interpreter& interpreter) const override - { - // 1. Assert: argumentsList is empty. - VERIFY(interpreter.vm().argument_count() == 0); + // 2. Assert: functionObject.[[ClassFieldInitializerName]] is not empty. + VERIFY(!m_class_field_identifier_name.is_empty()); - // 2. Assert: functionObject.[[ClassFieldInitializerName]] is not empty. - VERIFY(!m_class_field_identifier_name.is_empty()); + // 3. If IsAnonymousFunctionDefinition(AssignmentExpression) is true, then + // 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 - // 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)); + // 5. Return Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }. + return { Completion::Type::Return, value, {} }; +} - // 5. Return Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }. - return { Completion::Type::Return, value, {} }; - } - - void dump(int) const override - { - // This should not be dumped as it is never part of an actual AST. - VERIFY_NOT_REACHED(); - } - -private: - NonnullRefPtr m_expression; - DeprecatedFlyString m_class_field_identifier_name; // [[ClassFieldIdentifierName]] -}; +void ClassFieldInitializerStatement::dump(int) const +{ + // This should not be dumped as it is never part of an actual AST. + VERIFY_NOT_REACHED(); +} // 15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classfielddefinitionevaluation ThrowCompletionOr ClassField::class_element_evaluation(Interpreter& interpreter, Object& target) const diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index ad520d7576..c4269f8772 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -1455,6 +1455,26 @@ private: NonnullRefPtr 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, 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 generate_bytecode(Bytecode::Generator&) const override; + +private: + NonnullRefPtr m_expression; + DeprecatedFlyString m_class_field_identifier_name; // [[ClassFieldIdentifierName]] +}; + class SpreadExpression final : public Expression { public: explicit SpreadExpression(SourceRange source_range, NonnullRefPtr target) diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 8b90d2e67a..a1b30c1401 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -2593,4 +2593,13 @@ Bytecode::CodeGenerationErrorOr MetaProperty::generate_bytecode(Bytecode:: VERIFY_NOT_REACHED(); } + +Bytecode::CodeGenerationErrorOr ClassFieldInitializerStatement::generate_bytecode(Bytecode::Generator& generator) const +{ + TRY(m_expression->generate_bytecode(generator)); + generator.perform_needed_unwinds(); + generator.emit(); + return {}; +} + }