summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-05-18 11:15:49 +0200
committerAndreas Kling <kling@serenityos.org>2021-05-18 11:18:19 +0200
commit3ee092cd0cacb999469e50aa5ff220e397df2d79 (patch)
treeeccd068c825e6be502ebe2f8dacde40b9e7298ed /Userland/Libraries
parent94569e52f561eaa7fe4cb9f570792e063eb6922a (diff)
downloadserenity-3ee092cd0cacb999469e50aa5ff220e397df2d79.zip
LibJS: Implement Object.hasOwn() :^)
This is currently a TC39 Stage 2 proposal, but let's go for it! https://github.com/tc39/proposal-accessible-object-hasownproperty I wrote the C++, @linusg found bugs and wrote the test.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h1
-rw-r--r--Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp12
-rw-r--r--Userland/Libraries/LibJS/Runtime/ObjectConstructor.h1
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Object/Object.hasOwn.js35
4 files changed, 49 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
index fbccb97cac..cf740626c2 100644
--- a/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
+++ b/Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h
@@ -135,6 +135,7 @@ namespace JS {
P(globalThis) \
P(groups) \
P(has) \
+ P(hasOwn) \
P(hasOwnProperty) \
P(hypot) \
P(ignoreCase) \
diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp
index 5c1caabfa2..fddded47f1 100644
--- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp
+++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.cpp
@@ -45,6 +45,7 @@ void ObjectConstructor::initialize(GlobalObject& global_object)
define_native_function(vm.names.values, values, 1, attr);
define_native_function(vm.names.entries, entries, 1, attr);
define_native_function(vm.names.create, create, 2, attr);
+ define_native_function(vm.names.hasOwn, has_own, 2, attr);
}
ObjectConstructor::~ObjectConstructor()
@@ -310,4 +311,15 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::create)
return object;
}
+JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::has_own)
+{
+ auto* object = vm.argument(0).to_object(global_object);
+ if (vm.exception())
+ return {};
+ auto string_or_symbol = StringOrSymbol::from_value(global_object, vm.argument(1));
+ if (vm.exception())
+ return {};
+ return Value(object->has_own_property(string_or_symbol));
+}
+
}
diff --git a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h
index 8a4e3361d6..b616a5ffb6 100644
--- a/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h
+++ b/Userland/Libraries/LibJS/Runtime/ObjectConstructor.h
@@ -42,6 +42,7 @@ private:
JS_DECLARE_NATIVE_FUNCTION(values);
JS_DECLARE_NATIVE_FUNCTION(entries);
JS_DECLARE_NATIVE_FUNCTION(create);
+ JS_DECLARE_NATIVE_FUNCTION(has_own);
};
}
diff --git a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.hasOwn.js b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.hasOwn.js
new file mode 100644
index 0000000000..1ea82a309a
--- /dev/null
+++ b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.hasOwn.js
@@ -0,0 +1,35 @@
+describe("basic functionality", () => {
+ test("length", () => {
+ expect(Object.hasOwn).toHaveLength(2);
+ });
+
+ test("returns true for existent own property", () => {
+ const o = { foo: "bar" };
+ expect(Object.hasOwn(o, "foo")).toBeTrue();
+ });
+
+ test("returns false for non-existent own property", () => {
+ const o = {};
+ expect(Object.hasOwn(o, "foo")).toBeFalse();
+ });
+
+ test("returns false for existent prototype chain property", () => {
+ const o = {};
+ Object.prototype.foo = "bar";
+ expect(Object.hasOwn(o, "foo")).toBeFalse();
+ });
+});
+
+describe("errors", () => {
+ test("null argument", () => {
+ expect(() => {
+ Object.hasOwn(null);
+ }).toThrowWithMessage(TypeError, "ToObject on null or undefined");
+ });
+
+ test("undefined argument", () => {
+ expect(() => {
+ Object.hasOwn(undefined);
+ }).toThrowWithMessage(TypeError, "ToObject on null or undefined");
+ });
+});