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

LibJS: Cache commonly used FlyStrings in the VM

Roughly 7% of test-js runtime was spent creating FlyStrings from string
literals. This patch frontloads that work and caches all the commonly
used names in LibJS on a CommonPropertyNames struct that hangs off VM.
This commit is contained in:
Andreas Kling 2020-10-13 23:49:19 +02:00
parent 9f6c5f68b6
commit 7b863330dc
45 changed files with 651 additions and 392 deletions

View file

@ -698,6 +698,7 @@ Value ClassMethod::execute(Interpreter& interpreter, GlobalObject& global_object
Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const
{ {
auto& vm = interpreter.vm();
Value class_constructor_value = m_constructor->execute(interpreter, global_object); Value class_constructor_value = m_constructor->execute(interpreter, global_object);
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
@ -720,22 +721,22 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
Object* super_constructor_prototype = nullptr; Object* super_constructor_prototype = nullptr;
if (!super_constructor.is_null()) { if (!super_constructor.is_null()) {
super_constructor_prototype = &super_constructor.as_object().get("prototype").as_object(); super_constructor_prototype = &super_constructor.as_object().get(vm.names.prototype).as_object();
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
} }
prototype->set_prototype(super_constructor_prototype); prototype->set_prototype(super_constructor_prototype);
prototype->define_property("constructor", class_constructor, 0); prototype->define_property(vm.names.constructor, class_constructor, 0);
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
class_constructor->define_property("prototype", prototype, 0); class_constructor->define_property(vm.names.prototype, prototype, 0);
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
class_constructor->set_prototype(super_constructor.is_null() ? global_object.function_prototype() : &super_constructor.as_object()); class_constructor->set_prototype(super_constructor.is_null() ? global_object.function_prototype() : &super_constructor.as_object());
} }
auto class_prototype = class_constructor->get("prototype"); auto class_prototype = class_constructor->get(vm.names.prototype);
if (interpreter.exception()) if (interpreter.exception())
return {}; return {};
@ -1756,21 +1757,22 @@ void TaggedTemplateLiteral::dump(int indent) const
Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& global_object) const Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& global_object) const
{ {
auto& vm = interpreter.vm();
auto tag = m_tag->execute(interpreter, global_object); auto tag = m_tag->execute(interpreter, global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
if (!tag.is_function()) { if (!tag.is_function()) {
interpreter.vm().throw_exception<TypeError>(global_object, ErrorType::NotAFunction, tag.to_string_without_side_effects()); vm.throw_exception<TypeError>(global_object, ErrorType::NotAFunction, tag.to_string_without_side_effects());
return {}; return {};
} }
auto& tag_function = tag.as_function(); auto& tag_function = tag.as_function();
auto& expressions = m_template_literal->expressions(); auto& expressions = m_template_literal->expressions();
auto* strings = Array::create(global_object); auto* strings = Array::create(global_object);
MarkedValueList arguments(interpreter.heap()); MarkedValueList arguments(vm.heap());
arguments.append(strings); arguments.append(strings);
for (size_t i = 0; i < expressions.size(); ++i) { for (size_t i = 0; i < expressions.size(); ++i) {
auto value = expressions[i].execute(interpreter, global_object); auto value = expressions[i].execute(interpreter, global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
// tag`${foo}` -> "", foo, "" -> tag(["", ""], foo) // tag`${foo}` -> "", foo, "" -> tag(["", ""], foo)
// tag`foo${bar}baz${qux}` -> "foo", bar, "baz", qux, "" -> tag(["foo", "baz", ""], bar, qux) // tag`foo${bar}baz${qux}` -> "foo", bar, "baz", qux, "" -> tag(["foo", "baz", ""], bar, qux)
@ -1784,12 +1786,12 @@ Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& glo
auto* raw_strings = Array::create(global_object); auto* raw_strings = Array::create(global_object);
for (auto& raw_string : m_template_literal->raw_strings()) { for (auto& raw_string : m_template_literal->raw_strings()) {
auto value = raw_string.execute(interpreter, global_object); auto value = raw_string.execute(interpreter, global_object);
if (interpreter.exception()) if (vm.exception())
return {}; return {};
raw_strings->indexed_properties().append(value); raw_strings->indexed_properties().append(value);
} }
strings->define_property("raw", raw_strings, 0); strings->define_property(vm.names.raw, raw_strings, 0);
return interpreter.vm().call(tag_function, js_undefined(), move(arguments)); return vm.call(tag_function, js_undefined(), move(arguments));
} }
void TryStatement::dump(int indent) const void TryStatement::dump(int indent) const

View file

@ -69,7 +69,8 @@ Value Interpreter::run(GlobalObject& global_object, const Program& program)
CallFrame global_call_frame; CallFrame global_call_frame;
global_call_frame.this_value = &global_object; global_call_frame.this_value = &global_object;
global_call_frame.function_name = "(global execution context)"; static FlyString global_execution_context_name = "(global execution context)";
global_call_frame.function_name = global_execution_context_name;
global_call_frame.environment = heap().allocate<LexicalEnvironment>(global_object, LexicalEnvironment::EnvironmentRecordType::Global); global_call_frame.environment = heap().allocate<LexicalEnvironment>(global_object, LexicalEnvironment::EnvironmentRecordType::Global);
global_call_frame.environment->bind_this_value(global_object, &global_object); global_call_frame.environment->bind_this_value(global_object, &global_object);
global_call_frame.is_strict_mode = program.is_strict_mode(); global_call_frame.is_strict_mode = program.is_strict_mode();

View file

@ -40,7 +40,8 @@ Array* Array::create(GlobalObject& global_object)
Array::Array(Object& prototype) Array::Array(Object& prototype)
: Object(prototype) : Object(prototype)
{ {
define_native_property("length", length_getter, length_setter, Attribute::Writable); auto& vm = this->vm();
define_native_property(vm.names.length, length_getter, length_setter, Attribute::Writable);
} }
Array::~Array() Array::~Array()

View file

@ -37,7 +37,7 @@
namespace JS { namespace JS {
ArrayConstructor::ArrayConstructor(GlobalObject& global_object) ArrayConstructor::ArrayConstructor(GlobalObject& global_object)
: NativeFunction("Array", *global_object.function_prototype()) : NativeFunction(vm().names.Array, *global_object.function_prototype())
{ {
} }
@ -47,15 +47,16 @@ ArrayConstructor::~ArrayConstructor()
void ArrayConstructor::initialize(GlobalObject& global_object) void ArrayConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.array_prototype(), 0); define_property(vm.names.prototype, global_object.array_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("from", from, 1, attr); define_native_function(vm.names.from, from, 1, attr);
define_native_function("isArray", is_array, 1, attr); define_native_function(vm.names.isArray, is_array, 1, attr);
define_native_function("of", of, 0, attr); define_native_function(vm.names.of, of, 0, attr);
} }
Value ArrayConstructor::call() Value ArrayConstructor::call()

View file

@ -40,9 +40,10 @@ ArrayIteratorPrototype::ArrayIteratorPrototype(GlobalObject& global_object)
void ArrayIteratorPrototype::initialize(GlobalObject& global_object) void ArrayIteratorPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
define_native_function("next", next, 0, Attribute::Configurable | Attribute::Writable); define_native_function(vm.names.next, next, 0, Attribute::Configurable | Attribute::Writable);
define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Array Iterator"), Attribute::Configurable); define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Array Iterator"), Attribute::Configurable);
} }

View file

@ -46,40 +46,41 @@ ArrayPrototype::ArrayPrototype(GlobalObject& global_object)
void ArrayPrototype::initialize(GlobalObject& global_object) void ArrayPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("filter", filter, 1, attr); define_native_function(vm.names.filter, filter, 1, attr);
define_native_function("forEach", for_each, 1, attr); define_native_function(vm.names.forEach, for_each, 1, attr);
define_native_function("map", map, 1, attr); define_native_function(vm.names.map, map, 1, attr);
define_native_function("pop", pop, 0, attr); define_native_function(vm.names.pop, pop, 0, attr);
define_native_function("push", push, 1, attr); define_native_function(vm.names.push, push, 1, attr);
define_native_function("shift", shift, 0, attr); define_native_function(vm.names.shift, shift, 0, attr);
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
define_native_function("toLocaleString", to_locale_string, 0, attr); define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
define_native_function("unshift", unshift, 1, attr); define_native_function(vm.names.unshift, unshift, 1, attr);
define_native_function("join", join, 1, attr); define_native_function(vm.names.join, join, 1, attr);
define_native_function("concat", concat, 1, attr); define_native_function(vm.names.concat, concat, 1, attr);
define_native_function("slice", slice, 2, attr); define_native_function(vm.names.slice, slice, 2, attr);
define_native_function("indexOf", index_of, 1, attr); define_native_function(vm.names.indexOf, index_of, 1, attr);
define_native_function("reduce", reduce, 1, attr); define_native_function(vm.names.reduce, reduce, 1, attr);
define_native_function("reduceRight", reduce_right, 1, attr); define_native_function(vm.names.reduceRight, reduce_right, 1, attr);
define_native_function("reverse", reverse, 0, attr); define_native_function(vm.names.reverse, reverse, 0, attr);
define_native_function("lastIndexOf", last_index_of, 1, attr); define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
define_native_function("includes", includes, 1, attr); define_native_function(vm.names.includes, includes, 1, attr);
define_native_function("find", find, 1, attr); define_native_function(vm.names.find, find, 1, attr);
define_native_function("findIndex", find_index, 1, attr); define_native_function(vm.names.findIndex, find_index, 1, attr);
define_native_function("some", some, 1, attr); define_native_function(vm.names.some, some, 1, attr);
define_native_function("every", every, 1, attr); define_native_function(vm.names.every, every, 1, attr);
define_native_function("splice", splice, 2, attr); define_native_function(vm.names.splice, splice, 2, attr);
define_native_function("fill", fill, 1, attr); define_native_function(vm.names.fill, fill, 1, attr);
define_native_function("values", values, 0, attr); define_native_function(vm.names.values, values, 0, attr);
define_property("length", Value(0), Attribute::Configurable); define_property(vm.names.length, Value(0), Attribute::Configurable);
// Use define_property here instead of define_native_function so that // Use define_property here instead of define_native_function so that
// Object.is(Array.prototype[Symbol.iterator], Array.prototype.values) // Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
// evaluates to true // evaluates to true
define_property(global_object.vm().well_known_symbol_iterator(), get("values"), attr); define_property(vm.well_known_symbol_iterator(), get(vm.names.values), attr);
} }
ArrayPrototype::~ArrayPrototype() ArrayPrototype::~ArrayPrototype()
@ -103,7 +104,7 @@ static Function* callback_from_args(GlobalObject& global_object, const String& n
static size_t get_length(VM& vm, Object& object) static size_t get_length(VM& vm, Object& object)
{ {
auto length_property = object.get("length"); auto length_property = object.get(vm.names.length);
if (vm.exception()) if (vm.exception())
return 0; return 0;
return length_property.to_size_t(object.global_object()); return length_property.to_size_t(object.global_object());
@ -208,7 +209,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push)
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(vm.names.length, new_length_value);
if (vm.exception()) if (vm.exception())
return {}; return {};
return new_length_value; return new_length_value;
@ -237,7 +238,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
} }
auto length = get_length(vm, *this_object); auto length = get_length(vm, *this_object);
if (length == 0) { if (length == 0) {
this_object->put("length", Value(0)); this_object->put(vm.names.length, Value(0));
return js_undefined(); return js_undefined();
} }
auto index = length - 1; auto index = length - 1;
@ -247,7 +248,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
this_object->delete_property(index); this_object->delete_property(index);
if (vm.exception()) if (vm.exception())
return {}; return {};
this_object->put("length", Value((i32)index)); this_object->put(vm.names.length, Value((i32)index));
if (vm.exception()) if (vm.exception())
return {}; return {};
return element; return element;
@ -271,7 +272,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
auto* this_object = vm.this_value(global_object).to_object(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(vm.names.join);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (!join_function.is_function()) if (!join_function.is_function())
@ -789,7 +790,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
return {}; return {};
} }
this_object->put("length", Value((i32)new_length)); this_object->put(vm.names.length, Value((i32)new_length));
if (vm.exception()) if (vm.exception())
return {}; return {};

View file

@ -35,19 +35,20 @@
namespace JS { namespace JS {
BigIntConstructor::BigIntConstructor(GlobalObject& global_object) BigIntConstructor::BigIntConstructor(GlobalObject& global_object)
: NativeFunction("BigInt", *global_object.function_prototype()) : NativeFunction(vm().names.BigInt, *global_object.function_prototype())
{ {
} }
void BigIntConstructor::initialize(GlobalObject& global_object) void BigIntConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.bigint_prototype(), 0); define_property(vm.names.prototype, global_object.bigint_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("asIntN", as_int_n, 2, attr); define_native_function(vm.names.asIntN, as_int_n, 2, attr);
define_native_function("asUintN", as_uint_n, 2, attr); define_native_function(vm.names.asUintN, as_uint_n, 2, attr);
} }
BigIntConstructor::~BigIntConstructor() BigIntConstructor::~BigIntConstructor()

View file

@ -39,13 +39,14 @@ BigIntPrototype::BigIntPrototype(GlobalObject& global_object)
void BigIntPrototype::initialize(GlobalObject& global_object) void BigIntPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
define_native_function("toLocaleString", to_locale_string, 0, attr); define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
define_native_function("valueOf", value_of, 0, attr); define_native_function(vm.names.valueOf, value_of, 0, attr);
define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "BigInt"), Attribute::Configurable); define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), "BigInt"), Attribute::Configurable);
} }
BigIntPrototype::~BigIntPrototype() BigIntPrototype::~BigIntPrototype()

View file

@ -33,15 +33,16 @@
namespace JS { namespace JS {
BooleanConstructor::BooleanConstructor(GlobalObject& global_object) BooleanConstructor::BooleanConstructor(GlobalObject& global_object)
: NativeFunction("Boolean", *global_object.function_prototype()) : NativeFunction(vm().names.Boolean, *global_object.function_prototype())
{ {
} }
void BooleanConstructor::initialize(GlobalObject& global_object) void BooleanConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", Value(global_object.boolean_prototype()), 0); define_property(vm.names.prototype, Value(global_object.boolean_prototype()), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
} }
BooleanConstructor::~BooleanConstructor() BooleanConstructor::~BooleanConstructor()

View file

@ -38,9 +38,10 @@ BooleanPrototype::BooleanPrototype(GlobalObject& global_object)
void BooleanPrototype::initialize(GlobalObject& global_object) void BooleanPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
BooleanObject::initialize(global_object); BooleanObject::initialize(global_object);
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.toString, to_string, 0, Attribute::Writable | Attribute::Configurable);
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.valueOf, value_of, 0, Attribute::Writable | Attribute::Configurable);
} }
BooleanPrototype::~BooleanPrototype() BooleanPrototype::~BooleanPrototype()

View file

@ -40,8 +40,9 @@ BoundFunction::BoundFunction(GlobalObject& global_object, Function& target_funct
void BoundFunction::initialize(GlobalObject& global_object) void BoundFunction::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Function::initialize(global_object); Function::initialize(global_object);
define_property("length", Value(m_length), Attribute::Configurable); define_property(vm.names.length, Value(m_length), Attribute::Configurable);
} }
BoundFunction::~BoundFunction() BoundFunction::~BoundFunction()

View file

@ -0,0 +1,209 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <AK/FlyString.h>
#include <LibJS/Forward.h>
namespace JS {
#define ENUMERATE_STANDARD_PROPERTY_NAMES(P) \
P(BigInt) \
P(Boolean) \
P(E) \
P(EPSILON) \
P(Infinity) \
P(JSON) \
P(LN10) \
P(LN2) \
P(LOG10E) \
P(LOG2E) \
P(MAX_SAFE_INTEGER) \
P(MIN_SAFE_INTEGER) \
P(Math) \
P(NEGATIVE_INFINITY) \
P(NaN) \
P(Number) \
P(PI) \
P(POSITIVE_INFINITY) \
P(Proxy) \
P(Reflect) \
P(RegExp) \
P(SQRT1_2) \
P(SQRT2) \
P(String) \
P(Symbol) \
P(UTC) \
P(abs) \
P(acosh) \
P(apply) \
P(asIntN) \
P(asUintN) \
P(asinh) \
P(atanh) \
P(bind) \
P(call) \
P(cbrt) \
P(ceil) \
P(charAt) \
P(charCodeAt) \
P(clz32) \
P(concat) \
P(console) \
P(construct) \
P(constructor) \
P(cos) \
P(defineProperty) \
P(deleteProperty) \
P(description) \
P(done) \
P(entries) \
P(every) \
P(exp) \
P(expm1) \
P(fill) \
P(filter) \
P(find) \
P(findIndex) \
P(floor) \
P(forEach) \
P(from) \
P(fromCharCode) \
P(gc) \
P(get) \
P(getDate) \
P(getDay) \
P(getFullYear) \
P(getHours) \
P(getMilliseconds) \
P(getMinutes) \
P(getMonth) \
P(getOwnPropertyDescriptor) \
P(getOwnPropertyNames) \
P(getPrototypeOf) \
P(getSeconds) \
P(getTime) \
P(getUTCDate) \
P(getUTCDay) \
P(getUTCFullYear) \
P(getUTCHours) \
P(getUTCMilliseconds) \
P(getUTCMinutes) \
P(getUTCMonth) \
P(getUTCSeconds) \
P(globalThis) \
P(has) \
P(hasOwnProperty) \
P(includes) \
P(indexOf) \
P(is) \
P(isArray) \
P(isExtensible) \
P(isFinite) \
P(isInteger) \
P(isNaN) \
P(isSafeInteger) \
P(join) \
P(keyFor) \
P(keys) \
P(lastIndexOf) \
P(length) \
P(log1p) \
P(map) \
P(max) \
P(message) \
P(min) \
P(name) \
P(now) \
P(of) \
P(ownKeys) \
P(padEnd) \
P(padStart) \
P(parse) \
P(parseFloat) \
P(pop) \
P(pow) \
P(preventExtensions) \
P(prototype) \
P(push) \
P(random) \
P(raw) \
P(reduce) \
P(reduceRight) \
P(repeat) \
P(reverse) \
P(round) \
P(set) \
P(setPrototypeOf) \
P(shift) \
P(sign) \
P(sin) \
P(slice) \
P(some) \
P(splice) \
P(sqrt) \
P(startsWith) \
P(substring) \
P(tan) \
P(toDateString) \
P(toISOString) \
P(toJSON) \
P(toLocaleDateString) \
P(toLocaleString) \
P(toLocaleTimeString) \
P(toLowerCase) \
P(toString) \
P(toTimeString) \
P(toUpperCase) \
P(trim) \
P(trimEnd) \
P(trimStart) \
P(trunc) \
P(undefined) \
P(unshift) \
P(value) \
P(valueOf) \
P(enumerable) \
P(configurable) \
P(writable) \
P(next) \
P(values)
struct CommonPropertyNames {
FlyString for_ { "for" };
#define __ENUMERATE(x) FlyString x { #x };
ENUMERATE_STANDARD_PROPERTY_NAMES(__ENUMERATE)
#undef __ENUMERATE
#define __JS_ENUMERATE(x, a, b, c) FlyString x { #x };
JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE
#define __JS_ENUMERATE(x, a) FlyString x { #x };
JS_ENUMERATE_WELL_KNOWN_SYMBOLS
#undef __JS_ENUMERATE
};
}

View file

@ -138,19 +138,20 @@ static Value parse_simplified_iso8601(const String& iso_8601)
} }
DateConstructor::DateConstructor(GlobalObject& global_object) DateConstructor::DateConstructor(GlobalObject& global_object)
: NativeFunction("Date", *global_object.function_prototype()) : NativeFunction(vm().names.Date, *global_object.function_prototype())
{ {
} }
void DateConstructor::initialize(GlobalObject& global_object) void DateConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.date_prototype(), 0); define_property(vm.names.prototype, global_object.date_prototype(), 0);
define_property("length", Value(7), Attribute::Configurable); define_property(vm.names.length, Value(7), Attribute::Configurable);
define_native_function("now", now, 0, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.now, now, 0, Attribute::Writable | Attribute::Configurable);
define_native_function("parse", parse, 1, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.parse, parse, 1, Attribute::Writable | Attribute::Configurable);
define_native_function("UTC", utc, 1, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.UTC, utc, 1, Attribute::Writable | Attribute::Configurable);
} }
DateConstructor::~DateConstructor() DateConstructor::~DateConstructor()

View file

@ -54,35 +54,36 @@ DatePrototype::DatePrototype(GlobalObject& global_object)
void DatePrototype::initialize(GlobalObject& global_object) void DatePrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("getDate", get_date, 0, attr); define_native_function(vm.names.getDate, get_date, 0, attr);
define_native_function("getDay", get_day, 0, attr); define_native_function(vm.names.getDay, get_day, 0, attr);
define_native_function("getFullYear", get_full_year, 0, attr); define_native_function(vm.names.getFullYear, get_full_year, 0, attr);
define_native_function("getHours", get_hours, 0, attr); define_native_function(vm.names.getHours, get_hours, 0, attr);
define_native_function("getMilliseconds", get_milliseconds, 0, attr); define_native_function(vm.names.getMilliseconds, get_milliseconds, 0, attr);
define_native_function("getMinutes", get_minutes, 0, attr); define_native_function(vm.names.getMinutes, get_minutes, 0, attr);
define_native_function("getMonth", get_month, 0, attr); define_native_function(vm.names.getMonth, get_month, 0, attr);
define_native_function("getSeconds", get_seconds, 0, attr); define_native_function(vm.names.getSeconds, get_seconds, 0, attr);
define_native_function("getTime", get_time, 0, attr); define_native_function(vm.names.getTime, get_time, 0, attr);
define_native_function("getUTCDate", get_utc_date, 0, attr); define_native_function(vm.names.getUTCDate, get_utc_date, 0, attr);
define_native_function("getUTCDay", get_utc_day, 0, attr); define_native_function(vm.names.getUTCDay, get_utc_day, 0, attr);
define_native_function("getUTCFullYear", get_utc_full_year, 0, attr); define_native_function(vm.names.getUTCFullYear, get_utc_full_year, 0, attr);
define_native_function("getUTCHours", get_utc_hours, 0, attr); define_native_function(vm.names.getUTCHours, get_utc_hours, 0, attr);
define_native_function("getUTCMilliseconds", get_utc_milliseconds, 0, attr); define_native_function(vm.names.getUTCMilliseconds, get_utc_milliseconds, 0, attr);
define_native_function("getUTCMinutes", get_utc_minutes, 0, attr); define_native_function(vm.names.getUTCMinutes, get_utc_minutes, 0, attr);
define_native_function("getUTCMonth", get_utc_month, 0, attr); define_native_function(vm.names.getUTCMonth, get_utc_month, 0, attr);
define_native_function("getUTCSeconds", get_utc_seconds, 0, attr); define_native_function(vm.names.getUTCSeconds, get_utc_seconds, 0, attr);
define_native_function("toDateString", to_date_string, 0, attr); define_native_function(vm.names.toDateString, to_date_string, 0, attr);
define_native_function("toISOString", to_iso_string, 0, attr); define_native_function(vm.names.toISOString, to_iso_string, 0, attr);
define_native_function("toLocaleDateString", to_locale_date_string, 0, attr); define_native_function(vm.names.toLocaleDateString, to_locale_date_string, 0, attr);
define_native_function("toLocaleString", to_locale_string, 0, attr); define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
define_native_function("toLocaleTimeString", to_locale_time_string, 0, attr); define_native_function(vm.names.toLocaleTimeString, to_locale_time_string, 0, attr);
define_native_function("toTimeString", to_time_string, 0, attr); define_native_function(vm.names.toTimeString, to_time_string, 0, attr);
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
// Aliases. // Aliases.
define_native_function("valueOf", get_time, 0, attr); define_native_function(vm.names.valueOf, get_time, 0, attr);
// toJSON() isn't quite an alias for toISOString(): // toJSON() isn't quite an alias for toISOString():
// - it returns null instead of throwing RangeError // - it returns null instead of throwing RangeError
// - its .length is 1, not 0 // - its .length is 1, not 0

View file

@ -51,7 +51,7 @@ Error::~Error()
return global_object.heap().allocate<ClassName>(global_object, message, *global_object.snake_name##_prototype()); \ return global_object.heap().allocate<ClassName>(global_object, message, *global_object.snake_name##_prototype()); \
} \ } \
ClassName::ClassName(const String& message, Object& prototype) \ ClassName::ClassName(const String& message, Object& prototype) \
: Error(#ClassName, message, prototype) \ : Error(vm().names.ClassName, message, prototype) \
{ \ { \
} \ } \
ClassName::~ClassName() { } ClassName::~ClassName() { }

View file

@ -31,15 +31,16 @@
namespace JS { namespace JS {
ErrorConstructor::ErrorConstructor(GlobalObject& global_object) ErrorConstructor::ErrorConstructor(GlobalObject& global_object)
: NativeFunction("Error", *global_object.function_prototype()) : NativeFunction(vm().names.Error, *global_object.function_prototype())
{ {
} }
void ErrorConstructor::initialize(GlobalObject& global_object) void ErrorConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.error_prototype(), 0); define_property(vm.names.prototype, global_object.error_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
} }
ErrorConstructor::~ErrorConstructor() ErrorConstructor::~ErrorConstructor()
@ -60,7 +61,7 @@ Value ErrorConstructor::construct(Function&)
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
return Error::create(global_object(), "Error", message); return Error::create(global_object(), vm.names.Error, message);
} }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
@ -70,9 +71,10 @@ Value ErrorConstructor::construct(Function&)
} \ } \
void ConstructorName::initialize(GlobalObject& global_object) \ void ConstructorName::initialize(GlobalObject& global_object) \
{ \ { \
auto& vm = this->vm(); \
NativeFunction::initialize(global_object); \ NativeFunction::initialize(global_object); \
define_property("prototype", global_object.snake_name##_prototype(), 0); \ define_property(vm.names.prototype, global_object.snake_name##_prototype(), 0); \
define_property("length", Value(1), Attribute::Configurable); \ define_property(vm.names.length, Value(1), Attribute::Configurable); \
} \ } \
ConstructorName::~ConstructorName() { } \ ConstructorName::~ConstructorName() { } \
Value ConstructorName::call() \ Value ConstructorName::call() \

View file

@ -41,11 +41,12 @@ ErrorPrototype::ErrorPrototype(GlobalObject& global_object)
void ErrorPrototype::initialize(GlobalObject& global_object) void ErrorPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_property("name", name_getter, name_setter, attr); define_native_property(vm.names.name, name_getter, name_setter, attr);
define_native_property("message", message_getter, nullptr, attr); define_native_property(vm.names.message, message_getter, nullptr, attr);
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
} }
ErrorPrototype::~ErrorPrototype() ErrorPrototype::~ErrorPrototype()
@ -100,7 +101,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
auto& this_object = vm.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(vm.names.name);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (!name_property.is_empty() && !name_property.is_undefined()) { if (!name_property.is_empty() && !name_property.is_undefined()) {
@ -110,7 +111,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
} }
String message = ""; String message = "";
auto message_property = this_object.get("message"); auto message_property = this_object.get(vm.names.message);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (!message_property.is_empty() && !message_property.is_undefined()) { if (!message_property.is_empty() && !message_property.is_undefined()) {

View file

@ -35,7 +35,7 @@ Exception::Exception(Value value)
{ {
auto& call_stack = vm().call_stack(); auto& call_stack = vm().call_stack();
for (ssize_t i = call_stack.size() - 1; i >= 0; --i) { for (ssize_t i = call_stack.size() - 1; i >= 0; --i) {
auto function_name = call_stack[i].function_name; String function_name = call_stack[i].function_name;
if (function_name.is_empty()) if (function_name.is_empty())
function_name = "<anonymous>"; function_name = "<anonymous>";
m_trace.append(function_name); m_trace.append(function_name);

View file

@ -49,15 +49,16 @@ Function::~Function()
BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments) BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
{ {
auto& vm = this->vm();
Function& target_function = is_bound_function() ? static_cast<BoundFunction&>(*this).target_function() : *this; Function& target_function = is_bound_function() ? static_cast<BoundFunction&>(*this).target_function() : *this;
auto bound_this_object = [bound_this_value, this]() -> Value { auto bound_this_object = [&vm, bound_this_value, this]() -> Value {
if (!m_bound_this.is_empty()) if (!m_bound_this.is_empty())
return m_bound_this; return m_bound_this;
switch (bound_this_value.type()) { switch (bound_this_value.type()) {
case Value::Type::Undefined: case Value::Type::Undefined:
case Value::Type::Null: case Value::Type::Null:
if (vm().in_strict_mode()) if (vm.in_strict_mode())
return bound_this_value; return bound_this_value;
return &global_object(); return &global_object();
default: default:
@ -66,15 +67,15 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
}(); }();
i32 computed_length = 0; i32 computed_length = 0;
auto length_property = get("length"); auto length_property = get(vm.names.length);
if (vm().exception()) if (vm.exception())
return nullptr; return nullptr;
if (length_property.is_number()) if (length_property.is_number())
computed_length = max(0, length_property.as_i32() - static_cast<i32>(arguments.size())); computed_length = max(0, length_property.as_i32() - static_cast<i32>(arguments.size()));
Object* constructor_prototype = nullptr; Object* constructor_prototype = nullptr;
auto prototype_property = target_function.get("prototype"); auto prototype_property = target_function.get(vm.names.prototype);
if (vm().exception()) if (vm.exception())
return nullptr; return nullptr;
if (prototype_property.is_object()) if (prototype_property.is_object())
constructor_prototype = &prototype_property.as_object(); constructor_prototype = &prototype_property.as_object();

View file

@ -36,15 +36,16 @@
namespace JS { namespace JS {
FunctionConstructor::FunctionConstructor(GlobalObject& global_object) FunctionConstructor::FunctionConstructor(GlobalObject& global_object)
: NativeFunction("Function", *global_object.function_prototype()) : NativeFunction(vm().names.Function, *global_object.function_prototype())
{ {
} }
void FunctionConstructor::initialize(GlobalObject& global_object) void FunctionConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.function_prototype(), 0); define_property(vm.names.prototype, global_object.function_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
} }
FunctionConstructor::~FunctionConstructor() FunctionConstructor::~FunctionConstructor()

View file

@ -45,15 +45,16 @@ FunctionPrototype::FunctionPrototype(GlobalObject& global_object)
void FunctionPrototype::initialize(GlobalObject& global_object) void FunctionPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("apply", apply, 2, attr); define_native_function(vm.names.apply, apply, 2, attr);
define_native_function("bind", bind, 1, attr); define_native_function(vm.names.bind, bind, 1, attr);
define_native_function("call", call, 1, attr); define_native_function(vm.names.call, call, 1, attr);
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
define_native_function(global_object.vm().well_known_symbol_has_instance(), symbol_has_instance, 1, 0); define_native_function(vm.well_known_symbol_has_instance(), symbol_has_instance, 1, 0);
define_property("length", Value(0), Attribute::Configurable); define_property(vm.names.length, Value(0), Attribute::Configurable);
define_property("name", js_string(heap(), ""), Attribute::Configurable); define_property(vm.names.name, js_string(heap(), ""), Attribute::Configurable);
} }
FunctionPrototype::~FunctionPrototype() FunctionPrototype::~FunctionPrototype()
@ -78,7 +79,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
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(vm.names.length);
if (vm.exception()) if (vm.exception())
return {}; return {};
auto length = length_property.to_size_t(global_object); auto length = length_property.to_size_t(global_object);

View file

@ -75,6 +75,8 @@ GlobalObject::GlobalObject()
void GlobalObject::initialize() void GlobalObject::initialize()
{ {
auto& vm = this->vm();
ensure_shape_is_unique(); ensure_shape_is_unique();
// These are done first since other prototypes depend on their presence. // These are done first since other prototypes depend on their presence.
@ -98,36 +100,36 @@ void GlobalObject::initialize()
#undef __JS_ENUMERATE #undef __JS_ENUMERATE
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("gc", gc, 0, attr); define_native_function(vm.names.gc, gc, 0, attr);
define_native_function("isNaN", is_nan, 1, attr); define_native_function(vm.names.isNaN, is_nan, 1, attr);
define_native_function("isFinite", is_finite, 1, attr); define_native_function(vm.names.isFinite, is_finite, 1, attr);
define_native_function("parseFloat", parse_float, 1, attr); define_native_function(vm.names.parseFloat, parse_float, 1, attr);
define_property("NaN", js_nan(), 0); define_property(vm.names.NaN, js_nan(), 0);
define_property("Infinity", js_infinity(), 0); define_property(vm.names.Infinity, js_infinity(), 0);
define_property("undefined", js_undefined(), 0); define_property(vm.names.undefined, js_undefined(), 0);
define_property("globalThis", this, attr); define_property(vm.names.globalThis, this, attr);
define_property("console", heap().allocate<ConsoleObject>(*this, *this), attr); define_property(vm.names.console, heap().allocate<ConsoleObject>(*this, *this), attr);
define_property("Math", heap().allocate<MathObject>(*this, *this), attr); define_property(vm.names.Math, heap().allocate<MathObject>(*this, *this), attr);
define_property("JSON", heap().allocate<JSONObject>(*this, *this), attr); define_property(vm.names.JSON, heap().allocate<JSONObject>(*this, *this), attr);
define_property("Reflect", heap().allocate<ReflectObject>(*this, *this), attr); define_property(vm.names.Reflect, heap().allocate<ReflectObject>(*this, *this), attr);
add_constructor("Array", m_array_constructor, *m_array_prototype); add_constructor(vm.names.Array, m_array_constructor, *m_array_prototype);
add_constructor("BigInt", m_bigint_constructor, *m_bigint_prototype); add_constructor(vm.names.BigInt, m_bigint_constructor, *m_bigint_prototype);
add_constructor("Boolean", m_boolean_constructor, *m_boolean_prototype); add_constructor(vm.names.Boolean, m_boolean_constructor, *m_boolean_prototype);
add_constructor("Date", m_date_constructor, *m_date_prototype); add_constructor(vm.names.Date, m_date_constructor, *m_date_prototype);
add_constructor("Error", m_error_constructor, *m_error_prototype); add_constructor(vm.names.Error, m_error_constructor, *m_error_prototype);
add_constructor("Function", m_function_constructor, *m_function_prototype); add_constructor(vm.names.Function, m_function_constructor, *m_function_prototype);
add_constructor("Number", m_number_constructor, *m_number_prototype); add_constructor(vm.names.Number, m_number_constructor, *m_number_prototype);
add_constructor("Object", m_object_constructor, *m_object_prototype); add_constructor(vm.names.Object, m_object_constructor, *m_object_prototype);
add_constructor("Proxy", m_proxy_constructor, *m_proxy_prototype); add_constructor(vm.names.Proxy, m_proxy_constructor, *m_proxy_prototype);
add_constructor("RegExp", m_regexp_constructor, *m_regexp_prototype); add_constructor(vm.names.RegExp, m_regexp_constructor, *m_regexp_prototype);
add_constructor("String", m_string_constructor, *m_string_prototype); add_constructor(vm.names.String, m_string_constructor, *m_string_prototype);
add_constructor("Symbol", m_symbol_constructor, *m_symbol_prototype); add_constructor(vm.names.Symbol, m_symbol_constructor, *m_symbol_prototype);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
add_constructor(#ClassName, m_##snake_name##_constructor, *m_##snake_name##_prototype); add_constructor(vm.names.ClassName, m_##snake_name##_constructor, *m_##snake_name##_prototype);
JS_ENUMERATE_ERROR_SUBCLASSES JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE #undef __JS_ENUMERATE
} }

View file

@ -87,12 +87,13 @@ private:
template<typename ConstructorType> template<typename ConstructorType>
inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype) inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype)
{ {
auto& vm = this->vm();
constructor = heap().allocate<ConstructorType>(*this, *this); constructor = heap().allocate<ConstructorType>(*this, *this);
constructor->define_property("name", js_string(heap(), property_name), Attribute::Configurable); constructor->define_property(vm.names.name, js_string(heap(), property_name), Attribute::Configurable);
if (vm().exception()) if (vm.exception())
return; return;
prototype.define_property("constructor", constructor, Attribute::Writable | Attribute::Configurable); prototype.define_property(vm.names.constructor, constructor, Attribute::Writable | Attribute::Configurable);
if (vm().exception()) if (vm.exception())
return; return;
define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable); define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable);
} }

View file

@ -62,7 +62,7 @@ Object* iterator_next(Object& iterator, Value value)
{ {
auto& vm = iterator.vm(); auto& vm = iterator.vm();
auto& global_object = iterator.global_object(); auto& global_object = iterator.global_object();
auto next_method = iterator.get("next"); auto next_method = iterator.get(vm.names.next);
if (vm.exception()) if (vm.exception())
return {}; return {};
@ -95,9 +95,10 @@ void iterator_close(Object& iterator)
Value create_iterator_result_object(GlobalObject& global_object, Value value, bool done) Value create_iterator_result_object(GlobalObject& global_object, Value value, bool done)
{ {
auto& vm = global_object.vm();
auto* object = Object::create_empty(global_object); auto* object = Object::create_empty(global_object);
object->define_property("value", value); object->define_property(vm.names.value, value);
object->define_property("done", Value(done)); object->define_property(vm.names.done, Value(done));
return object; return object;
} }
@ -114,14 +115,14 @@ void get_iterator_values(GlobalObject& global_object, Value value, AK::Function<
if (!next_object) if (!next_object)
return; return;
auto done_property = next_object->get("done"); auto done_property = next_object->get(vm.names.done);
if (vm.exception()) if (vm.exception())
return; return;
if (!done_property.is_empty() && done_property.to_boolean()) if (!done_property.is_empty() && done_property.to_boolean())
return; return;
auto next_value = next_object->get("value"); auto next_value = next_object->get(vm.names.value);
if (vm.exception()) if (vm.exception())
return; return;

View file

@ -154,7 +154,7 @@ String JSONObject::serialize_json_property(GlobalObject& global_object, Stringif
if (vm.exception()) if (vm.exception())
return {}; return {};
if (value.is_object()) { if (value.is_object()) {
auto to_json = value.as_object().get("toJSON"); auto to_json = value.as_object().get(vm.names.toJSON);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (to_json.is_function()) { if (to_json.is_function()) {

View file

@ -40,41 +40,42 @@ MathObject::MathObject(GlobalObject& global_object)
void MathObject::initialize(GlobalObject& global_object) void MathObject::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("abs", abs, 1, attr); define_native_function(vm.names.abs, abs, 1, attr);
define_native_function("random", random, 0, attr); define_native_function(vm.names.random, random, 0, attr);
define_native_function("sqrt", sqrt, 1, attr); define_native_function(vm.names.sqrt, sqrt, 1, attr);
define_native_function("floor", floor, 1, attr); define_native_function(vm.names.floor, floor, 1, attr);
define_native_function("ceil", ceil, 1, attr); define_native_function(vm.names.ceil, ceil, 1, attr);
define_native_function("round", round, 1, attr); define_native_function(vm.names.round, round, 1, attr);
define_native_function("max", max, 2, attr); define_native_function(vm.names.max, max, 2, attr);
define_native_function("min", min, 2, attr); define_native_function(vm.names.min, min, 2, attr);
define_native_function("trunc", trunc, 1, attr); define_native_function(vm.names.trunc, trunc, 1, attr);
define_native_function("sin", sin, 1, attr); define_native_function(vm.names.sin, sin, 1, attr);
define_native_function("cos", cos, 1, attr); define_native_function(vm.names.cos, cos, 1, attr);
define_native_function("tan", tan, 1, attr); define_native_function(vm.names.tan, tan, 1, attr);
define_native_function("pow", pow, 2, attr); define_native_function(vm.names.pow, pow, 2, attr);
define_native_function("exp", exp, 1, attr); define_native_function(vm.names.exp, exp, 1, attr);
define_native_function("expm1", expm1, 1, attr); define_native_function(vm.names.expm1, expm1, 1, attr);
define_native_function("sign", sign, 1, attr); define_native_function(vm.names.sign, sign, 1, attr);
define_native_function("clz32", clz32, 1, attr); define_native_function(vm.names.clz32, clz32, 1, attr);
define_native_function("acosh", acosh, 1, attr); define_native_function(vm.names.acosh, acosh, 1, attr);
define_native_function("asinh", asinh, 1, attr); define_native_function(vm.names.asinh, asinh, 1, attr);
define_native_function("atanh", atanh, 1, attr); define_native_function(vm.names.atanh, atanh, 1, attr);
define_native_function("log1p", log1p, 1, attr); define_native_function(vm.names.log1p, log1p, 1, attr);
define_native_function("cbrt", cbrt, 1, attr); define_native_function(vm.names.cbrt, cbrt, 1, attr);
define_property("E", Value(M_E), 0); define_property(vm.names.E, Value(M_E), 0);
define_property("LN2", Value(M_LN2), 0); define_property(vm.names.LN2, Value(M_LN2), 0);
define_property("LN10", Value(M_LN10), 0); define_property(vm.names.LN10, Value(M_LN10), 0);
define_property("LOG2E", Value(log2(M_E)), 0); define_property(vm.names.LOG2E, Value(log2(M_E)), 0);
define_property("LOG10E", Value(log10(M_E)), 0); define_property(vm.names.LOG10E, Value(log10(M_E)), 0);
define_property("PI", Value(M_PI), 0); define_property(vm.names.PI, Value(M_PI), 0);
define_property("SQRT1_2", Value(M_SQRT1_2), 0); define_property(vm.names.SQRT1_2, Value(M_SQRT1_2), 0);
define_property("SQRT2", Value(M_SQRT2), 0); define_property(vm.names.SQRT2, Value(M_SQRT2), 0);
define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Math"), Attribute::Configurable); define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), "Math"), Attribute::Configurable);
} }
MathObject::~MathObject() MathObject::~MathObject()

View file

@ -30,34 +30,36 @@
#include <LibJS/Runtime/NumberObject.h> #include <LibJS/Runtime/NumberObject.h>
#include <math.h> #include <math.h>
#define EPSILON pow(2, -52) // FIXME: constexpr these?
#define MAX_SAFE_INTEGER pow(2, 53) - 1 #define EPSILON_VALUE pow(2, -52)
#define MIN_SAFE_INTEGER -(pow(2, 53) - 1) #define MAX_SAFE_INTEGER_VALUE pow(2, 53) - 1
#define MIN_SAFE_INTEGER_VALUE -(pow(2, 53) - 1)
namespace JS { namespace JS {
NumberConstructor::NumberConstructor(GlobalObject& global_object) NumberConstructor::NumberConstructor(GlobalObject& global_object)
: NativeFunction("Number", *global_object.function_prototype()) : NativeFunction(vm().names.Number, *global_object.function_prototype())
{ {
} }
void NumberConstructor::initialize(GlobalObject& global_object) void NumberConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("isFinite", is_finite, 1, attr); define_native_function(vm.names.isFinite, is_finite, 1, attr);
define_native_function("isInteger", is_integer, 1, attr); define_native_function(vm.names.isInteger, is_integer, 1, attr);
define_native_function("isNaN", is_nan, 1, attr); define_native_function(vm.names.isNaN, is_nan, 1, attr);
define_native_function("isSafeInteger", is_safe_integer, 1, attr); define_native_function(vm.names.isSafeInteger, is_safe_integer, 1, attr);
define_property("parseFloat", global_object.get("parseFloat")); define_property(vm.names.parseFloat, global_object.get(vm.names.parseFloat));
define_property("prototype", global_object.number_prototype(), 0); define_property(vm.names.prototype, global_object.number_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
define_property("EPSILON", Value(EPSILON), 0); define_property(vm.names.EPSILON, Value(EPSILON_VALUE), 0);
define_property("MAX_SAFE_INTEGER", Value(MAX_SAFE_INTEGER), 0); define_property(vm.names.MAX_SAFE_INTEGER, Value(MAX_SAFE_INTEGER_VALUE), 0);
define_property("MIN_SAFE_INTEGER", Value(MIN_SAFE_INTEGER), 0); define_property(vm.names.MIN_SAFE_INTEGER, Value(MIN_SAFE_INTEGER_VALUE), 0);
define_property("NEGATIVE_INFINITY", js_negative_infinity(), 0); define_property(vm.names.NEGATIVE_INFINITY, js_negative_infinity(), 0);
define_property("POSITIVE_INFINITY", js_infinity(), 0); define_property(vm.names.POSITIVE_INFINITY, js_infinity(), 0);
define_property("NaN", js_nan(), 0); define_property(vm.names.NaN, js_nan(), 0);
} }
NumberConstructor::~NumberConstructor() NumberConstructor::~NumberConstructor()
@ -102,7 +104,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_safe_integer)
if (!vm.argument(0).is_number()) if (!vm.argument(0).is_number())
return Value(false); return Value(false);
auto value = vm.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 && value <= MAX_SAFE_INTEGER_VALUE);
} }
} }

View file

@ -44,36 +44,36 @@ namespace JS {
PropertyDescriptor PropertyDescriptor::from_dictionary(VM& vm, const Object& object) PropertyDescriptor PropertyDescriptor::from_dictionary(VM& vm, const Object& object)
{ {
PropertyAttributes attributes; PropertyAttributes attributes;
if (object.has_property("configurable")) { if (object.has_property(vm.names.configurable)) {
attributes.set_has_configurable(); attributes.set_has_configurable();
if (object.get("configurable").value_or(Value(false)).to_boolean()) if (object.get(vm.names.configurable).value_or(Value(false)).to_boolean())
attributes.set_configurable(); attributes.set_configurable();
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
if (object.has_property("enumerable")) { if (object.has_property(vm.names.enumerable)) {
attributes.set_has_enumerable(); attributes.set_has_enumerable();
if (object.get("enumerable").value_or(Value(false)).to_boolean()) if (object.get(vm.names.enumerable).value_or(Value(false)).to_boolean())
attributes.set_enumerable(); attributes.set_enumerable();
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
if (object.has_property("writable")) { if (object.has_property(vm.names.writable)) {
attributes.set_has_writable(); attributes.set_has_writable();
if (object.get("writable").value_or(Value(false)).to_boolean()) if (object.get(vm.names.writable).value_or(Value(false)).to_boolean())
attributes.set_writable(); attributes.set_writable();
if (vm.exception()) if (vm.exception())
return {}; return {};
} }
PropertyDescriptor descriptor { attributes, object.get("value"), nullptr, nullptr }; PropertyDescriptor descriptor { attributes, object.get(vm.names.value), nullptr, nullptr };
if (vm.exception()) if (vm.exception())
return {}; return {};
auto getter = object.get("get"); auto getter = object.get(vm.names.get);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (getter.is_function()) if (getter.is_function())
descriptor.getter = &getter.as_function(); descriptor.getter = &getter.as_function();
auto setter = object.get("set"); auto setter = object.get(vm.names.set);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (setter.is_function()) if (setter.is_function())
@ -295,34 +295,35 @@ Optional<PropertyDescriptor> Object::get_own_property_descriptor(const PropertyN
Value Object::get_own_property_descriptor_object(const PropertyName& property_name) const Value Object::get_own_property_descriptor_object(const PropertyName& property_name) const
{ {
auto& vm = this->vm();
auto descriptor_opt = get_own_property_descriptor(property_name); auto descriptor_opt = get_own_property_descriptor(property_name);
if (!descriptor_opt.has_value()) if (!descriptor_opt.has_value())
return js_undefined(); return js_undefined();
auto descriptor = descriptor_opt.value(); auto descriptor = descriptor_opt.value();
auto* descriptor_object = Object::create_empty(global_object()); auto* descriptor_object = Object::create_empty(global_object());
descriptor_object->define_property("enumerable", Value(descriptor.attributes.is_enumerable())); descriptor_object->define_property(vm.names.enumerable, Value(descriptor.attributes.is_enumerable()));
if (vm().exception()) if (vm.exception())
return {}; return {};
descriptor_object->define_property("configurable", Value(descriptor.attributes.is_configurable())); descriptor_object->define_property(vm.names.configurable, Value(descriptor.attributes.is_configurable()));
if (vm().exception()) if (vm.exception())
return {}; return {};
if (descriptor.is_data_descriptor()) { if (descriptor.is_data_descriptor()) {
descriptor_object->define_property("value", descriptor.value.value_or(js_undefined())); descriptor_object->define_property(vm.names.value, descriptor.value.value_or(js_undefined()));
if (vm().exception()) if (vm.exception())
return {}; return {};
descriptor_object->define_property("writable", Value(descriptor.attributes.is_writable())); descriptor_object->define_property(vm.names.writable, Value(descriptor.attributes.is_writable()));
if (vm().exception()) if (vm.exception())
return {}; return {};
} else if (descriptor.is_accessor_descriptor()) { } else if (descriptor.is_accessor_descriptor()) {
if (descriptor.getter) { if (descriptor.getter) {
descriptor_object->define_property("get", Value(descriptor.getter)); descriptor_object->define_property(vm.names.get, Value(descriptor.getter));
if (vm().exception()) if (vm.exception())
return {}; return {};
} }
if (descriptor.setter) { if (descriptor.setter) {
descriptor_object->define_property("set", Value(descriptor.setter)); descriptor_object->define_property(vm.names.set, Value(descriptor.setter));
if (vm().exception()) if (vm.exception())
return {}; return {};
} }
} }
@ -337,35 +338,36 @@ void Object::set_shape(Shape& new_shape)
bool Object::define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions) bool Object::define_property(const StringOrSymbol& property_name, const Object& descriptor, bool throw_exceptions)
{ {
bool is_accessor_property = descriptor.has_property("get") || descriptor.has_property("set"); auto& vm = this->vm();
bool is_accessor_property = descriptor.has_property(vm.names.get) || descriptor.has_property(vm.names.set);
PropertyAttributes attributes; PropertyAttributes attributes;
if (descriptor.has_property("configurable")) { if (descriptor.has_property(vm.names.configurable)) {
attributes.set_has_configurable(); attributes.set_has_configurable();
if (descriptor.get("configurable").value_or(Value(false)).to_boolean()) if (descriptor.get(vm.names.configurable).value_or(Value(false)).to_boolean())
attributes.set_configurable(); attributes.set_configurable();
if (vm().exception()) if (vm.exception())
return false; return false;
} }
if (descriptor.has_property("enumerable")) { if (descriptor.has_property(vm.names.enumerable)) {
attributes.set_has_enumerable(); attributes.set_has_enumerable();
if (descriptor.get("enumerable").value_or(Value(false)).to_boolean()) if (descriptor.get(vm.names.enumerable).value_or(Value(false)).to_boolean())
attributes.set_enumerable(); attributes.set_enumerable();
if (vm().exception()) if (vm.exception())
return false; return false;
} }
if (is_accessor_property) { if (is_accessor_property) {
if (descriptor.has_property("value") || descriptor.has_property("writable")) { if (descriptor.has_property(vm.names.value) || descriptor.has_property(vm.names.writable)) {
if (throw_exceptions) if (throw_exceptions)
vm().throw_exception<TypeError>(global_object(), ErrorType::AccessorValueOrWritable); vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorValueOrWritable);
return false; return false;
} }
auto getter = descriptor.get("get").value_or(js_undefined()); auto getter = descriptor.get(vm.names.get).value_or(js_undefined());
if (vm().exception()) if (vm.exception())
return {}; return {};
auto setter = descriptor.get("set").value_or(js_undefined()); auto setter = descriptor.get(vm.names.set).value_or(js_undefined());
if (vm().exception()) if (vm.exception())
return {}; return {};
Function* getter_function { nullptr }; Function* getter_function { nullptr };
@ -374,14 +376,14 @@ bool Object::define_property(const StringOrSymbol& property_name, const Object&
if (getter.is_function()) { if (getter.is_function()) {
getter_function = &getter.as_function(); getter_function = &getter.as_function();
} else if (!getter.is_undefined()) { } else if (!getter.is_undefined()) {
vm().throw_exception<TypeError>(global_object(), ErrorType::AccessorBadField, "get"); vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorBadField, "get");
return false; return false;
} }
if (setter.is_function()) { if (setter.is_function()) {
setter_function = &setter.as_function(); setter_function = &setter.as_function();
} else if (!setter.is_undefined()) { } else if (!setter.is_undefined()) {
vm().throw_exception<TypeError>(global_object(), ErrorType::AccessorBadField, "set"); vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorBadField, "set");
return false; return false;
} }
@ -391,20 +393,20 @@ bool Object::define_property(const StringOrSymbol& property_name, const Object&
<< "setter=" << setter.to_string_without_side_effects() << "}"; << "setter=" << setter.to_string_without_side_effects() << "}";
#endif #endif
return define_property(property_name, Accessor::create(vm(), getter_function, setter_function), attributes, throw_exceptions); return define_property(property_name, Accessor::create(vm, getter_function, setter_function), attributes, throw_exceptions);
} }
auto value = descriptor.get("value"); auto value = descriptor.get(vm.names.value);
if (vm().exception()) if (vm.exception())
return {}; return {};
if (descriptor.has_property("writable")) { if (descriptor.has_property(vm.names.writable)) {
attributes.set_has_writable(); attributes.set_has_writable();
if (descriptor.get("writable").value_or(Value(false)).to_boolean()) if (descriptor.get(vm.names.writable).value_or(Value(false)).to_boolean())
attributes.set_writable(); attributes.set_writable();
if (vm().exception()) if (vm.exception())
return false; return false;
} }
if (vm().exception()) if (vm.exception())
return {}; return {};
#ifdef OBJECT_DEBUG #ifdef OBJECT_DEBUG
@ -462,6 +464,14 @@ bool Object::put_own_property(Object& this_object, const StringOrSymbol& propert
{ {
ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor())); ASSERT(!(mode == PutOwnPropertyMode::Put && value.is_accessor()));
if (value.is_accessor()) {
auto& accessor = value.as_accessor();
if (accessor.getter())
attributes.set_has_getter();
if (accessor.setter())
attributes.set_has_setter();
}
auto metadata = shape().lookup(property_name); auto metadata = shape().lookup(property_name);
bool new_property = !metadata.has_value(); bool new_property = !metadata.has_value();
@ -474,14 +484,6 @@ bool Object::put_own_property(Object& this_object, const StringOrSymbol& propert
return false; return false;
} }
if (value.is_accessor()) {
auto& accessor = value.as_accessor();
if (accessor.getter())
attributes.set_has_getter();
if (accessor.setter())
attributes.set_has_setter();
}
if (new_property) { if (new_property) {
if (!m_shape->is_unique() && shape().property_count() > 100) { if (!m_shape->is_unique() && shape().property_count() > 100) {
// If you add more than 100 properties to an object, let's stop doing // If you add more than 100 properties to an object, let's stop doing
@ -752,6 +754,7 @@ bool Object::put(const PropertyName& property_name, Value value, Value receiver)
bool Object::define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, 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)
{ {
auto& vm = this->vm();
String function_name; String function_name;
if (property_name.is_string()) { if (property_name.is_string()) {
function_name = property_name.as_string(); function_name = property_name.as_string();
@ -759,11 +762,11 @@ bool Object::define_native_function(const StringOrSymbol& property_name, AK::Fun
function_name = String::formatted("[{}]", property_name.as_symbol()->description()); function_name = String::formatted("[{}]", property_name.as_symbol()->description());
} }
auto* function = NativeFunction::create(global_object(), function_name, move(native_function)); auto* function = NativeFunction::create(global_object(), function_name, move(native_function));
function->define_property_without_transition("length", Value(length), Attribute::Configurable); function->define_property_without_transition(vm.names.length, Value(length), Attribute::Configurable);
if (vm().exception()) if (vm.exception())
return {}; return {};
function->define_property_without_transition("name", js_string(heap(), function_name), Attribute::Configurable); function->define_property_without_transition(vm.names.name, js_string(vm.heap(), function_name), Attribute::Configurable);
if (vm().exception()) if (vm.exception())
return {}; return {};
return define_property(property_name, function, attribute); return define_property(property_name, function, attribute);
} }
@ -846,7 +849,7 @@ Value Object::to_primitive(Value::PreferredType preferred_type) const
Value Object::to_string() const Value Object::to_string() const
{ {
auto& vm = this->vm(); auto& vm = this->vm();
auto to_string_property = get("toString"); auto to_string_property = get(vm.names.toString);
if (to_string_property.is_function()) { if (to_string_property.is_function()) {
auto& to_string_function = to_string_property.as_function(); auto& to_string_function = to_string_property.as_function();
auto to_string_result = vm.call(to_string_function, const_cast<Object*>(this)); auto to_string_result = vm.call(to_string_function, const_cast<Object*>(this));
@ -859,7 +862,7 @@ Value Object::to_string() const
return {}; return {};
return string; return string;
} }
return js_string(heap(), String::formatted("[object {}]", class_name())); return js_string(vm, String::formatted("[object {}]", class_name()));
} }
Value Object::invoke(const StringOrSymbol& property_name, Optional<MarkedValueList> arguments) Value Object::invoke(const StringOrSymbol& property_name, Optional<MarkedValueList> arguments)

View file

@ -35,28 +35,29 @@
namespace JS { namespace JS {
ObjectConstructor::ObjectConstructor(GlobalObject& global_object) ObjectConstructor::ObjectConstructor(GlobalObject& global_object)
: NativeFunction("Object", *global_object.function_prototype()) : NativeFunction(vm().names.Object, *global_object.function_prototype())
{ {
} }
void ObjectConstructor::initialize(GlobalObject& global_object) void ObjectConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.object_prototype(), 0); define_property(vm.names.prototype, global_object.object_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("defineProperty", define_property_, 3, attr); define_native_function(vm.names.defineProperty, define_property_, 3, attr);
define_native_function("is", is, 2, attr); define_native_function(vm.names.is, is, 2, attr);
define_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr); define_native_function(vm.names.getOwnPropertyDescriptor, get_own_property_descriptor, 2, attr);
define_native_function("getOwnPropertyNames", get_own_property_names, 1, attr); define_native_function(vm.names.getOwnPropertyNames, get_own_property_names, 1, attr);
define_native_function("getPrototypeOf", get_prototype_of, 1, attr); define_native_function(vm.names.getPrototypeOf, get_prototype_of, 1, attr);
define_native_function("setPrototypeOf", set_prototype_of, 2, attr); define_native_function(vm.names.setPrototypeOf, set_prototype_of, 2, attr);
define_native_function("isExtensible", is_extensible, 1, attr); define_native_function(vm.names.isExtensible, is_extensible, 1, attr);
define_native_function("preventExtensions", prevent_extensions, 1, attr); define_native_function(vm.names.preventExtensions, prevent_extensions, 1, attr);
define_native_function("keys", keys, 1, attr); define_native_function(vm.names.keys, keys, 1, attr);
define_native_function("values", values, 1, attr); define_native_function(vm.names.values, values, 1, attr);
define_native_function("entries", entries, 1, attr); define_native_function(vm.names.entries, entries, 1, attr);
} }
ObjectConstructor::~ObjectConstructor() ObjectConstructor::~ObjectConstructor()

View file

@ -40,14 +40,15 @@ ObjectPrototype::ObjectPrototype(GlobalObject& global_object)
void ObjectPrototype::initialize(GlobalObject& global_object) void ObjectPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
// This must be called after the constructor has returned, so that the below code // This must be called after the constructor has returned, so that the below code
// can find the ObjectPrototype through normal paths. // can find the ObjectPrototype through normal paths.
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("hasOwnProperty", has_own_property, 1, attr); define_native_function(vm.names.hasOwnProperty, has_own_property, 1, attr);
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
define_native_function("toLocaleString", to_locale_string, 0, attr); define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
define_native_function("valueOf", value_of, 0, attr); define_native_function(vm.names.valueOf, value_of, 0, attr);
} }
ObjectPrototype::~ObjectPrototype() ObjectPrototype::~ObjectPrototype()

View file

@ -33,15 +33,16 @@
namespace JS { namespace JS {
ProxyConstructor::ProxyConstructor(GlobalObject& global_object) ProxyConstructor::ProxyConstructor(GlobalObject& global_object)
: NativeFunction("Proxy", *global_object.function_prototype()) : NativeFunction(vm().names.Proxy, *global_object.function_prototype())
{ {
} }
void ProxyConstructor::initialize(GlobalObject& global_object) void ProxyConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.proxy_prototype(), 0); define_property(vm.names.prototype, global_object.proxy_prototype(), 0);
define_property("length", Value(2), Attribute::Configurable); define_property(vm.names.length, Value(2), Attribute::Configurable);
} }
ProxyConstructor::~ProxyConstructor() ProxyConstructor::~ProxyConstructor()

View file

@ -79,7 +79,7 @@ Object* ProxyObject::prototype()
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(vm().names.getPrototypeOf);
if (vm().exception()) if (vm().exception())
return nullptr; return nullptr;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -128,7 +128,7 @@ bool ProxyObject::set_prototype(Object* object)
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(vm().names.setPrototypeOf);
if (vm().exception()) if (vm().exception())
return false; return false;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -159,7 +159,7 @@ bool ProxyObject::is_extensible() const
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(vm().names.isExtensible);
if (vm().exception()) if (vm().exception())
return false; return false;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -186,7 +186,7 @@ bool ProxyObject::prevent_extensions()
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(vm().names.preventExtensions);
if (vm().exception()) if (vm().exception())
return false; return false;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -213,7 +213,7 @@ Optional<PropertyDescriptor> ProxyObject::get_own_property_descriptor(const Prop
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(vm().names.getOwnPropertyDescriptor);
if (vm().exception()) if (vm().exception())
return {}; return {};
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -268,7 +268,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
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(vm().names.defineProperty);
if (vm().exception()) if (vm().exception())
return false; return false;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -285,7 +285,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
if (vm().exception()) if (vm().exception())
return false; return false;
bool setting_config_false = false; bool setting_config_false = false;
if (descriptor.has_property("configurable") && !descriptor.get("configurable").to_boolean()) if (descriptor.has_property(vm().names.configurable) && !descriptor.get(vm().names.configurable).to_boolean())
setting_config_false = true; setting_config_false = true;
if (vm().exception()) if (vm().exception())
return false; return false;
@ -319,7 +319,7 @@ bool ProxyObject::has_property(const PropertyName& name) const
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(vm().names.has);
if (vm().exception()) if (vm().exception())
return false; return false;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -357,7 +357,7 @@ Value ProxyObject::get(const PropertyName& name, Value) const
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(vm().names.get);
if (vm().exception()) if (vm().exception())
return {}; return {};
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
@ -388,32 +388,33 @@ 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)
{ {
auto& vm = this->vm();
if (m_is_revoked) { if (m_is_revoked) {
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(vm.names.set);
if (vm().exception()) if (vm.exception())
return false; return false;
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
return m_target.put(name, value); return m_target.put(name, value);
if (!trap.is_function()) { if (!trap.is_function()) {
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 = 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(); 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(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)) {
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) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetNonConfigurableAccessor); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxySetNonConfigurableAccessor);
} }
} }
return true; return true;
@ -421,32 +422,33 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value)
Value ProxyObject::delete_property(const PropertyName& name) Value ProxyObject::delete_property(const PropertyName& name)
{ {
auto& vm = this->vm();
if (m_is_revoked) { if (m_is_revoked) {
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(vm.names.deleteProperty);
if (vm().exception()) if (vm.exception())
return {}; return {};
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
return m_target.delete_property(name); return m_target.delete_property(name);
if (!trap.is_function()) { if (!trap.is_function()) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty"); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty");
return {}; return {};
} }
auto trap_result = vm().call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm(), 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)
return Value(false); return Value(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 {}; return {};
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()) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyDeleteNonConfigurable); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyDeleteNonConfigurable);
return {}; return {};
} }
return Value(true); return Value(true);
@ -461,21 +463,22 @@ void ProxyObject::visit_children(Cell::Visitor& visitor)
Value ProxyObject::call() Value ProxyObject::call()
{ {
auto& vm = this->vm();
if (!is_function()) { if (!is_function()) {
vm().throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, Value(this).to_string_without_side_effects()); vm.throw_exception<TypeError>(global_object(), ErrorType::NotAFunction, Value(this).to_string_without_side_effects());
return {}; return {};
} }
if (m_is_revoked) { if (m_is_revoked) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
return {}; return {};
} }
auto trap = m_handler.get("apply"); auto trap = m_handler.get(vm.names.apply);
if (vm().exception()) if (vm.exception())
return {}; return {};
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())
return static_cast<Function&>(m_target).call(); return static_cast<Function&>(m_target).call();
if (!trap.is_function()) { if (!trap.is_function()) {
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "apply"); vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "apply");
return {}; return {};
} }
MarkedValueList arguments(heap()); MarkedValueList arguments(heap());
@ -483,12 +486,12 @@ Value ProxyObject::call()
arguments.append(Value(&m_handler)); arguments.append(Value(&m_handler));
// FIXME: Pass global object // FIXME: Pass global object
auto arguments_array = Array::create(global_object()); auto arguments_array = Array::create(global_object());
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);
return vm().call(trap.as_function(), Value(&m_handler), move(arguments)); return vm.call(trap.as_function(), Value(&m_handler), move(arguments));
} }
Value ProxyObject::construct(Function& new_target) Value ProxyObject::construct(Function& new_target)
@ -502,7 +505,7 @@ Value ProxyObject::construct(Function& new_target)
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(vm.names.construct);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (trap.is_empty() || trap.is_nullish()) if (trap.is_empty() || trap.is_nullish())

View file

@ -63,7 +63,7 @@ static void prepare_arguments_list(GlobalObject& global_object, Value value, Mar
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(vm.names.length);
if (vm.exception()) if (vm.exception())
return; return;
auto length = length_property.to_size_t(global_object); auto length = length_property.to_size_t(global_object);
@ -84,21 +84,22 @@ ReflectObject::ReflectObject(GlobalObject& global_object)
void ReflectObject::initialize(GlobalObject& global_object) void ReflectObject::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("apply", apply, 3, attr); define_native_function(vm.names.apply, apply, 3, attr);
define_native_function("construct", construct, 2, attr); define_native_function(vm.names.construct, construct, 2, attr);
define_native_function("defineProperty", define_property, 3, attr); define_native_function(vm.names.defineProperty, define_property, 3, attr);
define_native_function("deleteProperty", delete_property, 2, attr); define_native_function(vm.names.deleteProperty, delete_property, 2, attr);
define_native_function("get", get, 2, attr); define_native_function(vm.names.get, get, 2, attr);
define_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr); define_native_function(vm.names.getOwnPropertyDescriptor, get_own_property_descriptor, 2, attr);
define_native_function("getPrototypeOf", get_prototype_of, 1, attr); define_native_function(vm.names.getPrototypeOf, get_prototype_of, 1, attr);
define_native_function("has", has, 2, attr); define_native_function(vm.names.has, has, 2, attr);
define_native_function("isExtensible", is_extensible, 1, attr); define_native_function(vm.names.isExtensible, is_extensible, 1, attr);
define_native_function("ownKeys", own_keys, 1, attr); define_native_function(vm.names.ownKeys, own_keys, 1, attr);
define_native_function("preventExtensions", prevent_extensions, 1, attr); define_native_function(vm.names.preventExtensions, prevent_extensions, 1, attr);
define_native_function("set", set, 3, attr); define_native_function(vm.names.set, set, 3, attr);
define_native_function("setPrototypeOf", set_prototype_of, 2, attr); define_native_function(vm.names.setPrototypeOf, set_prototype_of, 2, attr);
} }
ReflectObject::~ReflectObject() ReflectObject::~ReflectObject()

View file

@ -32,15 +32,16 @@
namespace JS { namespace JS {
RegExpConstructor::RegExpConstructor(GlobalObject& global_object) RegExpConstructor::RegExpConstructor(GlobalObject& global_object)
: NativeFunction("RegExp", *global_object.function_prototype()) : NativeFunction(vm().names.RegExp, *global_object.function_prototype())
{ {
} }
void RegExpConstructor::initialize(GlobalObject& global_object) void RegExpConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.regexp_prototype(), 0); define_property(vm.names.prototype, global_object.regexp_prototype(), 0);
define_property("length", Value(2), Attribute::Configurable); define_property(vm.names.length, Value(2), Attribute::Configurable);
} }
RegExpConstructor::~RegExpConstructor() RegExpConstructor::~RegExpConstructor()

View file

@ -66,14 +66,15 @@ ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& nam
void ScriptFunction::initialize(GlobalObject& global_object) void ScriptFunction::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Function::initialize(global_object); Function::initialize(global_object);
if (!m_is_arrow_function) { if (!m_is_arrow_function) {
Object* prototype = Object::create_empty(global_object); Object* prototype = Object::create_empty(global_object);
prototype->define_property_without_transition("constructor", this, Attribute::Writable | Attribute::Configurable); prototype->define_property_without_transition(vm.names.constructor, this, Attribute::Writable | Attribute::Configurable);
define_property("prototype", prototype, 0); define_property(vm.names.prototype, prototype, 0);
} }
define_native_property("length", length_getter, nullptr, Attribute::Configurable); define_native_property(vm.names.length, length_getter, nullptr, Attribute::Configurable);
define_native_property("name", name_getter, nullptr, Attribute::Configurable); define_native_property(vm.names.name, name_getter, nullptr, Attribute::Configurable);
} }
ScriptFunction::~ScriptFunction() ScriptFunction::~ScriptFunction()

