diff --git a/Libraries/LibJS/Runtime/PropertyKey.h b/Libraries/LibJS/Runtime/PropertyKey.h index f4c3f3f976b..26fd5acbc13 100644 --- a/Libraries/LibJS/Runtime/PropertyKey.h +++ b/Libraries/LibJS/Runtime/PropertyKey.h @@ -105,6 +105,8 @@ public: return StringOrSymbol(as_symbol()); } + bool operator==(PropertyKey const&) const = default; + private: friend Traits; diff --git a/Libraries/LibJS/Runtime/Value.cpp b/Libraries/LibJS/Runtime/Value.cpp index 8313f41b183..50f0ac2f826 100644 --- a/Libraries/LibJS/Runtime/Value.cpp +++ b/Libraries/LibJS/Runtime/Value.cpp @@ -1220,7 +1220,21 @@ double to_integer_or_infinity(double number) ThrowCompletionOr Value::get(VM& vm, PropertyKey const& property_key) const { // 1. Let O be ? ToObject(V). - auto object = TRY(to_object(vm)); + auto object = TRY([&]() -> ThrowCompletionOr> { + // OPTIMIZATION: For primitive values, we can skip allocation of temporary object and look + // directly into prototype where requested property is located. + if (is_string() && property_key != vm.names.length) + return vm.current_realm()->intrinsics().string_prototype(); + if (is_boolean()) + return vm.current_realm()->intrinsics().boolean_prototype(); + if (is_number()) + return vm.current_realm()->intrinsics().number_prototype(); + if (is_bigint()) + return vm.current_realm()->intrinsics().bigint_prototype(); + if (is_symbol()) + return vm.current_realm()->intrinsics().symbol_prototype(); + return to_object(vm); + }()); // 2. Return ? O.[[Get]](P, V). return TRY(object->internal_get(property_key, *this));