mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +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:
parent
9f6c5f68b6
commit
7b863330dc
Notes:
sideshowbarker
2024-07-19 01:54:41 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/7b863330dc7
45 changed files with 651 additions and 392 deletions
|
@ -698,6 +698,7 @@ Value ClassMethod::execute(Interpreter& interpreter, GlobalObject& global_object
|
|||
|
||||
Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_object) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
Value class_constructor_value = m_constructor->execute(interpreter, global_object);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
|
@ -720,22 +721,22 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
|
|||
|
||||
Object* super_constructor_prototype = nullptr;
|
||||
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())
|
||||
return {};
|
||||
}
|
||||
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())
|
||||
return {};
|
||||
class_constructor->define_property("prototype", prototype, 0);
|
||||
class_constructor->define_property(vm.names.prototype, prototype, 0);
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
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())
|
||||
return {};
|
||||
|
||||
|
@ -1756,21 +1757,22 @@ void TaggedTemplateLiteral::dump(int indent) const
|
|||
|
||||
Value TaggedTemplateLiteral::execute(Interpreter& interpreter, GlobalObject& global_object) const
|
||||
{
|
||||
auto& vm = interpreter.vm();
|
||||
auto tag = m_tag->execute(interpreter, global_object);
|
||||
if (interpreter.exception())
|
||||
if (vm.exception())
|
||||
return {};
|
||||
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 {};
|
||||
}
|
||||
auto& tag_function = tag.as_function();
|
||||
auto& expressions = m_template_literal->expressions();
|
||||
auto* strings = Array::create(global_object);
|
||||
MarkedValueList arguments(interpreter.heap());
|
||||
MarkedValueList arguments(vm.heap());
|
||||
arguments.append(strings);
|
||||
for (size_t i = 0; i < expressions.size(); ++i) {
|
||||
auto value = expressions[i].execute(interpreter, global_object);
|
||||
if (interpreter.exception())
|
||||
if (vm.exception())
|
||||
return {};
|
||||
// tag`${foo}` -> "", foo, "" -> tag(["", ""], foo)
|
||||
// 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);
|
||||
for (auto& raw_string : m_template_literal->raw_strings()) {
|
||||
auto value = raw_string.execute(interpreter, global_object);
|
||||
if (interpreter.exception())
|
||||
if (vm.exception())
|
||||
return {};
|
||||
raw_strings->indexed_properties().append(value);
|
||||
}
|
||||
strings->define_property("raw", raw_strings, 0);
|
||||
return interpreter.vm().call(tag_function, js_undefined(), move(arguments));
|
||||
strings->define_property(vm.names.raw, raw_strings, 0);
|
||||
return vm.call(tag_function, js_undefined(), move(arguments));
|
||||
}
|
||||
|
||||
void TryStatement::dump(int indent) const
|
||||
|
|
|
@ -69,7 +69,8 @@ Value Interpreter::run(GlobalObject& global_object, const Program& program)
|
|||
|
||||
CallFrame global_call_frame;
|
||||
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->bind_this_value(global_object, &global_object);
|
||||
global_call_frame.is_strict_mode = program.is_strict_mode();
|
||||
|
|
|
@ -40,7 +40,8 @@ Array* Array::create(GlobalObject& global_object)
|
|||
Array::Array(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()
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
|
||||
define_property("prototype", global_object.array_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.array_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("from", from, 1, attr);
|
||||
define_native_function("isArray", is_array, 1, attr);
|
||||
define_native_function("of", of, 0, attr);
|
||||
define_native_function(vm.names.from, from, 1, attr);
|
||||
define_native_function(vm.names.isArray, is_array, 1, attr);
|
||||
define_native_function(vm.names.of, of, 0, attr);
|
||||
}
|
||||
|
||||
Value ArrayConstructor::call()
|
||||
|
|
|
@ -40,9 +40,10 @@ ArrayIteratorPrototype::ArrayIteratorPrototype(GlobalObject& global_object)
|
|||
|
||||
void ArrayIteratorPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,40 +46,41 @@ ArrayPrototype::ArrayPrototype(GlobalObject& global_object)
|
|||
|
||||
void ArrayPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
|
||||
define_native_function("filter", filter, 1, attr);
|
||||
define_native_function("forEach", for_each, 1, attr);
|
||||
define_native_function("map", map, 1, attr);
|
||||
define_native_function("pop", pop, 0, attr);
|
||||
define_native_function("push", push, 1, attr);
|
||||
define_native_function("shift", shift, 0, attr);
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_function("toLocaleString", to_locale_string, 0, attr);
|
||||
define_native_function("unshift", unshift, 1, attr);
|
||||
define_native_function("join", join, 1, attr);
|
||||
define_native_function("concat", concat, 1, attr);
|
||||
define_native_function("slice", slice, 2, attr);
|
||||
define_native_function("indexOf", index_of, 1, attr);
|
||||
define_native_function("reduce", reduce, 1, attr);
|
||||
define_native_function("reduceRight", reduce_right, 1, attr);
|
||||
define_native_function("reverse", reverse, 0, attr);
|
||||
define_native_function("lastIndexOf", last_index_of, 1, attr);
|
||||
define_native_function("includes", includes, 1, attr);
|
||||
define_native_function("find", find, 1, attr);
|
||||
define_native_function("findIndex", find_index, 1, attr);
|
||||
define_native_function("some", some, 1, attr);
|
||||
define_native_function("every", every, 1, attr);
|
||||
define_native_function("splice", splice, 2, attr);
|
||||
define_native_function("fill", fill, 1, attr);
|
||||
define_native_function("values", values, 0, attr);
|
||||
define_property("length", Value(0), Attribute::Configurable);
|
||||
define_native_function(vm.names.filter, filter, 1, attr);
|
||||
define_native_function(vm.names.forEach, for_each, 1, attr);
|
||||
define_native_function(vm.names.map, map, 1, attr);
|
||||
define_native_function(vm.names.pop, pop, 0, attr);
|
||||
define_native_function(vm.names.push, push, 1, attr);
|
||||
define_native_function(vm.names.shift, shift, 0, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
|
||||
define_native_function(vm.names.unshift, unshift, 1, attr);
|
||||
define_native_function(vm.names.join, join, 1, attr);
|
||||
define_native_function(vm.names.concat, concat, 1, attr);
|
||||
define_native_function(vm.names.slice, slice, 2, attr);
|
||||
define_native_function(vm.names.indexOf, index_of, 1, attr);
|
||||
define_native_function(vm.names.reduce, reduce, 1, attr);
|
||||
define_native_function(vm.names.reduceRight, reduce_right, 1, attr);
|
||||
define_native_function(vm.names.reverse, reverse, 0, attr);
|
||||
define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
|
||||
define_native_function(vm.names.includes, includes, 1, attr);
|
||||
define_native_function(vm.names.find, find, 1, attr);
|
||||
define_native_function(vm.names.findIndex, find_index, 1, attr);
|
||||
define_native_function(vm.names.some, some, 1, attr);
|
||||
define_native_function(vm.names.every, every, 1, attr);
|
||||
define_native_function(vm.names.splice, splice, 2, attr);
|
||||
define_native_function(vm.names.fill, fill, 1, attr);
|
||||
define_native_function(vm.names.values, values, 0, attr);
|
||||
define_property(vm.names.length, Value(0), Attribute::Configurable);
|
||||
|
||||
// Use define_property here instead of define_native_function so that
|
||||
// Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
|
||||
// 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()
|
||||
|
@ -103,7 +104,7 @@ static Function* callback_from_args(GlobalObject& global_object, const String& n
|
|||
|
||||
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())
|
||||
return 0;
|
||||
return length_property.to_size_t(object.global_object());
|
||||
|
@ -208,7 +209,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::push)
|
|||
return {};
|
||||
}
|
||||
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())
|
||||
return {};
|
||||
return new_length_value;
|
||||
|
@ -237,7 +238,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
|
|||
}
|
||||
auto length = get_length(vm, *this_object);
|
||||
if (length == 0) {
|
||||
this_object->put("length", Value(0));
|
||||
this_object->put(vm.names.length, Value(0));
|
||||
return js_undefined();
|
||||
}
|
||||
auto index = length - 1;
|
||||
|
@ -247,7 +248,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::pop)
|
|||
this_object->delete_property(index);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
this_object->put("length", Value((i32)index));
|
||||
this_object->put(vm.names.length, Value((i32)index));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
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);
|
||||
if (!this_object)
|
||||
return {};
|
||||
auto join_function = this_object->get("join");
|
||||
auto join_function = this_object->get(vm.names.join);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!join_function.is_function())
|
||||
|
@ -789,7 +790,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::splice)
|
|||
return {};
|
||||
}
|
||||
|
||||
this_object->put("length", Value((i32)new_length));
|
||||
this_object->put(vm.names.length, Value((i32)new_length));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
|
|
|
@ -35,19 +35,20 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.bigint_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.bigint_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("asIntN", as_int_n, 2, attr);
|
||||
define_native_function("asUintN", as_uint_n, 2, attr);
|
||||
define_native_function(vm.names.asIntN, as_int_n, 2, attr);
|
||||
define_native_function(vm.names.asUintN, as_uint_n, 2, attr);
|
||||
}
|
||||
|
||||
BigIntConstructor::~BigIntConstructor()
|
||||
|
|
|
@ -39,13 +39,14 @@ BigIntPrototype::BigIntPrototype(GlobalObject& global_object)
|
|||
|
||||
void BigIntPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_function("toLocaleString", to_locale_string, 0, attr);
|
||||
define_native_function("valueOf", value_of, 0, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleString, to_locale_string, 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()
|
||||
|
|
|
@ -33,15 +33,16 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", Value(global_object.boolean_prototype()), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, Value(global_object.boolean_prototype()), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
}
|
||||
|
||||
BooleanConstructor::~BooleanConstructor()
|
||||
|
|
|
@ -38,9 +38,10 @@ BooleanPrototype::BooleanPrototype(GlobalObject& global_object)
|
|||
|
||||
void BooleanPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
BooleanObject::initialize(global_object);
|
||||
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function(vm.names.toString, to_string, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function(vm.names.valueOf, value_of, 0, Attribute::Writable | Attribute::Configurable);
|
||||
}
|
||||
|
||||
BooleanPrototype::~BooleanPrototype()
|
||||
|
|
|
@ -40,8 +40,9 @@ BoundFunction::BoundFunction(GlobalObject& global_object, Function& target_funct
|
|||
|
||||
void BoundFunction::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Function::initialize(global_object);
|
||||
define_property("length", Value(m_length), Attribute::Configurable);
|
||||
define_property(vm.names.length, Value(m_length), Attribute::Configurable);
|
||||
}
|
||||
|
||||
BoundFunction::~BoundFunction()
|
||||
|
|
209
Libraries/LibJS/Runtime/CommonPropertyNames.h
Normal file
209
Libraries/LibJS/Runtime/CommonPropertyNames.h
Normal 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
|
||||
};
|
||||
|
||||
}
|
|
@ -138,19 +138,20 @@ static Value parse_simplified_iso8601(const String& iso_8601)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.date_prototype(), 0);
|
||||
define_property("length", Value(7), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.date_prototype(), 0);
|
||||
define_property(vm.names.length, Value(7), Attribute::Configurable);
|
||||
|
||||
define_native_function("now", now, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function("parse", parse, 1, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function("UTC", utc, 1, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function(vm.names.now, now, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function(vm.names.parse, parse, 1, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function(vm.names.UTC, utc, 1, Attribute::Writable | Attribute::Configurable);
|
||||
}
|
||||
|
||||
DateConstructor::~DateConstructor()
|
||||
|
|
|
@ -54,35 +54,36 @@ DatePrototype::DatePrototype(GlobalObject& global_object)
|
|||
|
||||
void DatePrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("getDate", get_date, 0, attr);
|
||||
define_native_function("getDay", get_day, 0, attr);
|
||||
define_native_function("getFullYear", get_full_year, 0, attr);
|
||||
define_native_function("getHours", get_hours, 0, attr);
|
||||
define_native_function("getMilliseconds", get_milliseconds, 0, attr);
|
||||
define_native_function("getMinutes", get_minutes, 0, attr);
|
||||
define_native_function("getMonth", get_month, 0, attr);
|
||||
define_native_function("getSeconds", get_seconds, 0, attr);
|
||||
define_native_function("getTime", get_time, 0, attr);
|
||||
define_native_function("getUTCDate", get_utc_date, 0, attr);
|
||||
define_native_function("getUTCDay", get_utc_day, 0, attr);
|
||||
define_native_function("getUTCFullYear", get_utc_full_year, 0, attr);
|
||||
define_native_function("getUTCHours", get_utc_hours, 0, attr);
|
||||
define_native_function("getUTCMilliseconds", get_utc_milliseconds, 0, attr);
|
||||
define_native_function("getUTCMinutes", get_utc_minutes, 0, attr);
|
||||
define_native_function("getUTCMonth", get_utc_month, 0, attr);
|
||||
define_native_function("getUTCSeconds", get_utc_seconds, 0, attr);
|
||||
define_native_function("toDateString", to_date_string, 0, attr);
|
||||
define_native_function("toISOString", to_iso_string, 0, attr);
|
||||
define_native_function("toLocaleDateString", to_locale_date_string, 0, attr);
|
||||
define_native_function("toLocaleString", to_locale_string, 0, attr);
|
||||
define_native_function("toLocaleTimeString", to_locale_time_string, 0, attr);
|
||||
define_native_function("toTimeString", to_time_string, 0, attr);
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_function(vm.names.getDate, get_date, 0, attr);
|
||||
define_native_function(vm.names.getDay, get_day, 0, attr);
|
||||
define_native_function(vm.names.getFullYear, get_full_year, 0, attr);
|
||||
define_native_function(vm.names.getHours, get_hours, 0, attr);
|
||||
define_native_function(vm.names.getMilliseconds, get_milliseconds, 0, attr);
|
||||
define_native_function(vm.names.getMinutes, get_minutes, 0, attr);
|
||||
define_native_function(vm.names.getMonth, get_month, 0, attr);
|
||||
define_native_function(vm.names.getSeconds, get_seconds, 0, attr);
|
||||
define_native_function(vm.names.getTime, get_time, 0, attr);
|
||||
define_native_function(vm.names.getUTCDate, get_utc_date, 0, attr);
|
||||
define_native_function(vm.names.getUTCDay, get_utc_day, 0, attr);
|
||||
define_native_function(vm.names.getUTCFullYear, get_utc_full_year, 0, attr);
|
||||
define_native_function(vm.names.getUTCHours, get_utc_hours, 0, attr);
|
||||
define_native_function(vm.names.getUTCMilliseconds, get_utc_milliseconds, 0, attr);
|
||||
define_native_function(vm.names.getUTCMinutes, get_utc_minutes, 0, attr);
|
||||
define_native_function(vm.names.getUTCMonth, get_utc_month, 0, attr);
|
||||
define_native_function(vm.names.getUTCSeconds, get_utc_seconds, 0, attr);
|
||||
define_native_function(vm.names.toDateString, to_date_string, 0, attr);
|
||||
define_native_function(vm.names.toISOString, to_iso_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleDateString, to_locale_date_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleTimeString, to_locale_time_string, 0, attr);
|
||||
define_native_function(vm.names.toTimeString, to_time_string, 0, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
|
||||
// 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():
|
||||
// - it returns null instead of throwing RangeError
|
||||
// - its .length is 1, not 0
|
||||
|
|
|
@ -51,7 +51,7 @@ Error::~Error()
|
|||
return global_object.heap().allocate<ClassName>(global_object, message, *global_object.snake_name##_prototype()); \
|
||||
} \
|
||||
ClassName::ClassName(const String& message, Object& prototype) \
|
||||
: Error(#ClassName, message, prototype) \
|
||||
: Error(vm().names.ClassName, message, prototype) \
|
||||
{ \
|
||||
} \
|
||||
ClassName::~ClassName() { }
|
||||
|
|
|
@ -31,15 +31,16 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.error_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.error_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
}
|
||||
|
||||
ErrorConstructor::~ErrorConstructor()
|
||||
|
@ -60,7 +61,7 @@ Value ErrorConstructor::construct(Function&)
|
|||
if (vm.exception())
|
||||
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) \
|
||||
|
@ -70,9 +71,10 @@ Value ErrorConstructor::construct(Function&)
|
|||
} \
|
||||
void ConstructorName::initialize(GlobalObject& global_object) \
|
||||
{ \
|
||||
auto& vm = this->vm(); \
|
||||
NativeFunction::initialize(global_object); \
|
||||
define_property("prototype", global_object.snake_name##_prototype(), 0); \
|
||||
define_property("length", Value(1), Attribute::Configurable); \
|
||||
define_property(vm.names.prototype, global_object.snake_name##_prototype(), 0); \
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable); \
|
||||
} \
|
||||
ConstructorName::~ConstructorName() { } \
|
||||
Value ConstructorName::call() \
|
||||
|
|
|
@ -41,11 +41,12 @@ ErrorPrototype::ErrorPrototype(GlobalObject& global_object)
|
|||
|
||||
void ErrorPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_property("name", name_getter, name_setter, attr);
|
||||
define_native_property("message", message_getter, nullptr, attr);
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_property(vm.names.name, name_getter, name_setter, attr);
|
||||
define_native_property(vm.names.message, message_getter, nullptr, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
}
|
||||
|
||||
ErrorPrototype::~ErrorPrototype()
|
||||
|
@ -100,7 +101,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
|
|||
auto& this_object = vm.this_value(global_object).as_object();
|
||||
|
||||
String name = "Error";
|
||||
auto name_property = this_object.get("name");
|
||||
auto name_property = this_object.get(vm.names.name);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!name_property.is_empty() && !name_property.is_undefined()) {
|
||||
|
@ -110,7 +111,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
|
|||
}
|
||||
|
||||
String message = "";
|
||||
auto message_property = this_object.get("message");
|
||||
auto message_property = this_object.get(vm.names.message);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!message_property.is_empty() && !message_property.is_undefined()) {
|
||||
|
|
|
@ -35,7 +35,7 @@ Exception::Exception(Value value)
|
|||
{
|
||||
auto& call_stack = vm().call_stack();
|
||||
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())
|
||||
function_name = "<anonymous>";
|
||||
m_trace.append(function_name);
|
||||
|
|
|
@ -49,15 +49,16 @@ Function::~Function()
|
|||
|
||||
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;
|
||||
|
||||
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())
|
||||
return m_bound_this;
|
||||
switch (bound_this_value.type()) {
|
||||
case Value::Type::Undefined:
|
||||
case Value::Type::Null:
|
||||
if (vm().in_strict_mode())
|
||||
if (vm.in_strict_mode())
|
||||
return bound_this_value;
|
||||
return &global_object();
|
||||
default:
|
||||
|
@ -66,15 +67,15 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
|
|||
}();
|
||||
|
||||
i32 computed_length = 0;
|
||||
auto length_property = get("length");
|
||||
if (vm().exception())
|
||||
auto length_property = get(vm.names.length);
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
if (length_property.is_number())
|
||||
computed_length = max(0, length_property.as_i32() - static_cast<i32>(arguments.size()));
|
||||
|
||||
Object* constructor_prototype = nullptr;
|
||||
auto prototype_property = target_function.get("prototype");
|
||||
if (vm().exception())
|
||||
auto prototype_property = target_function.get(vm.names.prototype);
|
||||
if (vm.exception())
|
||||
return nullptr;
|
||||
if (prototype_property.is_object())
|
||||
constructor_prototype = &prototype_property.as_object();
|
||||
|
|
|
@ -36,15 +36,16 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.function_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.function_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
}
|
||||
|
||||
FunctionConstructor::~FunctionConstructor()
|
||||
|
|
|
@ -45,15 +45,16 @@ FunctionPrototype::FunctionPrototype(GlobalObject& global_object)
|
|||
|
||||
void FunctionPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("apply", apply, 2, attr);
|
||||
define_native_function("bind", bind, 1, attr);
|
||||
define_native_function("call", call, 1, attr);
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_function(global_object.vm().well_known_symbol_has_instance(), symbol_has_instance, 1, 0);
|
||||
define_property("length", Value(0), Attribute::Configurable);
|
||||
define_property("name", js_string(heap(), ""), Attribute::Configurable);
|
||||
define_native_function(vm.names.apply, apply, 2, attr);
|
||||
define_native_function(vm.names.bind, bind, 1, attr);
|
||||
define_native_function(vm.names.call, call, 1, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(vm.well_known_symbol_has_instance(), symbol_has_instance, 1, 0);
|
||||
define_property(vm.names.length, Value(0), Attribute::Configurable);
|
||||
define_property(vm.names.name, js_string(heap(), ""), Attribute::Configurable);
|
||||
}
|
||||
|
||||
FunctionPrototype::~FunctionPrototype()
|
||||
|
@ -78,7 +79,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
|
|||
vm.throw_exception<TypeError>(global_object, ErrorType::FunctionArgsNotObject);
|
||||
return {};
|
||||
}
|
||||
auto length_property = arg_array.as_object().get("length");
|
||||
auto length_property = arg_array.as_object().get(vm.names.length);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto length = length_property.to_size_t(global_object);
|
||||
|
|
|
@ -75,6 +75,8 @@ GlobalObject::GlobalObject()
|
|||
|
||||
void GlobalObject::initialize()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
ensure_shape_is_unique();
|
||||
|
||||
// These are done first since other prototypes depend on their presence.
|
||||
|
@ -98,36 +100,36 @@ void GlobalObject::initialize()
|
|||
#undef __JS_ENUMERATE
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("gc", gc, 0, attr);
|
||||
define_native_function("isNaN", is_nan, 1, attr);
|
||||
define_native_function("isFinite", is_finite, 1, attr);
|
||||
define_native_function("parseFloat", parse_float, 1, attr);
|
||||
define_native_function(vm.names.gc, gc, 0, attr);
|
||||
define_native_function(vm.names.isNaN, is_nan, 1, attr);
|
||||
define_native_function(vm.names.isFinite, is_finite, 1, attr);
|
||||
define_native_function(vm.names.parseFloat, parse_float, 1, attr);
|
||||
|
||||
define_property("NaN", js_nan(), 0);
|
||||
define_property("Infinity", js_infinity(), 0);
|
||||
define_property("undefined", js_undefined(), 0);
|
||||
define_property(vm.names.NaN, js_nan(), 0);
|
||||
define_property(vm.names.Infinity, js_infinity(), 0);
|
||||
define_property(vm.names.undefined, js_undefined(), 0);
|
||||
|
||||
define_property("globalThis", this, attr);
|
||||
define_property("console", heap().allocate<ConsoleObject>(*this, *this), attr);
|
||||
define_property("Math", heap().allocate<MathObject>(*this, *this), attr);
|
||||
define_property("JSON", heap().allocate<JSONObject>(*this, *this), attr);
|
||||
define_property("Reflect", heap().allocate<ReflectObject>(*this, *this), attr);
|
||||
define_property(vm.names.globalThis, this, attr);
|
||||
define_property(vm.names.console, heap().allocate<ConsoleObject>(*this, *this), attr);
|
||||
define_property(vm.names.Math, heap().allocate<MathObject>(*this, *this), attr);
|
||||
define_property(vm.names.JSON, heap().allocate<JSONObject>(*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("BigInt", m_bigint_constructor, *m_bigint_prototype);
|
||||
add_constructor("Boolean", m_boolean_constructor, *m_boolean_prototype);
|
||||
add_constructor("Date", m_date_constructor, *m_date_prototype);
|
||||
add_constructor("Error", m_error_constructor, *m_error_prototype);
|
||||
add_constructor("Function", m_function_constructor, *m_function_prototype);
|
||||
add_constructor("Number", m_number_constructor, *m_number_prototype);
|
||||
add_constructor("Object", m_object_constructor, *m_object_prototype);
|
||||
add_constructor("Proxy", m_proxy_constructor, *m_proxy_prototype);
|
||||
add_constructor("RegExp", m_regexp_constructor, *m_regexp_prototype);
|
||||
add_constructor("String", m_string_constructor, *m_string_prototype);
|
||||
add_constructor("Symbol", m_symbol_constructor, *m_symbol_prototype);
|
||||
add_constructor(vm.names.Array, m_array_constructor, *m_array_prototype);
|
||||
add_constructor(vm.names.BigInt, m_bigint_constructor, *m_bigint_prototype);
|
||||
add_constructor(vm.names.Boolean, m_boolean_constructor, *m_boolean_prototype);
|
||||
add_constructor(vm.names.Date, m_date_constructor, *m_date_prototype);
|
||||
add_constructor(vm.names.Error, m_error_constructor, *m_error_prototype);
|
||||
add_constructor(vm.names.Function, m_function_constructor, *m_function_prototype);
|
||||
add_constructor(vm.names.Number, m_number_constructor, *m_number_prototype);
|
||||
add_constructor(vm.names.Object, m_object_constructor, *m_object_prototype);
|
||||
add_constructor(vm.names.Proxy, m_proxy_constructor, *m_proxy_prototype);
|
||||
add_constructor(vm.names.RegExp, m_regexp_constructor, *m_regexp_prototype);
|
||||
add_constructor(vm.names.String, m_string_constructor, *m_string_prototype);
|
||||
add_constructor(vm.names.Symbol, m_symbol_constructor, *m_symbol_prototype);
|
||||
|
||||
#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
|
||||
#undef __JS_ENUMERATE
|
||||
}
|
||||
|
|
|
@ -87,12 +87,13 @@ private:
|
|||
template<typename ConstructorType>
|
||||
inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
constructor = heap().allocate<ConstructorType>(*this, *this);
|
||||
constructor->define_property("name", js_string(heap(), property_name), Attribute::Configurable);
|
||||
if (vm().exception())
|
||||
constructor->define_property(vm.names.name, js_string(heap(), property_name), Attribute::Configurable);
|
||||
if (vm.exception())
|
||||
return;
|
||||
prototype.define_property("constructor", constructor, Attribute::Writable | Attribute::Configurable);
|
||||
if (vm().exception())
|
||||
prototype.define_property(vm.names.constructor, constructor, Attribute::Writable | Attribute::Configurable);
|
||||
if (vm.exception())
|
||||
return;
|
||||
define_property(property_name, constructor, Attribute::Writable | Attribute::Configurable);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ Object* iterator_next(Object& iterator, Value value)
|
|||
{
|
||||
auto& vm = iterator.vm();
|
||||
auto& global_object = iterator.global_object();
|
||||
auto next_method = iterator.get("next");
|
||||
auto next_method = iterator.get(vm.names.next);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
|
@ -95,9 +95,10 @@ void iterator_close(Object& iterator)
|
|||
|
||||
Value create_iterator_result_object(GlobalObject& global_object, Value value, bool done)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto* object = Object::create_empty(global_object);
|
||||
object->define_property("value", value);
|
||||
object->define_property("done", Value(done));
|
||||
object->define_property(vm.names.value, value);
|
||||
object->define_property(vm.names.done, Value(done));
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -114,14 +115,14 @@ void get_iterator_values(GlobalObject& global_object, Value value, AK::Function<
|
|||
if (!next_object)
|
||||
return;
|
||||
|
||||
auto done_property = next_object->get("done");
|
||||
auto done_property = next_object->get(vm.names.done);
|
||||
if (vm.exception())
|
||||
return;
|
||||
|
||||
if (!done_property.is_empty() && done_property.to_boolean())
|
||||
return;
|
||||
|
||||
auto next_value = next_object->get("value");
|
||||
auto next_value = next_object->get(vm.names.value);
|
||||
if (vm.exception())
|
||||
return;
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ String JSONObject::serialize_json_property(GlobalObject& global_object, Stringif
|
|||
if (vm.exception())
|
||||
return {};
|
||||
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())
|
||||
return {};
|
||||
if (to_json.is_function()) {
|
||||
|
|
|
@ -40,41 +40,42 @@ MathObject::MathObject(GlobalObject& global_object)
|
|||
|
||||
void MathObject::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("abs", abs, 1, attr);
|
||||
define_native_function("random", random, 0, attr);
|
||||
define_native_function("sqrt", sqrt, 1, attr);
|
||||
define_native_function("floor", floor, 1, attr);
|
||||
define_native_function("ceil", ceil, 1, attr);
|
||||
define_native_function("round", round, 1, attr);
|
||||
define_native_function("max", max, 2, attr);
|
||||
define_native_function("min", min, 2, attr);
|
||||
define_native_function("trunc", trunc, 1, attr);
|
||||
define_native_function("sin", sin, 1, attr);
|
||||
define_native_function("cos", cos, 1, attr);
|
||||
define_native_function("tan", tan, 1, attr);
|
||||
define_native_function("pow", pow, 2, attr);
|
||||
define_native_function("exp", exp, 1, attr);
|
||||
define_native_function("expm1", expm1, 1, attr);
|
||||
define_native_function("sign", sign, 1, attr);
|
||||
define_native_function("clz32", clz32, 1, attr);
|
||||
define_native_function("acosh", acosh, 1, attr);
|
||||
define_native_function("asinh", asinh, 1, attr);
|
||||
define_native_function("atanh", atanh, 1, attr);
|
||||
define_native_function("log1p", log1p, 1, attr);
|
||||
define_native_function("cbrt", cbrt, 1, attr);
|
||||
define_native_function(vm.names.abs, abs, 1, attr);
|
||||
define_native_function(vm.names.random, random, 0, attr);
|
||||
define_native_function(vm.names.sqrt, sqrt, 1, attr);
|
||||
define_native_function(vm.names.floor, floor, 1, attr);
|
||||
define_native_function(vm.names.ceil, ceil, 1, attr);
|
||||
define_native_function(vm.names.round, round, 1, attr);
|
||||
define_native_function(vm.names.max, max, 2, attr);
|
||||
define_native_function(vm.names.min, min, 2, attr);
|
||||
define_native_function(vm.names.trunc, trunc, 1, attr);
|
||||
define_native_function(vm.names.sin, sin, 1, attr);
|
||||
define_native_function(vm.names.cos, cos, 1, attr);
|
||||
define_native_function(vm.names.tan, tan, 1, attr);
|
||||
define_native_function(vm.names.pow, pow, 2, attr);
|
||||
define_native_function(vm.names.exp, exp, 1, attr);
|
||||
define_native_function(vm.names.expm1, expm1, 1, attr);
|
||||
define_native_function(vm.names.sign, sign, 1, attr);
|
||||
define_native_function(vm.names.clz32, clz32, 1, attr);
|
||||
define_native_function(vm.names.acosh, acosh, 1, attr);
|
||||
define_native_function(vm.names.asinh, asinh, 1, attr);
|
||||
define_native_function(vm.names.atanh, atanh, 1, attr);
|
||||
define_native_function(vm.names.log1p, log1p, 1, attr);
|
||||
define_native_function(vm.names.cbrt, cbrt, 1, attr);
|
||||
|
||||
define_property("E", Value(M_E), 0);
|
||||
define_property("LN2", Value(M_LN2), 0);
|
||||
define_property("LN10", Value(M_LN10), 0);
|
||||
define_property("LOG2E", Value(log2(M_E)), 0);
|
||||
define_property("LOG10E", Value(log10(M_E)), 0);
|
||||
define_property("PI", Value(M_PI), 0);
|
||||
define_property("SQRT1_2", Value(M_SQRT1_2), 0);
|
||||
define_property("SQRT2", Value(M_SQRT2), 0);
|
||||
define_property(vm.names.E, Value(M_E), 0);
|
||||
define_property(vm.names.LN2, Value(M_LN2), 0);
|
||||
define_property(vm.names.LN10, Value(M_LN10), 0);
|
||||
define_property(vm.names.LOG2E, Value(log2(M_E)), 0);
|
||||
define_property(vm.names.LOG10E, Value(log10(M_E)), 0);
|
||||
define_property(vm.names.PI, Value(M_PI), 0);
|
||||
define_property(vm.names.SQRT1_2, Value(M_SQRT1_2), 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()
|
||||
|
|
|
@ -30,34 +30,36 @@
|
|||
#include <LibJS/Runtime/NumberObject.h>
|
||||
#include <math.h>
|
||||
|
||||
#define EPSILON pow(2, -52)
|
||||
#define MAX_SAFE_INTEGER pow(2, 53) - 1
|
||||
#define MIN_SAFE_INTEGER -(pow(2, 53) - 1)
|
||||
// FIXME: constexpr these?
|
||||
#define EPSILON_VALUE pow(2, -52)
|
||||
#define MAX_SAFE_INTEGER_VALUE pow(2, 53) - 1
|
||||
#define MIN_SAFE_INTEGER_VALUE -(pow(2, 53) - 1)
|
||||
|
||||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("isFinite", is_finite, 1, attr);
|
||||
define_native_function("isInteger", is_integer, 1, attr);
|
||||
define_native_function("isNaN", is_nan, 1, attr);
|
||||
define_native_function("isSafeInteger", is_safe_integer, 1, attr);
|
||||
define_property("parseFloat", global_object.get("parseFloat"));
|
||||
define_property("prototype", global_object.number_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property("EPSILON", Value(EPSILON), 0);
|
||||
define_property("MAX_SAFE_INTEGER", Value(MAX_SAFE_INTEGER), 0);
|
||||
define_property("MIN_SAFE_INTEGER", Value(MIN_SAFE_INTEGER), 0);
|
||||
define_property("NEGATIVE_INFINITY", js_negative_infinity(), 0);
|
||||
define_property("POSITIVE_INFINITY", js_infinity(), 0);
|
||||
define_property("NaN", js_nan(), 0);
|
||||
define_native_function(vm.names.isFinite, is_finite, 1, attr);
|
||||
define_native_function(vm.names.isInteger, is_integer, 1, attr);
|
||||
define_native_function(vm.names.isNaN, is_nan, 1, attr);
|
||||
define_native_function(vm.names.isSafeInteger, is_safe_integer, 1, attr);
|
||||
define_property(vm.names.parseFloat, global_object.get(vm.names.parseFloat));
|
||||
define_property(vm.names.prototype, global_object.number_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.EPSILON, Value(EPSILON_VALUE), 0);
|
||||
define_property(vm.names.MAX_SAFE_INTEGER, Value(MAX_SAFE_INTEGER_VALUE), 0);
|
||||
define_property(vm.names.MIN_SAFE_INTEGER, Value(MIN_SAFE_INTEGER_VALUE), 0);
|
||||
define_property(vm.names.NEGATIVE_INFINITY, js_negative_infinity(), 0);
|
||||
define_property(vm.names.POSITIVE_INFINITY, js_infinity(), 0);
|
||||
define_property(vm.names.NaN, js_nan(), 0);
|
||||
}
|
||||
|
||||
NumberConstructor::~NumberConstructor()
|
||||
|
@ -102,7 +104,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberConstructor::is_safe_integer)
|
|||
if (!vm.argument(0).is_number())
|
||||
return Value(false);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -44,36 +44,36 @@ namespace JS {
|
|||
PropertyDescriptor PropertyDescriptor::from_dictionary(VM& vm, const Object& object)
|
||||
{
|
||||
PropertyAttributes attributes;
|
||||
if (object.has_property("configurable")) {
|
||||
if (object.has_property(vm.names.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();
|
||||
if (vm.exception())
|
||||
return {};
|
||||
}
|
||||
if (object.has_property("enumerable")) {
|
||||
if (object.has_property(vm.names.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();
|
||||
if (vm.exception())
|
||||
return {};
|
||||
}
|
||||
if (object.has_property("writable")) {
|
||||
if (object.has_property(vm.names.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();
|
||||
if (vm.exception())
|
||||
return {};
|
||||
}
|
||||
PropertyDescriptor descriptor { attributes, object.get("value"), nullptr, nullptr };
|
||||
PropertyDescriptor descriptor { attributes, object.get(vm.names.value), nullptr, nullptr };
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto getter = object.get("get");
|
||||
auto getter = object.get(vm.names.get);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (getter.is_function())
|
||||
descriptor.getter = &getter.as_function();
|
||||
auto setter = object.get("set");
|
||||
auto setter = object.get(vm.names.set);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
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
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto descriptor_opt = get_own_property_descriptor(property_name);
|
||||
if (!descriptor_opt.has_value())
|
||||
return js_undefined();
|
||||
auto descriptor = descriptor_opt.value();
|
||||
|
||||
auto* descriptor_object = Object::create_empty(global_object());
|
||||
descriptor_object->define_property("enumerable", Value(descriptor.attributes.is_enumerable()));
|
||||
if (vm().exception())
|
||||
descriptor_object->define_property(vm.names.enumerable, Value(descriptor.attributes.is_enumerable()));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
descriptor_object->define_property("configurable", Value(descriptor.attributes.is_configurable()));
|
||||
if (vm().exception())
|
||||
descriptor_object->define_property(vm.names.configurable, Value(descriptor.attributes.is_configurable()));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (descriptor.is_data_descriptor()) {
|
||||
descriptor_object->define_property("value", descriptor.value.value_or(js_undefined()));
|
||||
if (vm().exception())
|
||||
descriptor_object->define_property(vm.names.value, descriptor.value.value_or(js_undefined()));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
descriptor_object->define_property("writable", Value(descriptor.attributes.is_writable()));
|
||||
if (vm().exception())
|
||||
descriptor_object->define_property(vm.names.writable, Value(descriptor.attributes.is_writable()));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
} else if (descriptor.is_accessor_descriptor()) {
|
||||
if (descriptor.getter) {
|
||||
descriptor_object->define_property("get", Value(descriptor.getter));
|
||||
if (vm().exception())
|
||||
descriptor_object->define_property(vm.names.get, Value(descriptor.getter));
|
||||
if (vm.exception())
|
||||
return {};
|
||||
}
|
||||
if (descriptor.setter) {
|
||||
descriptor_object->define_property("set", Value(descriptor.setter));
|
||||
if (vm().exception())
|
||||
descriptor_object->define_property(vm.names.set, Value(descriptor.setter));
|
||||
if (vm.exception())
|
||||
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 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;
|
||||
if (descriptor.has_property("configurable")) {
|
||||
if (descriptor.has_property(vm.names.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();
|
||||
if (vm().exception())
|
||||
if (vm.exception())
|
||||
return false;
|
||||
}
|
||||
if (descriptor.has_property("enumerable")) {
|
||||
if (descriptor.has_property(vm.names.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();
|
||||
if (vm().exception())
|
||||
if (vm.exception())
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::AccessorValueOrWritable);
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::AccessorValueOrWritable);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto getter = descriptor.get("get").value_or(js_undefined());
|
||||
if (vm().exception())
|
||||
auto getter = descriptor.get(vm.names.get).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto setter = descriptor.get("set").value_or(js_undefined());
|
||||
if (vm().exception())
|
||||
auto setter = descriptor.get(vm.names.set).value_or(js_undefined());
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
Function* getter_function { nullptr };
|
||||
|
@ -374,14 +376,14 @@ bool Object::define_property(const StringOrSymbol& property_name, const Object&
|
|||
if (getter.is_function()) {
|
||||
getter_function = &getter.as_function();
|
||||
} 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;
|
||||
}
|
||||
|
||||
if (setter.is_function()) {
|
||||
setter_function = &setter.as_function();
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
@ -391,20 +393,20 @@ bool Object::define_property(const StringOrSymbol& property_name, const Object&
|
|||
<< "setter=" << setter.to_string_without_side_effects() << "}";
|
||||
#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");
|
||||
if (vm().exception())
|
||||
auto value = descriptor.get(vm.names.value);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (descriptor.has_property("writable")) {
|
||||
if (descriptor.has_property(vm.names.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();
|
||||
if (vm().exception())
|
||||
if (vm.exception())
|
||||
return false;
|
||||
}
|
||||
if (vm().exception())
|
||||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
#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()));
|
||||
|
||||
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);
|
||||
bool new_property = !metadata.has_value();
|
||||
|
||||
|
@ -474,14 +484,6 @@ bool Object::put_own_property(Object& this_object, const StringOrSymbol& propert
|
|||
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 (!m_shape->is_unique() && shape().property_count() > 100) {
|
||||
// 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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
String function_name;
|
||||
if (property_name.is_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());
|
||||
}
|
||||
auto* function = NativeFunction::create(global_object(), function_name, move(native_function));
|
||||
function->define_property_without_transition("length", Value(length), Attribute::Configurable);
|
||||
if (vm().exception())
|
||||
function->define_property_without_transition(vm.names.length, Value(length), Attribute::Configurable);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
function->define_property_without_transition("name", js_string(heap(), function_name), Attribute::Configurable);
|
||||
if (vm().exception())
|
||||
function->define_property_without_transition(vm.names.name, js_string(vm.heap(), function_name), Attribute::Configurable);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
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
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto to_string_property = get("toString");
|
||||
auto to_string_property = get(vm.names.toString);
|
||||
if (to_string_property.is_function()) {
|
||||
auto& to_string_function = to_string_property.as_function();
|
||||
auto to_string_result = vm.call(to_string_function, const_cast<Object*>(this));
|
||||
|
@ -859,7 +862,7 @@ Value Object::to_string() const
|
|||
return {};
|
||||
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)
|
||||
|
|
|
@ -35,28 +35,29 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.object_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.object_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("defineProperty", define_property_, 3, attr);
|
||||
define_native_function("is", is, 2, attr);
|
||||
define_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr);
|
||||
define_native_function("getOwnPropertyNames", get_own_property_names, 1, attr);
|
||||
define_native_function("getPrototypeOf", get_prototype_of, 1, attr);
|
||||
define_native_function("setPrototypeOf", set_prototype_of, 2, attr);
|
||||
define_native_function("isExtensible", is_extensible, 1, attr);
|
||||
define_native_function("preventExtensions", prevent_extensions, 1, attr);
|
||||
define_native_function("keys", keys, 1, attr);
|
||||
define_native_function("values", values, 1, attr);
|
||||
define_native_function("entries", entries, 1, attr);
|
||||
define_native_function(vm.names.defineProperty, define_property_, 3, attr);
|
||||
define_native_function(vm.names.is, is, 2, attr);
|
||||
define_native_function(vm.names.getOwnPropertyDescriptor, get_own_property_descriptor, 2, attr);
|
||||
define_native_function(vm.names.getOwnPropertyNames, get_own_property_names, 1, attr);
|
||||
define_native_function(vm.names.getPrototypeOf, get_prototype_of, 1, attr);
|
||||
define_native_function(vm.names.setPrototypeOf, set_prototype_of, 2, attr);
|
||||
define_native_function(vm.names.isExtensible, is_extensible, 1, attr);
|
||||
define_native_function(vm.names.preventExtensions, prevent_extensions, 1, attr);
|
||||
define_native_function(vm.names.keys, keys, 1, attr);
|
||||
define_native_function(vm.names.values, values, 1, attr);
|
||||
define_native_function(vm.names.entries, entries, 1, attr);
|
||||
}
|
||||
|
||||
ObjectConstructor::~ObjectConstructor()
|
||||
|
|
|
@ -40,14 +40,15 @@ ObjectPrototype::ObjectPrototype(GlobalObject& global_object)
|
|||
|
||||
void ObjectPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
// This must be called after the constructor has returned, so that the below code
|
||||
// can find the ObjectPrototype through normal paths.
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("hasOwnProperty", has_own_property, 1, attr);
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_function("toLocaleString", to_locale_string, 0, attr);
|
||||
define_native_function("valueOf", value_of, 0, attr);
|
||||
define_native_function(vm.names.hasOwnProperty, has_own_property, 1, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
|
||||
define_native_function(vm.names.valueOf, value_of, 0, attr);
|
||||
}
|
||||
|
||||
ObjectPrototype::~ObjectPrototype()
|
||||
|
|
|
@ -33,15 +33,16 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.proxy_prototype(), 0);
|
||||
define_property("length", Value(2), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.proxy_prototype(), 0);
|
||||
define_property(vm.names.length, Value(2), Attribute::Configurable);
|
||||
}
|
||||
|
||||
ProxyConstructor::~ProxyConstructor()
|
||||
|
|
|
@ -79,7 +79,7 @@ Object* ProxyObject::prototype()
|
|||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return nullptr;
|
||||
}
|
||||
auto trap = m_handler.get("getPrototypeOf");
|
||||
auto trap = m_handler.get(vm().names.getPrototypeOf);
|
||||
if (vm().exception())
|
||||
return nullptr;
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
auto trap = m_handler.get("setPrototypeOf");
|
||||
auto trap = m_handler.get(vm().names.setPrototypeOf);
|
||||
if (vm().exception())
|
||||
return false;
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
|
@ -159,7 +159,7 @@ bool ProxyObject::is_extensible() const
|
|||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return false;
|
||||
}
|
||||
auto trap = m_handler.get("isExtensible");
|
||||
auto trap = m_handler.get(vm().names.isExtensible);
|
||||
if (vm().exception())
|
||||
return false;
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
|
@ -186,7 +186,7 @@ bool ProxyObject::prevent_extensions()
|
|||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return false;
|
||||
}
|
||||
auto trap = m_handler.get("preventExtensions");
|
||||
auto trap = m_handler.get(vm().names.preventExtensions);
|
||||
if (vm().exception())
|
||||
return false;
|
||||
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);
|
||||
return {};
|
||||
}
|
||||
auto trap = m_handler.get("getOwnPropertyDescriptor");
|
||||
auto trap = m_handler.get(vm().names.getOwnPropertyDescriptor);
|
||||
if (vm().exception())
|
||||
return {};
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
auto trap = m_handler.get("defineProperty");
|
||||
auto trap = m_handler.get(vm().names.defineProperty);
|
||||
if (vm().exception())
|
||||
return false;
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
|
@ -285,7 +285,7 @@ bool ProxyObject::define_property(const StringOrSymbol& property_name, const Obj
|
|||
if (vm().exception())
|
||||
return 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;
|
||||
if (vm().exception())
|
||||
return false;
|
||||
|
@ -319,7 +319,7 @@ bool ProxyObject::has_property(const PropertyName& name) const
|
|||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return false;
|
||||
}
|
||||
auto trap = m_handler.get("has");
|
||||
auto trap = m_handler.get(vm().names.has);
|
||||
if (vm().exception())
|
||||
return false;
|
||||
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);
|
||||
return {};
|
||||
}
|
||||
auto trap = m_handler.get("get");
|
||||
auto trap = m_handler.get(vm().names.get);
|
||||
if (vm().exception())
|
||||
return {};
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (m_is_revoked) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return false;
|
||||
}
|
||||
auto trap = m_handler.get("set");
|
||||
if (vm().exception())
|
||||
auto trap = m_handler.get(vm.names.set);
|
||||
if (vm.exception())
|
||||
return false;
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
return m_target.put(name, value);
|
||||
if (!trap.is_function()) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "set");
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "set");
|
||||
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();
|
||||
if (vm().exception() || !trap_result)
|
||||
auto trap_result = vm.call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm, name.to_string()), value, Value(const_cast<ProxyObject*>(this))).to_boolean();
|
||||
if (vm.exception() || !trap_result)
|
||||
return false;
|
||||
auto target_desc = m_target.get_own_property_descriptor(name);
|
||||
if (vm().exception())
|
||||
if (vm.exception())
|
||||
return false;
|
||||
if (target_desc.has_value() && !target_desc.value().attributes.is_configurable()) {
|
||||
if (target_desc.value().is_data_descriptor() && !target_desc.value().attributes.is_writable() && !same_value(value, target_desc.value().value)) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxySetImmutableDataProperty);
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxySetImmutableDataProperty);
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
|
@ -421,32 +422,33 @@ bool ProxyObject::put(const PropertyName& name, Value value, Value)
|
|||
|
||||
Value ProxyObject::delete_property(const PropertyName& name)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (m_is_revoked) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return {};
|
||||
}
|
||||
auto trap = m_handler.get("deleteProperty");
|
||||
if (vm().exception())
|
||||
auto trap = m_handler.get(vm.names.deleteProperty);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
return m_target.delete_property(name);
|
||||
if (!trap.is_function()) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty");
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "deleteProperty");
|
||||
return {};
|
||||
}
|
||||
|
||||
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())
|
||||
auto trap_result = vm.call(trap.as_function(), Value(&m_handler), Value(&m_target), js_string(vm, name.to_string())).to_boolean();
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!trap_result)
|
||||
return Value(false);
|
||||
auto target_desc = m_target.get_own_property_descriptor(name);
|
||||
if (vm().exception())
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (!target_desc.has_value())
|
||||
return Value(true);
|
||||
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 Value(true);
|
||||
|
@ -461,21 +463,22 @@ void ProxyObject::visit_children(Cell::Visitor& visitor)
|
|||
|
||||
Value ProxyObject::call()
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
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 {};
|
||||
}
|
||||
if (m_is_revoked) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return {};
|
||||
}
|
||||
auto trap = m_handler.get("apply");
|
||||
if (vm().exception())
|
||||
auto trap = m_handler.get(vm.names.apply);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
return static_cast<Function&>(m_target).call();
|
||||
if (!trap.is_function()) {
|
||||
vm().throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "apply");
|
||||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyInvalidTrap, "apply");
|
||||
return {};
|
||||
}
|
||||
MarkedValueList arguments(heap());
|
||||
|
@ -483,12 +486,12 @@ Value ProxyObject::call()
|
|||
arguments.append(Value(&m_handler));
|
||||
// FIXME: Pass 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.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)
|
||||
|
@ -502,7 +505,7 @@ Value ProxyObject::construct(Function& new_target)
|
|||
vm.throw_exception<TypeError>(global_object(), ErrorType::ProxyRevoked);
|
||||
return {};
|
||||
}
|
||||
auto trap = m_handler.get("construct");
|
||||
auto trap = m_handler.get(vm.names.construct);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (trap.is_empty() || trap.is_nullish())
|
||||
|
|
|
@ -63,7 +63,7 @@ static void prepare_arguments_list(GlobalObject& global_object, Value value, Mar
|
|||
return;
|
||||
}
|
||||
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())
|
||||
return;
|
||||
auto length = length_property.to_size_t(global_object);
|
||||
|
@ -84,21 +84,22 @@ ReflectObject::ReflectObject(GlobalObject& global_object)
|
|||
|
||||
void ReflectObject::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("apply", apply, 3, attr);
|
||||
define_native_function("construct", construct, 2, attr);
|
||||
define_native_function("defineProperty", define_property, 3, attr);
|
||||
define_native_function("deleteProperty", delete_property, 2, attr);
|
||||
define_native_function("get", get, 2, attr);
|
||||
define_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2, attr);
|
||||
define_native_function("getPrototypeOf", get_prototype_of, 1, attr);
|
||||
define_native_function("has", has, 2, attr);
|
||||
define_native_function("isExtensible", is_extensible, 1, attr);
|
||||
define_native_function("ownKeys", own_keys, 1, attr);
|
||||
define_native_function("preventExtensions", prevent_extensions, 1, attr);
|
||||
define_native_function("set", set, 3, attr);
|
||||
define_native_function("setPrototypeOf", set_prototype_of, 2, attr);
|
||||
define_native_function(vm.names.apply, apply, 3, attr);
|
||||
define_native_function(vm.names.construct, construct, 2, attr);
|
||||
define_native_function(vm.names.defineProperty, define_property, 3, attr);
|
||||
define_native_function(vm.names.deleteProperty, delete_property, 2, attr);
|
||||
define_native_function(vm.names.get, get, 2, attr);
|
||||
define_native_function(vm.names.getOwnPropertyDescriptor, get_own_property_descriptor, 2, attr);
|
||||
define_native_function(vm.names.getPrototypeOf, get_prototype_of, 1, attr);
|
||||
define_native_function(vm.names.has, has, 2, attr);
|
||||
define_native_function(vm.names.isExtensible, is_extensible, 1, attr);
|
||||
define_native_function(vm.names.ownKeys, own_keys, 1, attr);
|
||||
define_native_function(vm.names.preventExtensions, prevent_extensions, 1, attr);
|
||||
define_native_function(vm.names.set, set, 3, attr);
|
||||
define_native_function(vm.names.setPrototypeOf, set_prototype_of, 2, attr);
|
||||
}
|
||||
|
||||
ReflectObject::~ReflectObject()
|
||||
|
|
|
@ -32,15 +32,16 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.regexp_prototype(), 0);
|
||||
define_property("length", Value(2), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.regexp_prototype(), 0);
|
||||
define_property(vm.names.length, Value(2), Attribute::Configurable);
|
||||
}
|
||||
|
||||
RegExpConstructor::~RegExpConstructor()
|
||||
|
|
|
@ -66,14 +66,15 @@ ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& nam
|
|||
|
||||
void ScriptFunction::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Function::initialize(global_object);
|
||||
if (!m_is_arrow_function) {
|
||||
Object* prototype = Object::create_empty(global_object);
|
||||
prototype->define_property_without_transition("constructor", this, Attribute::Writable | Attribute::Configurable);
|
||||
define_property("prototype", prototype, 0);
|
||||
prototype->define_property_without_transition(vm.names.constructor, this, Attribute::Writable | Attribute::Configurable);
|
||||
define_property(vm.names.prototype, prototype, 0);
|
||||
}
|
||||
define_native_property("length", length_getter, nullptr, Attribute::Configurable);
|
||||
define_native_property("name", name_getter, nullptr, Attribute::Configurable);
|
||||
define_native_property(vm.names.length, length_getter, nullptr, Attribute::Configurable);
|
||||
define_native_property(vm.names.name, name_getter, nullptr, Attribute::Configurable);
|
||||
}
|
||||
|
||||
ScriptFunction::~ScriptFunction()
|
||||
|
|
|
@ -35,19 +35,20 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.string_prototype(), 0);
|
||||
define_property("length", Value(1), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.string_prototype(), 0);
|
||||
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
define_native_function("raw", raw, 1, attr);
|
||||
define_native_function("fromCharCode", from_char_code, 1, attr);
|
||||
define_native_function(vm.names.raw, raw, 1, attr);
|
||||
define_native_function(vm.names.fromCharCode, from_char_code, 1, attr);
|
||||
}
|
||||
|
||||
StringConstructor::~StringConstructor()
|
||||
|
@ -84,7 +85,7 @@ JS_DEFINE_NATIVE_FUNCTION(StringConstructor::raw)
|
|||
if (vm.exception())
|
||||
return {};
|
||||
|
||||
auto raw = template_object->get("raw");
|
||||
auto raw = template_object->get(vm.names.raw);
|
||||
if (vm.exception())
|
||||
return {};
|
||||
if (raw.is_empty() || raw.is_nullish()) {
|
||||
|
|
|
@ -40,10 +40,10 @@ StringIteratorPrototype::StringIteratorPrototype(GlobalObject& global_object)
|
|||
|
||||
void StringIteratorPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
|
||||
define_native_function("next", next, 0, Attribute::Configurable | Attribute::Writable);
|
||||
define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "String Iterator"), Attribute::Configurable);
|
||||
define_native_function(vm.names.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);
|
||||
}
|
||||
|
||||
StringIteratorPrototype::~StringIteratorPrototype()
|
||||
|
|
|
@ -66,29 +66,30 @@ StringPrototype::StringPrototype(GlobalObject& global_object)
|
|||
|
||||
void StringPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
StringObject::initialize(global_object);
|
||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||
|
||||
define_native_property("length", length_getter, nullptr, 0);
|
||||
define_native_function("charAt", char_at, 1, attr);
|
||||
define_native_function("charCodeAt", char_code_at, 1, attr);
|
||||
define_native_function("repeat", repeat, 1, attr);
|
||||
define_native_function("startsWith", starts_with, 1, attr);
|
||||
define_native_function("indexOf", index_of, 1, attr);
|
||||
define_native_function("toLowerCase", to_lowercase, 0, attr);
|
||||
define_native_function("toUpperCase", to_uppercase, 0, attr);
|
||||
define_native_function("toString", to_string, 0, attr);
|
||||
define_native_function("padStart", pad_start, 1, attr);
|
||||
define_native_function("padEnd", pad_end, 1, attr);
|
||||
define_native_function("trim", trim, 0, attr);
|
||||
define_native_function("trimStart", trim_start, 0, attr);
|
||||
define_native_function("trimEnd", trim_end, 0, attr);
|
||||
define_native_function("concat", concat, 1, attr);
|
||||
define_native_function("substring", substring, 2, attr);
|
||||
define_native_function("includes", includes, 1, attr);
|
||||
define_native_function("slice", slice, 2, attr);
|
||||
define_native_function("lastIndexOf", last_index_of, 1, attr);
|
||||
define_native_function(global_object.vm().well_known_symbol_iterator(), symbol_iterator, 0, attr);
|
||||
define_native_property(vm.names.length, length_getter, nullptr, 0);
|
||||
define_native_function(vm.names.charAt, char_at, 1, attr);
|
||||
define_native_function(vm.names.charCodeAt, char_code_at, 1, attr);
|
||||
define_native_function(vm.names.repeat, repeat, 1, attr);
|
||||
define_native_function(vm.names.startsWith, starts_with, 1, attr);
|
||||
define_native_function(vm.names.indexOf, index_of, 1, attr);
|
||||
define_native_function(vm.names.toLowerCase, to_lowercase, 0, attr);
|
||||
define_native_function(vm.names.toUpperCase, to_uppercase, 0, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(vm.names.padStart, pad_start, 1, attr);
|
||||
define_native_function(vm.names.padEnd, pad_end, 1, attr);
|
||||
define_native_function(vm.names.trim, trim, 0, attr);
|
||||
define_native_function(vm.names.trimStart, trim_start, 0, attr);
|
||||
define_native_function(vm.names.trimEnd, trim_end, 0, attr);
|
||||
define_native_function(vm.names.concat, concat, 1, attr);
|
||||
define_native_function(vm.names.substring, substring, 2, attr);
|
||||
define_native_function(vm.names.includes, includes, 1, attr);
|
||||
define_native_function(vm.names.slice, slice, 2, attr);
|
||||
define_native_function(vm.names.lastIndexOf, last_index_of, 1, attr);
|
||||
define_native_function(vm.well_known_symbol_iterator(), symbol_iterator, 0, attr);
|
||||
}
|
||||
|
||||
StringPrototype::~StringPrototype()
|
||||
|
|
|
@ -32,21 +32,22 @@
|
|||
namespace JS {
|
||||
|
||||
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)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
NativeFunction::initialize(global_object);
|
||||
define_property("prototype", global_object.symbol_prototype(), 0);
|
||||
define_property("length", Value(0), Attribute::Configurable);
|
||||
define_property(vm.names.prototype, global_object.symbol_prototype(), 0);
|
||||
define_property(vm.names.length, Value(0), Attribute::Configurable);
|
||||
|
||||
define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function(vm.names.for_, 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_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
|
||||
#undef __JS_ENUMERATE
|
||||
}
|
||||
|
|
|
@ -45,10 +45,11 @@ SymbolPrototype::SymbolPrototype(GlobalObject& global_object)
|
|||
|
||||
void SymbolPrototype::initialize(GlobalObject& global_object)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
Object::initialize(global_object);
|
||||
define_native_property("description", description_getter, nullptr, Attribute::Configurable);
|
||||
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
|
||||
define_native_property(vm.names.description, description_getter, nullptr, Attribute::Configurable);
|
||||
define_native_function(vm.names.toString, to_string, 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);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ Uint8ClampedArray::Uint8ClampedArray(u32 length, Object& prototype)
|
|||
: Object(prototype)
|
||||
, 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];
|
||||
}
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
|
|||
current_environment()->bind_this_value(global_object, new_object);
|
||||
if (exception())
|
||||
return {};
|
||||
auto prototype = new_target.get("prototype");
|
||||
auto prototype = new_target.get(names.prototype);
|
||||
if (exception())
|
||||
return {};
|
||||
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).
|
||||
if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
|
||||
current_environment()->replace_this_binding(result);
|
||||
auto prototype = new_target.get("prototype");
|
||||
auto prototype = new_target.get(names.prototype);
|
||||
if (exception())
|
||||
return {};
|
||||
if (prototype.is_object()) {
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <AK/HashMap.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <LibJS/Heap/Heap.h>
|
||||
#include <LibJS/Runtime/CommonPropertyNames.h>
|
||||
#include <LibJS/Runtime/ErrorTypes.h>
|
||||
#include <LibJS/Runtime/Exception.h>
|
||||
#include <LibJS/Runtime/MarkedValueList.h>
|
||||
|
@ -223,6 +224,8 @@ public:
|
|||
return call(function, this_value);
|
||||
}
|
||||
|
||||
CommonPropertyNames names;
|
||||
|
||||
private:
|
||||
VM();
|
||||
|
||||
|
|
|
@ -738,7 +738,7 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
|
|||
return Value(false);
|
||||
|
||||
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())
|
||||
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)
|
||||
{
|
||||
ASSERT(value.is_object());
|
||||
auto result = value.as_object().get("length");
|
||||
if (global_object.vm().exception())
|
||||
auto& vm = global_object.vm();
|
||||
auto result = value.as_object().get(vm.names.length);
|
||||
if (vm.exception())
|
||||
return 0;
|
||||
return result.to_size_t(global_object);
|
||||
}
|
||||
|
|
|
@ -154,8 +154,10 @@ TestRunnerGlobalObject::~TestRunnerGlobalObject()
|
|||
void TestRunnerGlobalObject::initialize()
|
||||
{
|
||||
JS::GlobalObject::initialize();
|
||||
define_property("global", this, JS::Attribute::Enumerable);
|
||||
define_native_function("isStrictMode", is_strict_mode);
|
||||
static FlyString global_property_name { "global" };
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue