From 1eee11057562a07ac30a72cf82018f6732075b77 Mon Sep 17 00:00:00 2001 From: Simon Wanner Date: Sun, 29 Oct 2023 15:25:28 +0100 Subject: [PATCH] LibJS: Move SuperCallWithArgumentArray impl to CommonImplementations --- .../LibJS/Bytecode/CommonImplementations.cpp | 52 +++++++++++++++++++ .../LibJS/Bytecode/CommonImplementations.h | 1 + .../Libraries/LibJS/Bytecode/Interpreter.cpp | 48 +---------------- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp index 2f3c69e0fe..d931bfe3df 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -471,4 +472,55 @@ ThrowCompletionOr new_class(VM& vm, ClassExpression c return TRY(class_expression.create_class_constructor(vm, class_environment, vm.lexical_environment(), super_class, binding_name, class_name)); } +// 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation +ThrowCompletionOr> super_call_with_argument_array(VM& vm, Value argument_array, bool is_synthetic) +{ + auto& interpreter = vm.bytecode_interpreter(); + // 1. Let newTarget be GetNewTarget(). + auto new_target = vm.get_new_target(); + + // 2. Assert: Type(newTarget) is Object. + VERIFY(new_target.is_object()); + + // 3. Let func be GetSuperConstructor(). + auto* func = get_super_constructor(vm); + + // 4. Let argList be ? ArgumentListEvaluation of Arguments. + MarkedVector arg_list { vm.heap() }; + if (is_synthetic) { + VERIFY(argument_array.is_object() && is(argument_array.as_object())); + auto const& array_value = static_cast(argument_array.as_object()); + auto length = MUST(length_of_array_like(vm, array_value)); + for (size_t i = 0; i < length; ++i) + arg_list.append(array_value.get_without_side_effects(PropertyKey { i })); + } else { + arg_list = argument_list_evaluation(interpreter); + } + + // 5. If IsConstructor(func) is false, throw a TypeError exception. + if (!Value(func).is_constructor()) + return vm.throw_completion(ErrorType::NotAConstructor, "Super constructor"); + + // 6. Let result be ? Construct(func, argList, newTarget). + auto result = TRY(construct(vm, static_cast(*func), move(arg_list), &new_target.as_function())); + + // 7. Let thisER be GetThisEnvironment(). + auto& this_environment = verify_cast(*get_this_environment(vm)); + + // 8. Perform ? thisER.BindThisValue(result). + TRY(this_environment.bind_this_value(vm, result)); + + // 9. Let F be thisER.[[FunctionObject]]. + auto& f = this_environment.function_object(); + + // 10. Assert: F is an ECMAScript function object. + // NOTE: This is implied by the strong C++ type. + + // 11. Perform ? InitializeInstanceElements(result, F). + TRY(result->initialize_instance_elements(f)); + + // 12. Return result. + return result; +} + } diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index 723216dbf1..3f1d6e54d3 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -34,5 +34,6 @@ Value new_regexp(VM&, ParsedRegex const&, DeprecatedString const& pattern, Depre MarkedVector argument_list_evaluation(Bytecode::Interpreter&); ThrowCompletionOr create_variable(VM&, DeprecatedFlyString const& name, Op::EnvironmentMode, bool is_global, bool is_immutable, bool is_strict); ThrowCompletionOr new_class(VM&, ClassExpression const&, Optional const& lhs_name); +ThrowCompletionOr> super_call_with_argument_array(VM&, Value argument_array, bool is_synthetic); } diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index f6e8ba0c96..7ede7e46af 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1029,53 +1029,7 @@ ThrowCompletionOr CallWithArgumentArray::execute_impl(Bytecode::Interprete // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation ThrowCompletionOr SuperCallWithArgumentArray::execute_impl(Bytecode::Interpreter& interpreter) const { - auto& vm = interpreter.vm(); - // 1. Let newTarget be GetNewTarget(). - auto new_target = vm.get_new_target(); - - // 2. Assert: Type(newTarget) is Object. - VERIFY(new_target.is_object()); - - // 3. Let func be GetSuperConstructor(). - auto* func = get_super_constructor(vm); - - // 4. Let argList be ? ArgumentListEvaluation of Arguments. - MarkedVector arg_list { vm.heap() }; - if (m_is_synthetic) { - auto const& value = interpreter.accumulator(); - VERIFY(value.is_object() && is(value.as_object())); - auto const& array_value = static_cast(value.as_object()); - auto length = MUST(length_of_array_like(vm, array_value)); - for (size_t i = 0; i < length; ++i) - arg_list.append(array_value.get_without_side_effects(PropertyKey { i })); - } else { - arg_list = argument_list_evaluation(interpreter); - } - - // 5. If IsConstructor(func) is false, throw a TypeError exception. - if (!Value(func).is_constructor()) - return vm.throw_completion(ErrorType::NotAConstructor, "Super constructor"); - - // 6. Let result be ? Construct(func, argList, newTarget). - auto result = TRY(construct(vm, static_cast(*func), move(arg_list), &new_target.as_function())); - - // 7. Let thisER be GetThisEnvironment(). - auto& this_environment = verify_cast(*get_this_environment(vm)); - - // 8. Perform ? thisER.BindThisValue(result). - TRY(this_environment.bind_this_value(vm, result)); - - // 9. Let F be thisER.[[FunctionObject]]. - auto& f = this_environment.function_object(); - - // 10. Assert: F is an ECMAScript function object. - // NOTE: This is implied by the strong C++ type. - - // 11. Perform ? InitializeInstanceElements(result, F). - TRY(result->initialize_instance_elements(f)); - - // 12. Return result. - interpreter.accumulator() = result; + interpreter.accumulator() = TRY(super_call_with_argument_array(interpreter.vm(), interpreter.accumulator(), m_is_synthetic)); return {}; }