From 200c7572b7986f23e68f42bfe44caed34e4c008a Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 24 Dec 2020 17:51:28 +0000 Subject: [PATCH] LibJS: Implement Object.prototype.propertyIsEnumerable Spec: https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable This is used by core-js, which is used by frameworks such as Vue. --- Libraries/LibJS/Runtime/CommonPropertyNames.h | 1 + Libraries/LibJS/Runtime/ObjectPrototype.cpp | 15 +++++++++++++++ Libraries/LibJS/Runtime/ObjectPrototype.h | 1 + .../Object.prototype.propertyIsEnumerable.js | 15 +++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 Libraries/LibJS/Tests/builtins/Object/Object.prototype.propertyIsEnumerable.js diff --git a/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Libraries/LibJS/Runtime/CommonPropertyNames.h index 6037687e40..aa3d1b8ea6 100644 --- a/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -176,6 +176,7 @@ namespace JS { P(pop) \ P(pow) \ P(preventExtensions) \ + P(propertyIsEnumerable) \ P(prototype) \ P(push) \ P(random) \ diff --git a/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Libraries/LibJS/Runtime/ObjectPrototype.cpp index 2f620fa457..f5cd0604b1 100644 --- a/Libraries/LibJS/Runtime/ObjectPrototype.cpp +++ b/Libraries/LibJS/Runtime/ObjectPrototype.cpp @@ -49,6 +49,7 @@ void ObjectPrototype::initialize(GlobalObject& global_object) 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_native_function(vm.names.propertyIsEnumerable, property_is_enumerable, 1, attr); } ObjectPrototype::~ObjectPrototype() @@ -123,4 +124,18 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::value_of) return this_object->value_of(); } +JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::property_is_enumerable) +{ + auto name = vm.argument(0).to_string(global_object); + if (vm.exception()) + return {}; + auto* this_object = vm.this_value(global_object).to_object(global_object); + if (!this_object) + return {}; + auto property_descriptor = this_object->get_own_property_descriptor(name); + if (!property_descriptor.has_value()) + return Value(false); + return Value(property_descriptor.value().attributes.is_enumerable()); +} + } diff --git a/Libraries/LibJS/Runtime/ObjectPrototype.h b/Libraries/LibJS/Runtime/ObjectPrototype.h index f16a133774..325c6c9c79 100644 --- a/Libraries/LibJS/Runtime/ObjectPrototype.h +++ b/Libraries/LibJS/Runtime/ObjectPrototype.h @@ -45,6 +45,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(has_own_property); JS_DECLARE_NATIVE_FUNCTION(to_locale_string); JS_DECLARE_NATIVE_FUNCTION(value_of); + JS_DECLARE_NATIVE_FUNCTION(property_is_enumerable); }; } diff --git a/Libraries/LibJS/Tests/builtins/Object/Object.prototype.propertyIsEnumerable.js b/Libraries/LibJS/Tests/builtins/Object/Object.prototype.propertyIsEnumerable.js new file mode 100644 index 0000000000..01f55cd749 --- /dev/null +++ b/Libraries/LibJS/Tests/builtins/Object/Object.prototype.propertyIsEnumerable.js @@ -0,0 +1,15 @@ +test("basic functionality", () => { + var o = {}; + + o.foo = 1; + expect(o.propertyIsEnumerable("foo")).toBeTrue(); + expect(o.propertyIsEnumerable("bar")).toBeFalse(); + expect(o.propertyIsEnumerable()).toBeFalse(); + expect(o.propertyIsEnumerable(undefined)).toBeFalse(); + + o.undefined = 2; + expect(o.propertyIsEnumerable()).toBeTrue(); + expect(o.propertyIsEnumerable(undefined)).toBeTrue(); + + expect(globalThis.propertyIsEnumerable("globalThis")).toBeFalse(); +});