View file

@ -35,19 +35,20 @@
namespace JS { namespace JS {
StringConstructor::StringConstructor(GlobalObject& global_object) StringConstructor::StringConstructor(GlobalObject& global_object)
: NativeFunction("String", *global_object.function_prototype()) : NativeFunction(vm().names.String, *global_object.function_prototype())
{ {
} }
void StringConstructor::initialize(GlobalObject& global_object) void StringConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.string_prototype(), 0); define_property(vm.names.prototype, global_object.string_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property(vm.names.length, Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("raw", raw, 1, attr); define_native_function(vm.names.raw, raw, 1, attr);
define_native_function("fromCharCode", from_char_code, 1, attr); define_native_function(vm.names.fromCharCode, from_char_code, 1, attr);
} }
StringConstructor::~StringConstructor() StringConstructor::~StringConstructor()
@ -84,7 +85,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
if (vm.exception()) if (vm.exception())
return {}; return {};
auto raw = template_object->get("raw"); auto raw = template_object->get(vm.names.raw);
if (vm.exception()) if (vm.exception())
return {}; return {};
if (raw.is_empty() || raw.is_nullish()) { if (raw.is_empty() || raw.is_nullish()) {

View file

@ -40,10 +40,10 @@ StringIteratorPrototype::StringIteratorPrototype(GlobalObject& global_object)
void StringIteratorPrototype::initialize(GlobalObject& global_object) void StringIteratorPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
define_native_function(vm.names.next, next, 0, Attribute::Configurable | Attribute::Writable);
define_native_function("next", next, 0, Attribute::Configurable | Attribute::Writable); define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), "String Iterator"), Attribute::Configurable);
define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "String Iterator"), Attribute::Configurable);
} }
StringIteratorPrototype::~StringIteratorPrototype() StringIteratorPrototype::~StringIteratorPrototype()

