|
@@ -15,6 +15,7 @@
|
|
#include <LibJS/Runtime/DeclarativeEnvironment.h>
|
|
#include <LibJS/Runtime/DeclarativeEnvironment.h>
|
|
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
|
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
|
|
#include <LibJS/Runtime/Environment.h>
|
|
#include <LibJS/Runtime/Environment.h>
|
|
|
|
+#include <LibJS/Runtime/FunctionEnvironment.h>
|
|
#include <LibJS/Runtime/GlobalEnvironment.h>
|
|
#include <LibJS/Runtime/GlobalEnvironment.h>
|
|
#include <LibJS/Runtime/GlobalObject.h>
|
|
#include <LibJS/Runtime/GlobalObject.h>
|
|
#include <LibJS/Runtime/Iterator.h>
|
|
#include <LibJS/Runtime/Iterator.h>
|
|
@@ -525,6 +526,60 @@ ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) c
|
|
return {};
|
|
return {};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
|
|
|
|
+ThrowCompletionOr<void> SuperCall::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<Value> arg_list { vm.heap() };
|
|
|
|
+ if (m_is_synthetic) {
|
|
|
|
+ auto const& value = interpreter.accumulator();
|
|
|
|
+ VERIFY(value.is_object() && is<Array>(value.as_object()));
|
|
|
|
+ auto const& array_value = static_cast<Array const&>(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 {
|
|
|
|
+ for (size_t i = 0; i < m_argument_count; ++i)
|
|
|
|
+ arg_list.append(interpreter.reg(m_arguments[i]));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 5. If IsConstructor(func) is false, throw a TypeError exception.
|
|
|
|
+ if (!Value(func).is_constructor())
|
|
|
|
+ return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, "Super constructor");
|
|
|
|
+
|
|
|
|
+ // 6. Let result be ? Construct(func, argList, newTarget).
|
|
|
|
+ auto* result = TRY(construct(vm, static_cast<FunctionObject&>(*func), move(arg_list), &new_target.as_function()));
|
|
|
|
+
|
|
|
|
+ // 7. Let thisER be GetThisEnvironment().
|
|
|
|
+ auto& this_environment = verify_cast<FunctionEnvironment>(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(vm.initialize_instance_elements(*result, f));
|
|
|
|
+
|
|
|
|
+ // 12. Return result.
|
|
|
|
+ interpreter.accumulator() = result;
|
|
|
|
+ return {};
|
|
|
|
+}
|
|
|
|
+
|
|
ThrowCompletionOr<void> NewFunction::execute_impl(Bytecode::Interpreter& interpreter) const
|
|
ThrowCompletionOr<void> NewFunction::execute_impl(Bytecode::Interpreter& interpreter) const
|
|
{
|
|
{
|
|
auto& vm = interpreter.vm();
|
|
auto& vm = interpreter.vm();
|
|
@@ -1000,6 +1055,20 @@ String Call::to_string_impl(Bytecode::Executable const&) const
|
|
return builder.to_string();
|
|
return builder.to_string();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+String SuperCall::to_string_impl(Bytecode::Executable const&) const
|
|
|
|
+{
|
|
|
|
+ StringBuilder builder;
|
|
|
|
+ builder.append("SuperCall"sv);
|
|
|
|
+ if (m_is_synthetic) {
|
|
|
|
+ builder.append(" arguments:[...acc]"sv);
|
|
|
|
+ } else if (m_argument_count != 0) {
|
|
|
|
+ builder.append(" arguments:["sv);
|
|
|
|
+ builder.join(", "sv, Span<Register const>(m_arguments, m_argument_count));
|
|
|
|
+ builder.append(']');
|
|
|
|
+ }
|
|
|
|
+ return builder.to_string();
|
|
|
|
+}
|
|
|
|
+
|
|
String NewFunction::to_string_impl(Bytecode::Executable const&) const
|
|
String NewFunction::to_string_impl(Bytecode::Executable const&) const
|
|
{
|
|
{
|
|
return "NewFunction";
|
|
return "NewFunction";
|