1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 03:07:43 +00:00

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
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 String DateCell::display(Cell& cell, const CellTypeMetadata& metadata) const
{ {
auto timestamp = js_value(cell, metadata); 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) if (metadata.length >= 0)
return string.substring(0, metadata.length); 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 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 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()) if (metadata.format.is_empty())
string = value.to_string_without_side_effects(); string = value.to_string_without_side_effects();
else 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) if (metadata.length >= 0)
return string.substring(0, metadata.length); 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 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) JS_DEFINE_NATIVE_FUNCTION(SheetGlobalObject::parse_cell_name)
{ {
if (interpreter.argument_count() != 1) { if (vm.argument_count() != 1) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to parse_cell_name()"); vm.throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to parse_cell_name()");
return {}; return {};
} }
auto name_value = interpreter.argument(0); auto name_value = vm.argument(0);
if (!name_value.is_string()) { 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 {}; return {};
} }
auto position = Sheet::parse_cell_name(name_value.as_string().string()); auto position = Sheet::parse_cell_name(name_value.as_string().string());
if (!position.has_value()) if (!position.has_value())
return JS::js_undefined(); return JS::js_undefined();
auto object = JS::Object::create_empty(interpreter.global_object()); auto object = JS::Object::create_empty(global_object);
object->put("column", JS::js_string(interpreter, position.value().column)); object->put("column", JS::js_string(vm, position.value().column));
object->put("row", JS::Value((unsigned)position.value().row)); object->put("row", JS::Value((unsigned)position.value().row));
return object; return object;
@ -124,22 +124,22 @@ void WorkbookObject::initialize(JS::GlobalObject& global_object)
JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet) JS_DEFINE_NATIVE_FUNCTION(WorkbookObject::sheet)
{ {
if (interpreter.argument_count() != 1) { if (vm.argument_count() != 1) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to sheet()"); vm.throw_exception<JS::TypeError>(global_object, "Expected exactly one argument to sheet()");
return {}; return {};
} }
auto name_value = interpreter.argument(0); auto name_value = vm.argument(0);
if (!name_value.is_string() && !name_value.is_number()) { 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 {}; 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) if (!this_object)
return {}; return {};
if (!this_object->inherits("WorkbookObject")) { 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 {}; return {};
} }

View file

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

View file

@ -27,22 +27,22 @@
#pragma once #pragma once
#define JS_DECLARE_NATIVE_FUNCTION(name) \ #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) \ #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) \ #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) \ #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) \ #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) \ #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 \ #define JS_ENUMERATE_NATIVE_OBJECTS \
__JS_ENUMERATE(Array, array, ArrayPrototype, ArrayConstructor) \ __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) if (!this_object)
return {}; return {};
if (!this_object->is_array()) { 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 nullptr;
} }
return static_cast<Array*>(this_object); 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) JS_DEFINE_NATIVE_GETTER(Array::length_getter)
{ {
auto* array = typed_this(interpreter, global_object); auto* array = typed_this(vm, global_object);
if (!array) if (!array)
return {}; return {};
return Value(static_cast<i32>(array->indexed_properties().array_like_size())); 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) JS_DEFINE_NATIVE_SETTER(Array::length_setter)
{ {
auto* array = typed_this(interpreter, global_object); auto* array = typed_this(vm, global_object);
if (!array) if (!array)
return; return;
auto length = value.to_number(interpreter); auto length = value.to_number(global_object);
if (interpreter.exception()) if (vm.exception())
return; return;
if (length.is_nan() || length.is_infinity() || length.as_double() < 0) { 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; return;
} }
array->indexed_properties().set_array_like_size(length.as_double()); array->indexed_properties().set_array_like_size(length.as_double());

View file

@ -39,7 +39,7 @@ public:
explicit Array(Object& prototype); explicit Array(Object& prototype);
virtual ~Array() override; virtual ~Array() override;
static Array* typed_this(Interpreter&, GlobalObject&); static Array* typed_this(VM&, GlobalObject&);
private: private:
virtual bool is_array() const override { return true; } 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) JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
{ {
auto value = interpreter.argument(0); auto value = vm.argument(0);
auto object = value.to_object(interpreter, global_object); auto object = value.to_object(global_object);
if (!object) if (!object)
return {}; return {};
@ -98,23 +98,23 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// Array.from() lets you create Arrays from: // Array.from() lets you create Arrays from:
if (auto size = object->indexed_properties().array_like_size()) { if (auto size = object->indexed_properties().array_like_size()) {
// * array-like objects (objects with a length property and indexed elements) // * array-like objects (objects with a length property and indexed elements)
MarkedValueList elements(interpreter.heap()); MarkedValueList elements(vm.heap());
elements.ensure_capacity(size); elements.ensure_capacity(size);
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
elements.append(object->get(i)); elements.append(object->get(i));
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
array->set_indexed_property_elements(move(elements)); array->set_indexed_property_elements(move(elements));
} else { } else {
// * iterable objects // * iterable objects
get_iterator_values(global_object, value, [&](Value element) { get_iterator_values(global_object, value, [&](Value element) {
if (interpreter.exception()) if (vm.exception())
return IterationDecision::Break; return IterationDecision::Break;
array->indexed_properties().append(element); array->indexed_properties().append(element);
return IterationDecision::Continue; return IterationDecision::Continue;
}); });
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
@ -126,15 +126,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::is_array) JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::is_array)
{ {
auto value = interpreter.argument(0); auto value = vm.argument(0);
return Value(value.is_array()); return Value(value.is_array());
} }
JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::of) JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::of)
{ {
auto* array = Array::create(global_object); auto* array = Array::create(global_object);
for (size_t i = 0; i < interpreter.argument_count(); ++i) for (size_t i = 0; i < vm.argument_count(); ++i)
array->indexed_properties().append(interpreter.argument(i)); array->indexed_properties().append(vm.argument(i));
return array; return array;
} }

View file

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

View file

@ -50,27 +50,27 @@ BooleanPrototype::~BooleanPrototype()
JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::to_string) 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()) { 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()) { 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 {}; return {};
} }
bool bool_value = static_cast<BooleanObject&>(this_object.as_object()).value_of().as_bool(); 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) 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()) { if (this_object.is_boolean()) {
return this_object; return this_object;
} }
if (!this_object.is_object() || !this_object.as_object().is_boolean_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 {}; return {};
} }

View file

@ -56,7 +56,7 @@ Value BoundFunction::call()
Value BoundFunction::construct(Interpreter& interpreter, Function& new_target) 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); this_value.as_object().set_prototype(m_constructor_prototype);
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};

View file

@ -60,47 +60,47 @@ ConsoleObject::~ConsoleObject()
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::log) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::log)
{ {
return interpreter.console().log(); return vm.interpreter().console().log();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::debug) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::debug)
{ {
return interpreter.console().debug(); return vm.interpreter().console().debug();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::info) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::info)
{ {
return interpreter.console().info(); return vm.interpreter().console().info();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::warn) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::warn)
{ {
return interpreter.console().warn(); return vm.interpreter().console().warn();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::error) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::error)
{ {
return interpreter.console().error(); return vm.interpreter().console().error();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::trace) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::trace)
{ {
return interpreter.console().trace(); return vm.interpreter().console().trace();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::count) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::count)
{ {
return interpreter.console().count(); return vm.interpreter().console().count();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::count_reset) JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::count_reset)
{ {
return interpreter.console().count_reset(); return vm.interpreter().console().count_reset();
} }
JS_DEFINE_NATIVE_FUNCTION(ConsoleObject::clear) 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()); 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; struct timeval tv;
gettimeofday(&tv, nullptr); gettimeofday(&tv, nullptr);
auto datetime = Core::DateTime::now(); auto datetime = Core::DateTime::now();
auto milliseconds = static_cast<u16>(tv.tv_usec / 1000); auto milliseconds = static_cast<u16>(tv.tv_usec / 1000);
return Date::create(global_object(), datetime, milliseconds); return Date::create(global_object(), datetime, milliseconds);
} }
if (interpreter.argument_count() == 1) { if (vm().argument_count() == 1) {
auto value = interpreter.argument(0); auto value = vm().argument(0);
if (value.is_string()) if (value.is_string())
value = parse_simplified_iso8601(value.as_string().string()); value = parse_simplified_iso8601(value.as_string().string());
// A timestamp since the epoch, in UTC. // 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. // 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 datetime = Core::DateTime::from_timestamp(static_cast<time_t>(value_as_double / 1000));
auto milliseconds = static_cast<u16>(fmod(value_as_double, 1000)); auto milliseconds = static_cast<u16>(fmod(value_as_double, 1000));
return Date::create(global_object(), datetime, milliseconds); return Date::create(global_object(), datetime, milliseconds);
} }
// A date/time in components, in local time. // A date/time in components, in local time.
// FIXME: This doesn't construct an "Invalid Date" object if one of the parameters is NaN. // 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; }; auto arg_or = [this](size_t i, i32 fallback) { return vm().argument_count() > i ? vm().argument(i).to_i32(global_object()) : fallback; };
int year = interpreter.argument(0).to_i32(interpreter); int year = vm().argument(0).to_i32(global_object());
int month_index = interpreter.argument(1).to_i32(interpreter); int month_index = vm().argument(1).to_i32(global_object());
int day = arg_or(2, 1); int day = arg_or(2, 1);
int hours = arg_or(3, 0); int hours = arg_or(3, 0);
int minutes = arg_or(4, 0); int minutes = arg_or(4, 0);
@ -219,11 +219,11 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::now)
JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse) JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
{ {
if (!interpreter.argument_count()) if (!vm.argument_count())
return js_nan(); return js_nan();
auto iso_8601 = interpreter.argument(0).to_string(interpreter); auto iso_8601 = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return js_nan(); return js_nan();
return parse_simplified_iso8601(iso_8601); return parse_simplified_iso8601(iso_8601);
@ -231,8 +231,8 @@ JS_DEFINE_NATIVE_FUNCTION(DateConstructor::parse)
JS_DEFINE_NATIVE_FUNCTION(DateConstructor::utc) 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; }; 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 = interpreter.argument(0).to_i32(interpreter); int year = vm.argument(0).to_i32(global_object);
if (year >= 0 && year <= 99) if (year >= 0 && year <= 99)
year += 1900; year += 1900;

View file

@ -36,13 +36,13 @@
namespace JS { 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) if (!this_object)
return nullptr; return nullptr;
if (!this_object->is_date()) { 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 nullptr;
} }
return static_cast<Date*>(this_object); return static_cast<Date*>(this_object);
@ -96,7 +96,7 @@ DatePrototype::~DatePrototype()
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_date) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->date())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->day())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->full_year())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->hours())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->milliseconds())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->minutes())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->month())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->seconds())); 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) 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) if (!this_object)
return {}; return {};
return Value(this_object->time()); return Value(this_object->time());
@ -168,7 +168,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_time)
JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_date) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_date())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_day())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_full_year())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_hours())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_milliseconds())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_month())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_minutes())); 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) 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) if (!this_object)
return {}; return {};
return Value(static_cast<double>(this_object->utc_seconds())); 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) 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) if (!this_object)
return {}; return {};
auto string = this_object->date_string(); 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) 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) if (!this_object)
return {}; return {};
auto string = this_object->iso_date_string(); 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) 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) if (!this_object)
return {}; return {};
// FIXME: Optional locales, options params. // FIXME: Optional locales, options params.
auto string = this_object->locale_date_string(); 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) 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) if (!this_object)
return {}; return {};
// FIXME: Optional locales, options params. // FIXME: Optional locales, options params.
auto string = this_object->locale_string(); 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) 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) if (!this_object)
return {}; return {};
// FIXME: Optional locales, options params. // FIXME: Optional locales, options params.
auto string = this_object->locale_time_string(); 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) 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) if (!this_object)
return {}; return {};
auto string = this_object->time_string(); 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) 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) if (!this_object)
return {}; return {};
auto string = this_object->string(); 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 = ""; String message = "";
if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) { 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()) if (interpreter.exception())
return {}; return {};
} }
return Error::create(global_object(), "Error", message); return Error::create(global_object(), "Error", message);
} }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName::ConstructorName(GlobalObject& global_object) \ ConstructorName::ConstructorName(GlobalObject& global_object) \
: NativeFunction(*global_object.function_prototype()) \ : NativeFunction(*global_object.function_prototype()) \
{ \ { \
} \ } \
void ConstructorName::initialize(GlobalObject& global_object) \ void ConstructorName::initialize(GlobalObject& global_object) \
{ \ { \
NativeFunction::initialize(global_object); \ NativeFunction::initialize(global_object); \
define_property("prototype", global_object.snake_name##_prototype(), 0); \ define_property("prototype", global_object.snake_name##_prototype(), 0); \
define_property("length", Value(1), Attribute::Configurable); \ define_property("length", Value(1), Attribute::Configurable); \
} \ } \
ConstructorName::~ConstructorName() { } \ ConstructorName::~ConstructorName() { } \
Value ConstructorName::call() \ Value ConstructorName::call() \
{ \ { \
return construct(interpreter(), *this); \ return construct(interpreter(), *this); \
} \ } \
Value ConstructorName::construct(Interpreter& interpreter, Function&) \ Value ConstructorName::construct(Interpreter&, Function&) \
{ \ { \
String message = ""; \ String message = ""; \
if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) { \ if (!vm().call_frame().arguments.is_empty() && !vm().call_frame().arguments[0].is_undefined()) { \
message = interpreter.call_frame().arguments[0].to_string(interpreter); \ message = vm().call_frame().arguments[0].to_string(global_object()); \
if (interpreter.exception()) \ if (vm().exception()) \
return {}; \ return {}; \
} \ } \
return ClassName::create(global_object(), message); \ return ClassName::create(global_object(), message); \
} }
JS_ENUMERATE_ERROR_SUBCLASSES JS_ENUMERATE_ERROR_SUBCLASSES

