LibJS: Make native function/property callbacks take VM, not Interpreter

More work on decoupling the general runtime from Interpreter. The goal
is becoming clearer. Interpreter should be one possible way to execute
code inside a VM. In the future we might have other ways :^)
This commit is contained in:
Andreas Kling 2020-09-27 18:36:49 +02:00
parent 1ff9d33131
commit 340a115dfe
Notes: sideshowbarker 2024-07-19 02:10:35 +09:00
64 changed files with 1160 additions and 1114 deletions

View file

@ -43,7 +43,7 @@ DateCell::~DateCell()
String DateCell::display(Cell& cell, const CellTypeMetadata& metadata) const
{
auto timestamp = js_value(cell, metadata);
auto string = Core::DateTime::from_timestamp(timestamp.to_i32(cell.sheet->interpreter())).to_string(metadata.format.is_empty() ? "%Y-%m-%d %H:%M:%S" : metadata.format.characters());
auto string = Core::DateTime::from_timestamp(timestamp.to_i32(cell.sheet->global_object())).to_string(metadata.format.is_empty() ? "%Y-%m-%d %H:%M:%S" : metadata.format.characters());
if (metadata.length >= 0)
return string.substring(0, metadata.length);
@ -53,7 +53,7 @@ String DateCell::display(Cell& cell, const CellTypeMetadata& metadata) const
JS::Value DateCell::js_value(Cell& cell, const CellTypeMetadata&) const
{
auto value = cell.js_data().to_double(cell.sheet->interpreter());
auto value = cell.js_data().to_double(cell.sheet->global_object());
return JS::Value(value / 1000); // Turn it to seconds
}

View file

@ -47,7 +47,7 @@ String NumericCell::display(Cell& cell, const CellTypeMetadata& metadata) const
if (metadata.format.is_empty())
string = value.to_string_without_side_effects();
else
string = format_double(metadata.format.characters(), value.to_double(cell.sheet->interpreter()));
string = format_double(metadata.format.characters(), value.to_double(cell.sheet->global_object()));
if (metadata.length >= 0)
return string.substring(0, metadata.length);
@ -57,7 +57,7 @@ String NumericCell::display(Cell& cell, const CellTypeMetadata& metadata) const
JS::Value NumericCell::js_value(Cell& cell, const CellTypeMetadata&) const
{
return cell.js_data().to_number(cell.sheet->interpreter());
return cell.js_data().to_number(cell.sheet->global_object());
}
}

View file

@ -86,21 +86,21 @@ void SheetGlobalObject::initialize()
JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name)
{
if (interpreter.argument_count() != 1) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to parse_cell_name()");
if (vm.argument_count() != 1) {
vm.throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to parse_cell_name()");
return {};
}
auto name_value = interpreter.argument(0);
auto name_value = vm.argument(0);
if (!name_value.is_string()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, "Expected a String argument to parse_cell_name()");
vm.throw_exception<JS::TypeError>(global_object, "Expected a String argument to parse_cell_name()");
return {};
}
auto position = Sheet::parse_cell_name(name_value.as_string().string());
if (!position.has_value())
return JS::js_undefined();
auto object = JS::Object::create_empty(interpreter.global_object());
object->put("column", JS::js_string(interpreter, position.value().column));
auto object = JS::Object::create_empty(global_object);
object->put("column", JS::js_string(vm, position.value().column));
object->put("row", JS::Value((unsigned)position.value().row));
return object;
@ -124,22 +124,22 @@ void WorkbookObject::initialize(JS::GlobalObject& global_object)
JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet)
{
if (interpreter.argument_count() != 1) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to sheet()");
if (vm.argument_count() != 1) {
vm.throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to sheet()");
return {};
}
auto name_value = interpreter.argument(0);
auto name_value = vm.argument(0);
if (!name_value.is_string() && !name_value.is_number()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, "Expected a String or Number argument to sheet()");
vm.throw_exception<JS::TypeError>(global_object, "Expected a String or Number argument to sheet()");
return {};
}
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->inherits("WorkbookObject")) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WorkbookObject");
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WorkbookObject");
return {};
}

View file

@ -75,13 +75,13 @@ static void update_function_name(Value& value, const FlyString& name)
update_function_name(value, name, visited);
}
static String get_function_name(Interpreter& interpreter, Value value)
static String get_function_name(GlobalObject& global_object, Value value)
{
if (value.is_symbol())
return String::format("[%s]", value.as_symbol().description().characters());
if (value.is_string())
return value.as_string().string();
return value.to_string(interpreter);
return value.to_string(global_object);
}
Value ScopeNode::execute(Interpreter& interpreter, GlobalObject& global_object) const
@ -106,6 +106,8 @@ Value ExpressionStatement::execute(Interpreter& interpreter, GlobalObject& globa
CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interpreter& interpreter, GlobalObject& global_object) const
{
auto& vm = interpreter.vm();
if (is_new_expression()) {
// Computing |this| is irrelevant for "new" expression.
return { js_undefined(), m_callee->execute(interpreter, global_object) };
@ -129,13 +131,13 @@ CallExpression::ThisAndCallee CallExpression::compute_this_and_callee(Interprete
return {};
}
auto* this_value = is_super_property_lookup ? &interpreter.this_value(global_object).as_object() : lookup_target.to_object(interpreter, global_object);
auto* this_value = is_super_property_lookup ? &vm.this_value(global_object).as_object() : lookup_target.to_object(global_object);
if (interpreter.exception())
return {};
auto property_name = member_expression.computed_property_name(interpreter, global_object);
if (!property_name.is_valid())
return {};
auto callee = lookup_target.to_object(interpreter, global_object)->get(property_name).value_or(js_undefined());
auto callee = lookup_target.to_object(global_object)->get(property_name).value_or(js_undefined());
return { this_value, callee };
}
return { &global_object, m_callee->execute(interpreter, global_object) };
@ -387,7 +389,7 @@ Value ForInStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
auto rhs_result = m_rhs->execute(interpreter, global_object);
if (interpreter.exception())
return {};
auto* object = rhs_result.to_object(interpreter, global_object);
auto* object = rhs_result.to_object(global_object);
while (object) {
auto property_names = object->get_own_properties(*object, Object::PropertyKind::Key, true);
for (auto& property_name : property_names.as_object().indexed_properties()) {
@ -479,11 +481,11 @@ Value BinaryExpression::execute(Interpreter& interpreter, GlobalObject& global_o
case BinaryOp::Modulo:
return mod(interpreter, lhs_result, rhs_result);
case BinaryOp::Exponentiation:
return exp(interpreter, lhs_result, rhs_result);
return exp(global_object, lhs_result, rhs_result);
case BinaryOp::TypedEquals:
return Value(strict_eq(interpreter, lhs_result, rhs_result));
return Value(strict_eq(lhs_result, rhs_result));
case BinaryOp::TypedInequals:
return Value(!strict_eq(interpreter, lhs_result, rhs_result));
return Value(!strict_eq(lhs_result, rhs_result));
case BinaryOp::AbstractEquals:
return Value(abstract_eq(interpreter, lhs_result, rhs_result));
case BinaryOp::AbstractInequals:
@ -511,7 +513,7 @@ Value BinaryExpression::execute(Interpreter& interpreter, GlobalObject& global_o
case BinaryOp::In:
return in(interpreter, lhs_result, rhs_result);
case BinaryOp::InstanceOf:
return instance_of(interpreter, lhs_result, rhs_result);
return instance_of(global_object, lhs_result, rhs_result);
}
ASSERT_NOT_REACHED();
@ -576,6 +578,7 @@ Reference MemberExpression::to_reference(Interpreter& interpreter, GlobalObject&
Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const
{
auto& vm = interpreter.vm();
if (m_op == UnaryOp::Delete) {
auto reference = m_lhs->to_reference(interpreter, global_object);
if (interpreter.exception())
@ -586,7 +589,7 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
ASSERT(!reference.is_local_variable());
if (reference.is_global_variable())
return global_object.delete_property(reference.name());
auto* base_object = reference.base().to_object(interpreter, global_object);
auto* base_object = reference.base().to_object(global_object);
if (!base_object)
return {};
return base_object->delete_property(reference.name());
@ -626,25 +629,25 @@ Value UnaryExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
ASSERT_NOT_REACHED();
return {};
case Value::Type::Undefined:
return js_string(interpreter, "undefined");
return js_string(vm, "undefined");
case Value::Type::Null:
// yes, this is on purpose. yes, this is how javascript works.
// yes, it's silly.
return js_string(interpreter, "object");
return js_string(vm, "object");
case Value::Type::Number:
return js_string(interpreter, "number");
return js_string(vm, "number");
case Value::Type::String:
return js_string(interpreter, "string");
return js_string(vm, "string");
case Value::Type::Object:
if (lhs_result.is_function())
return js_string(interpreter, "function");
return js_string(interpreter, "object");
return js_string(vm, "function");
return js_string(vm, "object");
case Value::Type::Boolean:
return js_string(interpreter, "boolean");
return js_string(vm, "boolean");
case Value::Type::Symbol:
return js_string(interpreter, "symbol");
return js_string(vm, "symbol");
case Value::Type::BigInt:
return js_string(interpreter, "bigint");
return js_string(vm, "bigint");
default:
ASSERT_NOT_REACHED();
}
@ -730,20 +733,20 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
method_function.set_home_object(&target);
if (method.kind() == ClassMethod::Kind::Method) {
target.define_property(StringOrSymbol::from_value(interpreter, key), method_value);
target.define_property(StringOrSymbol::from_value(global_object, key), method_value);
} else {
String accessor_name = [&] {
switch (method.kind()) {
case ClassMethod::Kind::Getter:
return String::format("get %s", get_function_name(interpreter, key).characters());
return String::format("get %s", get_function_name(global_object, key).characters());
case ClassMethod::Kind::Setter:
return String::format("set %s", get_function_name(interpreter, key).characters());
return String::format("set %s", get_function_name(global_object, key).characters());
default:
ASSERT_NOT_REACHED();
}
}();
update_function_name(method_value, accessor_name);
target.define_accessor(StringOrSymbol::from_value(interpreter, key), method_function, method.kind() == ClassMethod::Kind::Getter, Attribute::Configurable | Attribute::Enumerable);
target.define_accessor(StringOrSymbol::from_value(global_object, key), method_function, method.kind() == ClassMethod::Kind::Getter, Attribute::Configurable | Attribute::Enumerable);
}
if (interpreter.exception())
return {};
@ -1232,7 +1235,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob
lhs_result = m_lhs->execute(interpreter, global_object);
if (interpreter.exception())
return {};
rhs_result = exp(interpreter, lhs_result, rhs_result);
rhs_result = exp(global_object, lhs_result, rhs_result);
break;
case AssignmentOp::BitwiseAndAssignment:
lhs_result = m_lhs->execute(interpreter, global_object);
@ -1282,7 +1285,7 @@ Value AssignmentExpression::execute(Interpreter& interpreter, GlobalObject& glob
interpreter.vm().throw_exception<ReferenceError>(global_object, ErrorType::InvalidLeftHandAssignment);
return {};
}
update_function_name(rhs_result, get_function_name(interpreter, reference.name().to_value(interpreter)));
update_function_name(rhs_result, get_function_name(global_object, reference.name().to_value(interpreter)));
reference.put(interpreter, global_object, rhs_result);
if (interpreter.exception())
@ -1298,7 +1301,7 @@ Value UpdateExpression::execute(Interpreter& interpreter, GlobalObject& global_o
auto old_value = reference.get(interpreter, global_object);
if (interpreter.exception())
return {};
old_value = old_value.to_numeric(interpreter);
old_value = old_value.to_numeric(global_object);
if (interpreter.exception())
return {};
@ -1528,7 +1531,7 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
if (value.is_function() && property.is_method())
value.as_function().set_home_object(object);
String name = get_function_name(interpreter, key);
String name = get_function_name(global_object, key);
if (property.type() == ObjectProperty::Type::Getter) {
name = String::format("get %s", name.characters());
} else if (property.type() == ObjectProperty::Type::Setter) {
@ -1539,11 +1542,11 @@ Value ObjectExpression::execute(Interpreter& interpreter, GlobalObject& global_o
if (property.type() == ObjectProperty::Type::Getter || property.type() == ObjectProperty::Type::Setter) {
ASSERT(value.is_function());
object->define_accessor(PropertyName::from_value(interpreter, key), value.as_function(), property.type() == ObjectProperty::Type::Getter, Attribute::Configurable | Attribute::Enumerable);
object->define_accessor(PropertyName::from_value(global_object, key), value.as_function(), property.type() == ObjectProperty::Type::Getter, Attribute::Configurable | Attribute::Enumerable);
if (interpreter.exception())
return {};
} else {
object->define_property(PropertyName::from_value(interpreter, key), value);
object->define_property(PropertyName::from_value(global_object, key), value);
if (interpreter.exception())
return {};
}
@ -1577,7 +1580,7 @@ PropertyName MemberExpression::computed_property_name(Interpreter& interpreter,
if (index.is_symbol())
return &index.as_symbol();
auto index_string = index.to_string(interpreter);
auto index_string = index.to_string(global_object);
if (interpreter.exception())
return {};
return index_string;
@ -1599,7 +1602,7 @@ Value MemberExpression::execute(Interpreter& interpreter, GlobalObject& global_o
auto object_value = m_object->execute(interpreter, global_object);
if (interpreter.exception())
return {};
auto* object_result = object_value.to_object(interpreter, global_object);
auto* object_result = object_value.to_object(global_object);
if (interpreter.exception())
return {};
auto property_name = computed_property_name(interpreter, global_object);
@ -1697,7 +1700,7 @@ Value TemplateLiteral::execute(Interpreter& interpreter, GlobalObject& global_ob
auto expr = expression.execute(interpreter, global_object);
if (interpreter.exception())
return {};
auto string = expr.to_string(interpreter);
auto string = expr.to_string(global_object);
if (interpreter.exception())
return {};
string_builder.append(string);
@ -1849,7 +1852,7 @@ Value SwitchStatement::execute(Interpreter& interpreter, GlobalObject& global_ob
auto test_result = switch_case.test()->execute(interpreter, global_object);
if (interpreter.exception())
return {};
if (!strict_eq(interpreter, discriminant_result, test_result))
if (!strict_eq(discriminant_result, test_result))
continue;
}
falling_through = true;

View file

@ -27,22 +27,22 @@
#pragma once
#define JS_DECLARE_NATIVE_FUNCTION(name) \
static JS::Value name(JS::Interpreter&, JS::GlobalObject&)
static JS::Value name(JS::VM&, JS::GlobalObject&)
#define JS_DECLARE_NATIVE_GETTER(name) \
static JS::Value name(JS::Interpreter&, JS::GlobalObject&)
static JS::Value name(JS::VM&, JS::GlobalObject&)
#define JS_DECLARE_NATIVE_SETTER(name) \
static void name(JS::Interpreter&, JS::GlobalObject&, JS::Value)
static void name(JS::VM&, JS::GlobalObject&, JS::Value)
#define JS_DEFINE_NATIVE_FUNCTION(name) \
JS::Value name([[maybe_unused]] JS::Interpreter& interpreter, [[maybe_unused]] JS::GlobalObject& global_object)
JS::Value name([[maybe_unused]] JS::VM& vm, [[maybe_unused]] JS::GlobalObject& global_object)
#define JS_DEFINE_NATIVE_GETTER(name) \
JS::Value name([[maybe_unused]] JS::Interpreter& interpreter, [[maybe_unused]] JS::GlobalObject& global_object)
JS::Value name([[maybe_unused]] JS::VM& vm, [[maybe_unused]] JS::GlobalObject& global_object)
#define JS_DEFINE_NATIVE_SETTER(name) \
void name([[maybe_unused]] JS::Interpreter& interpreter, [[maybe_unused]] JS::GlobalObject& global_object, JS::Value value)
void name([[maybe_unused]] JS::VM& vm, [[maybe_unused]] JS::GlobalObject& global_object, JS::Value value)
#define JS_ENUMERATE_NATIVE_OBJECTS \
__JS_ENUMERATE(Array, array, ArrayPrototype, ArrayConstructor) \

View file

@ -49,13 +49,13 @@ Array::~Array()
{
}
Array* Array::typed_this(Interpreter& interpreter, GlobalObject& global_object)
Array* Array::typed_this(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_array()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAn, "Array");
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Array");
return nullptr;
}
return static_cast<Array*>(this_object);
@ -63,7 +63,7 @@ Array* Array::typed_this(Interpreter& interpreter, GlobalObject& global_object)
JS_DEFINE_NATIVE_GETTER(Array::length_getter)
{
auto* array = typed_this(interpreter, global_object);
auto* array = typed_this(vm, global_object);
if (!array)
return {};
return Value(static_cast<i32>(array->indexed_properties().array_like_size()));
@ -71,14 +71,14 @@ JS_DEFINE_NATIVE_GETTER(Array::length_getter)
JS_DEFINE_NATIVE_SETTER(Array::length_setter)
{
auto* array = typed_this(interpreter, global_object);
auto* array = typed_this(vm, global_object);
if (!array)
return;
auto length = value.to_number(interpreter);
if (interpreter.exception())
auto length = value.to_number(global_object);
if (vm.exception())
return;
if (length.is_nan() || length.is_infinity() || length.as_double() < 0) {
interpreter.vm().throw_exception<RangeError>(global_object, ErrorType::ArrayInvalidLength);
vm.throw_exception<RangeError>(global_object, ErrorType::ArrayInvalidLength);
return;
}
array->indexed_properties().set_array_like_size(length.as_double());

View file

@ -39,7 +39,7 @@ public:
explicit Array(Object& prototype);
virtual ~Array() override;
static Array* typed_this(Interpreter&, GlobalObject&);
static Array* typed_this(VM&, GlobalObject&);
private:
virtual bool is_array() const override { return true; }

View file

@ -88,8 +88,8 @@ Value ArrayConstructor::construct(Interpreter&, Function&)
JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
{
auto value = interpreter.argument(0);
auto object = value.to_object(interpreter, global_object);
auto value = vm.argument(0);
auto object = value.to_object(global_object);
if (!object)
return {};
@ -98,23 +98,23 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// Array.from() lets you create Arrays from:
if (auto size = object->indexed_properties().array_like_size()) {
// * array-like objects (objects with a length property and indexed elements)
MarkedValueList elements(interpreter.heap());
MarkedValueList elements(vm.heap());
elements.ensure_capacity(size);
for (size_t i = 0; i < size; ++i) {
elements.append(object->get(i));
if (interpreter.exception())
if (vm.exception())
return {};
}
array->set_indexed_property_elements(move(elements));
} else {
// * iterable objects
get_iterator_values(global_object, value, [&](Value element) {
if (interpreter.exception())
if (vm.exception())
return IterationDecision::Break;
array->indexed_properties().append(element);
return IterationDecision::Continue;
});
if (interpreter.exception())
if (vm.exception())
return {};
}
@ -126,15 +126,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::is_array)
{
auto value = interpreter.argument(0);
auto value = vm.argument(0);
return Value(value.is_array());
}
JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::of)
{
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;
}

View file

@ -52,9 +52,9 @@ ArrayIteratorPrototype::~ArrayIteratorPrototype()
JS_DEFINE_NATIVE_FUNCTION(ArrayIteratorPrototype::next)
{
auto this_value = interpreter.this_value(global_object);
auto this_value = vm.this_value(global_object);
if (!this_value.is_object() || !this_value.as_object().is_array_iterator_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAn, "Array Iterator");
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Array Iterator");
return {};
}
auto& this_object = this_value.as_object();
@ -80,7 +80,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayIteratorPrototype::next)
return create_iterator_result_object(global_object, Value(static_cast<i32>(index)), false);
auto value = array.get(index);
if (interpreter.exception())
if (vm.exception())
return {};
if (iteration_kind == Object::PropertyKind::Value)
return create_iterator_result_object(global_object, value, false);

View file

@ -87,47 +87,48 @@ ArrayPrototype::~ArrayPrototype()
{
}
static Function* callback_from_args(Interpreter& interpreter, const String& name)
static Function* callback_from_args(GlobalObject& global_object, const String& name)
{
if (interpreter.argument_count() < 1) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::ArrayPrototypeOneArg, name.characters());
auto& vm = global_object.vm();
if (vm.argument_count() < 1) {
vm.throw_exception<TypeError>(global_object, ErrorType::ArrayPrototypeOneArg, name.characters());
return nullptr;
}
auto callback = interpreter.argument(0);
auto callback = vm.argument(0);
if (!callback.is_function()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::NotAFunction, callback.to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, callback.to_string_without_side_effects().characters());
return nullptr;
}
return &callback.as_function();
}
static size_t get_length(Interpreter& interpreter, Object& object)
static size_t get_length(VM& vm, Object& object)
{
auto length_property = object.get("length");
if (interpreter.exception())
if (vm.exception())
return 0;
return length_property.to_size_t(interpreter);
return length_property.to_size_t(object.global_object());
}
static void for_each_item(Interpreter& interpreter, GlobalObject& global_object, const String& name, AK::Function<IterationDecision(size_t index, Value value, Value callback_result)> callback, bool skip_empty = true)
static void for_each_item(VM& vm, GlobalObject& global_object, const String& name, AK::Function<IterationDecision(size_t index, Value value, Value callback_result)> callback, bool skip_empty = true)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return;
auto initial_length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto initial_length = get_length(vm, *this_object);
if (vm.exception())
return;
auto* callback_function = callback_from_args(interpreter, name);
auto* callback_function = callback_from_args(global_object, name);
if (!callback_function)
return;
auto this_value = interpreter.argument(1);
auto this_value = vm.argument(1);
for (size_t i = 0; i < initial_length; ++i) {
auto value = this_object->get(i);
if (interpreter.exception())
if (vm.exception())
return;
if (value.is_empty()) {
if (skip_empty)
@ -135,8 +136,8 @@ static void for_each_item(Interpreter& interpreter, GlobalObject& global_object,
value = js_undefined();
}
auto callback_result = interpreter.call(*callback_function, this_value, value, Value((i32)i), this_object);
if (interpreter.exception())
auto callback_result = vm.call(*callback_function, this_value, value, Value((i32)i), this_object);
if (vm.exception())
return;
if (callback(i, value, callback_result) == IterationDecision::Break)
@ -147,7 +148,7 @@ static void for_each_item(Interpreter& interpreter, GlobalObject& global_object,
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter)
{
auto* new_array = Array::create(global_object);
for_each_item(interpreter, global_object, "filter", [&](auto, auto value, auto callback_result) {
for_each_item(vm, global_object, "filter", [&](auto, auto value, auto callback_result) {
if (callback_result.to_boolean())
new_array->indexed_properties().append(value);
return IterationDecision::Continue;
@ -157,7 +158,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::for_each)
{
for_each_item(interpreter, global_object, "forEach", [](auto, auto, auto) {
for_each_item(vm, global_object, "forEach", [](auto, auto, auto) {
return IterationDecision::Continue;
});
return js_undefined();
@ -165,16 +166,16 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::for_each)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto initial_length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto initial_length = get_length(vm, *this_object);
if (vm.exception())
return {};
auto* new_array = Array::create(global_object);
new_array->indexed_properties().set_array_like_size(initial_length);
for_each_item(interpreter, global_object, "map", [&](auto index, auto, auto callback_result) {
if (interpreter.exception())
for_each_item(vm, global_object, "map", [&](auto index, auto, auto callback_result) {
if (vm.exception())
return IterationDecision::Break;
new_array->define_property(index, callback_result);
return IterationDecision::Continue;
@ -184,49 +185,49 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (this_object->is_array()) {
auto* array = static_cast<Array*>(this_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 Value(static_cast<i32>(array->indexed_properties().array_like_size()));
}
auto length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto length = get_length(vm, *this_object);
if (vm.exception())
return {};
auto argument_count = interpreter.argument_count();
auto argument_count = vm.argument_count();
auto new_length = length + argument_count;
if (new_length > MAX_ARRAY_LIKE_INDEX) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ArrayMaxSize);
vm.throw_exception<TypeError>(global_object, ErrorType::ArrayMaxSize);
return {};
}
for (size_t i = 0; i < argument_count; ++i) {
this_object->put(length + i, interpreter.argument(i));
if (interpreter.exception())
this_object->put(length + i, vm.argument(i));
if (vm.exception())
return {};
}
auto new_length_value = Value((i32)new_length);
this_object->put("length", new_length_value);
if (interpreter.exception())
if (vm.exception())
return {};
return new_length_value;
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
{
auto* array = Array::typed_this(interpreter, global_object);
auto* array = Array::typed_this(vm, global_object);
if (!array)
return {};
for (size_t i = 0; i < interpreter.argument_count(); ++i)
array->indexed_properties().insert(i, interpreter.argument(i));
for (size_t i = 0; i < vm.argument_count(); ++i)
array->indexed_properties().insert(i, vm.argument(i));
return Value(static_cast<i32>(array->indexed_properties().array_like_size()));
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (this_object->is_array()) {
@ -235,129 +236,129 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
return js_undefined();
return array->indexed_properties().take_last(array).value.value_or(js_undefined());
}
auto length = get_length(interpreter, *this_object);
auto length = get_length(vm, *this_object);
if (length == 0) {
this_object->put("length", Value(0));
return js_undefined();
}
auto index = length - 1;
auto element = this_object->get(index).value_or(js_undefined());
if (interpreter.exception())
if (vm.exception())
return {};
this_object->delete_property(index);
if (interpreter.exception())
if (vm.exception())
return {};
this_object->put("length", Value((i32)index));
if (interpreter.exception())
if (vm.exception())
return {};
return element;
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::shift)
{
auto* array = Array::typed_this(interpreter, global_object);
auto* array = Array::typed_this(vm, global_object);
if (!array)
return {};
if (array->indexed_properties().is_empty())
return js_undefined();
auto result = array->indexed_properties().take_first(array);
if (interpreter.exception())
if (vm.exception())
return {};
return result.value.value_or(js_undefined());
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto join_function = this_object->get("join");
if (interpreter.exception())
if (vm.exception())
return {};
if (!join_function.is_function())
return ObjectPrototype::to_string(interpreter, global_object);
return interpreter.call(join_function.as_function(), this_object);
return ObjectPrototype::to_string(vm, global_object);
return vm.call(join_function.as_function(), this_object);
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
String separator = ","; // NOTE: This is implementation-specific.
auto length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto length = get_length(vm, *this_object);
if (vm.exception())
return {};
StringBuilder builder;
for (size_t i = 0; i < length; ++i) {
if (i > 0)
builder.append(separator);
auto value = this_object->get(i).value_or(js_undefined());
if (interpreter.exception())
if (vm.exception())
return {};
if (value.is_undefined() || value.is_null())
continue;
auto* value_object = value.to_object(interpreter, global_object);
auto* value_object = value.to_object(global_object);
ASSERT(value_object);
auto locale_string_result = value_object->invoke("toLocaleString");
if (interpreter.exception())
if (vm.exception())
return {};
auto string = locale_string_result.to_string(interpreter);
if (interpreter.exception())
auto string = locale_string_result.to_string(global_object);
if (vm.exception())
return {};
builder.append(string);
}
return js_string(interpreter, builder.to_string());
return js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::join)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
String separator = ",";
if (interpreter.argument_count()) {
separator = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
if (vm.argument_count()) {
separator = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
auto length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto length = get_length(vm, *this_object);
if (vm.exception())
return {};
StringBuilder builder;
for (size_t i = 0; i < length; ++i) {
if (i > 0)
builder.append(separator);
auto value = this_object->get(i).value_or(js_undefined());
if (interpreter.exception())
if (vm.exception())
return {};
if (value.is_undefined() || value.is_null())
continue;
auto string = value.to_string(interpreter);
if (interpreter.exception())
auto string = value.to_string(global_object);
if (vm.exception())
return {};
builder.append(string);
}
return js_string(interpreter, builder.to_string());
return js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::concat)
{
auto* array = Array::typed_this(interpreter, global_object);
auto* array = Array::typed_this(vm, global_object);
if (!array)
return {};
auto* new_array = Array::create(global_object);
new_array->indexed_properties().append_all(array, array->indexed_properties());
if (interpreter.exception())
if (vm.exception())
return {};
for (size_t i = 0; i < interpreter.argument_count(); ++i) {
auto argument = interpreter.argument(i);
for (size_t i = 0; i < vm.argument_count(); ++i) {
auto argument = vm.argument(i);
if (argument.is_array()) {
auto& argument_object = argument.as_object();
new_array->indexed_properties().append_all(&argument_object, argument_object.indexed_properties());
if (interpreter.exception())
if (vm.exception())
return {};
} else {
new_array->indexed_properties().append(argument);
@ -369,21 +370,21 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::concat)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::slice)
{
auto* array = Array::typed_this(interpreter, global_object);
auto* array = Array::typed_this(vm, global_object);
if (!array)
return {};
auto* new_array = Array::create(global_object);
if (interpreter.argument_count() == 0) {
if (vm.argument_count() == 0) {
new_array->indexed_properties().append_all(array, array->indexed_properties());
if (interpreter.exception())
if (vm.exception())
return {};
return new_array;
}
ssize_t array_size = static_cast<ssize_t>(array->indexed_properties().array_like_size());
auto start_slice = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
auto start_slice = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
auto end_slice = array_size;
@ -393,9 +394,9 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::slice)
if (start_slice < 0)
start_slice = end_slice + start_slice;
if (interpreter.argument_count() >= 2) {
end_slice = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
end_slice = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (end_slice < 0)
end_slice = array_size + end_slice;
@ -405,7 +406,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::slice)
for (ssize_t i = start_slice; i < end_slice; ++i) {
new_array->indexed_properties().append(array->get(i));
if (interpreter.exception())
if (vm.exception())
return {};
}
@ -414,30 +415,30 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::slice)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::index_of)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
i32 length = get_length(interpreter, *this_object);
if (interpreter.exception())
i32 length = get_length(vm, *this_object);
if (vm.exception())
return {};
if (length == 0)
return Value(-1);
i32 from_index = 0;
if (interpreter.argument_count() >= 2) {
from_index = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
from_index = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (from_index >= length)
return Value(-1);
if (from_index < 0)
from_index = max(length + from_index, 0);
}
auto search_element = interpreter.argument(0);
auto search_element = vm.argument(0);
for (i32 i = from_index; i < length; ++i) {
auto element = this_object->get(i);
if (interpreter.exception())
if (vm.exception())
return {};
if (strict_eq(interpreter, element, search_element))
if (strict_eq(element, search_element))
return Value(i);
}
return Value(-1);
@ -445,28 +446,28 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::index_of)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto initial_length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto initial_length = get_length(vm, *this_object);
if (vm.exception())
return {};
auto* callback_function = callback_from_args(interpreter, "reduce");
auto* callback_function = callback_from_args(global_object, "reduce");
if (!callback_function)
return {};
size_t start = 0;
auto accumulator = js_undefined();
if (interpreter.argument_count() > 1) {
accumulator = interpreter.argument(1);
if (vm.argument_count() > 1) {
accumulator = vm.argument(1);
} else {
bool start_found = false;
while (!start_found && start < initial_length) {
auto value = this_object->get(start);
if (interpreter.exception())
if (vm.exception())
return {};
start_found = !value.is_empty();
if (start_found)
@ -474,7 +475,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
start += 1;
}
if (!start_found) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ReduceNoInitial);
vm.throw_exception<TypeError>(global_object, ErrorType::ReduceNoInitial);
return {};
}
}
@ -483,13 +484,13 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
for (size_t i = start; i < initial_length; ++i) {
auto value = this_object->get(i);
if (interpreter.exception())
if (vm.exception())
return {};
if (value.is_empty())
continue;
accumulator = interpreter.call(*callback_function, this_value, accumulator, value, Value((i32)i), this_object);
if (interpreter.exception())
accumulator = vm.call(*callback_function, this_value, accumulator, value, Value((i32)i), this_object);
if (vm.exception())
return {};
}
@ -498,28 +499,28 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto initial_length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto initial_length = get_length(vm, *this_object);
if (vm.exception())
return {};
auto* callback_function = callback_from_args(interpreter, "reduceRight");
auto* callback_function = callback_from_args(global_object, "reduceRight");
if (!callback_function)
return {};
int start = initial_length - 1;
auto accumulator = js_undefined();
if (interpreter.argument_count() > 1) {
accumulator = interpreter.argument(1);
if (vm.argument_count() > 1) {
accumulator = vm.argument(1);
} else {
bool start_found = false;
while (!start_found && start >= 0) {
auto value = this_object->get(start);
if (interpreter.exception())
if (vm.exception())
return {};
start_found = !value.is_empty();
if (start_found)
@ -527,7 +528,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
start -= 1;
}
if (!start_found) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ReduceNoInitial);
vm.throw_exception<TypeError>(global_object, ErrorType::ReduceNoInitial);
return {};
}
}
@ -536,13 +537,13 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
for (int i = start; i >= 0; --i) {
auto value = this_object->get(i);
if (interpreter.exception())
if (vm.exception())
return {};
if (value.is_empty())
continue;
accumulator = interpreter.call(*callback_function, this_value, accumulator, value, Value((i32)i), this_object);
if (interpreter.exception())
accumulator = vm.call(*callback_function, this_value, accumulator, value, Value((i32)i), this_object);
if (vm.exception())
return {};
}
@ -551,20 +552,20 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reverse)
{
auto* array = Array::typed_this(interpreter, global_object);
auto* array = Array::typed_this(vm, global_object);
if (!array)
return {};
if (array->indexed_properties().is_empty())
return array;
MarkedValueList array_reverse(interpreter.heap());
MarkedValueList array_reverse(vm.heap());
auto size = array->indexed_properties().array_like_size();
array_reverse.ensure_capacity(size);
for (ssize_t i = size - 1; i >= 0; --i) {
array_reverse.append(array->get(i));
if (interpreter.exception())
if (vm.exception())
return {};
}
@ -575,30 +576,30 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reverse)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::last_index_of)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
i32 length = get_length(interpreter, *this_object);
if (interpreter.exception())
i32 length = get_length(vm, *this_object);
if (vm.exception())
return {};
if (length == 0)
return Value(-1);
i32 from_index = length - 1;
if (interpreter.argument_count() >= 2) {
from_index = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
from_index = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (from_index >= 0)
from_index = min(from_index, length - 1);
else
from_index = length + from_index;
}
auto search_element = interpreter.argument(0);
auto search_element = vm.argument(0);
for (i32 i = from_index; i >= 0; --i) {
auto element = this_object->get(i);
if (interpreter.exception())
if (vm.exception())
return {};
if (strict_eq(interpreter, element, search_element))
if (strict_eq(element, search_element))
return Value(i);
}
return Value(-1);
@ -606,30 +607,30 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::last_index_of)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::includes)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
i32 length = get_length(interpreter, *this_object);
if (interpreter.exception())
i32 length = get_length(vm, *this_object);
if (vm.exception())
return {};
if (length == 0)
return Value(false);
i32 from_index = 0;
if (interpreter.argument_count() >= 2) {
from_index = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
from_index = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (from_index >= length)
return Value(false);
if (from_index < 0)
from_index = max(length + from_index, 0);
}
auto value_to_find = interpreter.argument(0);
auto value_to_find = vm.argument(0);
for (i32 i = from_index; i < length; ++i) {
auto element = this_object->get(i).value_or(js_undefined());
if (interpreter.exception())
if (vm.exception())
return {};
if (same_value_zero(interpreter, element, value_to_find))
if (same_value_zero(element, value_to_find))
return Value(true);
}
return Value(false);
@ -639,7 +640,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find)
{
auto result = js_undefined();
for_each_item(
interpreter, global_object, "find", [&](auto, auto value, auto callback_result) {
vm, global_object, "find", [&](auto, auto value, auto callback_result) {
if (callback_result.to_boolean()) {
result = value;
return IterationDecision::Break;
@ -654,7 +655,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index)
{
auto result_index = -1;
for_each_item(
interpreter, global_object, "findIndex", [&](auto index, auto, auto callback_result) {
vm, global_object, "findIndex", [&](auto index, auto, auto callback_result) {
if (callback_result.to_boolean()) {
result_index = index;
return IterationDecision::Break;
@ -668,7 +669,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
{
auto result = false;
for_each_item(interpreter, global_object, "some", [&](auto, auto, auto callback_result) {
for_each_item(vm, global_object, "some", [&](auto, auto, auto callback_result) {
if (callback_result.to_boolean()) {
result = true;
return IterationDecision::Break;
@ -681,7 +682,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
{
auto result = true;
for_each_item(interpreter, global_object, "every", [&](auto, auto, auto callback_result) {
for_each_item(vm, global_object, "every", [&](auto, auto, auto callback_result) {
if (!callback_result.to_boolean()) {
result = false;
return IterationDecision::Break;
@ -693,16 +694,16 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto initial_length = get_length(interpreter, *this_object);
if (interpreter.exception())
auto initial_length = get_length(vm, *this_object);
if (vm.exception())
return {};
auto relative_start = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
auto relative_start = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
size_t actual_start;
@ -715,12 +716,12 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
size_t insert_count = 0;
size_t actual_delete_count = 0;
if (interpreter.argument_count() == 1) {
if (vm.argument_count() == 1) {
actual_delete_count = initial_length - actual_start;
} else if (interpreter.argument_count() >= 2) {
insert_count = interpreter.argument_count() - 2;
i32 delete_count = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
} else if (vm.argument_count() >= 2) {
insert_count = vm.argument_count() - 2;
i32 delete_count = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
actual_delete_count = min((size_t)max(delete_count, 0), initial_length - actual_start);
@ -729,7 +730,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
size_t new_length = initial_length + insert_count - actual_delete_count;
if (new_length > MAX_ARRAY_LIKE_INDEX) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ArrayMaxSize);
vm.throw_exception<TypeError>(global_object, ErrorType::ArrayMaxSize);
return {};
}
@ -737,7 +738,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
for (size_t i = 0; i < actual_delete_count; ++i) {
auto value = this_object->get(actual_start + i);
if (interpreter.exception())
if (vm.exception())
return {};
removed_elements->indexed_properties().append(value);
@ -746,7 +747,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
if (insert_count < actual_delete_count) {
for (size_t i = actual_start; i < initial_length - actual_delete_count; ++i) {
auto from = this_object->get(i + actual_delete_count);
if (interpreter.exception())
if (vm.exception())
return {};
auto to = i + insert_count;
@ -756,19 +757,19 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
} else {
this_object->delete_property(to);
}
if (interpreter.exception())
if (vm.exception())
return {};
}
for (size_t i = initial_length; i > new_length; --i) {
this_object->delete_property(i - 1);
if (interpreter.exception())
if (vm.exception())
return {};
}
} else if (insert_count > actual_delete_count) {
for (size_t i = initial_length - actual_delete_count; i > actual_start; --i) {
auto from = this_object->get(i + actual_delete_count - 1);
if (interpreter.exception())
if (vm.exception())
return {};
auto to = i + insert_count - 1;
@ -778,19 +779,19 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
} else {
this_object->delete_property(to);
}
if (interpreter.exception())
if (vm.exception())
return {};
}
}
for (size_t i = 0; i < insert_count; ++i) {
this_object->put(actual_start + i, interpreter.argument(i + 2));
if (interpreter.exception())
this_object->put(actual_start + i, vm.argument(i + 2));
if (vm.exception())
return {};
}
this_object->put("length", Value((i32)new_length));
if (interpreter.exception())
if (vm.exception())
return {};
return removed_elements;
@ -798,26 +799,26 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::fill)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
ssize_t length = get_length(interpreter, *this_object);
if (interpreter.exception())
ssize_t length = get_length(vm, *this_object);
if (vm.exception())
return {};
ssize_t relative_start = 0;
ssize_t relative_end = length;
if (interpreter.argument_count() >= 2) {
relative_start = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
relative_start = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
}
if (interpreter.argument_count() >= 3) {
relative_end = interpreter.argument(2).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 3) {
relative_end = vm.argument(2).to_i32(global_object);
if (vm.exception())
return {};
}
@ -834,8 +835,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::fill)
to = min(relative_end, length);
for (size_t i = from; i < to; i++) {
this_object->put(i, interpreter.argument(0));
if (interpreter.exception())
this_object->put(i, vm.argument(0));
if (vm.exception())
return {};
}
@ -844,7 +845,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::fill)
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::values)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};

View file

@ -52,13 +52,13 @@ BigIntPrototype::~BigIntPrototype()
{
}
static BigIntObject* bigint_object_from(Interpreter& interpreter, GlobalObject& global_object)
static BigIntObject* bigint_object_from(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_bigint_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "BigInt");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "BigInt");
return nullptr;
}
return static_cast<BigIntObject*>(this_object);
@ -66,20 +66,20 @@ static BigIntObject* bigint_object_from(Interpreter& interpreter, GlobalObject&
JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_string)
{
auto* bigint_object = bigint_object_from(interpreter, global_object);
auto* bigint_object = bigint_object_from(vm, global_object);
if (!bigint_object)
return {};
return js_string(interpreter, bigint_object->bigint().big_integer().to_base10());
return js_string(vm, bigint_object->bigint().big_integer().to_base10());
}
JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::to_locale_string)
{
return to_string(interpreter, global_object);
return to_string(vm, global_object);
}
JS_DEFINE_NATIVE_FUNCTION(BigIntPrototype::value_of)
{
auto* bigint_object = bigint_object_from(interpreter, global_object);
auto* bigint_object = bigint_object_from(vm, global_object);
if (!bigint_object)
return {};
return bigint_object->value_of();

View file

@ -50,27 +50,27 @@ BooleanPrototype::~BooleanPrototype()
JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::to_string)
{
auto this_object = interpreter.this_value(global_object);
auto this_object = vm.this_value(global_object);
if (this_object.is_boolean()) {
return js_string(interpreter.heap(), this_object.as_bool() ? "true" : "false");
return js_string(vm, this_object.as_bool() ? "true" : "false");
}
if (!this_object.is_object() || !this_object.as_object().is_boolean_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Boolean");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Boolean");
return {};
}
bool bool_value = static_cast<BooleanObject&>(this_object.as_object()).value_of().as_bool();
return js_string(interpreter.heap(), bool_value ? "true" : "false");
return js_string(vm, bool_value ? "true" : "false");
}
JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::value_of)
{
auto this_object = interpreter.this_value(global_object);
auto this_object = vm.this_value(global_object);
if (this_object.is_boolean()) {
return this_object;
}
if (!this_object.is_object() || !this_object.as_object().is_boolean_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Boolean");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Boolean");
return {};
}

View file

@ -56,7 +56,7 @@ Value BoundFunction::call()
Value BoundFunction::construct(Interpreter& interpreter, Function& new_target)
{
if (auto this_value = interpreter.this_value(global_object()); m_constructor_prototype && this_value.is_object()) {
if (auto this_value = vm().this_value(global_object()); m_constructor_prototype && this_value.is_object()) {
this_value.as_object().set_prototype(m_constructor_prototype);
if (interpreter.exception())
return {};

View file

@ -60,47 +60,47 @@ ConsoleObject::~ConsoleObject()
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::log)
{
return interpreter.console().log();
return vm.interpreter().console().log();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::debug)
{
return interpreter.console().debug();
return vm.interpreter().console().debug();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::info)
{
return interpreter.console().info();
return vm.interpreter().console().info();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::warn)
{
return interpreter.console().warn();
return vm.interpreter().console().warn();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::error)
{
return interpreter.console().error();
return vm.interpreter().console().error();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::trace)
{
return interpreter.console().trace();
return vm.interpreter().console().trace();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::count)
{
return interpreter.console().count();
return vm.interpreter().console().count();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::count_reset)
{
return interpreter.console().count_reset();
return vm.interpreter().console().count_reset();
}
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::clear)
{
return interpreter.console().clear();
return vm.interpreter().console().clear();
}
}

View file

@ -165,31 +165,31 @@ Value DateConstructor::call()
return js_string(heap(), static_cast<Date&>(date.as_object()).string());
}
Value DateConstructor::construct(Interpreter& interpreter, Function&)
Value DateConstructor::construct(Interpreter&, Function&)
{
if (interpreter.argument_count() == 0) {
if (vm().argument_count() == 0) {
struct timeval tv;
gettimeofday(&tv, nullptr);
auto datetime = Core::DateTime::now();
auto milliseconds = static_cast<u16>(tv.tv_usec / 1000);
return Date::create(global_object(), datetime, milliseconds);
}
if (interpreter.argument_count() == 1) {
auto value = interpreter.argument(0);
if (vm().argument_count() == 1) {
auto value = vm().argument(0);
if (value.is_string())
value = parse_simplified_iso8601(value.as_string().string());
// A timestamp since the epoch, in UTC.
// FIXME: Date() probably should use a double as internal representation, so that NaN arguments and larger offsets are handled correctly.
double value_as_double = value.to_double(interpreter);
double value_as_double = value.to_double(global_object());
auto datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
auto milliseconds = static_cast<u16>(fmod(value_as_double, 1000));
return Date::create(global_object(), datetime, milliseconds);
}
// A date/time in components, in local time.
// FIXME: This doesn't construct an "Invalid Date" object if one of the parameters is NaN.
auto arg_or = [&interpreter](size_t i, i32 fallback) { return interpreter.argument_count() > i ? interpreter.argument(i).to_i32(interpreter) : fallback; };
int year = interpreter.argument(0).to_i32(interpreter);
int month_index = interpreter.argument(1).to_i32(interpreter);
auto arg_or = [this](size_t i, i32 fallback) { return vm().argument_count() > i ? vm().argument(i).to_i32(global_object()) : fallback; };
int year = vm().argument(0).to_i32(global_object());
int month_index = vm().argument(1).to_i32(global_object());
int day = arg_or(2, 1);
int hours = arg_or(3, 0);
int minutes = arg_or(4, 0);
@ -219,11 +219,11 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::now)
JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return js_nan();
auto iso_8601 = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto iso_8601 = vm.argument(0).to_string(global_object);
if (vm.exception())
return js_nan();
return parse_simplified_iso8601(iso_8601);
@ -231,8 +231,8 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
JS_DEFINE_NATIVE_FUNCTION(DateConstructor::utc)
{
auto arg_or = [&interpreter](size_t i, i32 fallback) { return interpreter.argument_count() > i ? interpreter.argument(i).to_i32(interpreter) : fallback; };
int year = interpreter.argument(0).to_i32(interpreter);
auto arg_or = [&vm, &global_object](size_t i, i32 fallback) { return vm.argument_count() > i ? vm.argument(i).to_i32(global_object) : fallback; };
int year = vm.argument(0).to_i32(global_object);
if (year >= 0 && year <= 99)
year += 1900;

View file

@ -36,13 +36,13 @@
namespace JS {
static Date* typed_this(Interpreter& interpreter, GlobalObject& global_object)
static Date* typed_this(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_date()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Date");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Date");
return nullptr;
}
return static_cast<Date*>(this_object);
@ -96,7 +96,7 @@ DatePrototype::~DatePrototype()
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_date)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->date()));
@ -104,7 +104,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_date)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_day)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->day()));
@ -112,7 +112,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_day)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_full_year)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->full_year()));
@ -120,7 +120,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_full_year)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_hours)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->hours()));
@ -128,7 +128,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_hours)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_milliseconds)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->milliseconds()));
@ -136,7 +136,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_milliseconds)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_minutes)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->minutes()));
@ -144,7 +144,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_minutes)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_month)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->month()));
@ -152,7 +152,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_month)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_seconds)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->seconds()));
@ -160,7 +160,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_seconds)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_time)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(this_object->time());
@ -168,7 +168,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_time)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_date)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_date()));
@ -176,7 +176,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_date)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_day)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_day()));
@ -184,7 +184,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_day)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_full_year)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_full_year()));
@ -192,7 +192,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_full_year)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_hours)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_hours()));
@ -200,7 +200,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_hours)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_milliseconds)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_milliseconds()));
@ -208,7 +208,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_milliseconds)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_month)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_month()));
@ -216,7 +216,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_month)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_minutes)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_minutes()));
@ -224,7 +224,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_minutes)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_seconds)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return Value(static_cast<double>(this_object->utc_seconds()));
@ -232,68 +232,68 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_seconds)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_date_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
auto string = this_object->date_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_iso_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
auto string = this_object->iso_date_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_date_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
// FIXME: Optional locales, options params.
auto string = this_object->locale_date_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
// FIXME: Optional locales, options params.
auto string = this_object->locale_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_time_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
// FIXME: Optional locales, options params.
auto string = this_object->locale_time_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_time_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
auto string = this_object->time_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
auto string = this_object->string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
}

View file

@ -56,38 +56,38 @@ Value ErrorConstructor::construct(Interpreter& interpreter, Function&)
{
String message = "";
if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) {
message = interpreter.call_frame().arguments[0].to_string(interpreter);
message = interpreter.call_frame().arguments[0].to_string(global_object());
if (interpreter.exception())
return {};
}
return Error::create(global_object(), "Error", message);
}
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName::ConstructorName(GlobalObject& global_object) \
: NativeFunction(*global_object.function_prototype()) \
{ \
} \
void ConstructorName::initialize(GlobalObject& global_object) \
{ \
NativeFunction::initialize(global_object); \
define_property("prototype", global_object.snake_name##_prototype(), 0); \
define_property("length", Value(1), Attribute::Configurable); \
} \
ConstructorName::~ConstructorName() { } \
Value ConstructorName::call() \
{ \
return construct(interpreter(), *this); \
} \
Value ConstructorName::construct(Interpreter& interpreter, Function&) \
{ \
String message = ""; \
if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) { \
message = interpreter.call_frame().arguments[0].to_string(interpreter); \
if (interpreter.exception()) \
return {}; \
} \
return ClassName::create(global_object(), message); \
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName::ConstructorName(GlobalObject& global_object) \
: NativeFunction(*global_object.function_prototype()) \
{ \
} \
void ConstructorName::initialize(GlobalObject& global_object) \
{ \
NativeFunction::initialize(global_object); \
define_property("prototype", global_object.snake_name##_prototype(), 0); \
define_property("length", Value(1), Attribute::Configurable); \
} \
ConstructorName::~ConstructorName() { } \
Value ConstructorName::call() \
{ \
return construct(interpreter(), *this); \
} \
Value ConstructorName::construct(Interpreter&, Function&) \
{ \
String message = ""; \
if (!vm().call_frame().arguments.is_empty() && !vm().call_frame().arguments[0].is_undefined()) { \
message = vm().call_frame().arguments[0].to_string(global_object()); \
if (vm().exception()) \
return {}; \
} \
return ClassName::create(global_object(), message); \
}
JS_ENUMERATE_ERROR_SUBCLASSES

View file

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

View file

@ -55,76 +55,76 @@ ErrorPrototype::~ErrorPrototype()
JS_DEFINE_NATIVE_GETTER(ErrorPrototype::name_getter)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_error()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
return {};
}
return js_string(interpreter, static_cast<const Error*>(this_object)->name());
return js_string(vm, static_cast<const Error*>(this_object)->name());
}
JS_DEFINE_NATIVE_SETTER(ErrorPrototype::name_setter)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return;
if (!this_object->is_error()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
return;
}
auto name = value.to_string(interpreter);
if (interpreter.exception())
auto name = value.to_string(global_object);
if (vm.exception())
return;
static_cast<Error*>(this_object)->set_name(name);
}
JS_DEFINE_NATIVE_GETTER(ErrorPrototype::message_getter)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_error()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
return {};
}
return js_string(interpreter, static_cast<const Error*>(this_object)->message());
return js_string(vm, static_cast<const Error*>(this_object)->message());
}
JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
{
if (!interpreter.this_value(global_object).is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAnObject, interpreter.this_value(global_object).to_string_without_side_effects().characters());
if (!vm.this_value(global_object).is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, vm.this_value(global_object).to_string_without_side_effects().characters());
return {};
}
auto& this_object = interpreter.this_value(global_object).as_object();
auto& this_object = vm.this_value(global_object).as_object();
String name = "Error";
auto name_property = this_object.get("name");
if (interpreter.exception())
if (vm.exception())
return {};
if (!name_property.is_empty() && !name_property.is_undefined()) {
name = name_property.to_string(interpreter);
if (interpreter.exception())
name = name_property.to_string(global_object);
if (vm.exception())
return {};
}
String message = "";
auto message_property = this_object.get("message");
if (interpreter.exception())
if (vm.exception())
return {};
if (!message_property.is_empty() && !message_property.is_undefined()) {
message = message_property.to_string(interpreter);
if (interpreter.exception())
message = message_property.to_string(global_object);
if (vm.exception())
return {};
}
if (name.length() == 0)
return js_string(interpreter, message);
return js_string(vm, message);
if (message.length() == 0)
return js_string(interpreter, name);
return js_string(interpreter, String::format("%s: %s", name.characters(), message.characters()));
return js_string(vm, name);
return js_string(vm, String::format("%s: %s", name.characters(), message.characters()));
}
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \

View file

@ -61,7 +61,7 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
return bound_this_value;
return &global_object();
default:
return bound_this_value.to_object(interpreter(), global_object());
return bound_this_value.to_object(global_object());
}
}();

View file

@ -58,25 +58,26 @@ Value FunctionConstructor::call()
Value FunctionConstructor::construct(Interpreter& interpreter, Function&)
{
auto& vm = this->vm();
String parameters_source = "";
String body_source = "";
if (interpreter.argument_count() == 1) {
body_source = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
if (vm.argument_count() == 1) {
body_source = vm.argument(0).to_string(global_object());
if (vm.exception())
return {};
}
if (interpreter.argument_count() > 1) {
if (vm.argument_count() > 1) {
Vector<String> parameters;
for (size_t i = 0; i < interpreter.argument_count() - 1; ++i) {
parameters.append(interpreter.argument(i).to_string(interpreter));
if (interpreter.exception())
for (size_t i = 0; i < vm.argument_count() - 1; ++i) {
parameters.append(vm.argument(i).to_string(global_object()));
if (vm.exception())
return {};
}
StringBuilder parameters_builder;
parameters_builder.join(',', parameters);
parameters_source = parameters_builder.build();
body_source = interpreter.argument(interpreter.argument_count() - 1).to_string(interpreter);
if (interpreter.exception())
body_source = vm.argument(vm.argument_count() - 1).to_string(global_object());
if (vm.exception())
return {};
}
auto source = String::format("function anonymous(%s) { %s }", parameters_source.characters(), body_source.characters());
@ -84,7 +85,7 @@ Value FunctionConstructor::construct(Interpreter& interpreter, Function&)
auto function_expression = parser.parse_function_node<FunctionExpression>();
if (parser.has_errors()) {
auto error = parser.errors()[0];
interpreter.vm().throw_exception<SyntaxError>(global_object(), error.to_string());
vm.throw_exception<SyntaxError>(global_object(), error.to_string());
return {};
}
return function_expression->execute(interpreter, global_object());

View file

@ -62,53 +62,53 @@ FunctionPrototype::~FunctionPrototype()
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
return {};
}
auto& function = static_cast<Function&>(*this_object);
auto this_arg = interpreter.argument(0);
auto arg_array = interpreter.argument(1);
auto this_arg = vm.argument(0);
auto arg_array = vm.argument(1);
if (arg_array.is_null() || arg_array.is_undefined())
return interpreter.call(function, this_arg);
return vm.call(function, this_arg);
if (!arg_array.is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::FunctionArgsNotObject);
vm.throw_exception<TypeError>(global_object, ErrorType::FunctionArgsNotObject);
return {};
}
auto length_property = arg_array.as_object().get("length");
if (interpreter.exception())
if (vm.exception())
return {};
auto length = length_property.to_size_t(interpreter);
if (interpreter.exception())
auto length = length_property.to_size_t(global_object);
if (vm.exception())
return {};
MarkedValueList arguments(interpreter.heap());
MarkedValueList arguments(vm.heap());
for (size_t i = 0; i < length; ++i) {
auto element = arg_array.as_object().get(i);
if (interpreter.exception())
if (vm.exception())
return {};
arguments.append(element.value_or(js_undefined()));
}
return interpreter.call(function, this_arg, move(arguments));
return vm.call(function, this_arg, move(arguments));
}
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::bind)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
return {};
}
auto& this_function = static_cast<Function&>(*this_object);
auto bound_this_arg = interpreter.argument(0);
auto bound_this_arg = vm.argument(0);
Vector<Value> arguments;
if (interpreter.argument_count() > 1) {
arguments = interpreter.call_frame().arguments;
if (vm.argument_count() > 1) {
arguments = vm.call_frame().arguments;
arguments.remove(0);
}
@ -117,30 +117,30 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::bind)
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
return {};
}
auto& function = static_cast<Function&>(*this_object);
auto this_arg = interpreter.argument(0);
MarkedValueList arguments(interpreter.heap());
if (interpreter.argument_count() > 1) {
for (size_t i = 1; i < interpreter.argument_count(); ++i)
arguments.append(interpreter.argument(i));
auto this_arg = vm.argument(0);
MarkedValueList arguments(vm.heap());
if (vm.argument_count() > 1) {
for (size_t i = 1; i < vm.argument_count(); ++i)
arguments.append(vm.argument(i));
}
return interpreter.call(function, this_arg, move(arguments));
return vm.call(function, this_arg, move(arguments));
}
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
return {};
}
String function_name = static_cast<Function*>(this_object)->name();
@ -173,19 +173,19 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string)
function_name.is_null() ? "" : function_name.characters(),
function_parameters.characters(),
function_body.characters());
return js_string(interpreter, function_source);
return js_string(vm, function_source);
}
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::symbol_has_instance)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Function");
return {};
}
return ordinary_has_instance(interpreter, interpreter.argument(0), this_object);
return ordinary_has_instance(global_object, vm.argument(0), this_object);
}
}

View file

@ -153,36 +153,36 @@ void GlobalObject::visit_children(Visitor& visitor)
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::gc)
{
dbg() << "Forced garbage collection requested!";
interpreter.heap().collect_garbage();
vm.heap().collect_garbage();
return js_undefined();
}
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::is_nan)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
return Value(number.is_nan());
}
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::is_finite)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
return Value(number.is_finite_number());
}
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_float)
{
if (interpreter.argument(0).is_number())
return interpreter.argument(0);
auto string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
if (vm.argument(0).is_number())
return vm.argument(0);
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
for (size_t length = string.length(); length > 0; --length) {
// This can't throw, so no exception check is fine.
auto number = Value(js_string(interpreter, string.substring(0, length))).to_number(interpreter);
auto number = Value(js_string(vm, string.substring(0, length))).to_number(global_object);
if (!number.is_nan())
return number;
}

View file

@ -38,7 +38,7 @@ Object* get_iterator(GlobalObject& global_object, Value value, String hint, Valu
if (method.is_empty()) {
if (hint == "async")
TODO();
auto object = value.to_object(interpreter, global_object);
auto object = value.to_object(global_object);
if (!object)
return {};
method = object->get(global_object.vm().well_known_symbol_iterator());

View file

@ -46,7 +46,7 @@ IteratorPrototype::~IteratorPrototype()
JS_DEFINE_NATIVE_FUNCTION(IteratorPrototype::symbol_iterator)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
return this_object;

View file

@ -76,13 +76,13 @@ String JSONObject::stringify_impl(Interpreter& interpreter, GlobalObject& global
return {};
String item;
if (replacer_value.is_string() || replacer_value.is_number()) {
item = replacer_value.to_string(interpreter);
item = replacer_value.to_string(global_object);
if (interpreter.exception())
return {};
} else if (replacer_value.is_object()) {
auto& value_object = replacer_value.as_object();
if (value_object.is_string_object() || value_object.is_number_object()) {
item = value_object.value_of().to_string(interpreter);
item = value_object.value_of().to_string(global_object);
if (interpreter.exception())
return {};
}
@ -133,22 +133,23 @@ String JSONObject::stringify_impl(Interpreter& interpreter, GlobalObject& global
JS_DEFINE_NATIVE_FUNCTION(JSONObject::stringify)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return js_undefined();
auto value = interpreter.argument(0);
auto replacer = interpreter.argument(1);
auto space = interpreter.argument(2);
auto value = vm.argument(0);
auto replacer = vm.argument(1);
auto space = vm.argument(2);
auto string = stringify_impl(interpreter, global_object, value, replacer, space);
auto string = stringify_impl(vm.interpreter(), global_object, value, replacer, space);
if (string.is_null())
return js_undefined();
return js_string(interpreter, string);
return js_string(vm, string);
}
String JSONObject::serialize_json_property(Interpreter& interpreter, StringifyState& state, const PropertyName& key, Object* holder)
{
auto& global_object = interpreter.global_object();
auto value = holder->get(key);
if (interpreter.exception())
return {};
@ -183,7 +184,7 @@ String JSONObject::serialize_json_property(Interpreter& interpreter, StringifySt
return quote_json_string(value.as_string().string());
if (value.is_number()) {
if (value.is_finite_number())
return value.to_string(interpreter);
return value.to_string(global_object);
return "null";
}
if (value.is_object() && !value.is_function()) {
@ -192,7 +193,7 @@ String JSONObject::serialize_json_property(Interpreter& interpreter, StringifySt
return serialize_json_object(interpreter, state, value.as_object());
}
if (value.is_bigint())
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::JsonBigInt);
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::JsonBigInt);
return {};
}
@ -385,25 +386,25 @@ String JSONObject::quote_json_string(String string)
JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return js_undefined();
auto string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto reviver = interpreter.argument(1);
auto reviver = vm.argument(1);
auto json = JsonValue::from_string(string);
if (!json.has_value()) {
interpreter.vm().throw_exception<SyntaxError>(global_object, ErrorType::JsonMalformed);
vm.throw_exception<SyntaxError>(global_object, ErrorType::JsonMalformed);
return {};
}
Value result = parse_json_value(interpreter, global_object, json.value());
Value result = parse_json_value(vm.interpreter(), global_object, json.value());
if (reviver.is_function()) {
auto* holder_object = Object::create_empty(global_object);
holder_object->define_property(String::empty(), result);
if (interpreter.exception())
if (vm.exception())
return {};
return internalize_json_property(interpreter, holder_object, String::empty(), reviver.as_function());
return internalize_json_property(vm.interpreter(), holder_object, String::empty(), reviver.as_function());
}
return result;
}

View file

@ -84,15 +84,15 @@ MathObject::~MathObject()
JS_DEFINE_NATIVE_FUNCTION(MathObject::abs)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
return Value(number.as_double() >= 0 ? number.as_double() : -number.as_double());
}
Value MathObject::random(Interpreter&, GlobalObject&)
JS_DEFINE_NATIVE_FUNCTION(MathObject::random)
{
#ifdef __serenity__
double r = (double)arc4random() / (double)UINT32_MAX;
@ -104,8 +104,8 @@ Value MathObject::random(Interpreter&, GlobalObject&)
JS_DEFINE_NATIVE_FUNCTION(MathObject::sqrt)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -114,8 +114,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::sqrt)
JS_DEFINE_NATIVE_FUNCTION(MathObject::floor)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -124,8 +124,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::floor)
JS_DEFINE_NATIVE_FUNCTION(MathObject::ceil)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -137,8 +137,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::ceil)
JS_DEFINE_NATIVE_FUNCTION(MathObject::round)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -147,15 +147,15 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::round)
JS_DEFINE_NATIVE_FUNCTION(MathObject::max)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return js_negative_infinity();
auto max = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto max = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
for (size_t i = 1; i < interpreter.argument_count(); ++i) {
auto cur = interpreter.argument(i).to_number(interpreter);
if (interpreter.exception())
for (size_t i = 1; i < vm.argument_count(); ++i) {
auto cur = vm.argument(i).to_number(global_object);
if (vm.exception())
return {};
max = Value(cur.as_double() > max.as_double() ? cur : max);
}
@ -164,15 +164,15 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::max)
JS_DEFINE_NATIVE_FUNCTION(MathObject::min)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return js_infinity();
auto min = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto min = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
for (size_t i = 1; i < interpreter.argument_count(); ++i) {
auto cur = interpreter.argument(i).to_number(interpreter);
if (interpreter.exception())
for (size_t i = 1; i < vm.argument_count(); ++i) {
auto cur = vm.argument(i).to_number(global_object);
if (vm.exception())
return {};
min = Value(cur.as_double() < min.as_double() ? cur : min);
}
@ -181,20 +181,20 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::min)
JS_DEFINE_NATIVE_FUNCTION(MathObject::trunc)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
if (number.as_double() < 0)
return MathObject::ceil(interpreter, global_object);
return MathObject::floor(interpreter, global_object);
return MathObject::ceil(vm, global_object);
return MathObject::floor(vm, global_object);
}
JS_DEFINE_NATIVE_FUNCTION(MathObject::sin)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -203,8 +203,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::sin)
JS_DEFINE_NATIVE_FUNCTION(MathObject::cos)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -213,8 +213,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::cos)
JS_DEFINE_NATIVE_FUNCTION(MathObject::tan)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -223,13 +223,13 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::tan)
JS_DEFINE_NATIVE_FUNCTION(MathObject::pow)
{
return JS::exp(interpreter, interpreter.argument(0), interpreter.argument(1));
return JS::exp(global_object, vm.argument(0), vm.argument(1));
}
JS_DEFINE_NATIVE_FUNCTION(MathObject::exp)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -238,8 +238,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::exp)
JS_DEFINE_NATIVE_FUNCTION(MathObject::expm1)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_nan())
return js_nan();
@ -248,8 +248,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::expm1)
JS_DEFINE_NATIVE_FUNCTION(MathObject::sign)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.is_positive_zero())
return Value(0);
@ -264,8 +264,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::sign)
JS_DEFINE_NATIVE_FUNCTION(MathObject::clz32)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (!number.is_finite_number() || (unsigned)number.as_double() == 0)
return Value(32);
@ -274,8 +274,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::clz32)
JS_DEFINE_NATIVE_FUNCTION(MathObject::acosh)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.as_double() < 1)
return JS::js_nan();
@ -284,16 +284,16 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::acosh)
JS_DEFINE_NATIVE_FUNCTION(MathObject::asinh)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
return Value(::asinh(number.as_double()));
}
JS_DEFINE_NATIVE_FUNCTION(MathObject::atanh)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.as_double() > 1 || number.as_double() < -1)
return JS::js_nan();
@ -302,8 +302,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::atanh)
JS_DEFINE_NATIVE_FUNCTION(MathObject::log1p)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (number.as_double() < -1)
return JS::js_nan();
@ -312,8 +312,8 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::log1p)
JS_DEFINE_NATIVE_FUNCTION(MathObject::cbrt)
{
auto number = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
auto number = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
return Value(::cbrt(number.as_double()));
}

View file

@ -31,7 +31,7 @@
namespace JS {
NativeFunction* NativeFunction::create(GlobalObject& global_object, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)> function)
NativeFunction* NativeFunction::create(GlobalObject& global_object, const FlyString& name, AK::Function<Value(VM&, GlobalObject&)> function)
{
return global_object.heap().allocate<NativeFunction>(global_object, name, move(function), *global_object.function_prototype());
}
@ -41,7 +41,7 @@ NativeFunction::NativeFunction(Object& prototype)
{
}
NativeFunction::NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)> native_function, Object& prototype)
NativeFunction::NativeFunction(const FlyString& name, AK::Function<Value(VM&, GlobalObject&)> native_function, Object& prototype)
: Function(prototype)
, m_name(name)
, m_native_function(move(native_function))
@ -60,7 +60,7 @@ NativeFunction::~NativeFunction()
Value NativeFunction::call()
{
return m_native_function(interpreter(), global_object());
return m_native_function(vm(), global_object());
}
Value NativeFunction::construct(Interpreter&, Function&)

View file

@ -35,9 +35,9 @@ class NativeFunction : public Function {
JS_OBJECT(NativeFunction, Function);
public:
static NativeFunction* create(GlobalObject&, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>);
static NativeFunction* create(GlobalObject&, const FlyString& name, AK::Function<Value(VM&, GlobalObject&)>);
explicit NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>, Object& prototype);
explicit NativeFunction(const FlyString& name, AK::Function<Value(VM&, GlobalObject&)>, Object& prototype);
virtual void initialize(GlobalObject&) override { }
virtual ~NativeFunction() override;
@ -56,7 +56,7 @@ private:
virtual LexicalEnvironment* create_environment() override final;
FlyString m_name;
AK::Function<Value(Interpreter&, GlobalObject&)> m_native_function;
AK::Function<Value(VM&, GlobalObject&)> m_native_function;
};
}

View file

@ -29,7 +29,7 @@
namespace JS {
NativeProperty::NativeProperty(AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter)
NativeProperty::NativeProperty(AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter)
: m_getter(move(getter))
, m_setter(move(setter))
{
@ -39,18 +39,18 @@ NativeProperty::~NativeProperty()
{
}
Value NativeProperty::get(Interpreter& interpreter, GlobalObject& global_object) const
Value NativeProperty::get(VM& vm, GlobalObject& global_object) const
{
if (!m_getter)
return js_undefined();
return m_getter(interpreter, global_object);
return m_getter(vm, global_object);
}
void NativeProperty::set(Interpreter& interpreter, GlobalObject& global_object, Value value)
void NativeProperty::set(VM& vm, GlobalObject& global_object, Value value)
{
if (!m_setter)
return;
m_setter(interpreter, global_object, move(value));
m_setter(vm, global_object, move(value));
}
}

View file

@ -33,17 +33,17 @@ namespace JS {
class NativeProperty final : public Cell {
public:
NativeProperty(AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter);
NativeProperty(AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter);
virtual ~NativeProperty() override;
Value get(Interpreter&, GlobalObject&) const;
void set(Interpreter&, GlobalObject&, Value);
Value get(VM&, GlobalObject&) const;
void set(VM&, GlobalObject&, Value);
private:
virtual const char* class_name() const override { return "NativeProperty"; }
AK::Function<Value(Interpreter&, GlobalObject&)> m_getter;
AK::Function<void(Interpreter&, GlobalObject&, Value)> m_setter;
AK::Function<Value(VM&, GlobalObject&)> m_getter;
AK::Function<void(VM&, GlobalObject&, Value)> m_setter;
};
}

View file

@ -69,15 +69,15 @@ Value NumberConstructor::call()
{
if (!vm().argument_count())
return Value(0);
return vm().argument(0).to_number(interpreter());
return vm().argument(0).to_number(global_object());
}
Value NumberConstructor::construct(Interpreter& interpreter, Function&)
Value NumberConstructor::construct(Interpreter&, Function&)
{
double number = 0;
if (interpreter.argument_count()) {
number = interpreter.argument(0).to_double(interpreter);
if (interpreter.exception())
if (vm().argument_count()) {
number = vm().argument(0).to_double(global_object());
if (vm().exception())
return {};
}
return NumberObject::create(global_object(), number);
@ -85,24 +85,24 @@ Value NumberConstructor::construct(Interpreter& interpreter, Function&)
JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_finite)
{
return Value(interpreter.argument(0).is_finite_number());
return Value(vm.argument(0).is_finite_number());
}
JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_integer)
{
return Value(interpreter.argument(0).is_integer());
return Value(vm.argument(0).is_integer());
}
JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_nan)
{
return Value(interpreter.argument(0).is_nan());
return Value(vm.argument(0).is_nan());
}
JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_safe_integer)
{
if (!interpreter.argument(0).is_number())
if (!vm.argument(0).is_number())
return Value(false);
auto value = interpreter.argument(0).as_double();
auto value = vm.argument(0).as_double();
return Value((int64_t)value == value && value >= MIN_SAFE_INTEGER && value <= MAX_SAFE_INTEGER);
}

View file

@ -63,37 +63,37 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string)
{
Value number_value;
auto this_value = interpreter.this_value(global_object);
auto this_value = vm.this_value(global_object);
if (this_value.is_number()) {
number_value = this_value;
} else if (this_value.is_object() && this_value.as_object().is_number_object()) {
number_value = static_cast<NumberObject&>(this_value.as_object()).value_of();
} else {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NumberIncompatibleThis, "toString");
vm.throw_exception<TypeError>(global_object, ErrorType::NumberIncompatibleThis, "toString");
return {};
}
int radix;
auto argument = interpreter.argument(0);
auto argument = vm.argument(0);
if (argument.is_undefined()) {
radix = 10;
} else {
radix = argument.to_i32(interpreter);
radix = argument.to_i32(global_object);
}
if (interpreter.exception() || radix < 2 || radix > 36) {
interpreter.vm().throw_exception<RangeError>(global_object, ErrorType::InvalidRadix);
if (vm.exception() || radix < 2 || radix > 36) {
vm.throw_exception<RangeError>(global_object, ErrorType::InvalidRadix);
return {};
}
if (number_value.is_positive_infinity())
return js_string(interpreter, "Infinity");
return js_string(vm, "Infinity");
if (number_value.is_negative_infinity())
return js_string(interpreter, "-Infinity");
return js_string(vm, "-Infinity");
if (number_value.is_nan())
return js_string(interpreter, "NaN");
return js_string(vm, "NaN");
if (number_value.is_positive_zero() || number_value.is_negative_zero())
return js_string(interpreter, "0");
return js_string(vm, "0");
double number = number_value.as_double();
bool negative = number < 0;
@ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string)
characters.take_last();
}
return js_string(interpreter, String(characters.data(), characters.size()));
return js_string(vm, String(characters.data(), characters.size()));
}
}

View file

@ -742,7 +742,7 @@ bool Object::put(const PropertyName& property_name, Value value, Value receiver)
return put_own_property(*this, string_or_symbol, value, default_attributes, PutOwnPropertyMode::Put);
}
bool Object::define_native_function(const StringOrSymbol& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
bool Object::define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
{
String function_name;
if (property_name.is_string()) {
@ -760,7 +760,7 @@ bool Object::define_native_function(const StringOrSymbol& property_name, AK::Fun
return define_property(property_name, function, attribute);
}
bool Object::define_native_property(const StringOrSymbol& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
bool Object::define_native_property(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
{
return define_property(property_name, heap().allocate_without_global_object<NativeProperty>(move(getter), move(setter)), attribute);
}
@ -846,7 +846,7 @@ Value Object::to_string() const
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::Convert, "object", "string");
if (interpreter.exception())
return {};
auto* string = to_string_result.to_primitive_string(interpreter);
auto* string = to_string_result.to_primitive_string(global_object());
if (interpreter.exception())
return {};
return string;
@ -872,7 +872,7 @@ Value Object::call_native_property_getter(Object* this_object, Value property) c
ASSERT(property.is_native_property());
auto& call_frame = vm().push_call_frame();
call_frame.this_value = this_object;
auto result = property.as_native_property().get(interpreter(), global_object());
auto result = property.as_native_property().get(vm(), global_object());
vm().pop_call_frame();
return result;
}
@ -882,7 +882,7 @@ void Object::call_native_property_setter(Object* this_object, Value property, Va
ASSERT(property.is_native_property());
auto& call_frame = vm().push_call_frame();
call_frame.this_value = this_object;
property.as_native_property().set(interpreter(), global_object(), value);
property.as_native_property().set(vm(), global_object(), value);
vm().pop_call_frame();
}

View file

@ -105,8 +105,8 @@ public:
bool define_property(const PropertyName&, Value value, PropertyAttributes attributes = default_attributes, bool throw_exceptions = true);
bool define_accessor(const PropertyName&, Function& getter_or_setter, bool is_getter, PropertyAttributes attributes = default_attributes, bool throw_exceptions = true);
bool define_native_function(const StringOrSymbol& property_name, AK::Function<Value(Interpreter&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes);
bool define_native_property(const StringOrSymbol& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes);
bool define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes);
bool define_native_property(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes);
virtual Value delete_property(const PropertyName&);

View file

@ -76,18 +76,18 @@ Value ObjectConstructor::construct(Interpreter&, Function&)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return {};
auto* object = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* object = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
auto* result = Array::create(global_object);
for (auto& entry : object->indexed_properties())
result->indexed_properties().append(js_string(interpreter, String::number(entry.index())));
result->indexed_properties().append(js_string(vm, String::number(entry.index())));
for (auto& it : object->shape().property_table_ordered()) {
if (!it.key.is_string())
continue;
result->indexed_properties().append(js_string(interpreter, it.key.as_string()));
result->indexed_properties().append(js_string(vm, it.key.as_string()));
}
return result;
@ -95,36 +95,36 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_prototype_of)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return {};
auto* object = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* object = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
return object->prototype();
}
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of)
{
if (interpreter.argument_count() < 2) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfTwoArgs);
if (vm.argument_count() < 2) {
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfTwoArgs);
return {};
}
auto* object = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* object = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
auto prototype_value = interpreter.argument(1);
auto prototype_value = vm.argument(1);
Object* prototype;
if (prototype_value.is_null()) {
prototype = nullptr;
} else if (prototype_value.is_object()) {
prototype = &prototype_value.as_object();
} else {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
return {};
}
if (!object->set_prototype(prototype)) {
if (!interpreter.exception())
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfReturnedFalse);
if (!vm.exception())
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfReturnedFalse);
return {};
}
return object;
@ -132,7 +132,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_extensible)
{
auto argument = interpreter.argument(0);
auto argument = vm.argument(0);
if (!argument.is_object())
return Value(false);
return Value(argument.as_object().is_extensible());
@ -140,12 +140,12 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_extensible)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::prevent_extensions)
{
auto argument = interpreter.argument(0);
auto argument = vm.argument(0);
if (!argument.is_object())
return argument;
if (!argument.as_object().prevent_extensions()) {
if (!interpreter.exception())
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectPreventExtensionsReturnedFalse);
if (!vm.exception())
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPreventExtensionsReturnedFalse);
return {};
}
return argument;
@ -153,36 +153,36 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::prevent_extensions)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptor)
{
auto* object = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* object = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
auto property_key = PropertyName::from_value(interpreter, interpreter.argument(1));
if (interpreter.exception())
auto property_key = PropertyName::from_value(global_object, vm.argument(1));
if (vm.exception())
return {};
return object->get_own_property_descriptor_object(property_key);
}
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
{
if (!interpreter.argument(0).is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
if (!vm.argument(0).is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
return {};
}
if (!interpreter.argument(2).is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument");
if (!vm.argument(2).is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument");
return {};
}
auto& object = interpreter.argument(0).as_object();
auto property_key = StringOrSymbol::from_value(interpreter, interpreter.argument(1));
if (interpreter.exception())
auto& object = vm.argument(0).as_object();
auto property_key = StringOrSymbol::from_value(global_object, vm.argument(1));
if (vm.exception())
return {};
auto& descriptor = interpreter.argument(2).as_object();
auto& descriptor = vm.argument(2).as_object();
if (!object.define_property(property_key, descriptor)) {
if (!interpreter.exception()) {
if (!vm.exception()) {
if (object.is_proxy_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectDefinePropertyReturnedFalse);
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectDefinePropertyReturnedFalse);
} else {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NonExtensibleDefine, property_key.to_display_string().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::NonExtensibleDefine, property_key.to_display_string().characters());
}
}
return {};
@ -192,18 +192,18 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is)
{
return Value(same_value(interpreter, interpreter.argument(0), interpreter.argument(1)));
return Value(same_value(vm.argument(0), vm.argument(1)));
}
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::keys)
{
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
if (!vm.argument_count()) {
vm.throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
return {};
}
auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* obj_arg = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
return obj_arg->get_own_properties(*obj_arg, PropertyKind::Key, true);
@ -211,12 +211,12 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::keys)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::values)
{
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
if (!vm.argument_count()) {
vm.throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
return {};
}
auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* obj_arg = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
return obj_arg->get_own_properties(*obj_arg, PropertyKind::Value, true);
@ -224,12 +224,12 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::values)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::entries)
{
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
if (!vm.argument_count()) {
vm.throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
return {};
}
auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* obj_arg = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
return obj_arg->get_own_properties(*obj_arg, PropertyKind::KeyAndValue, true);

View file

@ -57,25 +57,25 @@ ObjectPrototype::~ObjectPrototype()
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::has_own_property)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
auto name = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto name = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
return Value(this_object->has_own_property(name));
}
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
{
auto this_value = interpreter.this_value(global_object);
auto this_value = vm.this_value(global_object);
if (this_value.is_undefined())
return js_string(interpreter, "[object Undefined]");
return js_string(vm, "[object Undefined]");
if (this_value.is_null())
return js_string(interpreter, "[object Null]");
return js_string(vm, "[object Null]");
auto* this_object = this_value.to_object(interpreter, global_object);
auto* this_object = this_value.to_object(global_object);
if (!this_object)
return {};
@ -104,12 +104,12 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
tag = "Object";
}
return js_string(interpreter, String::format("[object %s]", tag.characters()));
return js_string(vm, String::format("[object %s]", tag.characters()));
}
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
return this_object->invoke("toString");
@ -117,7 +117,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string)
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::value_of)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
return this_object->value_of();

