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.
This commit is contained in:
parent
be31805e8b
commit
1ff9d33131
Notes:
sideshowbarker
2024-07-19 02:10:38 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/1ff9d331319
42 changed files with 167 additions and 142 deletions
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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&) \
|
||||
{ \
|
||||
|
|
|
@ -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: \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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&)
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue