Преглед изворни кода

LibJS: Make Function::call() not require an Interpreter&

This makes a difference inside ScriptFunction::call(), which will now
instantiate a temporary Interpreter if one is not attached to the VM.
Andreas Kling пре 4 година
родитељ
комит
1ff9d33131
42 измењених фајлова са 167 додато и 142 уклоњено
  1. 8 22
      Libraries/LibJS/Interpreter.cpp
  2. 6 1
      Libraries/LibJS/Interpreter.h
  3. 9 9
      Libraries/LibJS/Runtime/ArrayConstructor.cpp
  4. 1 1
      Libraries/LibJS/Runtime/ArrayConstructor.h
  5. 7 7
      Libraries/LibJS/Runtime/BigIntConstructor.cpp
  6. 1 1
      Libraries/LibJS/Runtime/BigIntConstructor.h
  7. 2 2
      Libraries/LibJS/Runtime/BooleanConstructor.cpp
  8. 1 1
      Libraries/LibJS/Runtime/BooleanConstructor.h
  9. 2 2
      Libraries/LibJS/Runtime/BoundFunction.cpp
  10. 1 1
      Libraries/LibJS/Runtime/BoundFunction.h
  11. 3 3
      Libraries/LibJS/Runtime/DateConstructor.cpp
  12. 1 1
      Libraries/LibJS/Runtime/DateConstructor.h
  13. 4 4
      Libraries/LibJS/Runtime/ErrorConstructor.cpp
  14. 2 2
      Libraries/LibJS/Runtime/ErrorConstructor.h
  15. 1 1
      Libraries/LibJS/Runtime/Function.h
  16. 2 2
      Libraries/LibJS/Runtime/FunctionConstructor.cpp
  17. 1 1
      Libraries/LibJS/Runtime/FunctionConstructor.h
  18. 2 2
      Libraries/LibJS/Runtime/NativeFunction.cpp
  19. 1 1
      Libraries/LibJS/Runtime/NativeFunction.h
  20. 3 3
      Libraries/LibJS/Runtime/NumberConstructor.cpp
  21. 1 1
      Libraries/LibJS/Runtime/NumberConstructor.h
  22. 4 4
      Libraries/LibJS/Runtime/Object.cpp
  23. 3 3
      Libraries/LibJS/Runtime/ObjectConstructor.cpp
  24. 1 1
      Libraries/LibJS/Runtime/ObjectConstructor.h
  25. 2 2
      Libraries/LibJS/Runtime/ProxyConstructor.cpp
  26. 1 1
      Libraries/LibJS/Runtime/ProxyConstructor.h
  27. 10 10
      Libraries/LibJS/Runtime/ProxyObject.cpp
  28. 1 1
      Libraries/LibJS/Runtime/ProxyObject.h
  29. 2 2
      Libraries/LibJS/Runtime/RegExpConstructor.cpp
  30. 1 1
      Libraries/LibJS/Runtime/RegExpConstructor.h
  31. 19 9
      Libraries/LibJS/Runtime/ScriptFunction.cpp
  32. 1 1
      Libraries/LibJS/Runtime/ScriptFunction.h
  33. 7 7
      Libraries/LibJS/Runtime/StringConstructor.cpp
  34. 1 1
      Libraries/LibJS/Runtime/StringConstructor.h
  35. 4 4
      Libraries/LibJS/Runtime/SymbolConstructor.cpp
  36. 1 1
      Libraries/LibJS/Runtime/SymbolConstructor.h
  37. 21 1
      Libraries/LibJS/Runtime/VM.cpp
  38. 2 0
      Libraries/LibJS/Runtime/VM.h
  39. 22 20
      Libraries/LibJS/Runtime/Value.cpp
  40. 2 2
      Libraries/LibJS/Runtime/Value.h
  41. 2 2
      Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp
  42. 1 1
      Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.h

+ 8 - 22
Libraries/LibJS/Interpreter.cpp

@@ -44,6 +44,14 @@
 
 namespace JS {
 
+NonnullOwnPtr<Interpreter> Interpreter::create_with_existing_global_object(GlobalObject& global_object)
+{
+    DeferGC defer_gc(global_object.heap());
+    auto interpreter = adopt_own(*new Interpreter(global_object.vm()));
+    interpreter->m_global_object = make_handle(static_cast<Object*>(&global_object));
+    return interpreter;
+}
+
 Interpreter::Interpreter(VM& vm)
     : m_vm(vm)
     , m_console(*this)
@@ -84,28 +92,6 @@ const GlobalObject& Interpreter::global_object() const
     return static_cast<const GlobalObject&>(*m_global_object.cell());
 }
 
-Value Interpreter::call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments)
-{
-    ASSERT(!exception());
-
-    VM::InterpreterExecutionScope scope(*this);
-
-    auto& call_frame = vm().push_call_frame();
-    call_frame.function_name = function.name();
-    call_frame.this_value = function.bound_this().value_or(this_value);
-    call_frame.arguments = function.bound_arguments();
-    if (arguments.has_value())
-        call_frame.arguments.append(arguments.value().values());
-    call_frame.environment = function.create_environment();
-
-    ASSERT(call_frame.environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
-    call_frame.environment->bind_this_value(call_frame.this_value);
-
-    auto result = function.call(*this);
-    vm().pop_call_frame();
-    return result;
-}
-
 void Interpreter::enter_scope(const ScopeNode& scope_node, ArgumentVector arguments, ScopeType scope_type, GlobalObject& global_object)
 {
     for (auto& declaration : scope_node.functions()) {

+ 6 - 1
Libraries/LibJS/Interpreter.h

@@ -58,6 +58,8 @@ public:
         return interpreter;
     }
 
+    static NonnullOwnPtr<Interpreter> create_with_existing_global_object(GlobalObject&);
+
     template<typename... Args>
     [[nodiscard]] ALWAYS_INLINE Value call(Function& function, Value this_value, Args... args)
     {
@@ -110,7 +112,10 @@ public:
 private:
     explicit Interpreter(VM&);
 
-    [[nodiscard]] Value call_internal(Function&, Value this_value, Optional<MarkedValueList>);
+    [[nodiscard]] Value call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments)
+    {
+        return vm().call(function, this_value, move(arguments));
+    }
 
     NonnullRefPtr<VM> m_vm;
 

+ 9 - 9
Libraries/LibJS/Runtime/ArrayConstructor.cpp

@@ -59,15 +59,15 @@ void ArrayConstructor::initialize(GlobalObject& global_object)
     define_native_function("of", of, 0, attr);
 }
 
-Value ArrayConstructor::call(Interpreter& interpreter)
+Value ArrayConstructor::call()
 {
-    if (interpreter.argument_count() <= 0)
+    if (vm().argument_count() <= 0)
         return Array::create(global_object());
 
-    if (interpreter.argument_count() == 1 && interpreter.argument(0).is_number()) {
-        auto array_length_value = interpreter.argument(0);
+    if (vm().argument_count() == 1 && vm().argument(0).is_number()) {
+        auto array_length_value = vm().argument(0);
         if (!array_length_value.is_integer() || array_length_value.as_i32() < 0) {
-            interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ArrayInvalidLength);
+            vm().throw_exception<TypeError>(global_object(), ErrorType::ArrayInvalidLength);
             return {};
         }
         auto* array = Array::create(global_object());
@@ -76,14 +76,14 @@ Value ArrayConstructor::call(Interpreter& interpreter)
     }
 
     auto* array = Array::create(global_object());
-    for (size_t i = 0; i < interpreter.argument_count(); ++i)
-        array->indexed_properties().append(interpreter.argument(i));
+    for (size_t i = 0; i < vm().argument_count(); ++i)
+        array->indexed_properties().append(vm().argument(i));
     return array;
 }
 
-Value ArrayConstructor::construct(Interpreter& interpreter, Function&)
+Value ArrayConstructor::construct(Interpreter&, Function&)
 {
-    return call(interpreter);
+    return call();
 }
 
 JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)

+ 1 - 1
Libraries/LibJS/Runtime/ArrayConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~ArrayConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 7 - 7
Libraries/LibJS/Runtime/BigIntConstructor.cpp

@@ -54,20 +54,20 @@ BigIntConstructor::~BigIntConstructor()
 {
 }
 
-Value BigIntConstructor::call(Interpreter& interpreter)
+Value BigIntConstructor::call()
 {
-    auto primitive = interpreter.argument(0).to_primitive(interpreter, Value::PreferredType::Number);
-    if (interpreter.exception())
+    auto primitive = vm().argument(0).to_primitive(Value::PreferredType::Number);
+    if (vm().exception())
         return {};
     if (primitive.is_number()) {
         if (!primitive.is_integer()) {
-            interpreter.vm().throw_exception<RangeError>(global_object(), ErrorType::BigIntIntArgument);
+            vm().throw_exception<RangeError>(global_object(), ErrorType::BigIntIntArgument);
             return {};
         }
-        return js_bigint(interpreter, Crypto::SignedBigInteger { primitive.as_i32() });
+        return js_bigint(heap(), Crypto::SignedBigInteger { primitive.as_i32() });
     }
-    auto* bigint = interpreter.argument(0).to_bigint(interpreter);
-    if (interpreter.exception())
+    auto* bigint = vm().argument(0).to_bigint(global_object());
+    if (vm().exception())
         return {};
     return bigint;
 }

+ 1 - 1
Libraries/LibJS/Runtime/BigIntConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~BigIntConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 2 - 2
Libraries/LibJS/Runtime/BooleanConstructor.cpp

@@ -49,9 +49,9 @@ BooleanConstructor::~BooleanConstructor()
 {
 }
 
-Value BooleanConstructor::call(Interpreter& interpreter)
+Value BooleanConstructor::call()
 {
-    return Value(interpreter.argument(0).to_boolean());
+    return Value(vm().argument(0).to_boolean());
 }
 
 Value BooleanConstructor::construct(Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/BooleanConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~BooleanConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 2 - 2
Libraries/LibJS/Runtime/BoundFunction.cpp

@@ -49,9 +49,9 @@ BoundFunction::~BoundFunction()
 {
 }
 
-Value BoundFunction::call(Interpreter& interpreter)
+Value BoundFunction::call()
 {
-    return m_target_function->call(interpreter);
+    return m_target_function->call();
 }
 
 Value BoundFunction::construct(Interpreter& interpreter, Function& new_target)

+ 1 - 1
Libraries/LibJS/Runtime/BoundFunction.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~BoundFunction();
 
-    virtual Value call(Interpreter& interpreter) override;
+    virtual Value call() override;
 
     virtual Value construct(Interpreter&, Function& new_target) override;
 

+ 3 - 3
Libraries/LibJS/Runtime/DateConstructor.cpp

@@ -157,12 +157,12 @@ DateConstructor::~DateConstructor()
 {
 }
 
-Value DateConstructor::call(Interpreter& interpreter)
+Value DateConstructor::call()
 {
-    auto date = construct(interpreter, *this);
+    auto date = construct(interpreter(), *this);
     if (!date.is_object())
         return {};
-    return js_string(interpreter, static_cast<Date&>(date.as_object()).string());
+    return js_string(heap(), static_cast<Date&>(date.as_object()).string());
 }
 
 Value DateConstructor::construct(Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/DateConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~DateConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 4 - 4
Libraries/LibJS/Runtime/ErrorConstructor.cpp

@@ -47,9 +47,9 @@ ErrorConstructor::~ErrorConstructor()
 {
 }
 
-Value ErrorConstructor::call(Interpreter& interpreter)
+Value ErrorConstructor::call()
 {
-    return construct(interpreter, *this);
+    return construct(interpreter(), *this);
 }
 
 Value ErrorConstructor::construct(Interpreter& interpreter, Function&)
@@ -75,9 +75,9 @@ Value ErrorConstructor::construct(Interpreter& interpreter, Function&)
         define_property("length", Value(1), Attribute::Configurable);                                                  \
     }                                                                                                                  \
     ConstructorName::~ConstructorName() { }                                                                            \
-    Value ConstructorName::call(Interpreter& interpreter)                                                              \
+    Value ConstructorName::call()                                                                                      \
     {                                                                                                                  \
-        return construct(interpreter, *this);                                                                          \
+        return construct(interpreter(), *this);                                                                        \
     }                                                                                                                  \
     Value ConstructorName::construct(Interpreter& interpreter, Function&)                                              \
     {                                                                                                                  \

+ 2 - 2
Libraries/LibJS/Runtime/ErrorConstructor.h

@@ -39,7 +39,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~ErrorConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:
@@ -54,7 +54,7 @@ private:
         explicit ConstructorName(GlobalObject&);                                                  \
         virtual void initialize(GlobalObject&) override;                                          \
         virtual ~ConstructorName() override;                                                      \
-        virtual Value call(Interpreter&) override;                                                \
+        virtual Value call() override;                                                \
         virtual Value construct(Interpreter&, Function& new_target) override;                     \
                                                                                                   \
     private:                                                                                      \

+ 1 - 1
Libraries/LibJS/Runtime/Function.h

@@ -43,7 +43,7 @@ public:
     virtual ~Function();
     virtual void initialize(GlobalObject&) override { }
 
-    virtual Value call(Interpreter&) = 0;
+    virtual Value call() = 0;
     virtual Value construct(Interpreter&, Function& new_target) = 0;
     virtual const FlyString& name() const = 0;
     virtual LexicalEnvironment* create_environment() = 0;

+ 2 - 2
Libraries/LibJS/Runtime/FunctionConstructor.cpp

@@ -51,9 +51,9 @@ FunctionConstructor::~FunctionConstructor()
 {
 }
 
-Value FunctionConstructor::call(Interpreter& interpreter)
+Value FunctionConstructor::call()
 {
-    return construct(interpreter, *this);
+    return construct(interpreter(), *this);
 }
 
 Value FunctionConstructor::construct(Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/FunctionConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~FunctionConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 2 - 2
Libraries/LibJS/Runtime/NativeFunction.cpp

@@ -58,9 +58,9 @@ NativeFunction::~NativeFunction()
 {
 }
 
-Value NativeFunction::call(Interpreter& interpreter)
+Value NativeFunction::call()
 {
-    return m_native_function(interpreter, global_object());
+    return m_native_function(interpreter(), global_object());
 }
 
 Value NativeFunction::construct(Interpreter&, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/NativeFunction.h

@@ -41,7 +41,7 @@ public:
     virtual void initialize(GlobalObject&) override { }
     virtual ~NativeFunction() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
     virtual const FlyString& name() const override { return m_name; };

+ 3 - 3
Libraries/LibJS/Runtime/NumberConstructor.cpp

@@ -65,11 +65,11 @@ NumberConstructor::~NumberConstructor()
 {
 }
 
-Value NumberConstructor::call(Interpreter& interpreter)
+Value NumberConstructor::call()
 {
-    if (!interpreter.argument_count())
+    if (!vm().argument_count())
         return Value(0);
-    return interpreter.argument(0).to_number(interpreter);
+    return vm().argument(0).to_number(interpreter());
 }
 
 Value NumberConstructor::construct(Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/NumberConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~NumberConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 4 - 4
Libraries/LibJS/Runtime/Object.cpp

@@ -870,20 +870,20 @@ Value Object::invoke(const StringOrSymbol& property_name, Optional<MarkedValueLi
 Value Object::call_native_property_getter(Object* this_object, Value property) const
 {
     ASSERT(property.is_native_property());
-    auto& call_frame = interpreter().vm().push_call_frame();
+    auto& call_frame = vm().push_call_frame();
     call_frame.this_value = this_object;
     auto result = property.as_native_property().get(interpreter(), global_object());
-    interpreter().vm().pop_call_frame();
+    vm().pop_call_frame();
     return result;
 }
 
 void Object::call_native_property_setter(Object* this_object, Value property, Value value) const
 {
     ASSERT(property.is_native_property());
-    auto& call_frame = interpreter().vm().push_call_frame();
+    auto& call_frame = vm().push_call_frame();
     call_frame.this_value = this_object;
     property.as_native_property().set(interpreter(), global_object(), value);
-    interpreter().vm().pop_call_frame();
+    vm().pop_call_frame();
 }
 
 }

+ 3 - 3
Libraries/LibJS/Runtime/ObjectConstructor.cpp

@@ -64,14 +64,14 @@ ObjectConstructor::~ObjectConstructor()
 {
 }
 
-Value ObjectConstructor::call(Interpreter&)
+Value ObjectConstructor::call()
 {
     return Object::create_empty(global_object());
 }
 
-Value ObjectConstructor::construct(Interpreter& interpreter, Function&)
+Value ObjectConstructor::construct(Interpreter&, Function&)
 {
-    return call(interpreter);
+    return call();
 }
 
 JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)

+ 1 - 1
Libraries/LibJS/Runtime/ObjectConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~ObjectConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 2 - 2
Libraries/LibJS/Runtime/ProxyConstructor.cpp

@@ -49,9 +49,9 @@ ProxyConstructor::~ProxyConstructor()
 {
 }
 
-Value ProxyConstructor::call(Interpreter& interpreter)
+Value ProxyConstructor::call()
 {
-    interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyCallWithNew);
+    vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyCallWithNew);
     return {};
 }
 

+ 1 - 1
Libraries/LibJS/Runtime/ProxyConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~ProxyConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 10 - 10
Libraries/LibJS/Runtime/ProxyObject.cpp

@@ -460,36 +460,36 @@ void ProxyObject::visit_children(Cell::Visitor& visitor)
     visitor.visit(&m_handler);
 }
 
-Value ProxyObject::call(Interpreter& interpreter)
+Value ProxyObject::call()
 {
     if (!is_function()) {
-        interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, Value(this).to_string_without_side_effects().characters());
+        vm().throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, Value(this).to_string_without_side_effects().characters());
         return {};
     }
     if (m_is_revoked) {
-        interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
+        vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
         return {};
     }
     auto trap = m_handler.get("apply");
-    if (interpreter.exception())
+    if (vm().exception())
         return {};
     if (trap.is_empty() || trap.is_undefined() || trap.is_null())
-        return static_cast<Function&>(m_target).call(interpreter);
+        return static_cast<Function&>(m_target).call();
     if (!trap.is_function()) {
-        interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "apply");
+        vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "apply");
         return {};
     }
-    MarkedValueList arguments(interpreter.heap());
+    MarkedValueList arguments(heap());
     arguments.append(Value(&m_target));
     arguments.append(Value(&m_handler));
     // FIXME: Pass global object
-    auto arguments_array = Array::create(interpreter.global_object());
-    interpreter.vm().for_each_argument([&](auto& argument) {
+    auto arguments_array = Array::create(global_object());
+    vm().for_each_argument([&](auto& argument) {
         arguments_array->indexed_properties().append(argument);
     });
     arguments.append(arguments_array);
 
-    return interpreter.call(trap.as_function(), Value(&m_handler), move(arguments));
+    return vm().call(trap.as_function(), Value(&m_handler), move(arguments));
 }
 
 Value ProxyObject::construct(Interpreter& interpreter, Function& new_target)

+ 1 - 1
Libraries/LibJS/Runtime/ProxyObject.h

@@ -39,7 +39,7 @@ public:
     ProxyObject(Object& target, Object& handler, Object& prototype);
     virtual ~ProxyObject() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
     virtual const FlyString& name() const override;
     virtual LexicalEnvironment* create_environment() override;

+ 2 - 2
Libraries/LibJS/Runtime/RegExpConstructor.cpp

@@ -48,9 +48,9 @@ RegExpConstructor::~RegExpConstructor()
 {
 }
 
-Value RegExpConstructor::call(Interpreter& interpreter)
+Value RegExpConstructor::call()
 {
-    return construct(interpreter, *this);
+    return construct(interpreter(), *this);
 }
 
 Value RegExpConstructor::construct(Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/RegExpConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~RegExpConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 19 - 9
Libraries/LibJS/Runtime/ScriptFunction.cpp

@@ -106,9 +106,19 @@ LexicalEnvironment* ScriptFunction::create_environment()
     return environment;
 }
 
-Value ScriptFunction::call(Interpreter& interpreter)
+Value ScriptFunction::call()
 {
-    auto& argument_values = interpreter.call_frame().arguments;
+    OwnPtr<Interpreter> local_interpreter;
+    Interpreter* interpreter = vm().interpreter_if_exists();
+
+    if (!interpreter) {
+        local_interpreter = Interpreter::create_with_existing_global_object(global_object());
+        interpreter = local_interpreter.ptr();
+    }
+
+    VM::InterpreterExecutionScope scope(*interpreter);
+
+    auto& argument_values = vm().call_frame().arguments;
     ArgumentVector arguments;
     for (size_t i = 0; i < m_parameters.size(); ++i) {
         auto parameter = parameters()[i];
@@ -122,24 +132,24 @@ Value ScriptFunction::call(Interpreter& interpreter)
             if (i < argument_values.size() && !argument_values[i].is_undefined()) {
                 value = argument_values[i];
             } else if (parameter.default_value) {
-                value = parameter.default_value->execute(interpreter, global_object());
-                if (interpreter.exception())
+                value = parameter.default_value->execute(*interpreter, global_object());
+                if (vm().exception())
                     return {};
             }
         }
         arguments.append({ parameter.name, value });
-        interpreter.current_environment()->set(parameter.name, { value, DeclarationKind::Var });
+        vm().current_environment()->set(parameter.name, { value, DeclarationKind::Var });
     }
-    return interpreter.execute_statement(global_object(), m_body, arguments, ScopeType::Function);
+    return interpreter->execute_statement(global_object(), m_body, arguments, ScopeType::Function);
 }
 
-Value ScriptFunction::construct(Interpreter& interpreter, Function&)
+Value ScriptFunction::construct(Interpreter&, Function&)
 {
     if (m_is_arrow_function) {
-        interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, m_name.characters());
+        vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, m_name.characters());
         return {};
     }
-    return call(interpreter);
+    return call();
 }
 
 JS_DEFINE_NATIVE_GETTER(ScriptFunction::length_getter)

+ 1 - 1
Libraries/LibJS/Runtime/ScriptFunction.h

@@ -44,7 +44,7 @@ public:
     const Statement& body() const { return m_body; }
     const Vector<FunctionNode::Parameter>& parameters() const { return m_parameters; };
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
     virtual const FlyString& name() const override { return m_name; };

+ 7 - 7
Libraries/LibJS/Runtime/StringConstructor.cpp

@@ -55,14 +55,14 @@ StringConstructor::~StringConstructor()
 {
 }
 
-Value StringConstructor::call(Interpreter& interpreter)
+Value StringConstructor::call()
 {
-    if (!interpreter.argument_count())
-        return js_string(interpreter, "");
-    if (interpreter.argument(0).is_symbol())
-        return js_string(interpreter, interpreter.argument(0).as_symbol().to_string());
-    auto* string = interpreter.argument(0).to_primitive_string(interpreter);
-    if (interpreter.exception())
+    if (!vm().argument_count())
+        return js_string(heap(), "");
+    if (vm().argument(0).is_symbol())
+        return js_string(heap(), vm().argument(0).as_symbol().to_string());
+    auto* string = vm().argument(0).to_primitive_string(interpreter());
+    if (vm().exception())
         return {};
     return string;
 }

+ 1 - 1
Libraries/LibJS/Runtime/StringConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~StringConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 4 - 4
Libraries/LibJS/Runtime/SymbolConstructor.cpp

@@ -56,11 +56,11 @@ SymbolConstructor::~SymbolConstructor()
 {
 }
 
-Value SymbolConstructor::call(Interpreter& interpreter)
+Value SymbolConstructor::call()
 {
-    if (!interpreter.argument_count())
-        return js_symbol(interpreter, "", false);
-    return js_symbol(interpreter, interpreter.argument(0).to_string(interpreter), false);
+    if (!vm().argument_count())
+        return js_symbol(heap(), "", false);
+    return js_symbol(heap(), vm().argument(0).to_string(interpreter()), false);
 }
 
 Value SymbolConstructor::construct(Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibJS/Runtime/SymbolConstructor.h

@@ -38,7 +38,7 @@ public:
     virtual void initialize(GlobalObject&) override;
     virtual ~SymbolConstructor() override;
 
-    virtual Value call(Interpreter&) override;
+    virtual Value call() override;
     virtual Value construct(Interpreter&, Function& new_target) override;
 
 private:

+ 21 - 1
Libraries/LibJS/Runtime/VM.cpp

@@ -24,8 +24,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <AK/StringBuilder.h>
 #include <AK/ScopeGuard.h>
+#include <AK/StringBuilder.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/GlobalObject.h>
@@ -300,4 +300,24 @@ Value VM::get_new_target() const
     return get_this_environment()->new_target();
 }
 
+Value VM::call(Function& function, Value this_value, Optional<MarkedValueList> arguments)
+{
+    ASSERT(!exception());
+
+    auto& call_frame = push_call_frame();
+    call_frame.function_name = function.name();
+    call_frame.this_value = function.bound_this().value_or(this_value);
+    call_frame.arguments = function.bound_arguments();
+    if (arguments.has_value())
+        call_frame.arguments.append(arguments.value().values());
+    call_frame.environment = function.create_environment();
+
+    ASSERT(call_frame.environment->this_binding_status() == LexicalEnvironment::ThisBindingStatus::Uninitialized);
+    call_frame.environment->bind_this_value(call_frame.this_value);
+
+    auto result = function.call();
+    pop_call_frame();
+    return result;
+}
+
 }

+ 2 - 0
Libraries/LibJS/Runtime/VM.h

@@ -206,6 +206,8 @@ public:
     const LexicalEnvironment* get_this_environment() const;
     Value get_new_target() const;
 
+    [[nodiscard]] Value call(Function&, Value this_value, Optional<MarkedValueList> arguments);
+
 private:
     VM();
 

+ 22 - 20
Libraries/LibJS/Runtime/Value.cpp

@@ -41,6 +41,7 @@
 #include <LibJS/Runtime/BoundFunction.h>
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/Function.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/NumberObject.h>
 #include <LibJS/Runtime/Object.h>
 #include <LibJS/Runtime/PrimitiveString.h>
@@ -203,7 +204,7 @@ bool Value::to_boolean() const
     }
 }
 
-Value Value::to_primitive(Interpreter&, PreferredType preferred_type) const
+Value Value::to_primitive(PreferredType preferred_type) const
 {
     if (is_object())
         return as_object().to_primitive(preferred_type);
@@ -237,7 +238,7 @@ Object* Value::to_object(Interpreter& interpreter, GlobalObject& global_object)
 
 Value Value::to_numeric(Interpreter& interpreter) const
 {
-    auto primitive = to_primitive(interpreter, Value::PreferredType::Number);
+    auto primitive = to_primitive(Value::PreferredType::Number);
     if (interpreter.exception())
         return {};
     if (primitive.is_bigint())
@@ -287,37 +288,38 @@ Value Value::to_number(Interpreter& interpreter) const
     }
 }
 
-BigInt* Value::to_bigint(Interpreter& interpreter) const
+BigInt* Value::to_bigint(GlobalObject& global_object) const
 {
-    auto primitive = to_primitive(interpreter, PreferredType::Number);
-    if (interpreter.exception())
+    auto& vm = global_object.vm();
+    auto primitive = to_primitive(PreferredType::Number);
+    if (vm.exception())
         return nullptr;
     switch (primitive.type()) {
     case Type::Undefined:
-        interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "undefined", "BigInt");
+        vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "undefined", "BigInt");
         return nullptr;
     case Type::Null:
-        interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "null", "BigInt");
+        vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "null", "BigInt");
         return nullptr;
     case Type::Boolean: {
         auto value = primitive.as_bool() ? 1 : 0;
-        return js_bigint(interpreter, Crypto::SignedBigInteger { value });
+        return js_bigint(vm.heap(), Crypto::SignedBigInteger { value });
     }
     case Type::BigInt:
         return &primitive.as_bigint();
     case Type::Number:
-        interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "number", "BigInt");
+        vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "number", "BigInt");
         return {};
     case Type::String: {
         auto& string = primitive.as_string().string();
         if (!is_valid_bigint_value(string)) {
-            interpreter.vm().throw_exception<SyntaxError>(interpreter.global_object(), ErrorType::BigIntInvalidValue, string.characters());
+            vm.throw_exception<SyntaxError>(global_object, ErrorType::BigIntInvalidValue, string.characters());
             return {};
         }
-        return js_bigint(interpreter, Crypto::SignedBigInteger::from_base10(string.trim_whitespace()));
+        return js_bigint(vm.heap(), Crypto::SignedBigInteger::from_base10(string.trim_whitespace()));
     }
     case Type::Symbol:
-        interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "symbol", "BigInt");
+        vm.throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "BigInt");
         return {};
     default:
         ASSERT_NOT_REACHED();
@@ -564,10 +566,10 @@ Value unsigned_right_shift(Interpreter& interpreter, Value lhs, Value rhs)
 
 Value add(Interpreter& interpreter, Value lhs, Value rhs)
 {
-    auto lhs_primitive = lhs.to_primitive(interpreter);
+    auto lhs_primitive = lhs.to_primitive();
     if (interpreter.exception())
         return {};
-    auto rhs_primitive = rhs.to_primitive(interpreter);
+    auto rhs_primitive = rhs.to_primitive();
     if (interpreter.exception())
         return {};
 
@@ -873,10 +875,10 @@ bool abstract_eq(Interpreter& interpreter, Value lhs, Value rhs)
         return abstract_eq(interpreter, lhs, rhs.to_number(interpreter));
 
     if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object())
-        return abstract_eq(interpreter, lhs, rhs.to_primitive(interpreter));
+        return abstract_eq(interpreter, lhs, rhs.to_primitive());
 
     if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || lhs.is_bigint() || rhs.is_symbol()))
-        return abstract_eq(interpreter, lhs.to_primitive(interpreter), rhs);
+        return abstract_eq(interpreter, lhs.to_primitive(), rhs);
 
     if ((lhs.is_bigint() && rhs.is_number()) || (lhs.is_number() && rhs.is_bigint())) {
         if (lhs.is_nan() || lhs.is_infinity() || rhs.is_nan() || rhs.is_infinity())
@@ -898,17 +900,17 @@ TriState abstract_relation(Interpreter& interpreter, bool left_first, Value lhs,
     Value y_primitive;
 
     if (left_first) {
-        x_primitive = lhs.to_primitive(interpreter, Value::PreferredType::Number);
+        x_primitive = lhs.to_primitive(Value::PreferredType::Number);
         if (interpreter.exception())
             return {};
-        y_primitive = rhs.to_primitive(interpreter, Value::PreferredType::Number);
+        y_primitive = rhs.to_primitive(Value::PreferredType::Number);
         if (interpreter.exception())
             return {};
     } else {
-        y_primitive = lhs.to_primitive(interpreter, Value::PreferredType::Number);
+        y_primitive = lhs.to_primitive(Value::PreferredType::Number);
         if (interpreter.exception())
             return {};
-        x_primitive = rhs.to_primitive(interpreter, Value::PreferredType::Number);
+        x_primitive = rhs.to_primitive(Value::PreferredType::Number);
         if (interpreter.exception())
             return {};
     }

+ 2 - 2
Libraries/LibJS/Runtime/Value.h

@@ -242,11 +242,11 @@ public:
 
     String to_string(Interpreter&) const;
     PrimitiveString* to_primitive_string(Interpreter&);
-    Value to_primitive(Interpreter&, PreferredType preferred_type = PreferredType::Default) const;
+    Value to_primitive(PreferredType preferred_type = PreferredType::Default) const;
     Object* to_object(Interpreter&, GlobalObject&) const;
     Value to_numeric(Interpreter&) const;
     Value to_number(Interpreter&) const;
-    BigInt* to_bigint(Interpreter&) const;
+    BigInt* to_bigint(GlobalObject&) const;
     double to_double(Interpreter&) const;
     i32 to_i32(Interpreter&) const;
     size_t to_size_t(Interpreter&) const;

+ 2 - 2
Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp

@@ -56,9 +56,9 @@ XMLHttpRequestConstructor::~XMLHttpRequestConstructor()
 {
 }
 
-JS::Value XMLHttpRequestConstructor::call(JS::Interpreter& interpreter)
+JS::Value XMLHttpRequestConstructor::call()
 {
-    return construct(interpreter, *this);
+    return construct(interpreter(), *this);
 }
 
 JS::Value XMLHttpRequestConstructor::construct(JS::Interpreter& interpreter, Function&)

+ 1 - 1
Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.h

@@ -36,7 +36,7 @@ public:
     virtual void initialize(JS::GlobalObject&) override;
     virtual ~XMLHttpRequestConstructor() override;
 
-    virtual JS::Value call(JS::Interpreter&) override;
+    virtual JS::Value call() override;
     virtual JS::Value construct(JS::Interpreter& interpreter, Function& new_target) override;
 
 private: