diff options
author | Andreas Kling <kling@serenityos.org> | 2021-06-13 18:59:07 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-13 19:11:29 +0200 |
commit | 5eef07d232fc179f0640bbb8cff575cd239c4d65 (patch) | |
tree | f2793ff33530445dcf110b42d0013636ee52c11c /Userland/Libraries/LibJS/Runtime | |
parent | 53a8a11973cb4be1dc688fc245775540630bf87d (diff) | |
download | serenity-5eef07d232fc179f0640bbb8cff575cd239c4d65.zip |
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.
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
24 files changed, 82 insertions, 56 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp index b690d7fa95..bee4662c2e 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayBufferPrototype.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp index d7d264696b..fd6d271c46 100644 --- a/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ArrayPrototype.cpp @@ -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); diff --git a/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp b/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp index 1086c2bd51..8d973784bc 100644 --- a/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/BigIntPrototype.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h index d17dd77527..b8c88aed25 100644 --- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -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 }; diff --git a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp index fb36c9e963..acca8172c9 100644 --- a/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/DatePrototype.cpp @@ -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 diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.h b/Userland/Libraries/LibJS/Runtime/GlobalObject.h index 910f3f17b1..16c766fdca 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.h +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.h @@ -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) diff --git a/Userland/Libraries/LibJS/Runtime/MapPrototype.cpp b/Userland/Libraries/LibJS/Runtime/MapPrototype.cpp index e50bbe5dfc..10d9f64f20 100644 --- a/Userland/Libraries/LibJS/Runtime/MapPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/MapPrototype.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/MathObject.cpp b/Userland/Libraries/LibJS/Runtime/MathObject.cpp index 38849e58ae..07d13e50e4 100644 --- a/Userland/Libraries/LibJS/Runtime/MathObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/MathObject.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp index 26f65463fa..9ddec6cdba 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.cpp @@ -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()) { } diff --git a/Userland/Libraries/LibJS/Runtime/NativeFunction.h b/Userland/Libraries/LibJS/Runtime/NativeFunction.h index 93661a3faf..4d8b8de6b4 100644 --- a/Userland/Libraries/LibJS/Runtime/NativeFunction.h +++ b/Userland/Libraries/LibJS/Runtime/NativeFunction.h @@ -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: diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index f84ef98ded..930519b35e 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -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); diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h index 798a3372df..444a67e84e 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.h +++ b/Userland/Libraries/LibJS/Runtime/Object.h @@ -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); diff --git a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp index 03d4d4a13a..cbb0730149 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp @@ -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 diff --git a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp index a3024aa011..9c2f1e93c2 100644 --- a/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/PromisePrototype.cpp @@ -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); } } diff --git a/Userland/Libraries/LibJS/Runtime/PropertyName.h b/Userland/Libraries/LibJS/Runtime/PropertyName.h index 68c3223f4b..565d683427 100644 --- a/Userland/Libraries/LibJS/Runtime/PropertyName.h +++ b/Userland/Libraries/LibJS/Runtime/PropertyName.h @@ -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()); + } +}; + +} diff --git a/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp b/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp index 376848bcbb..0ef298d202 100644 --- a/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/ReflectObject.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp b/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp index ab61917fda..eccf57e796 100644 --- a/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/SetPrototype.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/Shape.cpp b/Userland/Libraries/LibJS/Runtime/Shape.cpp index f21906be0f..e0cf827d35 100644 --- a/Userland/Libraries/LibJS/Runtime/Shape.cpp +++ b/Userland/Libraries/LibJS/Runtime/Shape.cpp @@ -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); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/Shape.h b/Userland/Libraries/LibJS/Runtime/Shape.h index 6f77ef6744..d068791692 100644 --- a/Userland/Libraries/LibJS/Runtime/Shape.h +++ b/Userland/Libraries/LibJS/Runtime/Shape.h @@ -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; diff --git a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp index 462ac7c1f3..9ba10cc508 100644 --- a/Userland/Libraries/LibJS/Runtime/TypedArray.cpp +++ b/Userland/Libraries/LibJS/Runtime/TypedArray.cpp @@ -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() { } \ diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 558dc48cd3..e818614db5 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -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. diff --git a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp index 41ea268ca8..f70453006c 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakMapPrototype.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/WeakRefPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakRefPrototype.cpp index 8e1e020bb0..3ccd52092a 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakRefPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakRefPrototype.cpp @@ -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() diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp index 412f9a82e3..20e068f273 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp @@ -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() |