View file

@ -48,7 +48,12 @@ PrimitiveString* js_string(Heap& heap, String string)
PrimitiveString* js_string(Interpreter& interpreter, String string)
{
return js_string(interpreter.heap(), string);
return js_string(interpreter.heap(), move(string));
}
PrimitiveString* js_string(VM& vm, String string)
{
return js_string(vm.heap(), move(string));
}
}

View file

@ -46,5 +46,6 @@ private:
PrimitiveString* js_string(Heap&, String);
PrimitiveString* js_string(Interpreter&, String);
PrimitiveString* js_string(VM&, String);
}

View file

@ -40,14 +40,14 @@ public:
Symbol,
};
static PropertyName from_value(Interpreter& interpreter, Value value)
static PropertyName from_value(GlobalObject& global_object, Value value)
{
if (value.is_symbol())
return &value.as_symbol();
if (value.is_number())
return value.as_i32();
if (!value.is_empty())
return value.to_string(interpreter);
return value.to_string(global_object);
return {};
}

View file

@ -33,7 +33,7 @@
namespace JS {
bool static is_compatible_property_descriptor(Interpreter& interpreter, bool is_extensible, PropertyDescriptor new_descriptor, Optional<PropertyDescriptor> current_descriptor_optional)
bool static is_compatible_property_descriptor(bool is_extensible, PropertyDescriptor new_descriptor, Optional<PropertyDescriptor> current_descriptor_optional)
{
if (!current_descriptor_optional.has_value())
return is_extensible;
@ -53,7 +53,7 @@ bool static is_compatible_property_descriptor(Interpreter& interpreter, bool is_
if (current_descriptor.is_data_descriptor() && new_descriptor.is_data_descriptor() && !current_descriptor.attributes.is_configurable() && !current_descriptor.attributes.is_writable()) {
if (new_descriptor.attributes.is_writable())
return false;
return new_descriptor.value.is_empty() && same_value(interpreter, new_descriptor.value, current_descriptor.value);
return new_descriptor.value.is_empty() && same_value(new_descriptor.value, current_descriptor.value);
}
return true;
}
@ -77,7 +77,7 @@ ProxyObject::~ProxyObject()
Object* ProxyObject::prototype()
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return nullptr;
}
auto trap = m_handler.get("getPrototypeOf");
@ -86,15 +86,15 @@ Object* ProxyObject::prototype()
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.prototype();
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "getPrototypeOf");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "getPrototypeOf");
return nullptr;
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target));
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target));
if (vm().exception())
return nullptr;
if (!trap_result.is_object() && !trap_result.is_null()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetPrototypeOfReturn);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetPrototypeOfReturn);
return nullptr;
}
if (m_target.is_extensible()) {
@ -107,8 +107,8 @@ Object* ProxyObject::prototype()
auto target_proto = m_target.prototype();
if (vm().exception())
return nullptr;
if (!same_value(interpreter(), trap_result, Value(target_proto))) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetPrototypeOfNonExtensible);
if (!same_value(trap_result, Value(target_proto))) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetPrototypeOfNonExtensible);
return nullptr;
}
return &trap_result.as_object();
@ -117,7 +117,7 @@ Object* ProxyObject::prototype()
const Object* ProxyObject::prototype() const
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return nullptr;
}
return const_cast<const Object*>(const_cast<ProxyObject*>(this)->prototype());
@ -126,7 +126,7 @@ const Object* ProxyObject::prototype() const
bool ProxyObject::set_prototype(Object* object)
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false;
}
auto trap = m_handler.get("setPrototypeOf");
@ -135,11 +135,11 @@ bool ProxyObject::set_prototype(Object* object)
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.set_prototype(object);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "setPrototypeOf");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "setPrototypeOf");
return false;
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), Value(object)).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), Value(object)).to_boolean();
if (vm().exception() || !trap_result)
return false;
if (m_target.is_extensible())
@ -147,8 +147,8 @@ bool ProxyObject::set_prototype(Object* object)
auto* target_proto = m_target.prototype();
if (vm().exception())
return false;
if (!same_value(interpreter(), Value(object), Value(target_proto))) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetPrototypeOfNonExtensible);
if (!same_value(Value(object), Value(target_proto))) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetPrototypeOfNonExtensible);
return false;
}
return true;
@ -157,7 +157,7 @@ bool ProxyObject::set_prototype(Object* object)
bool ProxyObject::is_extensible() const
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false;
}
auto trap = m_handler.get("isExtensible");
@ -166,16 +166,16 @@ bool ProxyObject::is_extensible() const
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.is_extensible();
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "isExtensible");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "isExtensible");
return {};
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target)).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target)).to_boolean();
if (vm().exception())
return false;
if (trap_result != m_target.is_extensible()) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyIsExtensibleReturn);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyIsExtensibleReturn);
return false;
}
return trap_result;
@ -184,7 +184,7 @@ bool ProxyObject::is_extensible() const
bool ProxyObject::prevent_extensions()
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false;
}
auto trap = m_handler.get("preventExtensions");
@ -193,16 +193,16 @@ bool ProxyObject::prevent_extensions()
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.prevent_extensions();
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "preventExtensions");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "preventExtensions");
return {};
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target)).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target)).to_boolean();
if (vm().exception())
return false;
if (trap_result && m_target.is_extensible()) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyPreventExtensionsReturn);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyPreventExtensionsReturn);
return false;
}
return trap_result;
@ -211,7 +211,7 @@ bool ProxyObject::prevent_extensions()
Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const PropertyName& name) const
{
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("getOwnPropertyDescriptor");
@ -220,15 +220,15 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const Prop
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.get_own_property_descriptor(name);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor");
return {};
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string()));
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm(), name.to_string()));
if (vm().exception())
return {};
if (!trap_result.is_object() && !trap_result.is_undefined()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorReturn);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorReturn);
return {};
}
auto target_desc = m_target.get_own_property_descriptor(name);
@ -238,12 +238,12 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const Prop
if (!target_desc.has_value())
return {};
if (!target_desc.value().attributes.is_configurable()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorNonConfigurable);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorNonConfigurable);
return {};
}
if (!m_target.is_extensible()) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorUndefReturn);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorUndefReturn);
return {};
}
return {};
@ -251,13 +251,13 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const Prop
auto result_desc = PropertyDescriptor::from_dictionary(vm(), trap_result.as_object());
if (vm().exception())
return {};
if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), result_desc, target_desc)) {
if (!is_compatible_property_descriptor(m_target.is_extensible(), result_desc, target_desc)) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidDescriptor);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidDescriptor);
return {};
}
if (!result_desc.attributes.is_configurable() && (!target_desc.has_value() || target_desc.value().attributes.is_configurable())) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidNonConfig);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidNonConfig);
return {};
}
return result_desc;
@ -266,7 +266,7 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const Prop
bool ProxyObject::define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions)
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false;
}
auto trap = m_handler.get("defineProperty");
@ -275,11 +275,11 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.define_property(property_name, descriptor, throw_exceptions);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "defineProperty");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "defineProperty");
return false;
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), property_name.to_value(interpreter()), Value(const_cast<Object*>(&descriptor))).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), property_name.to_value(interpreter()), Value(const_cast<Object*>(&descriptor))).to_boolean();
if (vm().exception() || !trap_result)
return false;
auto target_desc = m_target.get_own_property_descriptor(property_name);
@ -293,21 +293,21 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
if (!target_desc.has_value()) {
if (!m_target.is_extensible()) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonExtensible);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonExtensible);
return false;
}
if (setting_config_false) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonConfigurableNonExisting);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonConfigurableNonExisting);
return false;
}
} else {
if (!is_compatible_property_descriptor(interpreter(), m_target.is_extensible(), PropertyDescriptor::from_dictionary(vm(), descriptor), target_desc)) {
if (!is_compatible_property_descriptor(m_target.is_extensible(), PropertyDescriptor::from_dictionary(vm(), descriptor), target_desc)) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropIncompatibleDescriptor);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropIncompatibleDescriptor);
return false;
}
if (setting_config_false && target_desc.value().attributes.is_configurable()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropExistingConfigurable);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropExistingConfigurable);
return false;
}
}
@ -317,7 +317,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
bool ProxyObject::has_property(const PropertyName& name) const
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false;
}
auto trap = m_handler.get("has");
@ -326,11 +326,11 @@ bool ProxyObject::has_property(const PropertyName& name) const
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.has_property(name);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "has");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "has");
return false;
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string())).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm(), name.to_string())).to_boolean();
if (vm().exception())
return false;
if (!trap_result) {
@ -339,12 +339,12 @@ bool ProxyObject::has_property(const PropertyName& name) const
return false;
if (target_desc.has_value()) {
if (!target_desc.value().attributes.is_configurable()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyHasExistingNonConfigurable);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyHasExistingNonConfigurable);
return false;
}
if (!m_target.is_extensible()) {
if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyHasExistingNonExtensible);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyHasExistingNonExtensible);
return false;
}
}
@ -355,7 +355,7 @@ bool ProxyObject::has_property(const PropertyName& name) const
Value ProxyObject::get(const PropertyName& name, Value) const
{
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("get");
@ -364,23 +364,23 @@ Value ProxyObject::get(const PropertyName& name, Value) const
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.get(name);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "get");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "get");
return {};
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string()), Value(const_cast<ProxyObject*>(this)));
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm(), name.to_string()), Value(const_cast<ProxyObject*>(this)));
if (vm().exception())
return {};
auto target_desc = m_target.get_own_property_descriptor(name);
if (target_desc.has_value()) {
if (vm().exception())
return {};
if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), trap_result, target_desc.value().value)) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetImmutableDataProperty);
if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(trap_result, target_desc.value().value)) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetImmutableDataProperty);
return {};
}
if (target_desc.value().is_accessor_descriptor() && target_desc.value().getter == nullptr && !trap_result.is_undefined()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetNonConfigurableAccessor);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetNonConfigurableAccessor);
return {};
}
}
@ -390,7 +390,7 @@ Value ProxyObject::get(const PropertyName& name, Value) const
bool ProxyObject::put(const PropertyName& name, Value value, Value)
{
if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false;
}
auto trap = m_handler.get("set");
@ -399,22 +399,22 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value)
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.put(name, value);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "set");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "set");
return false;
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string()), value, Value(const_cast<ProxyObject*>(this))).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm(), name.to_string()), value, Value(const_cast<ProxyObject*>(this))).to_boolean();
if (vm().exception() || !trap_result)
return false;
auto target_desc = m_target.get_own_property_descriptor(name);
if (vm().exception())
return false;
if (target_desc.has_value() && !target_desc.value().attributes.is_configurable()) {
if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), value, target_desc.value().value)) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetImmutableDataProperty);
if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(value, target_desc.value().value)) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetImmutableDataProperty);
return false;
}
if (target_desc.value().is_accessor_descriptor() && !target_desc.value().setter) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetNonConfigurableAccessor);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetNonConfigurableAccessor);
}
}
return true;
@ -423,7 +423,7 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value)
Value ProxyObject::delete_property(const PropertyName& name)
{
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("deleteProperty");
@ -432,11 +432,11 @@ Value ProxyObject::delete_property(const PropertyName& name)
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.delete_property(name);
if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty");
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty");
return {};
}
auto trap_result = interpreter().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(interpreter(), name.to_string())).to_boolean();
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm(), name.to_string())).to_boolean();
if (vm().exception())
return {};
if (!trap_result)
@ -447,7 +447,7 @@ Value ProxyObject::delete_property(const PropertyName& name)
if (!target_desc.has_value())
return Value(true);
if (!target_desc.value().attributes.is_configurable()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDeleteNonConfigurable);
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDeleteNonConfigurable);
return {};
}
return Value(true);
@ -494,35 +494,36 @@ Value ProxyObject::call()
Value ProxyObject::construct(Interpreter& interpreter, Function& new_target)
{
auto& vm = this->vm();
if (!is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, Value(this).to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, 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("construct");
if (interpreter.exception())
if (vm.exception())
return {};
if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return static_cast<Function&>(m_target).construct(interpreter, new_target);
if (!trap.is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "construct");
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "construct");
return {};
}
MarkedValueList arguments(interpreter.heap());
MarkedValueList arguments(vm.heap());
arguments.append(Value(&m_target));
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);
arguments.append(Value(&new_target));
auto result = interpreter.call(trap.as_function(), Value(&m_handler), move(arguments));
auto result = vm.call(trap.as_function(), Value(&m_handler), move(arguments));
if (!result.is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyConstructBadReturnType);
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyConstructBadReturnType);
return {};
}
return result;

View file

@ -55,7 +55,7 @@ void Reference::put(Interpreter& interpreter, GlobalObject& global_object, Value
return;
}
auto* object = base().to_object(interpreter, global_object);
auto* object = base().to_object(global_object);
if (!object)
return;
@ -97,7 +97,7 @@ Value Reference::get(Interpreter& interpreter, GlobalObject& global_object)
return value;
}
auto* object = base().to_object(interpreter, global_object);
auto* object = base().to_object(global_object);
if (!object)
return {};

View file

@ -34,42 +34,45 @@
namespace JS {
static Object* get_target_object_from(Interpreter& interpreter, const String& name)
static Object* get_target_object_from(GlobalObject& global_object, const String& name)
{
auto target = interpreter.argument(0);
auto& vm = global_object.vm();
auto target = vm.argument(0);
if (!target.is_object()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::ReflectArgumentMustBeAnObject, name.characters());
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectArgumentMustBeAnObject, name.characters());
return nullptr;
}
return static_cast<Object*>(&target.as_object());
}
static Function* get_target_function_from(Interpreter& interpreter, const String& name)
static Function* get_target_function_from(GlobalObject& global_object, const String& name)
{
auto target = interpreter.argument(0);
auto& vm = global_object.vm();
auto target = vm.argument(0);
if (!target.is_function()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::ReflectArgumentMustBeAFunction, name.characters());
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectArgumentMustBeAFunction, name.characters());
return nullptr;
}
return &target.as_function();
}
static void prepare_arguments_list(Interpreter& interpreter, Value value, MarkedValueList* arguments)
static void prepare_arguments_list(GlobalObject& global_object, Value value, MarkedValueList* arguments)
{
auto& vm = global_object.vm();
if (!value.is_object()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::ReflectBadArgumentsList);
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectBadArgumentsList);
return;
}
auto& arguments_list = value.as_object();
auto length_property = arguments_list.get("length");
if (interpreter.exception())
if (vm.exception())
return;
auto length = length_property.to_size_t(interpreter);
if (interpreter.exception())
auto length = length_property.to_size_t(global_object);
if (vm.exception())
return;
for (size_t i = 0; i < length; ++i) {
auto element = arguments_list.get(String::number(i));
if (interpreter.exception())
if (vm.exception())
return;
arguments->append(element.value_or(js_undefined()));
}
@ -105,70 +108,70 @@ ReflectObject::~ReflectObject()
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::apply)
{
auto* target = get_target_function_from(interpreter, "apply");
auto* target = get_target_function_from(global_object, "apply");
if (!target)
return {};
auto this_arg = interpreter.argument(1);
MarkedValueList arguments(interpreter.heap());
prepare_arguments_list(interpreter, interpreter.argument(2), &arguments);
if (interpreter.exception())
auto this_arg = vm.argument(1);
MarkedValueList arguments(vm.heap());
prepare_arguments_list(global_object, vm.argument(2), &arguments);
if (vm.exception())
return {};
return interpreter.call(*target, this_arg, move(arguments));
return vm.call(*target, this_arg, move(arguments));
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::construct)
{
auto* target = get_target_function_from(interpreter, "construct");
auto* target = get_target_function_from(global_object, "construct");
if (!target)
return {};
MarkedValueList arguments(interpreter.heap());
prepare_arguments_list(interpreter, interpreter.argument(1), &arguments);
if (interpreter.exception())
MarkedValueList arguments(vm.heap());
prepare_arguments_list(global_object, vm.argument(1), &arguments);
if (vm.exception())
return {};
auto* new_target = target;
if (interpreter.argument_count() > 2) {
auto new_target_value = interpreter.argument(2);
if (vm.argument_count() > 2) {
auto new_target_value = vm.argument(2);
if (!new_target_value.is_function()
|| (new_target_value.as_object().is_native_function() && !static_cast<NativeFunction&>(new_target_value.as_object()).has_constructor())) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ReflectBadNewTarget);
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectBadNewTarget);
return {};
}
new_target = &new_target_value.as_function();
}
return interpreter.vm().construct(*target, *new_target, move(arguments), global_object);
return vm.construct(*target, *new_target, move(arguments), global_object);
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::define_property)
{
auto* target = get_target_object_from(interpreter, "defineProperty");
auto* target = get_target_object_from(global_object, "defineProperty");
if (!target)
return {};
if (!interpreter.argument(2).is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ReflectBadDescriptorArgument);
if (!vm.argument(2).is_object()) {
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectBadDescriptorArgument);
return {};
}
auto property_key = StringOrSymbol::from_value(interpreter, interpreter.argument(1));
if (interpreter.exception())
auto property_key = StringOrSymbol::from_value(global_object, vm.argument(1));
if (vm.exception())
return {};
auto& descriptor = interpreter.argument(2).as_object();
auto& descriptor = vm.argument(2).as_object();
auto success = target->define_property(property_key, descriptor, false);
if (interpreter.exception())
if (vm.exception())
return {};
return Value(success);
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::delete_property)
{
auto* target = get_target_object_from(interpreter, "deleteProperty");
auto* target = get_target_object_from(global_object, "deleteProperty");
if (!target)
return {};
auto property_key = interpreter.argument(1);
auto property_name = PropertyName::from_value(interpreter, property_key);
if (interpreter.exception())
auto property_key = vm.argument(1);
auto property_name = PropertyName::from_value(global_object, property_key);
if (vm.exception())
return {};
auto property_key_number = property_key.to_number(interpreter);
if (interpreter.exception())
auto property_key_number = property_key.to_number(global_object);
if (vm.exception())
return {};
if (property_key_number.is_finite_number()) {
auto property_key_as_double = property_key_number.as_double();
@ -180,32 +183,32 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::delete_property)
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::get)
{
auto* target = get_target_object_from(interpreter, "get");
auto* target = get_target_object_from(global_object, "get");
if (!target)
return {};
auto property_key = PropertyName::from_value(interpreter, interpreter.argument(1));
if (interpreter.exception())
auto property_key = PropertyName::from_value(global_object, vm.argument(1));
if (vm.exception())
return {};
Value receiver = {};
if (interpreter.argument_count() > 2)
receiver = interpreter.argument(2);
if (vm.argument_count() > 2)
receiver = vm.argument(2);
return target->get(property_key, receiver).value_or(js_undefined());
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::get_own_property_descriptor)
{
auto* target = get_target_object_from(interpreter, "getOwnPropertyDescriptor");
auto* target = get_target_object_from(global_object, "getOwnPropertyDescriptor");
if (!target)
return {};
auto property_key = PropertyName::from_value(interpreter, interpreter.argument(1));
if (interpreter.exception())
auto property_key = PropertyName::from_value(global_object, vm.argument(1));
if (vm.exception())
return {};
return target->get_own_property_descriptor_object(property_key);
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::get_prototype_of)
{
auto* target = get_target_object_from(interpreter, "getPrototypeOf");
auto* target = get_target_object_from(global_object, "getPrototypeOf");
if (!target)
return {};
return target->prototype();
@ -213,18 +216,18 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::get_prototype_of)
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::has)
{
auto* target = get_target_object_from(interpreter, "has");
auto* target = get_target_object_from(global_object, "has");
if (!target)
return {};
auto property_key = PropertyName::from_value(interpreter, interpreter.argument(1));
if (interpreter.exception())
auto property_key = PropertyName::from_value(global_object, vm.argument(1));
if (vm.exception())
return {};
return Value(target->has_property(property_key));
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::is_extensible)
{
auto* target = get_target_object_from(interpreter, "isExtensible");
auto* target = get_target_object_from(global_object, "isExtensible");
if (!target)
return {};
return Value(target->is_extensible());
@ -232,7 +235,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::is_extensible)
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::own_keys)
{
auto* target = get_target_object_from(interpreter, "ownKeys");
auto* target = get_target_object_from(global_object, "ownKeys");
if (!target)
return {};
return target->get_own_properties(*target, PropertyKind::Key);
@ -240,7 +243,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::own_keys)
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::prevent_extensions)
{
auto* target = get_target_object_from(interpreter, "preventExtensions");
auto* target = get_target_object_from(global_object, "preventExtensions");
if (!target)
return {};
return Value(target->prevent_extensions());
@ -248,27 +251,27 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::prevent_extensions)
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::set)
{
auto* target = get_target_object_from(interpreter, "set");
auto* target = get_target_object_from(global_object, "set");
if (!target)
return {};
auto property_key = interpreter.argument(1).to_string(interpreter);
if (interpreter.exception())
auto property_key = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
auto value = interpreter.argument(2);
auto value = vm.argument(2);
Value receiver = {};
if (interpreter.argument_count() > 3)
receiver = interpreter.argument(3);
if (vm.argument_count() > 3)
receiver = vm.argument(3);
return Value(target->put(property_key, value, receiver));
}
JS_DEFINE_NATIVE_FUNCTION(ReflectObject::set_prototype_of)
{
auto* target = get_target_object_from(interpreter, "setPrototypeOf");
auto* target = get_target_object_from(global_object, "setPrototypeOf");
if (!target)
return {};
auto prototype_value = interpreter.argument(1);
auto prototype_value = vm.argument(1);
if (!prototype_value.is_object() && !prototype_value.is_null()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
return {};
}
Object* prototype = nullptr;

View file

@ -53,15 +53,16 @@ Value RegExpConstructor::call()
return construct(interpreter(), *this);
}
Value RegExpConstructor::construct(Interpreter& interpreter, Function&)
Value RegExpConstructor::construct(Interpreter&, Function&)
{
if (!interpreter.argument_count())
auto& vm = this->vm();
if (!vm.argument_count())
return RegExpObject::create(global_object(), "(?:)", "");
auto contents = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto contents = vm.argument(0).to_string(global_object());
if (vm.exception())
return {};
auto flags = interpreter.argument_count() > 1 ? interpreter.argument(1).to_string(interpreter) : "";
if (interpreter.exception())
auto flags = vm.argument_count() > 1 ? vm.argument(1).to_string(global_object()) : "";
if (vm.exception())
return {};
return RegExpObject::create(global_object(), contents, flags);
}

View file

@ -35,13 +35,13 @@
namespace JS {
static ScriptFunction* typed_this(Interpreter& interpreter, GlobalObject& global_object)
static ScriptFunction* typed_this(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAFunctionNoParam);
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunctionNoParam);
return nullptr;
}
return static_cast<ScriptFunction*>(this_object);
@ -154,7 +154,7 @@ Value ScriptFunction::construct(Interpreter&, Function&)
JS_DEFINE_NATIVE_GETTER(ScriptFunction::length_getter)
{
auto* function = typed_this(interpreter, global_object);
auto* function = typed_this(vm, global_object);
if (!function)
return {};
return Value(static_cast<i32>(function->m_function_length));
@ -162,10 +162,10 @@ JS_DEFINE_NATIVE_GETTER(ScriptFunction::length_getter)
JS_DEFINE_NATIVE_GETTER(ScriptFunction::name_getter)
{
auto* function = typed_this(interpreter, global_object);
auto* function = typed_this(vm, global_object);
if (!function)
return {};
return js_string(interpreter, function->name().is_null() ? "" : function->name());
return js_string(vm, function->name().is_null() ? "" : function->name());
}
}

View file

@ -61,19 +61,19 @@ Value StringConstructor::call()
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());
auto* string = vm().argument(0).to_primitive_string(global_object());
if (vm().exception())
return {};
return string;
}
Value StringConstructor::construct(Interpreter& interpreter, Function&)
Value StringConstructor::construct(Interpreter&, Function&)
{
PrimitiveString* primitive_string = nullptr;
if (!interpreter.argument_count())
primitive_string = js_string(interpreter, "");
if (!vm().argument_count())
primitive_string = js_string(vm(), "");
else
primitive_string = interpreter.argument(0).to_primitive_string(interpreter);
primitive_string = vm().argument(0).to_primitive_string(global_object());
if (!primitive_string)
return {};
return StringObject::create(global_object(), *primitive_string);
@ -81,55 +81,55 @@ Value StringConstructor::construct(Interpreter& interpreter, Function&)
JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
{
auto* template_object = interpreter.argument(0).to_object(interpreter, global_object);
if (interpreter.exception())
auto* template_object = vm.argument(0).to_object(global_object);
if (vm.exception())
return {};
auto raw = template_object->get("raw");
if (interpreter.exception())
if (vm.exception())
return {};
if (raw.is_empty() || raw.is_undefined() || raw.is_null()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::StringRawCannotConvert, raw.is_null() ? "null" : "undefined");
vm.throw_exception<TypeError>(global_object, ErrorType::StringRawCannotConvert, raw.is_null() ? "null" : "undefined");
return {};
}
if (!raw.is_array())
return js_string(interpreter, "");
return js_string(vm, "");
auto* array = static_cast<Array*>(raw.to_object(interpreter, global_object));
auto* array = static_cast<Array*>(raw.to_object(global_object));
auto& raw_array_elements = array->indexed_properties();
StringBuilder builder;
for (size_t i = 0; i < raw_array_elements.array_like_size(); ++i) {
auto result = raw_array_elements.get(array, i);
if (interpreter.exception())
if (vm.exception())
return {};
if (!result.has_value())
continue;
builder.append(result.value().value.to_string(interpreter));
if (interpreter.exception())
builder.append(result.value().value.to_string(global_object));
if (vm.exception())
return {};
if (i + 1 < interpreter.argument_count() && i < raw_array_elements.array_like_size() - 1) {
builder.append(interpreter.argument(i + 1).to_string(interpreter));
if (interpreter.exception())
if (i + 1 < vm.argument_count() && i < raw_array_elements.array_like_size() - 1) {
builder.append(vm.argument(i + 1).to_string(global_object));
if (vm.exception())
return {};
}
}
return js_string(interpreter, builder.build());
return js_string(vm, builder.build());
}
JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_char_code)
{
StringBuilder builder;
for (size_t i = 0; i < interpreter.argument_count(); ++i) {
auto char_code = interpreter.argument(i).to_i32(interpreter);
if (interpreter.exception())
for (size_t i = 0; i < vm.argument_count(); ++i) {
auto char_code = vm.argument(i).to_i32(global_object);
if (vm.exception())
return {};
auto truncated = char_code & 0xffff;
// FIXME: We need an Utf16View :^)
builder.append(Utf32View((u32*)&truncated, 1));
}
return js_string(interpreter, builder.build());
return js_string(vm, builder.build());
}
}

View file

@ -52,9 +52,9 @@ StringIteratorPrototype::~StringIteratorPrototype()
JS_DEFINE_NATIVE_FUNCTION(StringIteratorPrototype::next)
{
auto this_value = interpreter.this_value(global_object);
auto this_value = vm.this_value(global_object);
if (!this_value.is_object() || !this_value.as_object().is_string_iterator_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "String Iterator");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "String Iterator");
return {};
}
@ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringIteratorPrototype::next)
builder.append_code_point(*utf8_iterator);
++utf8_iterator;
return create_iterator_result_object(global_object, js_string(interpreter, builder.to_string()), false);
return create_iterator_result_object(global_object, js_string(vm, builder.to_string()), false);
}
}

View file

@ -34,12 +34,12 @@ namespace JS {
class StringOrSymbol {
public:
static StringOrSymbol from_value(Interpreter& interpreter, Value value)
static StringOrSymbol from_value(GlobalObject& global_object, Value value)
{
if (value.is_symbol())
return &value.as_symbol();
if (!value.is_empty())
return value.to_string(interpreter);
return value.to_string(global_object);
return {};
}

View file

@ -40,24 +40,24 @@
namespace JS {
static StringObject* typed_this(Interpreter& interpreter, GlobalObject& global_object)
static StringObject* typed_this(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_string_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "String");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "String");
return nullptr;
}
return static_cast<StringObject*>(this_object);
}
static String ak_string_from(Interpreter& interpreter, GlobalObject& global_object)
static String ak_string_from(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
return Value(this_object).to_string(interpreter);
return Value(this_object).to_string(global_object);
}
StringPrototype::StringPrototype(GlobalObject& global_object)
@ -98,30 +98,30 @@ StringPrototype::~StringPrototype()
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
i32 index = 0;
if (interpreter.argument_count()) {
index = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count()) {
index = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
}
if (index < 0 || index >= static_cast<i32>(string.length()))
return js_string(interpreter, String::empty());
return js_string(vm, String::empty());
// FIXME: This should return a character corresponding to the i'th UTF-16 code point.
return js_string(interpreter, string.substring(index, 1));
return js_string(vm, string.substring(index, 1));
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_code_at)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
i32 index = 0;
if (interpreter.argument_count()) {
index = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count()) {
index = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
}
if (index < 0 || index >= static_cast<i32>(string.length()))
@ -132,50 +132,50 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_code_at)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::repeat)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
if (!interpreter.argument_count())
return js_string(interpreter, String::empty());
auto count_value = interpreter.argument(0).to_number(interpreter);
if (interpreter.exception())
if (!vm.argument_count())
return js_string(vm, String::empty());
auto count_value = vm.argument(0).to_number(global_object);
if (vm.exception())
return {};
if (count_value.as_double() < 0) {
interpreter.vm().throw_exception<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "positive");
vm.throw_exception<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "positive");
return {};
}
if (count_value.is_infinity()) {
interpreter.vm().throw_exception<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "finite");
vm.throw_exception<RangeError>(global_object, ErrorType::StringRepeatCountMustBe, "finite");
return {};
}
auto count = count_value.to_size_t(interpreter);
if (interpreter.exception())
auto count = count_value.to_size_t(global_object);
if (vm.exception())
return {};
StringBuilder builder;
for (size_t i = 0; i < count; ++i)
builder.append(string);
return js_string(interpreter, builder.to_string());
return js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
if (!interpreter.argument_count())
if (!vm.argument_count())
return Value(false);
auto search_string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto search_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto string_length = string.length();
auto search_string_length = search_string.length();
size_t start = 0;
if (interpreter.argument_count() > 1) {
auto number = interpreter.argument(1).to_number(interpreter);
if (interpreter.exception())
if (vm.argument_count() > 1) {
auto number = vm.argument(1).to_number(global_object);
if (vm.exception())
return {};
if (!number.is_nan())
start = min(number.to_size_t(interpreter), string_length);
start = min(number.to_size_t(global_object), string_length);
}
if (start + search_string_length > string_length)
return Value(false);
@ -186,34 +186,34 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::index_of)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
auto needle = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto needle = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
return Value((i32)string.index_of(needle).value_or(-1));
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_lowercase)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return js_string(interpreter, string.to_lowercase());
return js_string(vm, string.to_lowercase());
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_uppercase)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return js_string(interpreter, string.to_uppercase());
return js_string(vm, string.to_uppercase());
}
JS_DEFINE_NATIVE_GETTER(StringPrototype::length_getter)
{
auto* string_object = typed_this(interpreter, global_object);
auto* string_object = typed_this(vm, global_object);
if (!string_object)
return {};
return Value((i32)string_object->primitive_string().string().length());
@ -221,10 +221,10 @@ JS_DEFINE_NATIVE_GETTER(StringPrototype::length_getter)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_string)
{
auto* string_object = typed_this(interpreter, global_object);
auto* string_object = typed_this(vm, global_object);
if (!string_object)
return {};
return js_string(interpreter, string_object->primitive_string().string());
return js_string(vm, string_object->primitive_string().string());
}
enum class PadPlacement {
@ -232,21 +232,22 @@ enum class PadPlacement {
End,
};
static Value pad_string(Interpreter& interpreter, const String& string, PadPlacement placement)
static Value pad_string(GlobalObject& global_object, const String& string, PadPlacement placement)
{
auto max_length = interpreter.argument(0).to_size_t(interpreter);
if (interpreter.exception())
auto& vm = global_object.vm();
auto max_length = vm.argument(0).to_size_t(global_object);
if (vm.exception())
return {};
if (max_length <= string.length())
return js_string(interpreter, string);
return js_string(vm, string);
String fill_string = " ";
if (!interpreter.argument(1).is_undefined()) {
fill_string = interpreter.argument(1).to_string(interpreter);
if (interpreter.exception())
if (!vm.argument(1).is_undefined()) {
fill_string = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
if (fill_string.is_empty())
return js_string(interpreter, string);
return js_string(vm, string);
}
auto fill_length = max_length - string.length();
@ -257,92 +258,92 @@ static Value pad_string(Interpreter& interpreter, const String& string, PadPlace
auto filler = filler_builder.build().substring(0, fill_length);
if (placement == PadPlacement::Start)
return js_string(interpreter, String::format("%s%s", filler.characters(), string.characters()));
return js_string(interpreter, String::format("%s%s", string.characters(), filler.characters()));
return js_string(vm, String::format("%s%s", filler.characters(), string.characters()));
return js_string(vm, String::format("%s%s", string.characters(), filler.characters()));
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::pad_start)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return pad_string(interpreter, string, PadPlacement::Start);
return pad_string(global_object, string, PadPlacement::Start);
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::pad_end)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return pad_string(interpreter, string, PadPlacement::End);
return pad_string(global_object, string, PadPlacement::End);
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return js_string(interpreter, string.trim_whitespace(String::TrimMode::Both));
return js_string(vm, string.trim_whitespace(String::TrimMode::Both));
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim_start)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return js_string(interpreter, string.trim_whitespace(String::TrimMode::Left));
return js_string(vm, string.trim_whitespace(String::TrimMode::Left));
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim_end)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
return js_string(interpreter, string.trim_whitespace(String::TrimMode::Right));
return js_string(vm, string.trim_whitespace(String::TrimMode::Right));
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::concat)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
StringBuilder builder;
builder.append(string);
for (size_t i = 0; i < interpreter.argument_count(); ++i) {
auto string_argument = interpreter.argument(i).to_string(interpreter);
if (interpreter.exception())
for (size_t i = 0; i < vm.argument_count(); ++i) {
auto string_argument = vm.argument(i).to_string(global_object);
if (vm.exception())
return {};
builder.append(string_argument);
}
return js_string(interpreter, builder.to_string());
return js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
if (interpreter.argument_count() == 0)
return js_string(interpreter, string);
if (vm.argument_count() == 0)
return js_string(vm, string);
// FIXME: index_start and index_end should index a UTF-16 code_point view of the string.
auto string_length = string.length();
auto index_start = min(interpreter.argument(0).to_size_t(interpreter), string_length);
if (interpreter.exception())
auto index_start = min(vm.argument(0).to_size_t(global_object), string_length);
if (vm.exception())
return {};
auto index_end = string_length;
if (interpreter.argument_count() >= 2) {
index_end = min(interpreter.argument(1).to_size_t(interpreter), string_length);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
index_end = min(vm.argument(1).to_size_t(global_object), string_length);
if (vm.exception())
return {};
}
if (index_start == index_end)
return js_string(interpreter, String(""));
return js_string(vm, String(""));
if (index_start > index_end) {
if (interpreter.argument_count() == 1)
return js_string(interpreter, String(""));
if (vm.argument_count() == 1)
return js_string(vm, String(""));
auto temp_index_start = index_start;
index_start = index_end;
index_end = temp_index_start;
@ -350,23 +351,23 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
auto part_length = index_end - index_start;
auto string_part = string.substring(index_start, part_length);
return js_string(interpreter, string_part);
return js_string(vm, string_part);
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::includes)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
auto search_string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto search_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
// FIXME: position should index a UTF-16 code_point view of the string.
size_t position = 0;
if (interpreter.argument_count() >= 2) {
position = interpreter.argument(1).to_size_t(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
position = vm.argument(1).to_size_t(global_object);
if (vm.exception())
return {};
if (position >= string.length())
return Value(false);
@ -382,17 +383,17 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::includes)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
if (interpreter.argument_count() == 0)
return js_string(interpreter, string);
if (vm.argument_count() == 0)
return js_string(vm, string);
// FIXME: index_start and index_end should index a UTF-16 code_point view of the string.
auto string_length = static_cast<i32>(string.length());
auto index_start = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
auto index_start = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
auto index_end = string_length;
@ -402,13 +403,13 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
else if (index_start < 0)
index_start = string_length + index_start;
if (interpreter.argument_count() >= 2) {
index_end = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
index_end = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (index_end < negative_min_index)
return js_string(interpreter, String::empty());
return js_string(vm, String::empty());
if (index_end > string_length)
index_end = string_length;
@ -417,33 +418,33 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
}
if (index_start >= index_end)
return js_string(interpreter, String::empty());
return js_string(vm, String::empty());
auto part_length = index_end - index_start;
auto string_part = string.substring(index_start, part_length);
return js_string(interpreter, string_part);
return js_string(vm, string_part);
}
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::last_index_of)
{
auto string = ak_string_from(interpreter, global_object);
auto string = ak_string_from(vm, global_object);
if (string.is_null())
return {};
if (interpreter.argument_count() == 0)
if (vm.argument_count() == 0)
return Value(-1);
auto search_string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto search_string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
if (search_string.length() > string.length())
return Value(-1);
auto max_index = string.length() - search_string.length();
auto from_index = max_index;
if (interpreter.argument_count() >= 2) {
if (vm.argument_count() >= 2) {
// FIXME: from_index should index a UTF-16 code_point view of the string.
from_index = min(interpreter.argument(1).to_size_t(interpreter), max_index);
if (interpreter.exception())
from_index = min(vm.argument(1).to_size_t(global_object), max_index);
if (vm.exception())
return {};
}
@ -458,14 +459,14 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::last_index_of)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::symbol_iterator)
{
auto this_object = interpreter.this_value(global_object);
auto this_object = vm.this_value(global_object);
if (this_object.is_undefined() || this_object.is_null()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndef);
vm.throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndef);
return {};
}
auto string = this_object.to_string(interpreter);
if (interpreter.exception())
auto string = this_object.to_string(global_object);
if (vm.exception())
return {};
return StringIterator::create(global_object, string);
}

View file

@ -60,7 +60,7 @@ Value SymbolConstructor::call()
{
if (!vm().argument_count())
return js_symbol(heap(), "", false);
return js_symbol(heap(), vm().argument(0).to_string(interpreter()), false);
return js_symbol(heap(), vm().argument(0).to_string(global_object()), false);
}
Value SymbolConstructor::construct(Interpreter& interpreter, Function&)
@ -72,10 +72,10 @@ Value SymbolConstructor::construct(Interpreter& interpreter, Function&)
JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_)
{
String description;
if (!interpreter.argument_count()) {
if (!vm.argument_count()) {
description = "undefined";
} else {
description = interpreter.argument(0).to_string(interpreter);
description = vm.argument(0).to_string(global_object);
}
return global_object.vm().get_global_symbol(description);
@ -83,15 +83,15 @@ JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_)
JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::key_for)
{
auto argument = interpreter.argument(0);
auto argument = vm.argument(0);
if (!argument.is_symbol()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotASymbol, argument.to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::NotASymbol, argument.to_string_without_side_effects().characters());
return {};
}
auto& symbol = argument.as_symbol();
if (symbol.is_global())
return js_string(interpreter, symbol.description());
return js_string(vm, symbol.description());
return js_undefined();
}

View file

@ -58,13 +58,13 @@ SymbolPrototype::~SymbolPrototype()
{
}
static SymbolObject* typed_this(Interpreter& interpreter, GlobalObject& global_object)
static SymbolObject* typed_this(VM& vm, GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_symbol_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Symbol");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Symbol");
return nullptr;
}
return static_cast<SymbolObject*>(this_object);
@ -72,24 +72,24 @@ static SymbolObject* typed_this(Interpreter& interpreter, GlobalObject& global_o
JS_DEFINE_NATIVE_GETTER(SymbolPrototype::description_getter)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return js_string(interpreter, this_object->description());
return js_string(vm, this_object->description());
}
JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::to_string)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
auto string = this_object->primitive_symbol().to_string();
return js_string(interpreter, move(string));
return js_string(vm, move(string));
}
JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::value_of)
{
auto* this_object = typed_this(interpreter, global_object);
auto* this_object = typed_this(vm, global_object);
if (!this_object)
return {};
return this_object->value_of();

View file

@ -55,11 +55,11 @@ Uint8ClampedArray::~Uint8ClampedArray()
JS_DEFINE_NATIVE_GETTER(Uint8ClampedArray::length_getter)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (StringView(this_object->class_name()) != "Uint8ClampedArray") {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotA, "Uint8ClampedArray");
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Uint8ClampedArray");
return {};
}
return Value(static_cast<const Uint8ClampedArray*>(this_object)->length());
@ -69,7 +69,7 @@ bool Uint8ClampedArray::put_by_index(u32 property_index, Value value)
{
// FIXME: Use attributes
ASSERT(property_index < m_length);
auto number = value.to_i32(interpreter());
auto number = value.to_i32(global_object());
if (vm().exception())
return {};
m_data[property_index] = clamp(number, 0, 255);

View file

@ -300,7 +300,7 @@ Value VM::get_new_target() const
return get_this_environment()->new_target();
}
Value VM::call(Function& function, Value this_value, Optional<MarkedValueList> arguments)
Value VM::call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments)
{
ASSERT(!exception());

View file

@ -32,6 +32,7 @@
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/ErrorTypes.h>
#include <LibJS/Runtime/Exception.h>
#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
@ -206,11 +207,26 @@ public:
const LexicalEnvironment* get_this_environment() const;
Value get_new_target() const;
[[nodiscard]] Value call(Function&, Value this_value, Optional<MarkedValueList> arguments);
template<typename... Args>
[[nodiscard]] ALWAYS_INLINE Value call(Function& function, Value this_value, Args... args)
{
// Are there any values in this argpack?
// args = [] -> if constexpr (false)
// args = [x, y, z] -> if constexpr ((void)x, true || ...)
if constexpr ((((void)args, true) || ...)) {
MarkedValueList arglist { heap() };
(..., arglist.append(move(args)));
return call(function, this_value, move(arglist));
}
return call(function, this_value);
}
private:
VM();
[[nodiscard]] Value call_internal(Function&, Value this_value, Optional<MarkedValueList> arguments);
Exception* m_exception { nullptr };
Heap m_heap;
@ -234,4 +250,13 @@ private:
#undef __JS_ENUMERATE
};
template<>
[[nodiscard]] ALWAYS_INLINE Value VM::call(Function& function, Value this_value, MarkedValueList arguments) { return call_internal(function, this_value, move(arguments)); }
template<>
[[nodiscard]] ALWAYS_INLINE Value VM::call(Function& function, Value this_value, Optional<MarkedValueList> arguments) { return call_internal(function, this_value, move(arguments)); }
template<>
[[nodiscard]] ALWAYS_INLINE Value VM::call(Function& function, Value this_value) { return call(function, this_value, Optional<MarkedValueList> {}); }
}

View file

@ -134,17 +134,17 @@ String Value::to_string_without_side_effects() const
}
}
PrimitiveString* Value::to_primitive_string(Interpreter& interpreter)
PrimitiveString* Value::to_primitive_string(GlobalObject& global_object)
{
if (is_string())
return &as_string();
auto string = to_string(interpreter);
if (interpreter.exception())
auto string = to_string(global_object);
if (global_object.vm().exception())
return nullptr;
return js_string(interpreter, string);
return js_string(global_object.heap(), string);
}
String Value::to_string(Interpreter& interpreter) const
String Value::to_string(GlobalObject& global_object) const
{
switch (m_type) {
case Type::Undefined:
@ -164,15 +164,15 @@ String Value::to_string(Interpreter& interpreter) const
case Type::String:
return m_value.as_string->string();
case Type::Symbol:
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "symbol", "string");
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "string");
return {};
case Type::BigInt:
return m_value.as_bigint->big_integer().to_base10();
case Type::Object: {
auto primitive_value = as_object().to_primitive(PreferredType::String);
if (interpreter.exception())
if (global_object.vm().exception())
return {};
return primitive_value.to_string(interpreter);
return primitive_value.to_string(global_object);
}
default:
ASSERT_NOT_REACHED();
@ -211,12 +211,12 @@ Value Value::to_primitive(PreferredType preferred_type) const
return *this;
}
Object* Value::to_object(Interpreter& interpreter, GlobalObject& global_object) const
Object* Value::to_object(GlobalObject& global_object) const
{
switch (m_type) {
case Type::Undefined:
case Type::Null:
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndef);
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndef);
return nullptr;
case Type::Boolean:
return BooleanObject::create(global_object, m_value.as_bool);
@ -236,17 +236,17 @@ Object* Value::to_object(Interpreter& interpreter, GlobalObject& global_object)
}
}
Value Value::to_numeric(Interpreter& interpreter) const
Value Value::to_numeric(GlobalObject& global_object) const
{
auto primitive = to_primitive(Value::PreferredType::Number);
if (interpreter.exception())
if (global_object.vm().exception())
return {};
if (primitive.is_bigint())
return primitive;
return primitive.to_number(interpreter);
return primitive.to_number(global_object);
}
Value Value::to_number(Interpreter& interpreter) const
Value Value::to_number(GlobalObject& global_object) const
{
switch (m_type) {
case Type::Undefined:
@ -272,16 +272,16 @@ Value Value::to_number(Interpreter& interpreter) const
return Value(parsed_double);
}
case Type::Symbol:
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "symbol", "number");
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "symbol", "number");
return {};
case Type::BigInt:
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::Convert, "BigInt", "number");
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::Convert, "BigInt", "number");
return {};
case Type::Object: {
auto primitive = m_value.as_object->to_primitive(PreferredType::Number);
if (interpreter.exception())
if (global_object.vm().exception())
return {};
return primitive.to_number(interpreter);
return primitive.to_number(global_object);
}
default:
ASSERT_NOT_REACHED();
@ -337,18 +337,18 @@ size_t Value::as_size_t() const
return min((double)as_i32(), MAX_ARRAY_LIKE_INDEX);
}
double Value::to_double(Interpreter& interpreter) const
double Value::to_double(GlobalObject& global_object) const
{
auto number = to_number(interpreter);
if (interpreter.exception())
auto number = to_number(global_object);
if (global_object.vm().exception())
return 0;
return number.as_double();
}
i32 Value::to_i32(Interpreter& interpreter) const
i32 Value::to_i32(GlobalObject& global_object) const
{
auto number = to_number(interpreter);
if (interpreter.exception())
auto number = to_number(global_object);
if (global_object.vm().exception())
return 0;
if (number.is_nan())
return 0;
@ -357,12 +357,12 @@ i32 Value::to_i32(Interpreter& interpreter) const
return number.as_i32();
}
size_t Value::to_size_t(Interpreter& interpreter) const
size_t Value::to_size_t(GlobalObject& global_object) const
{
if (is_empty())
return 0;
auto number = to_number(interpreter);
if (interpreter.exception())
auto number = to_number(global_object);
if (global_object.vm().exception())
return 0;
if (number.is_nan())
return 0;
@ -405,10 +405,10 @@ Value less_than_equals(Interpreter& interpreter, Value lhs, Value rhs)
Value bitwise_and(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -424,10 +424,10 @@ Value bitwise_and(Interpreter& interpreter, Value lhs, Value rhs)
Value bitwise_or(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -447,10 +447,10 @@ Value bitwise_or(Interpreter& interpreter, Value lhs, Value rhs)
Value bitwise_xor(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -470,7 +470,7 @@ Value bitwise_xor(Interpreter& interpreter, Value lhs, Value rhs)
Value bitwise_not(Interpreter& interpreter, Value lhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (lhs_numeric.is_number())
@ -483,12 +483,12 @@ Value bitwise_not(Interpreter& interpreter, Value lhs)
Value unary_plus(Interpreter& interpreter, Value lhs)
{
return lhs.to_number(interpreter);
return lhs.to_number(interpreter.global_object());
}
Value unary_minus(Interpreter& interpreter, Value lhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (lhs_numeric.is_number()) {
@ -505,10 +505,10 @@ Value unary_minus(Interpreter& interpreter, Value lhs)
Value left_shift(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -526,10 +526,10 @@ Value left_shift(Interpreter& interpreter, Value lhs, Value rhs)
Value right_shift(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -547,10 +547,10 @@ Value right_shift(Interpreter& interpreter, Value lhs, Value rhs)
Value unsigned_right_shift(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -574,10 +574,10 @@ Value add(Interpreter& interpreter, Value lhs, Value rhs)
return {};
if (lhs_primitive.is_string() || rhs_primitive.is_string()) {
auto lhs_string = lhs_primitive.to_string(interpreter);
auto lhs_string = lhs_primitive.to_string(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_string = rhs_primitive.to_string(interpreter);
auto rhs_string = rhs_primitive.to_string(interpreter.global_object());
if (interpreter.exception())
return {};
StringBuilder builder(lhs_string.length() + rhs_string.length());
@ -586,10 +586,10 @@ Value add(Interpreter& interpreter, Value lhs, Value rhs)
return js_string(interpreter, builder.to_string());
}
auto lhs_numeric = lhs_primitive.to_numeric(interpreter);
auto lhs_numeric = lhs_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs_primitive.to_numeric(interpreter);
auto rhs_numeric = rhs_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric))
@ -602,10 +602,10 @@ Value add(Interpreter& interpreter, Value lhs, Value rhs)
Value sub(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric))
@ -618,10 +618,10 @@ Value sub(Interpreter& interpreter, Value lhs, Value rhs)
Value mul(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric))
@ -634,10 +634,10 @@ Value mul(Interpreter& interpreter, Value lhs, Value rhs)
Value div(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric))
@ -650,10 +650,10 @@ Value div(Interpreter& interpreter, Value lhs, Value rhs)
Value mod(Interpreter& interpreter, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
auto lhs_numeric = lhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric)) {
@ -670,19 +670,20 @@ Value mod(Interpreter& interpreter, Value lhs, Value rhs)
return {};
}
Value exp(Interpreter& interpreter, Value lhs, Value rhs)
Value exp(GlobalObject& global_object, Value lhs, Value rhs)
{
auto lhs_numeric = lhs.to_numeric(interpreter);
if (interpreter.exception())
auto& vm = global_object.vm();
auto lhs_numeric = lhs.to_numeric(global_object);
if (vm.exception())
return {};
auto rhs_numeric = rhs.to_numeric(interpreter);
if (interpreter.exception())
auto rhs_numeric = rhs.to_numeric(global_object);
if (vm.exception())
return {};
if (both_number(lhs_numeric, rhs_numeric))
return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double()));
if (both_bigint(lhs_numeric, rhs_numeric))
return js_bigint(interpreter, Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer()));
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::BigIntBadOperatorOtherType, "exponentiation");
return js_bigint(vm.heap(), Crypto::NumberTheory::Power(lhs_numeric.as_bigint().big_integer(), rhs_numeric.as_bigint().big_integer()));
vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation");
return {};
}
@ -692,44 +693,46 @@ Value in(Interpreter& interpreter, Value lhs, Value rhs)
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::InOperatorWithObject);
return {};
}
auto lhs_string = lhs.to_string(interpreter);
auto lhs_string = lhs.to_string(interpreter.global_object());
if (interpreter.exception())
return {};
return Value(rhs.as_object().has_property(lhs_string));
}
Value instance_of(Interpreter& interpreter, Value lhs, Value rhs)
Value instance_of(GlobalObject& global_object, Value lhs, Value rhs)
{
auto& vm = global_object.vm();
if (!rhs.is_object()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::NotAnObject, rhs.to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, rhs.to_string_without_side_effects().characters());
return {};
}
auto has_instance_method = rhs.as_object().get(interpreter.vm().well_known_symbol_has_instance());
auto has_instance_method = rhs.as_object().get(vm.well_known_symbol_has_instance());
if (!has_instance_method.is_empty()) {
if (!has_instance_method.is_function()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::NotAFunction, has_instance_method.to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, has_instance_method.to_string_without_side_effects().characters());
return {};
}
return Value(interpreter.call(has_instance_method.as_function(), rhs, lhs).to_boolean());
return Value(vm.call(has_instance_method.as_function(), rhs, lhs).to_boolean());
}
if (!rhs.is_function()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::NotAFunction, rhs.to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, rhs.to_string_without_side_effects().characters());
return {};
}
return ordinary_has_instance(interpreter, lhs, rhs);
return ordinary_has_instance(global_object, lhs, rhs);
}
Value ordinary_has_instance(Interpreter& interpreter, Value lhs, Value rhs)
Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
{
auto& vm = global_object.vm();
if (!rhs.is_function())
return Value(false);
auto& rhs_function = rhs.as_function();
if (rhs_function.is_bound_function()) {
auto& bound_target = static_cast<BoundFunction&>(rhs_function);
return instance_of(interpreter, lhs, Value(&bound_target.target_function()));
return instance_of(global_object, lhs, Value(&bound_target.target_function()));
}
if (!lhs.is_object())
@ -737,20 +740,20 @@ Value ordinary_has_instance(Interpreter& interpreter, Value lhs, Value rhs)
Object* lhs_object = &lhs.as_object();
auto rhs_prototype = rhs_function.get("prototype");
if (interpreter.exception())
if (vm.exception())
return {};
if (!rhs_prototype.is_object()) {
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::InstanceOfOperatorBadPrototype, rhs_prototype.to_string_without_side_effects().characters());
vm.throw_exception<TypeError>(global_object, ErrorType::InstanceOfOperatorBadPrototype, rhs_prototype.to_string_without_side_effects().characters());
return {};
}
while (true) {
lhs_object = lhs_object->prototype();
if (interpreter.exception())
if (vm.exception())
return {};
if (!lhs_object)
return Value(false);
if (same_value(interpreter, rhs_prototype, lhs_object))
if (same_value(rhs_prototype, lhs_object))
return Value(true);
}
}
@ -760,7 +763,7 @@ const LogStream& operator<<(const LogStream& stream, const Value& value)
return stream << (value.is_empty() ? "<empty>" : value.to_string_without_side_effects());
}
bool same_value(Interpreter& interpreter, Value lhs, Value rhs)
bool same_value(Value lhs, Value rhs)
{
if (lhs.type() != rhs.type())
return false;
@ -783,10 +786,10 @@ bool same_value(Interpreter& interpreter, Value lhs, Value rhs)
return lhs_big_integer == rhs_big_integer;
}
return same_value_non_numeric(interpreter, lhs, rhs);
return same_value_non_numeric(lhs, rhs);
}
bool same_value_zero(Interpreter& interpreter, Value lhs, Value rhs)
bool same_value_zero(Value lhs, Value rhs)
{
if (lhs.type() != rhs.type())
return false;
@ -800,10 +803,10 @@ bool same_value_zero(Interpreter& interpreter, Value lhs, Value rhs)
if (lhs.is_bigint())
return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer();
return same_value_non_numeric(interpreter, lhs, rhs);
return same_value_non_numeric(lhs, rhs);
}
bool same_value_non_numeric(Interpreter&, Value lhs, Value rhs)
bool same_value_non_numeric(Value lhs, Value rhs)
{
ASSERT(!lhs.is_number() && !lhs.is_bigint());
ASSERT(lhs.type() == rhs.type());
@ -825,7 +828,7 @@ bool same_value_non_numeric(Interpreter&, Value lhs, Value rhs)
}
}
bool strict_eq(Interpreter& interpreter, Value lhs, Value rhs)
bool strict_eq(Value lhs, Value rhs)
{
if (lhs.type() != rhs.type())
return false;
@ -841,22 +844,22 @@ bool strict_eq(Interpreter& interpreter, Value lhs, Value rhs)
if (lhs.is_bigint())
return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer();
return same_value_non_numeric(interpreter, lhs, rhs);
return same_value_non_numeric(lhs, rhs);
}
bool abstract_eq(Interpreter& interpreter, Value lhs, Value rhs)
{
if (lhs.type() == rhs.type())
return strict_eq(interpreter, lhs, rhs);
return strict_eq(lhs, rhs);
if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
return true;
if (lhs.is_number() && rhs.is_string())
return abstract_eq(interpreter, lhs, rhs.to_number(interpreter));
return abstract_eq(interpreter, lhs, rhs.to_number(interpreter.global_object()));
if (lhs.is_string() && rhs.is_number())
return abstract_eq(interpreter, lhs.to_number(interpreter), rhs);
return abstract_eq(interpreter, lhs.to_number(interpreter.global_object()), rhs);
if (lhs.is_bigint() && rhs.is_string()) {
auto& rhs_string = rhs.as_string().string();
@ -869,10 +872,10 @@ bool abstract_eq(Interpreter& interpreter, Value lhs, Value rhs)
return abstract_eq(interpreter, rhs, lhs);
if (lhs.is_boolean())
return abstract_eq(interpreter, lhs.to_number(interpreter), rhs);
return abstract_eq(interpreter, lhs.to_number(interpreter.global_object()), rhs);
if (rhs.is_boolean())
return abstract_eq(interpreter, lhs, rhs.to_number(interpreter));
return abstract_eq(interpreter, lhs, rhs.to_number(interpreter.global_object()));
if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object())
return abstract_eq(interpreter, lhs, rhs.to_primitive());
@ -960,10 +963,10 @@ TriState abstract_relation(Interpreter& interpreter, bool left_first, Value lhs,
return TriState::False;
}
auto x_numeric = x_primitive.to_numeric(interpreter);
auto x_numeric = x_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
auto y_numeric = y_primitive.to_numeric(interpreter);
auto y_numeric = y_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception())
return {};
@ -1014,7 +1017,7 @@ size_t length_of_array_like(Interpreter& interpreter, Value value)
auto result = value.as_object().get("length");
if (interpreter.exception())
return 0;
return result.to_size_t(interpreter);
return result.to_size_t(interpreter.global_object());
}
}

View file

@ -240,16 +240,16 @@ public:
i32 as_i32() const;
size_t as_size_t() const;
String to_string(Interpreter&) const;
PrimitiveString* to_primitive_string(Interpreter&);
String to_string(GlobalObject&) const;
PrimitiveString* to_primitive_string(GlobalObject&);
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;
Object* to_object(GlobalObject&) const;
Value to_numeric(GlobalObject&) const;
Value to_number(GlobalObject&) const;
BigInt* to_bigint(GlobalObject&) const;
double to_double(Interpreter&) const;
i32 to_i32(Interpreter&) const;
size_t to_size_t(Interpreter&) const;
double to_double(GlobalObject&) const;
i32 to_i32(GlobalObject&) const;
size_t to_size_t(GlobalObject&) const;
bool to_boolean() const;
String to_string_without_side_effects() const;
@ -320,16 +320,16 @@ Value sub(Interpreter&, Value lhs, Value rhs);
Value mul(Interpreter&, Value lhs, Value rhs);
Value div(Interpreter&, Value lhs, Value rhs);
Value mod(Interpreter&, Value lhs, Value rhs);
Value exp(Interpreter&, Value lhs, Value rhs);
Value exp(GlobalObject&, Value lhs, Value rhs);
Value in(Interpreter&, Value lhs, Value rhs);
Value instance_of(Interpreter&, Value lhs, Value rhs);
Value ordinary_has_instance(Interpreter& interpreter, Value lhs, Value rhs);
Value instance_of(GlobalObject&, Value lhs, Value rhs);
Value ordinary_has_instance(GlobalObject&, Value lhs, Value rhs);
bool abstract_eq(Interpreter&, Value lhs, Value rhs);
bool strict_eq(Interpreter&, Value lhs, Value rhs);
bool same_value(Interpreter&, Value lhs, Value rhs);
bool same_value_zero(Interpreter&, Value lhs, Value rhs);
bool same_value_non_numeric(Interpreter&, Value lhs, Value rhs);
bool strict_eq(Value lhs, Value rhs);
bool same_value(Value lhs, Value rhs);
bool same_value_zero(Value lhs, Value rhs);
bool same_value_non_numeric(Value lhs, Value rhs);
TriState abstract_relation(Interpreter&, bool left_first, Value lhs, Value rhs);
size_t length_of_array_like(Interpreter&, Value);

View file

@ -62,14 +62,14 @@ LocationObject::~LocationObject()
JS_DEFINE_NATIVE_GETTER(LocationObject::href_getter)
{
auto& window = static_cast<WindowObject&>(global_object);
return JS::js_string(interpreter, window.impl().document().url().to_string());
return JS::js_string(vm, window.impl().document().url().to_string());
}
JS_DEFINE_NATIVE_SETTER(LocationObject::href_setter)
{
auto& window = static_cast<WindowObject&>(global_object);
auto new_href = value.to_string(interpreter);
if (interpreter.exception())
auto new_href = value.to_string(global_object);
if (vm.exception())
return;
window.impl().did_set_location_href({}, new_href);
}
@ -77,13 +77,13 @@ JS_DEFINE_NATIVE_SETTER(LocationObject::href_setter)
JS_DEFINE_NATIVE_GETTER(LocationObject::pathname_getter)
{
auto& window = static_cast<WindowObject&>(global_object);
return JS::js_string(interpreter, window.impl().document().url().path());
return JS::js_string(vm, window.impl().document().url().path());
}
JS_DEFINE_NATIVE_GETTER(LocationObject::hostname_getter)
{
auto& window = static_cast<WindowObject&>(global_object);
return JS::js_string(interpreter, window.impl().document().url().host());
return JS::js_string(vm, window.impl().document().url().host());
}
JS_DEFINE_NATIVE_GETTER(LocationObject::host_getter)
@ -94,7 +94,7 @@ JS_DEFINE_NATIVE_GETTER(LocationObject::host_getter)
builder.append(url.host());
builder.append(':');
builder.appendf("%u", url.port());
return JS::js_string(interpreter, builder.to_string());
return JS::js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_GETTER(LocationObject::hash_getter)
@ -102,11 +102,11 @@ JS_DEFINE_NATIVE_GETTER(LocationObject::hash_getter)
auto& window = static_cast<WindowObject&>(global_object);
auto fragment = window.impl().document().url().fragment();
if (!fragment.length())
return JS::js_string(interpreter, "");
return JS::js_string(vm, "");
StringBuilder builder;
builder.append('#');
builder.append(fragment);
return JS::js_string(interpreter, builder.to_string());
return JS::js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_GETTER(LocationObject::search_getter)
@ -114,11 +114,11 @@ JS_DEFINE_NATIVE_GETTER(LocationObject::search_getter)
auto& window = static_cast<WindowObject&>(global_object);
auto query = window.impl().document().url().query();
if (!query.length())
return JS::js_string(interpreter, "");
return JS::js_string(vm, "");
StringBuilder builder;
builder.append('?');
builder.append(query);
return JS::js_string(interpreter, builder.to_string());
return JS::js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_GETTER(LocationObject::protocol_getter)
@ -127,7 +127,7 @@ JS_DEFINE_NATIVE_GETTER(LocationObject::protocol_getter)
StringBuilder builder;
builder.append(window.impl().document().url().protocol());
builder.append(':');
return JS::js_string(interpreter, builder.to_string());
return JS::js_string(vm, builder.to_string());
}
JS_DEFINE_NATIVE_FUNCTION(LocationObject::reload)

View file

@ -62,7 +62,7 @@ NavigatorObject::~NavigatorObject()
JS_DEFINE_NATIVE_GETTER(NavigatorObject::user_agent_getter)
{
return JS::js_string(interpreter, ResourceLoader::the().user_agent());
return JS::js_string(vm, ResourceLoader::the().user_agent());
}
}

View file

@ -99,15 +99,15 @@ Origin WindowObject::origin() const
return impl().document().origin();
}
static DOM::Window* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& global_object)
static DOM::Window* impl_from(JS::VM& vm, JS::GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object) {
ASSERT_NOT_REACHED();
return nullptr;
}
if (StringView("WindowObject") != this_object->class_name()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WindowObject");
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WindowObject");
return nullptr;
}
return &static_cast<WindowObject*>(this_object)->impl();
@ -115,13 +115,13 @@ static DOM::Window* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& gl
JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
String message = "";
if (interpreter.argument_count()) {
message = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
if (vm.argument_count()) {
message = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
impl->alert(message);
@ -130,13 +130,13 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
String message = "";
if (interpreter.argument_count()) {
message = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
if (vm.argument_count()) {
message = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
}
return JS::Value(impl->confirm(message));
@ -144,24 +144,24 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval");
return {};
}
auto* callback_object = interpreter.argument(0).to_object(interpreter, global_object);
auto* callback_object = vm.argument(0).to_object(global_object);
if (!callback_object)
return {};
if (!callback_object->is_function()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
return {};
}
i32 interval = 0;
if (interpreter.argument_count() >= 2) {
interval = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
interval = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (interval < 0)
interval = 0;
@ -173,24 +173,24 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setTimeout");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setTimeout");
return {};
}
auto* callback_object = interpreter.argument(0).to_object(interpreter, global_object);
auto* callback_object = vm.argument(0).to_object(global_object);
if (!callback_object)
return {};
if (!callback_object->is_function()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
return {};
}
i32 interval = 0;
if (interpreter.argument_count() >= 2) {
interval = interpreter.argument(1).to_i32(interpreter);
if (interpreter.exception())
if (vm.argument_count() >= 2) {
interval = vm.argument(1).to_i32(global_object);
if (vm.exception())
return {};
if (interval < 0)
interval = 0;
@ -202,15 +202,15 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearTimeout");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearTimeout");
return {};
}
i32 timer_id = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
i32 timer_id = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
impl->clear_timeout(timer_id);
return JS::js_undefined();
@ -218,15 +218,15 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearInterval");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearInterval");
return {};
}
i32 timer_id = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
i32 timer_id = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
impl->clear_timeout(timer_id);
return JS::js_undefined();
@ -234,18 +234,18 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "requestAnimationFrame");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "requestAnimationFrame");
return {};
}
auto* callback_object = interpreter.argument(0).to_object(interpreter, global_object);
auto* callback_object = vm.argument(0).to_object(global_object);
if (!callback_object)
return {};
if (!callback_object->is_function()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAFunctionNoParam);
return {};
}
return JS::Value(impl->request_animation_frame(*static_cast<JS::Function*>(callback_object)));
@ -253,15 +253,15 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "cancelAnimationFrame");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "cancelAnimationFrame");
return {};
}
auto id = interpreter.argument(0).to_i32(interpreter);
if (interpreter.exception())
auto id = vm.argument(0).to_i32(global_object);
if (vm.exception())
return {};
impl->cancel_animation_frame(id);
return JS::js_undefined();
@ -269,52 +269,52 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "atob");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "atob");
return {};
}
auto string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto decoded = decode_base64(StringView(string));
// decode_base64() returns a byte string. LibJS uses UTF-8 for strings. Use Latin1Decoder to convert bytes 128-255 to UTF-8.
return JS::js_string(interpreter, TextCodec::decoder_for("iso-8859-1")->to_utf8(decoded));
return JS::js_string(vm, TextCodec::decoder_for("iso-8859-1")->to_utf8(decoded));
}
JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
if (!interpreter.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "btoa");
if (!vm.argument_count()) {
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "btoa");
return {};
}
auto string = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto string = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
Vector<u8> byte_string;
byte_string.ensure_capacity(string.length());
for (u32 code_point : Utf8View(string)) {
if (code_point > 0xff) {
interpreter.vm().throw_exception<JS::InvalidCharacterError>(global_object, JS::ErrorType::NotAByteString, "btoa");
vm.throw_exception<JS::InvalidCharacterError>(global_object, JS::ErrorType::NotAByteString, "btoa");
return {};
}
byte_string.append(code_point);
}
auto encoded = encode_base64(byte_string.span());
return JS::js_string(interpreter, move(encoded));
return JS::js_string(vm, move(encoded));
}
JS_DEFINE_NATIVE_GETTER(WindowObject::document_getter)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
return wrap(global_object, impl->document());

View file

@ -58,13 +58,13 @@ XMLHttpRequestPrototype::~XMLHttpRequestPrototype()
{
}
static XMLHttpRequest* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& global_object)
static XMLHttpRequest* impl_from(JS::VM& vm, JS::GlobalObject& global_object)
{
auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (StringView("XMLHttpRequestWrapper") != this_object->class_name()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "XMLHttpRequest");
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "XMLHttpRequest");
return nullptr;
}
return &static_cast<XMLHttpRequestWrapper*>(this_object)->impl();
@ -72,14 +72,14 @@ static XMLHttpRequest* impl_from(JS::Interpreter& interpreter, JS::GlobalObject&
JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::open)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
auto arg0 = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto arg0 = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
auto arg1 = interpreter.argument(1).to_string(interpreter);
if (interpreter.exception())
auto arg1 = vm.argument(1).to_string(global_object);
if (vm.exception())
return {};
impl->open(arg0, arg1);
return JS::js_undefined();
@ -87,7 +87,7 @@ JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::open)
JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::send)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
impl->send();
@ -96,7 +96,7 @@ JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::send)
JS_DEFINE_NATIVE_GETTER(XMLHttpRequestPrototype::ready_state_getter)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
return JS::Value((i32)impl->ready_state());
@ -104,10 +104,10 @@ JS_DEFINE_NATIVE_GETTER(XMLHttpRequestPrototype::ready_state_getter)
JS_DEFINE_NATIVE_GETTER(XMLHttpRequestPrototype::response_text_getter)
{
auto* impl = impl_from(interpreter, global_object);
auto* impl = impl_from(vm, global_object);
if (!impl)
return {};
return JS::js_string(interpreter, impl->response_text());
return JS::js_string(vm, impl->response_text());
}
}

View file

@ -500,13 +500,13 @@ void generate_implementation(const IDL::Interface& interface)
// Implementation: impl_from()
if (!interface.attributes.is_empty() || !interface.functions.is_empty()) {
out() << "static " << interface.fully_qualified_name << "* impl_from(JS::Interpreter& interpreter, JS::GlobalObject& global_object)";
out() << "static " << interface.fully_qualified_name << "* impl_from(JS::VM& vm, JS::GlobalObject& global_object)";
out() << "{";
out() << " auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);";
out() << " auto* this_object = vm.this_value(global_object).to_object(global_object);";
out() << " if (!this_object)";
out() << " return {};";
out() << " if (!this_object->inherits(\"" << wrapper_class << "\")) {";
out() << " interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << interface.fully_qualified_name << "\");";
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << interface.fully_qualified_name << "\");";
out() << " return nullptr;";
out() << " }";
out() << " return &static_cast<" << wrapper_class << "*>(this_object)->impl();";
@ -521,27 +521,27 @@ void generate_implementation(const IDL::Interface& interface)
out() << " return {};";
};
if (parameter.type.name == "DOMString") {
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_string(interpreter);";
out() << " if (interpreter.exception())";
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_string(global_object);";
out() << " if (vm.exception())";
generate_return();
} else if (parameter.type.name == "EventListener") {
out() << " if (!" << js_name << js_suffix << ".is_function()) {";
out() << " interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"Function\");";
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"Function\");";
generate_return();
out() << " }";
out() << " auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));";
} else if (is_wrappable_type(parameter.type)) {
out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(interpreter, global_object);";
out() << " if (interpreter.exception())";
out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(global_object);";
out() << " if (vm.exception())";
generate_return();
out() << " if (!" << cpp_name << "_object->inherits(\"" << parameter.type.name << "Wrapper\")) {";
out() << " interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << parameter.type.name << "\");";
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << parameter.type.name << "\");";
generate_return();
out() << " }";
out() << " auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();";
} else if (parameter.type.name == "double") {
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(interpreter);";
out() << " if (interpreter.exception())";
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(global_object);";
out() << " if (vm.exception())";
generate_return();
} else if (parameter.type.name == "boolean") {
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_boolean();";
@ -556,7 +556,7 @@ void generate_implementation(const IDL::Interface& interface)
size_t argument_index = 0;
for (auto& parameter : parameters) {
parameter_names.append(snake_name(parameter.name));
out() << " auto arg" << argument_index << " = interpreter.argument(" << argument_index << ");";
out() << " auto arg" << argument_index << " = vm.argument(" << argument_index << ");";
generate_to_cpp(parameter, "arg", argument_index, snake_name(parameter.name), return_void);
++argument_index;
}
@ -580,7 +580,7 @@ void generate_implementation(const IDL::Interface& interface)
}
if (return_type.name == "DOMString") {
out() << " return JS::js_string(interpreter, retval);";
out() << " return JS::js_string(vm, retval);";
} else if (return_type.name == "ArrayFromVector") {
// FIXME: Remove this fake type hack once it's no longer needed.
// Basically once we have NodeList we can throw this out.
@ -604,7 +604,7 @@ void generate_implementation(const IDL::Interface& interface)
for (auto& attribute : interface.attributes) {
out() << "JS_DEFINE_NATIVE_GETTER(" << wrapper_class << "::" << attribute.getter_callback_name << ")";
out() << "{";
out() << " auto* impl = impl_from(interpreter, global_object);";
out() << " auto* impl = impl_from(vm, global_object);";
out() << " if (!impl)";
out() << " return {};";
@ -629,7 +629,7 @@ void generate_implementation(const IDL::Interface& interface)
if (!attribute.readonly) {
out() << "JS_DEFINE_NATIVE_SETTER(" << wrapper_class << "::" << attribute.setter_callback_name << ")";
out() << "{";
out() << " auto* impl = impl_from(interpreter, global_object);";
out() << " auto* impl = impl_from(vm, global_object);";
out() << " if (!impl)";
out() << " return;";
@ -652,15 +652,15 @@ void generate_implementation(const IDL::Interface& interface)
for (auto& function : interface.functions) {
out() << "JS_DEFINE_NATIVE_FUNCTION(" << wrapper_class << "::" << snake_name(function.name) << ")";
out() << "{";
out() << " auto* impl = impl_from(interpreter, global_object);";
out() << " auto* impl = impl_from(vm, global_object);";
out() << " if (!impl)";
out() << " return {};";
if (function.length() > 0) {
out() << " if (interpreter.argument_count() < " << function.length() << ") {";
out() << " if (vm.argument_count() < " << function.length() << ") {";
if (function.length() == 1)
out() << " interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, \"" << function.name << "\");";
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, \"" << function.name << "\");";
else
out() << " interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");";
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");";
out() << " return {};";
out() << " }";
}

View file

@ -390,9 +390,9 @@ ReplObject::~ReplObject()
JS_DEFINE_NATIVE_FUNCTION(ReplObject::save_to_file)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return JS::Value(false);
String save_path = interpreter.argument(0).to_string_without_side_effects();
String save_path = vm.argument(0).to_string_without_side_effects();
StringView path = StringView(save_path.characters());
if (write_to_file(path)) {
return JS::Value(true);
@ -402,9 +402,9 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::save_to_file)
JS_DEFINE_NATIVE_FUNCTION(ReplObject::exit_interpreter)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
exit(0);
auto exit_code = interpreter.argument(0).to_number(interpreter);
auto exit_code = vm.argument(0).to_number(global_object);
if (::vm->exception())
return {};
exit(exit_code.as_double());
@ -422,10 +422,10 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::repl_help)
JS_DEFINE_NATIVE_FUNCTION(ReplObject::load_file)
{
if (!interpreter.argument_count())
if (!vm.argument_count())
return JS::Value(false);
for (auto& file : interpreter.call_frame().arguments) {
for (auto& file : vm.call_frame().arguments) {
String file_name = file.as_string().string();
auto js_file = Core::File::construct(file_name);
if (!js_file->open(Core::IODevice::ReadOnly)) {
@ -439,7 +439,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReplObject::load_file)
} else {
source = file_contents;
}
parse_and_run(interpreter, source);
parse_and_run(vm.interpreter(), source);
}
return JS::Value(true);
}
@ -822,7 +822,7 @@ int main(int argc, char** argv)
if (!variable.is_object())
break;
const auto* object = variable.to_object(*interpreter, interpreter->global_object());
const auto* object = variable.to_object(interpreter->global_object());
const auto& shape = object->shape();
list_all_properties(shape, property_name);
if (results.size())

View file

@ -160,7 +160,7 @@ void TestRunnerGlobalObject::initialize()
JS_DEFINE_NATIVE_FUNCTION(TestRunnerGlobalObject::is_strict_mode)
{
return JS::Value(interpreter.in_strict_mode());
return JS::Value(vm.interpreter().in_strict_mode());
}
static void cleanup_and_exit()

View file

@ -125,8 +125,8 @@ TestRunnerObject::~TestRunnerObject()
JS_DEFINE_NATIVE_FUNCTION(TestRunnerObject::change_page)
{
auto url = interpreter.argument(0).to_string(interpreter);
if (interpreter.exception())
auto url = vm.argument(0).to_string(global_object);
if (vm.exception())
return {};
if (g_on_page_change)