View file

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

View file

@ -55,76 +55,76 @@ ErrorPrototype::~ErrorPrototype()
JS_DEFINE_NATIVE_GETTER(ErrorPrototype::name_getter) 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) if (!this_object)
return {}; return {};
if (!this_object->is_error()) { 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 {};
} }
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) 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) if (!this_object)
return; return;
if (!this_object->is_error()) { 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;
} }
auto name = value.to_string(interpreter); auto name = value.to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return; return;
static_cast<Error*>(this_object)->set_name(name); static_cast<Error*>(this_object)->set_name(name);
} }
JS_DEFINE_NATIVE_GETTER(ErrorPrototype::message_getter) 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) if (!this_object)
return {}; return {};
if (!this_object->is_error()) { 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 {};
} }
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) JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
{ {
if (!interpreter.this_value(global_object).is_object()) { if (!vm.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()); vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, vm.this_value(global_object).to_string_without_side_effects().characters());
return {}; return {};
} }
auto& this_object = interpreter.this_value(global_object).as_object(); auto& this_object = vm.this_value(global_object).as_object();
String name = "Error"; String name = "Error";
auto name_property = this_object.get("name"); auto name_property = this_object.get("name");
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!name_property.is_empty() && !name_property.is_undefined()) { if (!name_property.is_empty() && !name_property.is_undefined()) {
name = name_property.to_string(interpreter); name = name_property.to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
String message = ""; String message = "";
auto message_property = this_object.get("message"); auto message_property = this_object.get("message");
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!message_property.is_empty() && !message_property.is_undefined()) { if (!message_property.is_empty() && !message_property.is_undefined()) {
message = message_property.to_string(interpreter); message = message_property.to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
if (name.length() == 0) if (name.length() == 0)
return js_string(interpreter, message); return js_string(vm, message);
if (message.length() == 0) if (message.length() == 0)
return js_string(interpreter, name); return js_string(vm, name);
return js_string(interpreter, String::format("%s: %s", name.characters(), message.characters())); return js_string(vm, String::format("%s: %s", name.characters(), message.characters()));
} }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #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 bound_this_value;
return &global_object(); return &global_object();
default: 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&) Value FunctionConstructor::construct(Interpreter& interpreter, Function&)
{ {
auto& vm = this->vm();
String parameters_source = ""; String parameters_source = "";
String body_source = ""; String body_source = "";
if (interpreter.argument_count() == 1) { if (vm.argument_count() == 1) {
body_source = interpreter.argument(0).to_string(interpreter); body_source = vm.argument(0).to_string(global_object());
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
if (interpreter.argument_count() > 1) { if (vm.argument_count() > 1) {
Vector<String> parameters; Vector<String> parameters;
for (size_t i = 0; i < interpreter.argument_count() - 1; ++i) { for (size_t i = 0; i < vm.argument_count() - 1; ++i) {
parameters.append(interpreter.argument(i).to_string(interpreter)); parameters.append(vm.argument(i).to_string(global_object()));
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
StringBuilder parameters_builder; StringBuilder parameters_builder;
parameters_builder.join(',', parameters); parameters_builder.join(',', parameters);
parameters_source = parameters_builder.build(); parameters_source = parameters_builder.build();
body_source = interpreter.argument(interpreter.argument_count() - 1).to_string(interpreter); body_source = vm.argument(vm.argument_count() - 1).to_string(global_object());
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
auto source = String::format("function anonymous(%s) { %s }", parameters_source.characters(), body_source.characters()); 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>(); auto function_expression = parser.parse_function_node<FunctionExpression>();
if (parser.has_errors()) { if (parser.has_errors()) {
auto error = parser.errors()[0]; 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 {};
} }
return function_expression->execute(interpreter, global_object()); return function_expression->execute(interpreter, global_object());

View file

@ -62,53 +62,53 @@ FunctionPrototype::~FunctionPrototype()
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply) 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) if (!this_object)
return {}; return {};
if (!this_object->is_function()) { 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 {};
} }
auto& function = static_cast<Function&>(*this_object); auto& function = static_cast<Function&>(*this_object);
auto this_arg = interpreter.argument(0); auto this_arg = vm.argument(0);
auto arg_array = interpreter.argument(1); auto arg_array = vm.argument(1);
if (arg_array.is_null() || arg_array.is_undefined()) 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()) { if (!arg_array.is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::FunctionArgsNotObject); vm.throw_exception<TypeError>(global_object, ErrorType::FunctionArgsNotObject);
return {}; return {};
} }
auto length_property = arg_array.as_object().get("length"); auto length_property = arg_array.as_object().get("length");
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto length = length_property.to_size_t(interpreter); auto length = length_property.to_size_t(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
MarkedValueList arguments(interpreter.heap()); MarkedValueList arguments(vm.heap());
for (size_t i = 0; i < length; ++i) { for (size_t i = 0; i < length; ++i) {
auto element = arg_array.as_object().get(i); auto element = arg_array.as_object().get(i);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
arguments.append(element.value_or(js_undefined())); 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) 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) if (!this_object)
return {}; return {};
if (!this_object->is_function()) { 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 {};
} }
auto& this_function = static_cast<Function&>(*this_object); 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; Vector<Value> arguments;
if (interpreter.argument_count() > 1) { if (vm.argument_count() > 1) {
arguments = interpreter.call_frame().arguments; arguments = vm.call_frame().arguments;
arguments.remove(0); arguments.remove(0);
} }
@ -117,30 +117,30 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::bind)
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call) 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) if (!this_object)
return {}; return {};
if (!this_object->is_function()) { 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 {};
} }
auto& function = static_cast<Function&>(*this_object); auto& function = static_cast<Function&>(*this_object);
auto this_arg = interpreter.argument(0); auto this_arg = vm.argument(0);
MarkedValueList arguments(interpreter.heap()); MarkedValueList arguments(vm.heap());
if (interpreter.argument_count() > 1) { if (vm.argument_count() > 1) {
for (size_t i = 1; i < interpreter.argument_count(); ++i) for (size_t i = 1; i < vm.argument_count(); ++i)
arguments.append(interpreter.argument(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) 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) if (!this_object)
return {}; return {};
if (!this_object->is_function()) { 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 {};
} }
String function_name = static_cast<Function*>(this_object)->name(); 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_name.is_null() ? "" : function_name.characters(),
function_parameters.characters(), function_parameters.characters(),
function_body.characters()); function_body.characters());
return js_string(interpreter, function_source); return js_string(vm, function_source);
} }
JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::symbol_has_instance) 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) if (!this_object)
return {}; return {};
if (!this_object->is_function()) { 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 {};
} }
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) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::gc)
{ {
dbg() << "Forced garbage collection requested!"; dbg() << "Forced garbage collection requested!";
interpreter.heap().collect_garbage(); vm.heap().collect_garbage();
return js_undefined(); return js_undefined();
} }
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::is_nan) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::is_nan)
{ {
auto number = interpreter.argument(0).to_number(interpreter); auto number = vm.argument(0).to_number(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return Value(number.is_nan()); return Value(number.is_nan());
} }
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::is_finite) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::is_finite)
{ {
auto number = interpreter.argument(0).to_number(interpreter); auto number = vm.argument(0).to_number(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return Value(number.is_finite_number()); return Value(number.is_finite_number());
} }
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_float) JS_DEFINE_NATIVE_FUNCTION(GlobalObject::parse_float)
{ {
if (interpreter.argument(0).is_number()) if (vm.argument(0).is_number())
return interpreter.argument(0); return vm.argument(0);
auto string = interpreter.argument(0).to_string(interpreter); auto string = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
for (size_t length = string.length(); length > 0; --length) { for (size_t length = string.length(); length > 0; --length) {
// This can't throw, so no exception check is fine. // 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()) if (!number.is_nan())
return number; return number;
} }

View file

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

View file

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

View file

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

View file

@ -31,7 +31,7 @@
namespace JS { 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()); 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) : Function(prototype)
, m_name(name) , m_name(name)
, m_native_function(move(native_function)) , m_native_function(move(native_function))
@ -60,7 +60,7 @@ NativeFunction::~NativeFunction()
Value NativeFunction::call() Value NativeFunction::call()
{ {
return m_native_function(interpreter(), global_object()); return m_native_function(vm(), global_object());
} }
Value NativeFunction::construct(Interpreter&, Function&) Value NativeFunction::construct(Interpreter&, Function&)

View file

@ -35,9 +35,9 @@ class NativeFunction : public Function {
JS_OBJECT(NativeFunction, Function); JS_OBJECT(NativeFunction, Function);
public: 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 void initialize(GlobalObject&) override { }
virtual ~NativeFunction() override; virtual ~NativeFunction() override;
@ -56,7 +56,7 @@ private:
virtual LexicalEnvironment* create_environment() override final; virtual LexicalEnvironment* create_environment() override final;
FlyString m_name; 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 { 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_getter(move(getter))
, m_setter(move(setter)) , 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) if (!m_getter)
return js_undefined(); 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) if (!m_setter)
return; 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 { class NativeProperty final : public Cell {
public: 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; virtual ~NativeProperty() override;
Value get(Interpreter&, GlobalObject&) const; Value get(VM&, GlobalObject&) const;
void set(Interpreter&, GlobalObject&, Value); void set(VM&, GlobalObject&, Value);
private: private:
virtual const char* class_name() const override { return "NativeProperty"; } virtual const char* class_name() const override { return "NativeProperty"; }
AK::Function<Value(Interpreter&, GlobalObject&)> m_getter; AK::Function<Value(VM&, GlobalObject&)> m_getter;
AK::Function<void(Interpreter&, GlobalObject&, Value)> m_setter; AK::Function<void(VM&, GlobalObject&, Value)> m_setter;
}; };
} }

View file

@ -69,15 +69,15 @@ Value NumberConstructor::call()
{ {
if (!vm().argument_count()) if (!vm().argument_count())
return Value(0); 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; double number = 0;
if (interpreter.argument_count()) { if (vm().argument_count()) {
number = interpreter.argument(0).to_double(interpreter); number = vm().argument(0).to_double(global_object());
if (interpreter.exception()) if (vm().exception())
return {}; return {};
} }
return NumberObject::create(global_object(), number); return NumberObject::create(global_object(), number);
@ -85,24 +85,24 @@ Value NumberConstructor::construct(Interpreter& interpreter, Function&)
JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_finite) 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) 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) 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) JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_safe_integer)
{ {
if (!interpreter.argument(0).is_number()) if (!vm.argument(0).is_number())
return Value(false); 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); 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; Value number_value;
auto this_value = interpreter.this_value(global_object); auto this_value = vm.this_value(global_object);
if (this_value.is_number()) { if (this_value.is_number()) {
number_value = this_value; number_value = this_value;
} else if (this_value.is_object() && this_value.as_object().is_number_object()) { } else if (this_value.is_object() && this_value.as_object().is_number_object()) {
number_value = static_cast<NumberObject&>(this_value.as_object()).value_of(); number_value = static_cast<NumberObject&>(this_value.as_object()).value_of();
} else { } else {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NumberIncompatibleThis, "toString"); vm.throw_exception<TypeError>(global_object, ErrorType::NumberIncompatibleThis, "toString");
return {}; return {};
} }
int radix; int radix;
auto argument = interpreter.argument(0); auto argument = vm.argument(0);
if (argument.is_undefined()) { if (argument.is_undefined()) {
radix = 10; radix = 10;
} else { } else {
radix = argument.to_i32(interpreter); radix = argument.to_i32(global_object);
} }
if (interpreter.exception() || radix < 2 || radix > 36) { if (vm.exception() || radix < 2 || radix > 36) {
interpreter.vm().throw_exception<RangeError>(global_object, ErrorType::InvalidRadix); vm.throw_exception<RangeError>(global_object, ErrorType::InvalidRadix);
return {}; return {};
} }
if (number_value.is_positive_infinity()) if (number_value.is_positive_infinity())
return js_string(interpreter, "Infinity"); return js_string(vm, "Infinity");
if (number_value.is_negative_infinity()) if (number_value.is_negative_infinity())
return js_string(interpreter, "-Infinity"); return js_string(vm, "-Infinity");
if (number_value.is_nan()) 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()) 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(); double number = number_value.as_double();
bool negative = number < 0; bool negative = number < 0;
@ -140,7 +140,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string)
characters.take_last(); 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); 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; String function_name;
if (property_name.is_string()) { 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); 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); 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"); interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::Convert, "object", "string");
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
auto* string = to_string_result.to_primitive_string(interpreter); auto* string = to_string_result.to_primitive_string(global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
return string; return string;
@ -872,7 +872,7 @@ Value Object::call_native_property_getter(Object* this_object, Value property) c
ASSERT(property.is_native_property()); ASSERT(property.is_native_property());
auto& call_frame = vm().push_call_frame(); auto& call_frame = vm().push_call_frame();
call_frame.this_value = this_object; 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(); vm().pop_call_frame();
return result; return result;
} }
@ -882,7 +882,7 @@ void Object::call_native_property_setter(Object* this_object, Value property, Va
ASSERT(property.is_native_property()); ASSERT(property.is_native_property());
auto& call_frame = vm().push_call_frame(); auto& call_frame = vm().push_call_frame();
call_frame.this_value = this_object; 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(); 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_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_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_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(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, 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&); 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) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
{ {
if (!interpreter.argument_count()) if (!vm.argument_count())
return {}; return {};
auto* object = interpreter.argument(0).to_object(interpreter, global_object); auto* object = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto* result = Array::create(global_object); auto* result = Array::create(global_object);
for (auto& entry : object->indexed_properties()) 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()) { for (auto& it : object->shape().property_table_ordered()) {
if (!it.key.is_string()) if (!it.key.is_string())
continue; 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; return result;
@ -95,36 +95,36 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_names)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_prototype_of) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_prototype_of)
{ {
if (!interpreter.argument_count()) if (!vm.argument_count())
return {}; return {};
auto* object = interpreter.argument(0).to_object(interpreter, global_object); auto* object = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return object->prototype(); return object->prototype();
} }
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of)
{ {
if (interpreter.argument_count() < 2) { if (vm.argument_count() < 2) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfTwoArgs); vm.throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfTwoArgs);
return {}; return {};
} }
auto* object = interpreter.argument(0).to_object(interpreter, global_object); auto* object = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto prototype_value = interpreter.argument(1); auto prototype_value = vm.argument(1);
Object* prototype; Object* prototype;
if (prototype_value.is_null()) { if (prototype_value.is_null()) {
prototype = nullptr; prototype = nullptr;
} else if (prototype_value.is_object()) { } else if (prototype_value.is_object()) {
prototype = &prototype_value.as_object(); prototype = &prototype_value.as_object();
} else { } else {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType); vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPrototypeWrongType);
return {}; return {};
} }
if (!object->set_prototype(prototype)) { if (!object->set_prototype(prototype)) {
if (!interpreter.exception()) if (!vm.exception())
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfReturnedFalse); vm.throw_exception<TypeError>(global_object, ErrorType::ObjectSetPrototypeOfReturnedFalse);
return {}; return {};
} }
return object; return object;
@ -132,7 +132,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::set_prototype_of)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_extensible) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is_extensible)
{ {
auto argument = interpreter.argument(0); auto argument = vm.argument(0);
if (!argument.is_object()) if (!argument.is_object())
return Value(false); return Value(false);
return Value(argument.as_object().is_extensible()); 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) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::prevent_extensions)
{ {
auto argument = interpreter.argument(0); auto argument = vm.argument(0);
if (!argument.is_object()) if (!argument.is_object())
return argument; return argument;
if (!argument.as_object().prevent_extensions()) { if (!argument.as_object().prevent_extensions()) {
if (!interpreter.exception()) if (!vm.exception())
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectPreventExtensionsReturnedFalse); vm.throw_exception<TypeError>(global_object, ErrorType::ObjectPreventExtensionsReturnedFalse);
return {}; return {};
} }
return argument; return argument;
@ -153,36 +153,36 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::prevent_extensions)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptor) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptor)
{ {
auto* object = interpreter.argument(0).to_object(interpreter, global_object); auto* object = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto property_key = PropertyName::from_value(interpreter, interpreter.argument(1)); auto property_key = PropertyName::from_value(global_object, vm.argument(1));
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return object->get_own_property_descriptor_object(property_key); return object->get_own_property_descriptor_object(property_key);
} }
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
{ {
if (!interpreter.argument(0).is_object()) { if (!vm.argument(0).is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument"); vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
return {}; return {};
} }
if (!interpreter.argument(2).is_object()) { if (!vm.argument(2).is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument"); vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument");
return {}; return {};
} }
auto& object = interpreter.argument(0).as_object(); auto& object = vm.argument(0).as_object();
auto property_key = StringOrSymbol::from_value(interpreter, interpreter.argument(1)); auto property_key = StringOrSymbol::from_value(global_object, vm.argument(1));
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto& descriptor = interpreter.argument(2).as_object(); auto& descriptor = vm.argument(2).as_object();
if (!object.define_property(property_key, descriptor)) { if (!object.define_property(property_key, descriptor)) {
if (!interpreter.exception()) { if (!vm.exception()) {
if (object.is_proxy_object()) { if (object.is_proxy_object()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ObjectDefinePropertyReturnedFalse); vm.throw_exception<TypeError>(global_object, ErrorType::ObjectDefinePropertyReturnedFalse);
} else { } 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 {}; return {};
@ -192,18 +192,18 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::is) 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) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::keys)
{ {
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject); vm.throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
return {}; return {};
} }
auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object); auto* obj_arg = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return obj_arg->get_own_properties(*obj_arg, PropertyKind::Key, true); 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) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::values)
{ {
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject); vm.throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
return {}; return {};
} }
auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object); auto* obj_arg = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return obj_arg->get_own_properties(*obj_arg, PropertyKind::Value, true); 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) JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::entries)
{ {
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject); vm.throw_exception<TypeError>(global_object, ErrorType::ConvertUndefinedToObject);
return {}; return {};
} }
auto* obj_arg = interpreter.argument(0).to_object(interpreter, global_object); auto* obj_arg = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return obj_arg->get_own_properties(*obj_arg, PropertyKind::KeyAndValue, true); 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) 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) if (!this_object)
return {}; return {};
auto name = interpreter.argument(0).to_string(interpreter); auto name = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return Value(this_object->has_own_property(name)); return Value(this_object->has_own_property(name));
} }
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string) 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()) if (this_value.is_undefined())
return js_string(interpreter, "[object Undefined]"); return js_string(vm, "[object Undefined]");
if (this_value.is_null()) 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) if (!this_object)
return {}; return {};
@ -104,12 +104,12 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
tag = "Object"; 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) 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) if (!this_object)
return {}; return {};
return this_object->invoke("toString"); return this_object->invoke("toString");
@ -117,7 +117,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string)
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::value_of) 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) if (!this_object)
return {}; return {};
return this_object->value_of(); 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) 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(Heap&, String);
PrimitiveString* js_string(Interpreter&, String); PrimitiveString* js_string(Interpreter&, String);
PrimitiveString* js_string(VM&, String);
} }

View file

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

View file

@ -33,7 +33,7 @@
namespace JS { 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()) if (!current_descriptor_optional.has_value())
return is_extensible; 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 (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()) if (new_descriptor.attributes.is_writable())
return false; 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; return true;
} }
@ -77,7 +77,7 @@ ProxyObject::~ProxyObject()
Object* ProxyObject::prototype() Object* ProxyObject::prototype()
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return nullptr; return nullptr;
} }
auto trap = m_handler.get("getPrototypeOf"); auto trap = m_handler.get("getPrototypeOf");
@ -86,15 +86,15 @@ Object* ProxyObject::prototype()
if (trap.is_empty() || trap.is_undefined() || trap.is_null()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.prototype(); return m_target.prototype();
if (!trap.is_function()) { 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; 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()) if (vm().exception())
return nullptr; return nullptr;
if (!trap_result.is_object() && !trap_result.is_null()) { 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; return nullptr;
} }
if (m_target.is_extensible()) { if (m_target.is_extensible()) {
@ -107,8 +107,8 @@ Object* ProxyObject::prototype()
auto target_proto = m_target.prototype(); auto target_proto = m_target.prototype();
if (vm().exception()) if (vm().exception())
return nullptr; return nullptr;
if (!same_value(interpreter(), trap_result, Value(target_proto))) { if (!same_value(trap_result, Value(target_proto))) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetPrototypeOfNonExtensible); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetPrototypeOfNonExtensible);
return nullptr; return nullptr;
} }
return &trap_result.as_object(); return &trap_result.as_object();
@ -117,7 +117,7 @@ Object* ProxyObject::prototype()
const Object* ProxyObject::prototype() const const Object* ProxyObject::prototype() const
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return nullptr; return nullptr;
} }
return const_cast<const Object*>(const_cast<ProxyObject*>(this)->prototype()); 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) bool ProxyObject::set_prototype(Object* object)
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false; return false;
} }
auto trap = m_handler.get("setPrototypeOf"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.set_prototype(object); return m_target.set_prototype(object);
if (!trap.is_function()) { 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; 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) if (vm().exception() || !trap_result)
return false; return false;
if (m_target.is_extensible()) if (m_target.is_extensible())
@ -147,8 +147,8 @@ bool ProxyObject::set_prototype(Object* object)
auto* target_proto = m_target.prototype(); auto* target_proto = m_target.prototype();
if (vm().exception()) if (vm().exception())
return false; return false;
if (!same_value(interpreter(), Value(object), Value(target_proto))) { if (!same_value(Value(object), Value(target_proto))) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetPrototypeOfNonExtensible); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetPrototypeOfNonExtensible);
return false; return false;
} }
return true; return true;
@ -157,7 +157,7 @@ bool ProxyObject::set_prototype(Object* object)
bool ProxyObject::is_extensible() const bool ProxyObject::is_extensible() const
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false; return false;
} }
auto trap = m_handler.get("isExtensible"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.is_extensible(); return m_target.is_extensible();
if (!trap.is_function()) { if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "isExtensible"); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "isExtensible");
return {}; 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()) if (vm().exception())
return false; return false;
if (trap_result != m_target.is_extensible()) { if (trap_result != m_target.is_extensible()) {
if (!vm().exception()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyIsExtensibleReturn); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyIsExtensibleReturn);
return false; return false;
} }
return trap_result; return trap_result;
@ -184,7 +184,7 @@ bool ProxyObject::is_extensible() const
bool ProxyObject::prevent_extensions() bool ProxyObject::prevent_extensions()
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false; return false;
} }
auto trap = m_handler.get("preventExtensions"); auto trap = m_handler.get("preventExtensions");
@ -193,16 +193,16 @@ bool ProxyObject::prevent_extensions()
if (trap.is_empty() || trap.is_undefined() || trap.is_null()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.prevent_extensions(); return m_target.prevent_extensions();
if (!trap.is_function()) { if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "preventExtensions"); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "preventExtensions");
return {}; 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()) if (vm().exception())
return false; return false;
if (trap_result && m_target.is_extensible()) { if (trap_result && m_target.is_extensible()) {
if (!vm().exception()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyPreventExtensionsReturn); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyPreventExtensionsReturn);
return false; return false;
} }
return trap_result; return trap_result;
@ -211,7 +211,7 @@ bool ProxyObject::prevent_extensions()
Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const PropertyName& name) const Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const PropertyName& name) const
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return {}; return {};
} }
auto trap = m_handler.get("getOwnPropertyDescriptor"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.get_own_property_descriptor(name); return m_target.get_own_property_descriptor(name);
if (!trap.is_function()) { if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor"); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "getOwnPropertyDescriptor");
return {}; 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()) if (vm().exception())
return {}; return {};
if (!trap_result.is_object() && !trap_result.is_undefined()) { 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 {}; return {};
} }
auto target_desc = m_target.get_own_property_descriptor(name); 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()) if (!target_desc.has_value())
return {}; return {};
if (!target_desc.value().attributes.is_configurable()) { 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 {}; return {};
} }
if (!m_target.is_extensible()) { if (!m_target.is_extensible()) {
if (!vm().exception()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorUndefReturn); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorUndefReturn);
return {}; return {};
} }
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()); auto result_desc = PropertyDescriptor::from_dictionary(vm(), trap_result.as_object());
if (vm().exception()) if (vm().exception())
return {}; 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()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidDescriptor); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetOwnDescriptorInvalidDescriptor);
return {}; return {};
} }
if (!result_desc.attributes.is_configurable() && (!target_desc.has_value() || target_desc.value().attributes.is_configurable())) { 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 {};
} }
return result_desc; 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) bool ProxyObject::define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions)
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false; return false;
} }
auto trap = m_handler.get("defineProperty"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.define_property(property_name, descriptor, throw_exceptions); return m_target.define_property(property_name, descriptor, throw_exceptions);
if (!trap.is_function()) { 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; 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) if (vm().exception() || !trap_result)
return false; return false;
auto target_desc = m_target.get_own_property_descriptor(property_name); 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 (!target_desc.has_value()) {
if (!m_target.is_extensible()) { if (!m_target.is_extensible()) {
if (!vm().exception()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonExtensible); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonExtensible);
return false; return false;
} }
if (setting_config_false) { if (setting_config_false) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonConfigurableNonExisting); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropNonConfigurableNonExisting);
return false; return false;
} }
} else { } 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()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropIncompatibleDescriptor); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDefinePropIncompatibleDescriptor);
return false; return false;
} }
if (setting_config_false && target_desc.value().attributes.is_configurable()) { 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; return false;
} }
} }
@ -317,7 +317,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
bool ProxyObject::has_property(const PropertyName& name) const bool ProxyObject::has_property(const PropertyName& name) const
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false; return false;
} }
auto trap = m_handler.get("has"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.has_property(name); return m_target.has_property(name);
if (!trap.is_function()) { 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; 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()) if (vm().exception())
return false; return false;
if (!trap_result) { if (!trap_result) {
@ -339,12 +339,12 @@ bool ProxyObject::has_property(const PropertyName& name) const
return false; return false;
if (target_desc.has_value()) { if (target_desc.has_value()) {
if (!target_desc.value().attributes.is_configurable()) { 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; return false;
} }
if (!m_target.is_extensible()) { if (!m_target.is_extensible()) {
if (!vm().exception()) if (!vm().exception())
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyHasExistingNonExtensible); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyHasExistingNonExtensible);
return false; return false;
} }
} }
@ -355,7 +355,7 @@ bool ProxyObject::has_property(const PropertyName& name) const
Value ProxyObject::get(const PropertyName& name, Value) const Value ProxyObject::get(const PropertyName& name, Value) const
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return {}; return {};
} }
auto trap = m_handler.get("get"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.get(name); return m_target.get(name);
if (!trap.is_function()) { if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "get"); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "get");
return {}; 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()) if (vm().exception())
return {}; return {};
auto target_desc = m_target.get_own_property_descriptor(name); auto target_desc = m_target.get_own_property_descriptor(name);
if (target_desc.has_value()) { if (target_desc.has_value()) {
if (vm().exception()) if (vm().exception())
return {}; return {};
if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(interpreter(), trap_result, target_desc.value().value)) { if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(trap_result, target_desc.value().value)) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetImmutableDataProperty); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyGetImmutableDataProperty);
return {}; return {};
} }
if (target_desc.value().is_accessor_descriptor() && target_desc.value().getter == nullptr && !trap_result.is_undefined()) { 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 {}; return {};
} }
} }
@ -390,7 +390,7 @@ Value ProxyObject::get(const PropertyName& name, Value) const
bool ProxyObject::put(const PropertyName& name, Value value, Value) bool ProxyObject::put(const PropertyName& name, Value value, Value)
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return false; return false;
} }
auto trap = m_handler.get("set"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.put(name, value); return m_target.put(name, value);
if (!trap.is_function()) { 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; 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) if (vm().exception() || !trap_result)
return false; return false;
auto target_desc = m_target.get_own_property_descriptor(name); auto target_desc = m_target.get_own_property_descriptor(name);
if (vm().exception()) if (vm().exception())
return false; return false;
if (target_desc.has_value() && !target_desc.value().attributes.is_configurable()) { 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)) { if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(value, target_desc.value().value)) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetImmutableDataProperty); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetImmutableDataProperty);
return false; return false;
} }
if (target_desc.value().is_accessor_descriptor() && !target_desc.value().setter) { 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; return true;
@ -423,7 +423,7 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value)
Value ProxyObject::delete_property(const PropertyName& name) Value ProxyObject::delete_property(const PropertyName& name)
{ {
if (m_is_revoked) { if (m_is_revoked) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return {}; return {};
} }
auto trap = m_handler.get("deleteProperty"); 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()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return m_target.delete_property(name); return m_target.delete_property(name);
if (!trap.is_function()) { if (!trap.is_function()) {
interpreter().vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty"); vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty");
return {}; 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()) if (vm().exception())
return {}; return {};
if (!trap_result) if (!trap_result)
@ -447,7 +447,7 @@ Value ProxyObject::delete_property(const PropertyName& name)
if (!target_desc.has_value()) if (!target_desc.has_value())
return Value(true); return Value(true);
if (!target_desc.value().attributes.is_configurable()) { 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 {};
} }
return Value(true); return Value(true);
@ -494,35 +494,36 @@ Value ProxyObject::call()
Value ProxyObject::construct(Interpreter& interpreter, Function& new_target) Value ProxyObject::construct(Interpreter& interpreter, Function& new_target)
{ {
auto& vm = this->vm();
if (!is_function()) { 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 {}; return {};
} }
if (m_is_revoked) { if (m_is_revoked) {
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return {}; return {};
} }
auto trap = m_handler.get("construct"); auto trap = m_handler.get("construct");
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (trap.is_empty() || trap.is_undefined() || trap.is_null()) if (trap.is_empty() || trap.is_undefined() || trap.is_null())
return static_cast<Function&>(m_target).construct(interpreter, new_target); return static_cast<Function&>(m_target).construct(interpreter, new_target);
if (!trap.is_function()) { if (!trap.is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "construct"); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "construct");
return {}; return {};
} }
MarkedValueList arguments(interpreter.heap()); MarkedValueList arguments(vm.heap());
arguments.append(Value(&m_target)); arguments.append(Value(&m_target));
auto arguments_array = Array::create(interpreter.global_object()); auto arguments_array = Array::create(global_object());
interpreter.vm().for_each_argument([&](auto& argument) { vm.for_each_argument([&](auto& argument) {
arguments_array->indexed_properties().append(argument); arguments_array->indexed_properties().append(argument);
}); });
arguments.append(arguments_array); arguments.append(arguments_array);
arguments.append(Value(&new_target)); 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()) { if (!result.is_object()) {
interpreter.vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyConstructBadReturnType); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyConstructBadReturnType);
return {}; return {};
} }
return result; return result;

View file

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

View file

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

View file

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

View file

@ -35,13 +35,13 @@
namespace JS { 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) if (!this_object)
return nullptr; return nullptr;
if (!this_object->is_function()) { 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 nullptr;
} }
return static_cast<ScriptFunction*>(this_object); return static_cast<ScriptFunction*>(this_object);
@ -154,7 +154,7 @@ Value ScriptFunction::construct(Interpreter&, Function&)
JS_DEFINE_NATIVE_GETTER(ScriptFunction::length_getter) JS_DEFINE_NATIVE_GETTER(ScriptFunction::length_getter)
{ {
auto* function = typed_this(interpreter, global_object); auto* function = typed_this(vm, global_object);
if (!function) if (!function)
return {}; return {};
return Value(static_cast<i32>(function->m_function_length)); 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) JS_DEFINE_NATIVE_GETTER(ScriptFunction::name_getter)
{ {
auto* function = typed_this(interpreter, global_object); auto* function = typed_this(vm, global_object);
if (!function) if (!function)
return {}; 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(), ""); return js_string(heap(), "");
if (vm().argument(0).is_symbol()) if (vm().argument(0).is_symbol())
return js_string(heap(), vm().argument(0).as_symbol().to_string()); 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()) if (vm().exception())
return {}; return {};
return string; return string;
} }
Value StringConstructor::construct(Interpreter& interpreter, Function&) Value StringConstructor::construct(Interpreter&, Function&)
{ {
PrimitiveString* primitive_string = nullptr; PrimitiveString* primitive_string = nullptr;
if (!interpreter.argument_count()) if (!vm().argument_count())
primitive_string = js_string(interpreter, ""); primitive_string = js_string(vm(), "");
else else
primitive_string = interpreter.argument(0).to_primitive_string(interpreter); primitive_string = vm().argument(0).to_primitive_string(global_object());
if (!primitive_string) if (!primitive_string)
return {}; return {};
return StringObject::create(global_object(), *primitive_string); return StringObject::create(global_object(), *primitive_string);
@ -81,55 +81,55 @@ Value StringConstructor::construct(Interpreter& interpreter, Function&)
JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw) JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
{ {
auto* template_object = interpreter.argument(0).to_object(interpreter, global_object); auto* template_object = vm.argument(0).to_object(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto raw = template_object->get("raw"); auto raw = template_object->get("raw");
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (raw.is_empty() || raw.is_undefined() || raw.is_null()) { 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 {}; return {};
} }
if (!raw.is_array()) 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(); auto& raw_array_elements = array->indexed_properties();
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < raw_array_elements.array_like_size(); ++i) { for (size_t i = 0; i < raw_array_elements.array_like_size(); ++i) {
auto result = raw_array_elements.get(array, i); auto result = raw_array_elements.get(array, i);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!result.has_value()) if (!result.has_value())
continue; continue;
builder.append(result.value().value.to_string(interpreter)); builder.append(result.value().value.to_string(global_object));
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (i + 1 < interpreter.argument_count() && i < raw_array_elements.array_like_size() - 1) { if (i + 1 < vm.argument_count() && i < raw_array_elements.array_like_size() - 1) {
builder.append(interpreter.argument(i + 1).to_string(interpreter)); builder.append(vm.argument(i + 1).to_string(global_object));
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
} }
return js_string(interpreter, builder.build()); return js_string(vm, builder.build());
} }
JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_char_code) JS_DEFINE_NATIVE_FUNCTION(StringConstructor::from_char_code)
{ {
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < interpreter.argument_count(); ++i) { for (size_t i = 0; i < vm.argument_count(); ++i) {
auto char_code = interpreter.argument(i).to_i32(interpreter); auto char_code = vm.argument(i).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto truncated = char_code & 0xffff; auto truncated = char_code & 0xffff;
// FIXME: We need an Utf16View :^) // FIXME: We need an Utf16View :^)
builder.append(Utf32View((u32*)&truncated, 1)); 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) 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()) { 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 {}; return {};
} }
@ -74,7 +74,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringIteratorPrototype::next)
builder.append_code_point(*utf8_iterator); builder.append_code_point(*utf8_iterator);
++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 { class StringOrSymbol {
public: public:
static StringOrSymbol from_value(Interpreter& interpreter, Value value) static StringOrSymbol from_value(GlobalObject& global_object, Value value)
{ {
if (value.is_symbol()) if (value.is_symbol())
return &value.as_symbol(); return &value.as_symbol();
if (!value.is_empty()) if (!value.is_empty())
return value.to_string(interpreter); return value.to_string(global_object);
return {}; return {};
} }

View file

@ -40,24 +40,24 @@
namespace JS { 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) if (!this_object)
return nullptr; return nullptr;
if (!this_object->is_string_object()) { 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 nullptr;
} }
return static_cast<StringObject*>(this_object); 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) if (!this_object)
return {}; return {};
return Value(this_object).to_string(interpreter); return Value(this_object).to_string(global_object);
} }
StringPrototype::StringPrototype(GlobalObject& global_object) StringPrototype::StringPrototype(GlobalObject& global_object)
@ -98,30 +98,30 @@ StringPrototype::~StringPrototype()
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at) 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()) if (string.is_null())
return {}; return {};
i32 index = 0; i32 index = 0;
if (interpreter.argument_count()) { if (vm.argument_count()) {
index = interpreter.argument(0).to_i32(interpreter); index = vm.argument(0).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
if (index < 0 || index >= static_cast<i32>(string.length())) 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. // 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) 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()) if (string.is_null())
return {}; return {};
i32 index = 0; i32 index = 0;
if (interpreter.argument_count()) { if (vm.argument_count()) {
index = interpreter.argument(0).to_i32(interpreter); index = vm.argument(0).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
if (index < 0 || index >= static_cast<i32>(string.length())) 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) 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()) if (string.is_null())
return {}; return {};
if (!interpreter.argument_count()) if (!vm.argument_count())
return js_string(interpreter, String::empty()); return js_string(vm, String::empty());
auto count_value = interpreter.argument(0).to_number(interpreter); auto count_value = vm.argument(0).to_number(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (count_value.as_double() < 0) { 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 {}; return {};
} }
if (count_value.is_infinity()) { 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 {}; return {};
} }
auto count = count_value.to_size_t(interpreter); auto count = count_value.to_size_t(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
StringBuilder builder; StringBuilder builder;
for (size_t i = 0; i < count; ++i) for (size_t i = 0; i < count; ++i)
builder.append(string); builder.append(string);
return js_string(interpreter, builder.to_string()); return js_string(vm, builder.to_string());
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with) 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()) if (string.is_null())
return {}; return {};
if (!interpreter.argument_count()) if (!vm.argument_count())
return Value(false); return Value(false);
auto search_string = interpreter.argument(0).to_string(interpreter); auto search_string = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto string_length = string.length(); auto string_length = string.length();
auto search_string_length = search_string.length(); auto search_string_length = search_string.length();
size_t start = 0; size_t start = 0;
if (interpreter.argument_count() > 1) { if (vm.argument_count() > 1) {
auto number = interpreter.argument(1).to_number(interpreter); auto number = vm.argument(1).to_number(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!number.is_nan()) 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) if (start + search_string_length > string_length)
return Value(false); return Value(false);
@ -186,34 +186,34 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::index_of) 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()) if (string.is_null())
return {}; return {};
auto needle = interpreter.argument(0).to_string(interpreter); auto needle = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return Value((i32)string.index_of(needle).value_or(-1)); return Value((i32)string.index_of(needle).value_or(-1));
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_lowercase) 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()) if (string.is_null())
return {}; return {};
return js_string(interpreter, string.to_lowercase()); return js_string(vm, string.to_lowercase());
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_uppercase) 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()) if (string.is_null())
return {}; return {};
return js_string(interpreter, string.to_uppercase()); return js_string(vm, string.to_uppercase());
} }
JS_DEFINE_NATIVE_GETTER(StringPrototype::length_getter) 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) if (!string_object)
return {}; return {};
return Value((i32)string_object->primitive_string().string().length()); 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) 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) if (!string_object)
return {}; return {};
return js_string(interpreter, string_object->primitive_string().string()); return js_string(vm, string_object->primitive_string().string());
} }
enum class PadPlacement { enum class PadPlacement {
@ -232,21 +232,22 @@ enum class PadPlacement {
End, 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); auto& vm = global_object.vm();
if (interpreter.exception()) auto max_length = vm.argument(0).to_size_t(global_object);
if (vm.exception())
return {}; return {};
if (max_length <= string.length()) if (max_length <= string.length())
return js_string(interpreter, string); return js_string(vm, string);
String fill_string = " "; String fill_string = " ";
if (!interpreter.argument(1).is_undefined()) { if (!vm.argument(1).is_undefined()) {
fill_string = interpreter.argument(1).to_string(interpreter); fill_string = vm.argument(1).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (fill_string.is_empty()) if (fill_string.is_empty())
return js_string(interpreter, string); return js_string(vm, string);
} }
auto fill_length = max_length - string.length(); 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); auto filler = filler_builder.build().substring(0, fill_length);
if (placement == PadPlacement::Start) if (placement == PadPlacement::Start)
return js_string(interpreter, String::format("%s%s", filler.characters(), string.characters())); return js_string(vm, 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", string.characters(), filler.characters()));
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::pad_start) 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()) if (string.is_null())
return {}; return {};
return pad_string(interpreter, string, PadPlacement::Start); return pad_string(global_object, string, PadPlacement::Start);
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::pad_end) 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()) if (string.is_null())
return {}; return {};
return pad_string(interpreter, string, PadPlacement::End); return pad_string(global_object, string, PadPlacement::End);
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::trim) 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()) if (string.is_null())
return {}; 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) 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()) if (string.is_null())
return {}; 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) 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()) if (string.is_null())
return {}; 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) 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()) if (string.is_null())
return {}; return {};
StringBuilder builder; StringBuilder builder;
builder.append(string); builder.append(string);
for (size_t i = 0; i < interpreter.argument_count(); ++i) { for (size_t i = 0; i < vm.argument_count(); ++i) {
auto string_argument = interpreter.argument(i).to_string(interpreter); auto string_argument = vm.argument(i).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
builder.append(string_argument); builder.append(string_argument);
} }
return js_string(interpreter, builder.to_string()); return js_string(vm, builder.to_string());
} }
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring) 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()) if (string.is_null())
return {}; return {};
if (interpreter.argument_count() == 0) if (vm.argument_count() == 0)
return js_string(interpreter, string); return js_string(vm, string);
// FIXME: index_start and index_end should index a UTF-16 code_point view of the string. // FIXME: index_start and index_end should index a UTF-16 code_point view of the string.
auto string_length = string.length(); auto string_length = string.length();
auto index_start = min(interpreter.argument(0).to_size_t(interpreter), string_length); auto index_start = min(vm.argument(0).to_size_t(global_object), string_length);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto index_end = string_length; auto index_end = string_length;
if (interpreter.argument_count() >= 2) { if (vm.argument_count() >= 2) {
index_end = min(interpreter.argument(1).to_size_t(interpreter), string_length); index_end = min(vm.argument(1).to_size_t(global_object), string_length);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
if (index_start == index_end) if (index_start == index_end)
return js_string(interpreter, String("")); return js_string(vm, String(""));
if (index_start > index_end) { if (index_start > index_end) {
if (interpreter.argument_count() == 1) if (vm.argument_count() == 1)
return js_string(interpreter, String("")); return js_string(vm, String(""));
auto temp_index_start = index_start; auto temp_index_start = index_start;
index_start = index_end; index_start = index_end;
index_end = temp_index_start; index_end = temp_index_start;
@ -350,23 +351,23 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
auto part_length = index_end - index_start; auto part_length = index_end - index_start;
auto string_part = string.substring(index_start, part_length); 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) 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()) if (string.is_null())
return {}; return {};
auto search_string = interpreter.argument(0).to_string(interpreter); auto search_string = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
// FIXME: position should index a UTF-16 code_point view of the string. // FIXME: position should index a UTF-16 code_point view of the string.
size_t position = 0; size_t position = 0;
if (interpreter.argument_count() >= 2) { if (vm.argument_count() >= 2) {
position = interpreter.argument(1).to_size_t(interpreter); position = vm.argument(1).to_size_t(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (position >= string.length()) if (position >= string.length())
return Value(false); return Value(false);
@ -382,17 +383,17 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::includes)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice) 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()) if (string.is_null())
return {}; return {};
if (interpreter.argument_count() == 0) if (vm.argument_count() == 0)
return js_string(interpreter, string); return js_string(vm, string);
// FIXME: index_start and index_end should index a UTF-16 code_point view of the 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 string_length = static_cast<i32>(string.length());
auto index_start = interpreter.argument(0).to_i32(interpreter); auto index_start = vm.argument(0).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto index_end = string_length; auto index_end = string_length;
@ -402,13 +403,13 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
else if (index_start < 0) else if (index_start < 0)
index_start = string_length + index_start; index_start = string_length + index_start;
if (interpreter.argument_count() >= 2) { if (vm.argument_count() >= 2) {
index_end = interpreter.argument(1).to_i32(interpreter); index_end = vm.argument(1).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (index_end < negative_min_index) if (index_end < negative_min_index)
return js_string(interpreter, String::empty()); return js_string(vm, String::empty());
if (index_end > string_length) if (index_end > string_length)
index_end = string_length; index_end = string_length;
@ -417,33 +418,33 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::slice)
} }
if (index_start >= index_end) 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 part_length = index_end - index_start;
auto string_part = string.substring(index_start, part_length); 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) 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()) if (string.is_null())
return {}; return {};
if (interpreter.argument_count() == 0) if (vm.argument_count() == 0)
return Value(-1); return Value(-1);
auto search_string = interpreter.argument(0).to_string(interpreter); auto search_string = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (search_string.length() > string.length()) if (search_string.length() > string.length())
return Value(-1); return Value(-1);
auto max_index = string.length() - search_string.length(); auto max_index = string.length() - search_string.length();
auto from_index = max_index; 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. // 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); from_index = min(vm.argument(1).to_size_t(global_object), max_index);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
@ -458,14 +459,14 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::last_index_of)
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::symbol_iterator) 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()) { 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 {}; return {};
} }
auto string = this_object.to_string(interpreter); auto string = this_object.to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
return StringIterator::create(global_object, string); return StringIterator::create(global_object, string);
} }

View file

@ -60,7 +60,7 @@ Value SymbolConstructor::call()
{ {
if (!vm().argument_count()) if (!vm().argument_count())
return js_symbol(heap(), "", false); 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&) Value SymbolConstructor::construct(Interpreter& interpreter, Function&)
@ -72,10 +72,10 @@ Value SymbolConstructor::construct(Interpreter& interpreter, Function&)
JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_) JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_)
{ {
String description; String description;
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
description = "undefined"; description = "undefined";
} else { } else {
description = interpreter.argument(0).to_string(interpreter); description = vm.argument(0).to_string(global_object);
} }
return global_object.vm().get_global_symbol(description); 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) JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::key_for)
{ {
auto argument = interpreter.argument(0); auto argument = vm.argument(0);
if (!argument.is_symbol()) { 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 {}; return {};
} }
auto& symbol = argument.as_symbol(); auto& symbol = argument.as_symbol();
if (symbol.is_global()) if (symbol.is_global())
return js_string(interpreter, symbol.description()); return js_string(vm, symbol.description());
return js_undefined(); 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) if (!this_object)
return nullptr; return nullptr;
if (!this_object->is_symbol_object()) { 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 nullptr;
} }
return static_cast<SymbolObject*>(this_object); 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) 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) if (!this_object)
return {}; return {};
return js_string(interpreter, this_object->description()); return js_string(vm, this_object->description());
} }
JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::to_string) 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) if (!this_object)
return {}; return {};
auto string = this_object->primitive_symbol().to_string(); 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) 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) if (!this_object)
return {}; return {};
return this_object->value_of(); return this_object->value_of();

View file

@ -55,11 +55,11 @@ Uint8ClampedArray::~Uint8ClampedArray()
JS_DEFINE_NATIVE_GETTER(Uint8ClampedArray::length_getter) 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) if (!this_object)
return {}; return {};
if (StringView(this_object->class_name()) != "Uint8ClampedArray") { 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 {};
} }
return Value(static_cast<const Uint8ClampedArray*>(this_object)->length()); 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 // FIXME: Use attributes
ASSERT(property_index < m_length); ASSERT(property_index < m_length);
auto number = value.to_i32(interpreter()); auto number = value.to_i32(global_object());
if (vm().exception()) if (vm().exception())
return {}; return {};
m_data[property_index] = clamp(number, 0, 255); 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(); 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()); ASSERT(!exception());

View file

@ -32,6 +32,7 @@
#include <LibJS/Heap/Heap.h> #include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/ErrorTypes.h> #include <LibJS/Runtime/ErrorTypes.h>
#include <LibJS/Runtime/Exception.h> #include <LibJS/Runtime/Exception.h>
#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/Value.h> #include <LibJS/Runtime/Value.h>
namespace JS { namespace JS {
@ -206,11 +207,26 @@ public:
const LexicalEnvironment* get_this_environment() const; const LexicalEnvironment* get_this_environment() const;
Value get_new_target() 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: private:
VM(); VM();
[[nodiscard]] Value call_internal(Function&, Value this_value, Optional<MarkedValueList> arguments);
Exception* m_exception { nullptr }; Exception* m_exception { nullptr };
Heap m_heap; Heap m_heap;
@ -234,4 +250,13 @@ private:
#undef __JS_ENUMERATE #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()) if (is_string())
return &as_string(); return &as_string();
auto string = to_string(interpreter); auto string = to_string(global_object);
if (interpreter.exception()) if (global_object.vm().exception())
return nullptr; 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) { switch (m_type) {
case Type::Undefined: case Type::Undefined:
@ -164,15 +164,15 @@ String Value::to_string(Interpreter& interpreter) const
case Type::String: case Type::String:
return m_value.as_string->string(); return m_value.as_string->string();
case Type::Symbol: 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 {}; return {};
case Type::BigInt: case Type::BigInt:
return m_value.as_bigint->big_integer().to_base10(); return m_value.as_bigint->big_integer().to_base10();
case Type::Object: { case Type::Object: {
auto primitive_value = as_object().to_primitive(PreferredType::String); auto primitive_value = as_object().to_primitive(PreferredType::String);
if (interpreter.exception()) if (global_object.vm().exception())
return {}; return {};
return primitive_value.to_string(interpreter); return primitive_value.to_string(global_object);
} }
default: default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@ -211,12 +211,12 @@ Value Value::to_primitive(PreferredType preferred_type) const
return *this; return *this;
} }
Object* Value::to_object(Interpreter& interpreter, GlobalObject& global_object) const Object* Value::to_object(GlobalObject& global_object) const
{ {
switch (m_type) { switch (m_type) {
case Type::Undefined: case Type::Undefined:
case Type::Null: case Type::Null:
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndef); global_object.vm().throw_exception<TypeError>(global_object, ErrorType::ToObjectNullOrUndef);
return nullptr; return nullptr;
case Type::Boolean: case Type::Boolean:
return BooleanObject::create(global_object, m_value.as_bool); 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); auto primitive = to_primitive(Value::PreferredType::Number);
if (interpreter.exception()) if (global_object.vm().exception())
return {}; return {};
if (primitive.is_bigint()) if (primitive.is_bigint())
return primitive; 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) { switch (m_type) {
case Type::Undefined: case Type::Undefined:
@ -272,16 +272,16 @@ Value Value::to_number(Interpreter& interpreter) const
return Value(parsed_double); return Value(parsed_double);
} }
case Type::Symbol: 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 {}; return {};
case Type::BigInt: 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 {}; return {};
case Type::Object: { case Type::Object: {
auto primitive = m_value.as_object->to_primitive(PreferredType::Number); auto primitive = m_value.as_object->to_primitive(PreferredType::Number);
if (interpreter.exception()) if (global_object.vm().exception())
return {}; return {};
return primitive.to_number(interpreter); return primitive.to_number(global_object);
} }
default: default:
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
@ -337,18 +337,18 @@ size_t Value::as_size_t() const
return min((double)as_i32(), MAX_ARRAY_LIKE_INDEX); 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); auto number = to_number(global_object);
if (interpreter.exception()) if (global_object.vm().exception())
return 0; return 0;
return number.as_double(); return number.as_double();
} }
i32 Value::to_i32(Interpreter& interpreter) const i32 Value::to_i32(GlobalObject& global_object) const
{ {
auto number = to_number(interpreter); auto number = to_number(global_object);
if (interpreter.exception()) if (global_object.vm().exception())
return 0; return 0;
if (number.is_nan()) if (number.is_nan())
return 0; return 0;
@ -357,12 +357,12 @@ i32 Value::to_i32(Interpreter& interpreter) const
return number.as_i32(); 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()) if (is_empty())
return 0; return 0;
auto number = to_number(interpreter); auto number = to_number(global_object);
if (interpreter.exception()) if (global_object.vm().exception())
return 0; return 0;
if (number.is_nan()) if (number.is_nan())
return 0; 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { 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) 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()) if (interpreter.exception())
return {}; return {};
if (lhs_numeric.is_number()) if (lhs_numeric.is_number())
@ -483,12 +483,12 @@ Value bitwise_not(Interpreter& interpreter, Value lhs)
Value unary_plus(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) 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()) if (interpreter.exception())
return {}; return {};
if (lhs_numeric.is_number()) { 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
@ -574,10 +574,10 @@ Value add(Interpreter& interpreter, Value lhs, Value rhs)
return {}; return {};
if (lhs_primitive.is_string() || rhs_primitive.is_string()) { 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()) if (interpreter.exception())
return {}; return {};
auto rhs_string = rhs_primitive.to_string(interpreter); auto rhs_string = rhs_primitive.to_string(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
StringBuilder builder(lhs_string.length() + rhs_string.length()); 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()); 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs_primitive.to_numeric(interpreter); auto rhs_numeric = rhs_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) 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) 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()) if (interpreter.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) { if (both_number(lhs_numeric, rhs_numeric)) {
@ -670,19 +670,20 @@ Value mod(Interpreter& interpreter, Value lhs, Value rhs)
return {}; 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); auto& vm = global_object.vm();
if (interpreter.exception()) auto lhs_numeric = lhs.to_numeric(global_object);
if (vm.exception())
return {}; return {};
auto rhs_numeric = rhs.to_numeric(interpreter); auto rhs_numeric = rhs.to_numeric(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (both_number(lhs_numeric, rhs_numeric)) if (both_number(lhs_numeric, rhs_numeric))
return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double())); return Value(pow(lhs_numeric.as_double(), rhs_numeric.as_double()));
if (both_bigint(lhs_numeric, rhs_numeric)) 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())); return js_bigint(vm.heap(), 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"); vm.throw_exception<TypeError>(global_object, ErrorType::BigIntBadOperatorOtherType, "exponentiation");
return {}; return {};
} }
@ -692,44 +693,46 @@ Value in(Interpreter& interpreter, Value lhs, Value rhs)
interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::InOperatorWithObject); interpreter.vm().throw_exception<TypeError>(interpreter.global_object(), ErrorType::InOperatorWithObject);
return {}; return {};
} }
auto lhs_string = lhs.to_string(interpreter); auto lhs_string = lhs.to_string(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
return Value(rhs.as_object().has_property(lhs_string)); 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()) { 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 {}; 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_empty()) {
if (!has_instance_method.is_function()) { 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 {};
} }
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()) { 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 {};
} }
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()) if (!rhs.is_function())
return Value(false); return Value(false);
auto& rhs_function = rhs.as_function(); auto& rhs_function = rhs.as_function();
if (rhs_function.is_bound_function()) { if (rhs_function.is_bound_function()) {
auto& bound_target = static_cast<BoundFunction&>(rhs_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()) if (!lhs.is_object())
@ -737,20 +740,20 @@ Value ordinary_has_instance(Interpreter& interpreter, Value lhs, Value rhs)
Object* lhs_object = &lhs.as_object(); Object* lhs_object = &lhs.as_object();
auto rhs_prototype = rhs_function.get("prototype"); auto rhs_prototype = rhs_function.get("prototype");
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!rhs_prototype.is_object()) { 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 {}; return {};
} }
while (true) { while (true) {
lhs_object = lhs_object->prototype(); lhs_object = lhs_object->prototype();
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!lhs_object) if (!lhs_object)
return Value(false); return Value(false);
if (same_value(interpreter, rhs_prototype, lhs_object)) if (same_value(rhs_prototype, lhs_object))
return Value(true); 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()); 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()) if (lhs.type() != rhs.type())
return false; return false;
@ -783,10 +786,10 @@ bool same_value(Interpreter& interpreter, Value lhs, Value rhs)
return lhs_big_integer == rhs_big_integer; 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()) if (lhs.type() != rhs.type())
return false; return false;
@ -800,10 +803,10 @@ bool same_value_zero(Interpreter& interpreter, Value lhs, Value rhs)
if (lhs.is_bigint()) if (lhs.is_bigint())
return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer(); 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.is_number() && !lhs.is_bigint());
ASSERT(lhs.type() == rhs.type()); 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()) if (lhs.type() != rhs.type())
return false; return false;
@ -841,22 +844,22 @@ bool strict_eq(Interpreter& interpreter, Value lhs, Value rhs)
if (lhs.is_bigint()) if (lhs.is_bigint())
return lhs.as_bigint().big_integer() == rhs.as_bigint().big_integer(); 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) bool abstract_eq(Interpreter& interpreter, Value lhs, Value rhs)
{ {
if (lhs.type() == rhs.type()) 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())) if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
return true; return true;
if (lhs.is_number() && rhs.is_string()) 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()) 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()) { if (lhs.is_bigint() && rhs.is_string()) {
auto& rhs_string = rhs.as_string().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); return abstract_eq(interpreter, rhs, lhs);
if (lhs.is_boolean()) 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()) 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()) if ((lhs.is_string() || lhs.is_number() || lhs.is_bigint() || lhs.is_symbol()) && rhs.is_object())
return abstract_eq(interpreter, lhs, rhs.to_primitive()); 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; return TriState::False;
} }
auto x_numeric = x_primitive.to_numeric(interpreter); auto x_numeric = x_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
auto y_numeric = y_primitive.to_numeric(interpreter); auto y_numeric = y_primitive.to_numeric(interpreter.global_object());
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
@ -1014,7 +1017,7 @@ size_t length_of_array_like(Interpreter& interpreter, Value value)
auto result = value.as_object().get("length"); auto result = value.as_object().get("length");
if (interpreter.exception()) if (interpreter.exception())
return 0; 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; i32 as_i32() const;
size_t as_size_t() const; size_t as_size_t() const;
String to_string(Interpreter&) const; String to_string(GlobalObject&) const;
PrimitiveString* to_primitive_string(Interpreter&); PrimitiveString* to_primitive_string(GlobalObject&);
Value to_primitive(PreferredType preferred_type = PreferredType::Default) const; Value to_primitive(PreferredType preferred_type = PreferredType::Default) const;
Object* to_object(Interpreter&, GlobalObject&) const; Object* to_object(GlobalObject&) const;
Value to_numeric(Interpreter&) const; Value to_numeric(GlobalObject&) const;
Value to_number(Interpreter&) const; Value to_number(GlobalObject&) const;
BigInt* to_bigint(GlobalObject&) const; BigInt* to_bigint(GlobalObject&) const;
double to_double(Interpreter&) const; double to_double(GlobalObject&) const;
i32 to_i32(Interpreter&) const; i32 to_i32(GlobalObject&) const;
size_t to_size_t(Interpreter&) const; size_t to_size_t(GlobalObject&) const;
bool to_boolean() const; bool to_boolean() const;
String to_string_without_side_effects() 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 mul(Interpreter&, Value lhs, Value rhs);
Value div(Interpreter&, Value lhs, Value rhs); Value div(Interpreter&, Value lhs, Value rhs);
Value mod(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 in(Interpreter&, Value lhs, Value rhs);
Value instance_of(Interpreter&, Value lhs, Value rhs); Value instance_of(GlobalObject&, Value lhs, Value rhs);
Value ordinary_has_instance(Interpreter& interpreter, Value lhs, Value rhs); Value ordinary_has_instance(GlobalObject&, Value lhs, Value rhs);
bool abstract_eq(Interpreter&, Value lhs, Value rhs); bool abstract_eq(Interpreter&, Value lhs, Value rhs);
bool strict_eq(Interpreter&, Value lhs, Value rhs); bool strict_eq(Value lhs, Value rhs);
bool same_value(Interpreter&, Value lhs, Value rhs); bool same_value(Value lhs, Value rhs);
bool same_value_zero(Interpreter&, Value lhs, Value rhs); bool same_value_zero(Value lhs, Value rhs);
bool same_value_non_numeric(Interpreter&, Value lhs, Value rhs); bool same_value_non_numeric(Value lhs, Value rhs);
TriState abstract_relation(Interpreter&, bool left_first, Value lhs, Value rhs); TriState abstract_relation(Interpreter&, bool left_first, Value lhs, Value rhs);
size_t length_of_array_like(Interpreter&, Value); size_t length_of_array_like(Interpreter&, Value);

View file

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

View file

@ -62,7 +62,7 @@ NavigatorObject::~NavigatorObject()
JS_DEFINE_NATIVE_GETTER(NavigatorObject::user_agent_getter) 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(); 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) { if (!this_object) {
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
return nullptr; return nullptr;
} }
if (StringView("WindowObject") != this_object->class_name()) { 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 nullptr;
} }
return &static_cast<WindowObject*>(this_object)->impl(); 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) JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
String message = ""; String message = "";
if (interpreter.argument_count()) { if (vm.argument_count()) {
message = interpreter.argument(0).to_string(interpreter); message = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
impl->alert(message); impl->alert(message);
@ -130,13 +130,13 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::alert)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm) JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
String message = ""; String message = "";
if (interpreter.argument_count()) { if (vm.argument_count()) {
message = interpreter.argument(0).to_string(interpreter); message = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
} }
return JS::Value(impl->confirm(message)); return JS::Value(impl->confirm(message));
@ -144,24 +144,24 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::confirm)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval) JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setInterval");
return {}; 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) if (!callback_object)
return {}; return {};
if (!callback_object->is_function()) { 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 {};
} }
i32 interval = 0; i32 interval = 0;
if (interpreter.argument_count() >= 2) { if (vm.argument_count() >= 2) {
interval = interpreter.argument(1).to_i32(interpreter); interval = vm.argument(1).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (interval < 0) if (interval < 0)
interval = 0; interval = 0;
@ -173,24 +173,24 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_interval)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout) JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setTimeout"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "setTimeout");
return {}; 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) if (!callback_object)
return {}; return {};
if (!callback_object->is_function()) { 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 {};
} }
i32 interval = 0; i32 interval = 0;
if (interpreter.argument_count() >= 2) { if (vm.argument_count() >= 2) {
interval = interpreter.argument(1).to_i32(interpreter); interval = vm.argument(1).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (interval < 0) if (interval < 0)
interval = 0; interval = 0;
@ -202,15 +202,15 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::set_timeout)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout) JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearTimeout"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearTimeout");
return {}; return {};
} }
i32 timer_id = interpreter.argument(0).to_i32(interpreter); i32 timer_id = vm.argument(0).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
impl->clear_timeout(timer_id); impl->clear_timeout(timer_id);
return JS::js_undefined(); return JS::js_undefined();
@ -218,15 +218,15 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_timeout)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval) JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearInterval"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountAtLeastOne, "clearInterval");
return {}; return {};
} }
i32 timer_id = interpreter.argument(0).to_i32(interpreter); i32 timer_id = vm.argument(0).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
impl->clear_timeout(timer_id); impl->clear_timeout(timer_id);
return JS::js_undefined(); return JS::js_undefined();
@ -234,18 +234,18 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::clear_interval)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame) JS_DEFINE_NATIVE_FUNCTION(WindowObject::request_animation_frame)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "requestAnimationFrame"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "requestAnimationFrame");
return {}; 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) if (!callback_object)
return {}; return {};
if (!callback_object->is_function()) { 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 {};
} }
return JS::Value(impl->request_animation_frame(*static_cast<JS::Function*>(callback_object))); 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) JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "cancelAnimationFrame"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "cancelAnimationFrame");
return {}; return {};
} }
auto id = interpreter.argument(0).to_i32(interpreter); auto id = vm.argument(0).to_i32(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
impl->cancel_animation_frame(id); impl->cancel_animation_frame(id);
return JS::js_undefined(); return JS::js_undefined();
@ -269,52 +269,52 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::cancel_animation_frame)
JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob) JS_DEFINE_NATIVE_FUNCTION(WindowObject::atob)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "atob"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "atob");
return {}; return {};
} }
auto string = interpreter.argument(0).to_string(interpreter); auto string = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto decoded = decode_base64(StringView(string)); 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. // 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) JS_DEFINE_NATIVE_FUNCTION(WindowObject::btoa)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
if (!interpreter.argument_count()) { if (!vm.argument_count()) {
interpreter.vm().throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "btoa"); vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, "btoa");
return {}; return {};
} }
auto string = interpreter.argument(0).to_string(interpreter); auto string = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
Vector<u8> byte_string; Vector<u8> byte_string;
byte_string.ensure_capacity(string.length()); byte_string.ensure_capacity(string.length());
for (u32 code_point : Utf8View(string)) { for (u32 code_point : Utf8View(string)) {
if (code_point > 0xff) { 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 {}; return {};
} }
byte_string.append(code_point); byte_string.append(code_point);
} }
auto encoded = encode_base64(byte_string.span()); 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) JS_DEFINE_NATIVE_GETTER(WindowObject::document_getter)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
return wrap(global_object, impl->document()); 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) if (!this_object)
return nullptr; return nullptr;
if (StringView("XMLHttpRequestWrapper") != this_object->class_name()) { 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 nullptr;
} }
return &static_cast<XMLHttpRequestWrapper*>(this_object)->impl(); 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) JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::open)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
auto arg0 = interpreter.argument(0).to_string(interpreter); auto arg0 = vm.argument(0).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
auto arg1 = interpreter.argument(1).to_string(interpreter); auto arg1 = vm.argument(1).to_string(global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
impl->open(arg0, arg1); impl->open(arg0, arg1);
return JS::js_undefined(); return JS::js_undefined();
@ -87,7 +87,7 @@ JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::open)
JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::send) JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::send)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
impl->send(); impl->send();
@ -96,7 +96,7 @@ JS_DEFINE_NATIVE_FUNCTION(XMLHttpRequestPrototype::send)
JS_DEFINE_NATIVE_GETTER(XMLHttpRequestPrototype::ready_state_getter) JS_DEFINE_NATIVE_GETTER(XMLHttpRequestPrototype::ready_state_getter)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; return {};
return JS::Value((i32)impl->ready_state()); 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) JS_DEFINE_NATIVE_GETTER(XMLHttpRequestPrototype::response_text_getter)
{ {
auto* impl = impl_from(interpreter, global_object); auto* impl = impl_from(vm, global_object);
if (!impl) if (!impl)
return {}; 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() // Implementation: impl_from()
if (!interface.attributes.is_empty() || !interface.functions.is_empty()) { 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() << "{";
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() << " if (!this_object)";
out() << " return {};"; out() << " return {};";
out() << " if (!this_object->inherits(\"" << wrapper_class << "\")) {"; 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() << " return nullptr;";
out() << " }"; out() << " }";
out() << " return &static_cast<" << wrapper_class << "*>(this_object)->impl();"; out() << " return &static_cast<" << wrapper_class << "*>(this_object)->impl();";
@ -521,27 +521,27 @@ void generate_implementation(const IDL::Interface& interface)
out() << " return {};"; out() << " return {};";
}; };
if (parameter.type.name == "DOMString") { if (parameter.type.name == "DOMString") {
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_string(interpreter);"; out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_string(global_object);";
out() << " if (interpreter.exception())"; out() << " if (vm.exception())";
generate_return(); generate_return();
} else if (parameter.type.name == "EventListener") { } else if (parameter.type.name == "EventListener") {
out() << " if (!" << js_name << js_suffix << ".is_function()) {"; 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(); generate_return();
out() << " }"; out() << " }";
out() << " auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));"; out() << " auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));";
} else if (is_wrappable_type(parameter.type)) { } else if (is_wrappable_type(parameter.type)) {
out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(interpreter, global_object);"; out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(global_object);";
out() << " if (interpreter.exception())"; out() << " if (vm.exception())";
generate_return(); generate_return();
out() << " if (!" << cpp_name << "_object->inherits(\"" << parameter.type.name << "Wrapper\")) {"; 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(); generate_return();
out() << " }"; out() << " }";
out() << " auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();"; out() << " auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();";
} else if (parameter.type.name == "double") { } else if (parameter.type.name == "double") {
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(interpreter);"; out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(global_object);";
out() << " if (interpreter.exception())"; out() << " if (vm.exception())";
generate_return(); generate_return();
} else if (parameter.type.name == "boolean") { } else if (parameter.type.name == "boolean") {
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_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; size_t argument_index = 0;
for (auto& parameter : parameters) { for (auto& parameter : parameters) {
parameter_names.append(snake_name(parameter.name)); 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); generate_to_cpp(parameter, "arg", argument_index, snake_name(parameter.name), return_void);
++argument_index; ++argument_index;
} }
@ -580,7 +580,7 @@ void generate_implementation(const IDL::Interface& interface)
} }
if (return_type.name == "DOMString") { 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") { } else if (return_type.name == "ArrayFromVector") {
// FIXME: Remove this fake type hack once it's no longer needed. // FIXME: Remove this fake type hack once it's no longer needed.
// Basically once we have NodeList we can throw this out. // 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) { for (auto& attribute : interface.attributes) {
out() << "JS_DEFINE_NATIVE_GETTER(" << wrapper_class << "::" << attribute.getter_callback_name << ")"; out() << "JS_DEFINE_NATIVE_GETTER(" << wrapper_class << "::" << attribute.getter_callback_name << ")";
out() << "{"; out() << "{";
out() << " auto* impl = impl_from(interpreter, global_object);"; out() << " auto* impl = impl_from(vm, global_object);";
out() << " if (!impl)"; out() << " if (!impl)";
out() << " return {};"; out() << " return {};";
@ -629,7 +629,7 @@ void generate_implementation(const IDL::Interface& interface)
if (!attribute.readonly) { if (!attribute.readonly) {
out() << "JS_DEFINE_NATIVE_SETTER(" << wrapper_class << "::" << attribute.setter_callback_name << ")"; out() << "JS_DEFINE_NATIVE_SETTER(" << wrapper_class << "::" << attribute.setter_callback_name << ")";
out() << "{"; out() << "{";
out() << " auto* impl = impl_from(interpreter, global_object);"; out() << " auto* impl = impl_from(vm, global_object);";
out() << " if (!impl)"; out() << " if (!impl)";
out() << " return;"; out() << " return;";
@ -652,15 +652,15 @@ void generate_implementation(const IDL::Interface& interface)
for (auto& function : interface.functions) { for (auto& function : interface.functions) {
out() << "JS_DEFINE_NATIVE_FUNCTION(" << wrapper_class << "::" << snake_name(function.name) << ")"; out() << "JS_DEFINE_NATIVE_FUNCTION(" << wrapper_class << "::" << snake_name(function.name) << ")";
out() << "{"; out() << "{";
out() << " auto* impl = impl_from(interpreter, global_object);"; out() << " auto* impl = impl_from(vm, global_object);";
out() << " if (!impl)"; out() << " if (!impl)";
out() << " return {};"; out() << " return {};";
if (function.length() > 0) { if (function.length() > 0) {
out() << " if (interpreter.argument_count() < " << function.length() << ") {"; out() << " if (vm.argument_count() < " << function.length() << ") {";
if (function.length() == 1) 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 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() << " return {};";
out() << " }"; out() << " }";
} }

View file

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

View file

@ -160,7 +160,7 @@ void TestRunnerGlobalObject::initialize()
JS_DEFINE_NATIVE_FUNCTION(TestRunnerGlobalObject::is_strict_mode) 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() static void cleanup_and_exit()

View file

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