View file

@ -66,29 +66,30 @@ StringPrototype::StringPrototype(GlobalObject& global_object)
void StringPrototype::initialize(GlobalObject& global_object) void StringPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
StringObject::initialize(global_object); StringObject::initialize(global_object);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_property("length", length_getter, nullptr, 0); define_native_property(vm.names.length, length_getter, nullptr, 0);
define_native_function("charAt", char_at, 1, attr); define_native_function(vm.names.charAt, char_at, 1, attr);
define_native_function("charCodeAt", char_code_at, 1, attr); define_native_function(vm.names.charCodeAt, char_code_at, 1, attr);
define_native_function("repeat", repeat, 1, attr); define_native_function(vm.names.repeat, repeat, 1, attr);
define_native_function("startsWith", starts_with, 1, attr); define_native_function(vm.names.startsWith, starts_with, 1, attr);
define_native_function("indexOf", index_of, 1, attr); define_native_function(vm.names.indexOf, index_of, 1, attr);
define_native_function("toLowerCase", to_lowercase, 0, attr); define_native_function(vm.names.toLowerCase, to_lowercase, 0, attr);
define_native_function("toUpperCase", to_uppercase, 0, attr); define_native_function(vm.names.toUpperCase, to_uppercase, 0, attr);
define_native_function("toString", to_string, 0, attr); define_native_function(vm.names.toString, to_string, 0, attr);
define_native_function("padStart", pad_start, 1, attr); define_native_function(vm.names.padStart, pad_start, 1, attr);
define_native_function("padEnd", pad_end, 1, attr); define_native_function(vm.names.padEnd, pad_end, 1, attr);
define_native_function("trim", trim, 0, attr); define_native_function(vm.names.trim, trim, 0, attr);
define_native_function("trimStart", trim_start, 0, attr); define_native_function(vm.names.trimStart, trim_start, 0, attr);
define_native_function("trimEnd", trim_end, 0, attr); define_native_function(vm.names.trimEnd, trim_end, 0, attr);
define_native_function("concat", concat, 1, attr); define_native_function(vm.names.concat, concat, 1, attr);
define_native_function("substring", substring, 2, attr); define_native_function(vm.names.substring, substring, 2, attr);
define_native_function("includes", includes, 1, attr); define_native_function(vm.names.includes, includes, 1, attr);
define_native_function("slice", slice, 2, attr); define_native_function(vm.names.slice, slice, 2, attr);
define_native_function("lastIndexOf", last_index_of, 1, attr); define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
define_native_function(global_object.vm().well_known_symbol_iterator(), symbol_iterator, 0, attr); define_native_function(vm.well_known_symbol_iterator(), symbol_iterator, 0, attr);
} }
StringPrototype::~StringPrototype() StringPrototype::~StringPrototype()

View file

@ -32,21 +32,22 @@
namespace JS { namespace JS {
SymbolConstructor::SymbolConstructor(GlobalObject& global_object) SymbolConstructor::SymbolConstructor(GlobalObject& global_object)
: NativeFunction("Symbol", *global_object.function_prototype()) : NativeFunction(vm().names.Symbol, *global_object.function_prototype())
{ {
} }
void SymbolConstructor::initialize(GlobalObject& global_object) void SymbolConstructor::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
NativeFunction::initialize(global_object); NativeFunction::initialize(global_object);
define_property("prototype", global_object.symbol_prototype(), 0); define_property(vm.names.prototype, global_object.symbol_prototype(), 0);
define_property("length", Value(0), Attribute::Configurable); define_property(vm.names.length, Value(0), Attribute::Configurable);
define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.for_, for_, 1, Attribute::Writable | Attribute::Configurable);
define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.keyFor, key_for, 1, Attribute::Writable | Attribute::Configurable);
#define __JS_ENUMERATE(SymbolName, snake_name) \ #define __JS_ENUMERATE(SymbolName, snake_name) \
define_property(#SymbolName, global_object.vm().well_known_symbol_##snake_name(), 0); define_property(vm.names.SymbolName, vm.well_known_symbol_##snake_name(), 0);
JS_ENUMERATE_WELL_KNOWN_SYMBOLS JS_ENUMERATE_WELL_KNOWN_SYMBOLS
#undef __JS_ENUMERATE #undef __JS_ENUMERATE
} }

View file

@ -45,10 +45,11 @@ SymbolPrototype::SymbolPrototype(GlobalObject& global_object)
void SymbolPrototype::initialize(GlobalObject& global_object) void SymbolPrototype::initialize(GlobalObject& global_object)
{ {
auto& vm = this->vm();
Object::initialize(global_object); Object::initialize(global_object);
define_native_property("description", description_getter, nullptr, Attribute::Configurable); define_native_property(vm.names.description, description_getter, nullptr, Attribute::Configurable);
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.toString, to_string, 0, Attribute::Writable | Attribute::Configurable);
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable); define_native_function(vm.names.valueOf, value_of, 0, Attribute::Writable | Attribute::Configurable);
define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Symbol"), Attribute::Configurable); define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Symbol"), Attribute::Configurable);
} }

View file

@ -40,7 +40,8 @@ Uint8ClampedArray::Uint8ClampedArray(u32 length, Object& prototype)
: Object(prototype) : Object(prototype)
, m_length(length) , m_length(length)
{ {
define_native_property("length", length_getter, nullptr); auto& vm = this->vm();
define_native_property(vm.names.length, length_getter, nullptr);
m_data = new u8[m_length]; m_data = new u8[m_length];
} }

View file

@ -207,7 +207,7 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
current_environment()->bind_this_value(global_object, new_object); current_environment()->bind_this_value(global_object, new_object);
if (exception()) if (exception())
return {}; return {};
auto prototype = new_target.get("prototype"); auto prototype = new_target.get(names.prototype);
if (exception()) if (exception())
return {}; return {};
if (prototype.is_object()) { if (prototype.is_object()) {
@ -230,7 +230,7 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
// set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses). // set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) { if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
current_environment()->replace_this_binding(result); current_environment()->replace_this_binding(result);
auto prototype = new_target.get("prototype"); auto prototype = new_target.get(names.prototype);
if (exception()) if (exception())
return {}; return {};
if (prototype.is_object()) { if (prototype.is_object()) {

View file

@ -30,6 +30,7 @@
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <LibJS/Heap/Heap.h> #include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/CommonPropertyNames.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/MarkedValueList.h>
@ -223,6 +224,8 @@ public:
return call(function, this_value); return call(function, this_value);
} }
CommonPropertyNames names;
private: private:
VM(); VM();

View file

@ -738,7 +738,7 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
return Value(false); return Value(false);
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(vm.names.prototype);
if (vm.exception()) if (vm.exception())
return {}; return {};
@ -1013,8 +1013,9 @@ TriState abstract_relation(GlobalObject& global_object, bool left_first, Value l
size_t length_of_array_like(GlobalObject& global_object, Value value) size_t length_of_array_like(GlobalObject& global_object, Value value)
{ {
ASSERT(value.is_object()); ASSERT(value.is_object());
auto result = value.as_object().get("length"); auto& vm = global_object.vm();
if (global_object.vm().exception()) auto result = value.as_object().get(vm.names.length);
if (vm.exception())
return 0; return 0;
return result.to_size_t(global_object); return result.to_size_t(global_object);
} }

View file

@ -154,8 +154,10 @@ TestRunnerGlobalObject::~TestRunnerGlobalObject()
void TestRunnerGlobalObject::initialize() void TestRunnerGlobalObject::initialize()
{ {
JS::GlobalObject::initialize(); JS::GlobalObject::initialize();
define_property("global", this, JS::Attribute::Enumerable); static FlyString global_property_name { "global" };
define_native_function("isStrictMode", is_strict_mode); static FlyString is_strict_mode_property_name { "isStrictMode" };
define_property(global_property_name, this, JS::Attribute::Enumerable);
define_native_function(is_strict_mode_property_name, is_strict_mode);
} }
JS_DEFINE_NATIVE_FUNCTION(TestRunnerGlobalObject::is_strict_mode) JS_DEFINE_NATIVE_FUNCTION(TestRunnerGlobalObject::is_strict_mode)