mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:07:35 +00:00
LibJS: Avoid lots of string-to-int during global object construction
We were doing a *lot* of string-to-int conversion while creating a new global object. This happened because Object::put() would try to convert the property name (string) to an integer to see if it refers to an indexed property. Sidestep this issue by using PropertyName for the CommonPropertyNames struct on VM (vm.names.foo), and giving PropertyName a flag that tells us whether it's a string that *may be* a number. All CommonPropertyNames are set up so they are known to not be numbers.
This commit is contained in:
parent
53a8a11973
commit
5eef07d232
25 changed files with 84 additions and 58 deletions
|
@ -144,8 +144,8 @@ void MarkupGenerator::date_to_html(const Object& date, StringBuilder& html_outpu
|
|||
|
||||
void MarkupGenerator::error_to_html(const Object& object, StringBuilder& html_output, HashTable<Object*>&)
|
||||
{
|
||||
auto name = object.get_without_side_effects("name").value_or(JS::js_undefined());
|
||||
auto message = object.get_without_side_effects("message").value_or(JS::js_undefined());
|
||||
auto name = object.get_without_side_effects(PropertyName("name")).value_or(JS::js_undefined());
|
||||
auto message = object.get_without_side_effects(PropertyName("message")).value_or(JS::js_undefined());
|
||||
if (name.is_accessor() || name.is_native_property() || message.is_accessor() || message.is_native_property()) {
|
||||
html_output.append(wrap_string_in_style(JS::Value(&object).to_string_without_side_effects(), StyleType::Invalid));
|
||||
} else {
|
||||
|
|
|
@ -28,7 +28,7 @@ void ArrayBufferPrototype::initialize(GlobalObject& global_object)
|
|||
define_native_property(vm.names.byteLength, byte_length_getter, {}, Attribute::Configurable);
|
||||
|
||||
// 25.1.5.4 ArrayBuffer.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-arraybuffer.prototype-@@tostringtag
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), "ArrayBuffer"), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.ArrayBuffer.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
ArrayBufferPrototype::~ArrayBufferPrototype()
|
||||
|
|
|
@ -302,7 +302,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
|
|||
auto* value_object = value.to_object(global_object);
|
||||
if (!value_object)
|
||||
return {};
|
||||
auto locale_string_result = value_object->invoke(vm.names.toLocaleString);
|
||||
auto locale_string_result = value_object->invoke(vm.names.toLocaleString.as_string());
|
||||
if (vm.exception())
|
||||
return {};
|
||||
auto string = locale_string_result.to_string(global_object);
|
||||
|
|
|
@ -27,7 +27,7 @@ void BigIntPrototype::initialize(GlobalObject& global_object)
|
|||
define_native_function(vm.names.valueOf, value_of, 0, attr);
|
||||
|
||||
// 21.2.3.5 BigInt.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-bigint.prototype-@@tostringtag
|
||||
define_property(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(), vm.names.BigInt.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
BigIntPrototype::~BigIntPrototype()
|
||||
|
|
|
@ -295,18 +295,18 @@ namespace JS {
|
|||
P(writable)
|
||||
|
||||
struct CommonPropertyNames {
|
||||
FlyString catch_ { "catch" };
|
||||
FlyString delete_ { "delete" };
|
||||
FlyString for_ { "for" };
|
||||
FlyString return_ { "return" };
|
||||
FlyString throw_ { "throw" };
|
||||
#define __ENUMERATE(x) FlyString x { #x };
|
||||
PropertyName catch_ { "catch", PropertyName::StringMayBeNumber::No };
|
||||
PropertyName delete_ { "delete", PropertyName::StringMayBeNumber::No };
|
||||
PropertyName for_ { "for", PropertyName::StringMayBeNumber::No };
|
||||
PropertyName return_ { "return", PropertyName::StringMayBeNumber::No };
|
||||
PropertyName throw_ { "throw", PropertyName::StringMayBeNumber::No };
|
||||
#define __ENUMERATE(x) PropertyName x { #x, PropertyName::StringMayBeNumber::No };
|
||||
ENUMERATE_STANDARD_PROPERTY_NAMES(__ENUMERATE)
|
||||
#undef __ENUMERATE
|
||||
#define __JS_ENUMERATE(x, a, b, c, t) FlyString x { #x };
|
||||
#define __JS_ENUMERATE(x, a, b, c, t) PropertyName x { #x, PropertyName::StringMayBeNumber::No };
|
||||
JS_ENUMERATE_BUILTIN_TYPES
|
||||
#undef __JS_ENUMERATE
|
||||
#define __JS_ENUMERATE(x, a) FlyString x { #x };
|
||||
#define __JS_ENUMERATE(x, a) PropertyName x { #x, PropertyName::StringMayBeNumber::No };
|
||||
JS_ENUMERATE_WELL_KNOWN_SYMBOLS
|
||||
#undef __JS_ENUMERATE
|
||||
};
|
||||
|
|
|
@ -849,7 +849,7 @@ JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_json)
|
|||
if (time_value.is_number() && !time_value.is_finite_number())
|
||||
return js_null();
|
||||
|
||||
return this_object->invoke(vm.names.toISOString);
|
||||
return this_object->invoke(vm.names.toISOString.as_string());
|
||||
}
|
||||
|
||||
// 21.4.4.45 Date.prototype [ @@toPrimitive ] ( hint ), https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive
|
||||
|
|
|
@ -52,9 +52,9 @@ protected:
|
|||
virtual void visit_edges(Visitor&) override;
|
||||
|
||||
template<typename ConstructorType>
|
||||
void initialize_constructor(const FlyString& property_name, ConstructorType*&, Object* prototype);
|
||||
void initialize_constructor(PropertyName const&, ConstructorType*&, Object* prototype);
|
||||
template<typename ConstructorType>
|
||||
void add_constructor(const FlyString& property_name, ConstructorType*&, Object* prototype);
|
||||
void add_constructor(PropertyName const&, ConstructorType*&, Object* prototype);
|
||||
|
||||
private:
|
||||
virtual bool is_global_object() const final { return true; }
|
||||
|
@ -94,11 +94,11 @@ private:
|
|||
};
|
||||
|
||||
template<typename ConstructorType>
|
||||
inline void GlobalObject::initialize_constructor(const FlyString& property_name, ConstructorType*& constructor, Object* prototype)
|
||||
inline void GlobalObject::initialize_constructor(PropertyName const& property_name, ConstructorType*& constructor, Object* prototype)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
constructor = heap().allocate<ConstructorType>(*this, *this);
|
||||
constructor->define_property(vm.names.name, js_string(heap(), property_name), Attribute::Configurable);
|
||||
constructor->define_property(vm.names.name, js_string(heap(), property_name.as_string()), Attribute::Configurable);
|
||||
if (vm.exception())
|
||||
return;
|
||||
if (prototype) {
|
||||
|
@ -109,7 +109,7 @@ inline void GlobalObject::initialize_constructor(const FlyString& property_name,
|
|||
}
|
||||
|
||||
template<typename ConstructorType>
|
||||
inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object* prototype)
|
||||
inline void GlobalObject::add_constructor(PropertyName const& property_name, ConstructorType*& constructor, Object* prototype)
|
||||
{
|
||||
// Some constructors are pre-initialized separately.
|
||||
if (!constructor)
|
||||
|
|
|
@ -34,7 +34,7 @@ void MapPrototype::initialize(GlobalObject& global_object)
|
|||
define_native_accessor(vm.names.size, size_getter, {}, Attribute::Configurable);
|
||||
|
||||
define_property(vm.well_known_symbol_iterator(), Object::get(vm.names.entries), attr);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.Map), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.Map.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
MapPrototype::~MapPrototype()
|
||||
|
|
|
@ -71,7 +71,7 @@ void MathObject::initialize(GlobalObject& global_object)
|
|||
define_property(vm.names.SQRT2, Value(M_SQRT2), 0);
|
||||
|
||||
// 21.3.1.9 Math [ @@toStringTag ], https://tc39.es/ecma262/#sec-math-@@tostringtag
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), "Math"), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.Math.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
MathObject::~MathObject()
|
||||
|
|
|
@ -20,16 +20,16 @@ NativeFunction::NativeFunction(Object& prototype)
|
|||
{
|
||||
}
|
||||
|
||||
NativeFunction::NativeFunction(const FlyString& name, AK::Function<Value(VM&, GlobalObject&)> native_function, Object& prototype)
|
||||
NativeFunction::NativeFunction(PropertyName const& name, AK::Function<Value(VM&, GlobalObject&)> native_function, Object& prototype)
|
||||
: Function(prototype)
|
||||
, m_name(name)
|
||||
, m_name(name.as_string())
|
||||
, m_native_function(move(native_function))
|
||||
{
|
||||
}
|
||||
|
||||
NativeFunction::NativeFunction(const FlyString& name, Object& prototype)
|
||||
NativeFunction::NativeFunction(PropertyName const& name, Object& prototype)
|
||||
: Function(prototype)
|
||||
, m_name(name)
|
||||
, m_name(name.as_string())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class NativeFunction : public Function {
|
|||
public:
|
||||
static NativeFunction* create(GlobalObject&, const FlyString& name, AK::Function<Value(VM&, GlobalObject&)>);
|
||||
|
||||
explicit NativeFunction(const FlyString& name, AK::Function<Value(VM&, GlobalObject&)>, Object& prototype);
|
||||
explicit NativeFunction(PropertyName const& name, AK::Function<Value(VM&, GlobalObject&)>, Object& prototype);
|
||||
virtual void initialize(GlobalObject&) override { }
|
||||
virtual ~NativeFunction() override;
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
|||
virtual bool is_strict_mode() const override;
|
||||
|
||||
protected:
|
||||
NativeFunction(const FlyString& name, Object& prototype);
|
||||
NativeFunction(PropertyName const& name, Object& prototype);
|
||||
explicit NativeFunction(Object& prototype);
|
||||
|
||||
private:
|
||||
|
|
|
@ -190,7 +190,7 @@ bool Object::set_integrity_level(IntegrityLevel level)
|
|||
case IntegrityLevel::Sealed:
|
||||
for (auto& key : keys) {
|
||||
auto property_name = PropertyName::from_value(global_object(), key);
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
i32 property_index = property_name.as_string().to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
property_name = property_index;
|
||||
|
@ -203,7 +203,7 @@ bool Object::set_integrity_level(IntegrityLevel level)
|
|||
case IntegrityLevel::Frozen:
|
||||
for (auto& key : keys) {
|
||||
auto property_name = PropertyName::from_value(global_object(), key);
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
i32 property_index = property_name.as_string().to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
property_name = property_index;
|
||||
|
@ -389,7 +389,7 @@ Optional<PropertyDescriptor> Object::get_own_property_descriptor(const PropertyN
|
|||
value = existing_value.value().value;
|
||||
attributes = existing_value.value().attributes;
|
||||
} else {
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
i32 property_index = property_name.as_string().to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
return get_own_property_descriptor(property_index);
|
||||
|
@ -537,7 +537,7 @@ bool Object::define_property(const PropertyName& property_name, Value value, Pro
|
|||
if (property_name.is_number())
|
||||
return put_own_property_by_index(property_name.as_number(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
||||
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
i32 property_index = property_name.as_string().to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
return put_own_property_by_index(property_index, value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
||||
|
@ -545,7 +545,7 @@ bool Object::define_property(const PropertyName& property_name, Value value, Pro
|
|||
return put_own_property(property_name.to_string_or_symbol(), value, attributes, PutOwnPropertyMode::DefineProperty, throw_exceptions);
|
||||
}
|
||||
|
||||
bool Object::define_native_accessor(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attribute)
|
||||
bool Object::define_native_accessor(PropertyName const& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attribute)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
String formatted_property_name;
|
||||
|
@ -749,7 +749,7 @@ bool Object::delete_property(const PropertyName& property_name)
|
|||
if (property_name.is_number())
|
||||
return m_indexed_properties.remove(property_name.as_number());
|
||||
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
i32 property_index = property_name.as_string().to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
return m_indexed_properties.remove(property_index);
|
||||
|
@ -807,7 +807,7 @@ Value Object::get(const PropertyName& property_name, Value receiver, bool withou
|
|||
if (property_name.is_number())
|
||||
return get_by_index(property_name.as_number());
|
||||
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
auto& property_string = property_name.as_string();
|
||||
i32 property_index = property_string.to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
|
@ -875,7 +875,7 @@ bool Object::put(const PropertyName& property_name, Value value, Value receiver)
|
|||
|
||||
VERIFY(!value.is_empty());
|
||||
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
auto& property_string = property_name.as_string();
|
||||
i32 property_index = property_string.to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
|
@ -910,7 +910,7 @@ bool Object::put(const PropertyName& property_name, Value value, Value receiver)
|
|||
return put_own_property(string_or_symbol, value, default_attributes, PutOwnPropertyMode::Put);
|
||||
}
|
||||
|
||||
bool Object::define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
|
||||
bool Object::define_native_function(PropertyName const& property_name, AK::Function<Value(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
String function_name;
|
||||
|
@ -929,7 +929,7 @@ bool Object::define_native_function(const StringOrSymbol& property_name, AK::Fun
|
|||
return define_property(property_name, function, attribute);
|
||||
}
|
||||
|
||||
bool Object::define_native_property(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
|
||||
bool Object::define_native_property(PropertyName const& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
|
||||
{
|
||||
return define_property(property_name, heap().allocate_without_global_object<NativeProperty>(move(getter), move(setter)), attribute);
|
||||
}
|
||||
|
@ -1016,7 +1016,7 @@ bool Object::has_own_property(const PropertyName& property_name) const
|
|||
if (property_name.is_number())
|
||||
return has_indexed_property(property_name.as_number());
|
||||
|
||||
if (property_name.is_string()) {
|
||||
if (property_name.is_string() && property_name.string_may_be_number()) {
|
||||
i32 property_index = property_name.as_string().to_int().value_or(-1);
|
||||
if (property_index >= 0)
|
||||
return has_indexed_property(property_index);
|
||||
|
@ -1033,9 +1033,9 @@ Value Object::ordinary_to_primitive(Value::PreferredType preferred_type) const
|
|||
|
||||
Vector<FlyString, 2> method_names;
|
||||
if (preferred_type == Value::PreferredType::String)
|
||||
method_names = { vm.names.toString, vm.names.valueOf };
|
||||
method_names = { vm.names.toString.as_string(), vm.names.valueOf.as_string() };
|
||||
else
|
||||
method_names = { vm.names.valueOf, vm.names.toString };
|
||||
method_names = { vm.names.valueOf.as_string(), vm.names.toString.as_string() };
|
||||
|
||||
for (auto& method_name : method_names) {
|
||||
auto method = get(method_name);
|
||||
|
|
|
@ -93,9 +93,9 @@ public:
|
|||
bool define_property_without_transition(const PropertyName&, Value value, PropertyAttributes attributes = default_attributes, bool throw_exceptions = true);
|
||||
bool define_accessor(const PropertyName&, Function* getter, Function* setter, PropertyAttributes attributes = default_attributes, bool throw_exceptions = true);
|
||||
|
||||
bool define_native_function(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes);
|
||||
bool define_native_property(const StringOrSymbol& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes);
|
||||
bool define_native_accessor(StringOrSymbol const& property_name, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attributes = default_attributes);
|
||||
bool define_native_function(PropertyName const&, AK::Function<Value(VM&, GlobalObject&)>, i32 length = 0, PropertyAttributes attributes = default_attributes);
|
||||
bool define_native_property(PropertyName const&, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<void(VM&, GlobalObject&, Value)> setter, PropertyAttributes attributes = default_attributes);
|
||||
bool define_native_accessor(PropertyName const&, AK::Function<Value(VM&, GlobalObject&)> getter, AK::Function<Value(VM&, GlobalObject&)> setter, PropertyAttributes attributes = default_attributes);
|
||||
|
||||
void define_properties(Value properties);
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_locale_string)
|
|||
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||
if (!this_object)
|
||||
return {};
|
||||
return this_object->invoke(vm.names.toString);
|
||||
return this_object->invoke(vm.names.toString.as_string());
|
||||
}
|
||||
|
||||
// 20.1.3.7 Object.prototype.valueOf ( ), https://tc39.es/ecma262/#sec-object.prototype.valueof
|
||||
|
|
|
@ -31,7 +31,7 @@ void PromisePrototype::initialize(GlobalObject& global_object)
|
|||
define_native_function(vm.names.finally, finally, 1, attr);
|
||||
|
||||
// 27.2.5.5 Promise.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-promise.prototype-@@tostringtag
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), "Promise"), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.Promise.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
static Promise* promise_from(VM& vm, GlobalObject& global_object)
|
||||
|
@ -70,7 +70,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::catch_)
|
|||
if (!this_object)
|
||||
return {};
|
||||
auto on_rejected = vm.argument(0);
|
||||
return this_object->invoke(vm.names.then, js_undefined(), on_rejected);
|
||||
return this_object->invoke(vm.names.then.as_string(), js_undefined(), on_rejected);
|
||||
}
|
||||
|
||||
// 27.2.5.3 Promise.prototype.finally ( onFinally ), https://tc39.es/ecma262/#sec-promise.prototype.finally
|
||||
|
@ -103,7 +103,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
|||
auto* value_thunk = NativeFunction::create(global_object, "", [value](auto&, auto&) -> Value {
|
||||
return value;
|
||||
});
|
||||
return promise->invoke(vm.names.then, value_thunk);
|
||||
return promise->invoke(vm.names.then.as_string(), value_thunk);
|
||||
});
|
||||
then_finally_function->define_property(vm.names.length, Value(1));
|
||||
|
||||
|
@ -122,14 +122,14 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
|||
vm.throw_exception(global_object, reason);
|
||||
return {};
|
||||
});
|
||||
return promise->invoke(vm.names.then, thrower);
|
||||
return promise->invoke(vm.names.then.as_string(), thrower);
|
||||
});
|
||||
catch_finally_function->define_property(vm.names.length, Value(1));
|
||||
|
||||
then_finally = Value(then_finally_function);
|
||||
catch_finally = Value(catch_finally_function);
|
||||
}
|
||||
return promise->invoke(vm.names.then, then_finally, catch_finally);
|
||||
return promise->invoke(vm.names.then.as_string(), then_finally, catch_finally);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,13 +13,18 @@ namespace JS {
|
|||
|
||||
class PropertyName {
|
||||
public:
|
||||
enum class Type {
|
||||
enum class Type : u8 {
|
||||
Invalid,
|
||||
Number,
|
||||
String,
|
||||
Symbol,
|
||||
};
|
||||
|
||||
enum class StringMayBeNumber {
|
||||
Yes,
|
||||
No,
|
||||
};
|
||||
|
||||
static PropertyName from_value(GlobalObject& global_object, Value value)
|
||||
{
|
||||
if (value.is_empty())
|
||||
|
@ -56,8 +61,9 @@ public:
|
|||
VERIFY(!string.is_null());
|
||||
}
|
||||
|
||||
PropertyName(FlyString const& string)
|
||||
PropertyName(FlyString const& string, StringMayBeNumber string_may_be_number = StringMayBeNumber::Yes)
|
||||
: m_type(Type::String)
|
||||
, m_string_may_be_number(string_may_be_number == StringMayBeNumber::Yes)
|
||||
, m_string(string)
|
||||
{
|
||||
VERIFY(!string.is_null());
|
||||
|
@ -85,6 +91,7 @@ public:
|
|||
bool is_number() const { return m_type == Type::Number; }
|
||||
bool is_string() const { return m_type == Type::String; }
|
||||
bool is_symbol() const { return m_type == Type::Symbol; }
|
||||
bool string_may_be_number() const { return m_string_may_be_number; }
|
||||
|
||||
u32 as_number() const
|
||||
{
|
||||
|
@ -135,9 +142,22 @@ public:
|
|||
|
||||
private:
|
||||
Type m_type { Type::Invalid };
|
||||
bool m_string_may_be_number { true };
|
||||
FlyString m_string;
|
||||
Symbol* m_symbol { nullptr };
|
||||
u32 m_number { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace AK {
|
||||
|
||||
template<>
|
||||
struct Formatter<JS::PropertyName> : Formatter<StringView> {
|
||||
void format(FormatBuilder& builder, JS::PropertyName const& value)
|
||||
{
|
||||
Formatter<StringView>::format(builder, value.to_string());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ void ReflectObject::initialize(GlobalObject& global_object)
|
|||
define_native_function(vm.names.setPrototypeOf, set_prototype_of, 2, attr);
|
||||
|
||||
// 28.1.14 Reflect [ @@toStringTag ], https://tc39.es/ecma262/#sec-reflect-@@tostringtag
|
||||
Object::define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), "Reflect"), Attribute::Configurable);
|
||||
Object::define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.Reflect.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
ReflectObject::~ReflectObject()
|
||||
|
|
|
@ -37,7 +37,7 @@ void SetPrototype::initialize(GlobalObject& global_object)
|
|||
define_property(vm.well_known_symbol_iterator(), get(vm.names.values), attr);
|
||||
|
||||
// 24.2.3.12 Set.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-set.prototype-@@tostringtag
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.Set), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.Set.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
SetPrototype::~SetPrototype()
|
||||
|
|
|
@ -214,4 +214,9 @@ void Shape::add_property_without_transition(const StringOrSymbol& property_name,
|
|||
++m_property_count;
|
||||
}
|
||||
|
||||
FLATTEN void Shape::add_property_without_transition(PropertyName const& property_name, PropertyAttributes attributes)
|
||||
{
|
||||
add_property_without_transition(StringOrSymbol(property_name.as_string()), attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
Shape* create_prototype_transition(Object* new_prototype);
|
||||
|
||||
void add_property_without_transition(const StringOrSymbol&, PropertyAttributes);
|
||||
void add_property_without_transition(PropertyName const&, PropertyAttributes);
|
||||
|
||||
bool is_unique() const { return m_unique; }
|
||||
Shape* create_unique_clone() const;
|
||||
|
|
|
@ -209,7 +209,7 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
|
|||
PrototypeName::~PrototypeName() { } \
|
||||
\
|
||||
ConstructorName::ConstructorName(GlobalObject& global_object) \
|
||||
: TypedArrayConstructor(vm().names.ClassName, *global_object.typed_array_constructor()) \
|
||||
: TypedArrayConstructor(vm().names.ClassName.as_string(), *global_object.typed_array_constructor()) \
|
||||
{ \
|
||||
} \
|
||||
ConstructorName::~ConstructorName() { } \
|
||||
|
|
|
@ -331,7 +331,7 @@ void VM::assign(const NonnullRefPtr<BindingPattern>& target, Value value, Global
|
|||
Value VM::get_variable(const FlyString& name, GlobalObject& global_object)
|
||||
{
|
||||
if (!m_call_stack.is_empty()) {
|
||||
if (name == names.arguments && !call_frame().callee.is_empty()) {
|
||||
if (name == names.arguments.as_string() && !call_frame().callee.is_empty()) {
|
||||
// HACK: Special handling for the name "arguments":
|
||||
// If the name "arguments" is defined in the current scope, for example via
|
||||
// a function parameter, or by a local var declaration, we use that.
|
||||
|
|
|
@ -26,7 +26,7 @@ void WeakMapPrototype::initialize(GlobalObject& global_object)
|
|||
define_native_function(vm.names.set, set, 2, attr);
|
||||
|
||||
// 24.3.3.6 WeakMap.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-weakmap.prototype-@@tostringtag
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakMap), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.WeakMap.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
WeakMapPrototype::~WeakMapPrototype()
|
||||
|
|
|
@ -20,7 +20,7 @@ void WeakRefPrototype::initialize(GlobalObject& global_object)
|
|||
|
||||
define_native_function(vm.names.deref, deref, 0, Attribute::Writable | Attribute::Configurable);
|
||||
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakRef), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm.heap(), vm.names.WeakRef.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
WeakRefPrototype::~WeakRefPrototype()
|
||||
|
|
|
@ -25,7 +25,7 @@ void WeakSetPrototype::initialize(GlobalObject& global_object)
|
|||
define_native_function(vm.names.has, has, 1, attr);
|
||||
|
||||
// 24.4.3.5 WeakSet.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-weakset.prototype-@@tostringtag
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakSet), Attribute::Configurable);
|
||||
define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakSet.as_string()), Attribute::Configurable);
|
||||
}
|
||||
|
||||
WeakSetPrototype::~WeakSetPrototype()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue