diff options
author | Luke <luke.wilde@live.co.uk> | 2020-12-28 01:22:38 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-28 13:10:07 +0100 |
commit | be30dc2b18621d8932a4122b22af692e1f9139f5 (patch) | |
tree | 3e23895d9caf80520fa1db013c22239e180dbb5c | |
parent | ee1d9217aa8dd25442ea4593836c998dfd7f49fb (diff) | |
download | serenity-be30dc2b18621d8932a4122b22af692e1f9139f5.zip |
LibJS: Implement Object.prototype.isPrototypeOf
Spec: https://tc39.es/ecma262/#sec-object.prototype.isprototypeof
4 files changed, 40 insertions, 0 deletions
diff --git a/Libraries/LibJS/Runtime/CommonPropertyNames.h b/Libraries/LibJS/Runtime/CommonPropertyNames.h index 3e92dce93c..f6d96fa552 100644 --- a/Libraries/LibJS/Runtime/CommonPropertyNames.h +++ b/Libraries/LibJS/Runtime/CommonPropertyNames.h @@ -149,6 +149,7 @@ namespace JS { P(isFinite) \ P(isInteger) \ P(isNaN) \ + P(isPrototypeOf) \ P(isSafeInteger) \ P(isView) \ P(join) \ diff --git a/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Libraries/LibJS/Runtime/ObjectPrototype.cpp index f5cd0604b1..b580769980 100644 --- a/Libraries/LibJS/Runtime/ObjectPrototype.cpp +++ b/Libraries/LibJS/Runtime/ObjectPrototype.cpp @@ -50,6 +50,7 @@ void ObjectPrototype::initialize(GlobalObject& global_object) 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); + define_native_function(vm.names.isPrototypeOf, is_prototype_of, 1, attr); } ObjectPrototype::~ObjectPrototype() @@ -138,4 +139,23 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::property_is_enumerable) return Value(property_descriptor.value().attributes.is_enumerable()); } +JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::is_prototype_of) +{ + auto object_argument = vm.argument(0); + if (!object_argument.is_object()) + return Value(false); + auto* object = &object_argument.as_object(); + auto* this_object = vm.this_value(global_object).to_object(global_object); + if (!this_object) + return {}; + + for (;;) { + object = object->prototype(); + if (!object) + return Value(false); + if (same_value(this_object, object)) + return Value(true); + } +} + } diff --git a/Libraries/LibJS/Runtime/ObjectPrototype.h b/Libraries/LibJS/Runtime/ObjectPrototype.h index 325c6c9c79..a68857e8ae 100644 --- a/Libraries/LibJS/Runtime/ObjectPrototype.h +++ b/Libraries/LibJS/Runtime/ObjectPrototype.h @@ -46,6 +46,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(to_locale_string); JS_DECLARE_NATIVE_FUNCTION(value_of); JS_DECLARE_NATIVE_FUNCTION(property_is_enumerable); + JS_DECLARE_NATIVE_FUNCTION(is_prototype_of); }; } diff --git a/Libraries/LibJS/Tests/builtins/Object/Object.prototype.isPrototypeOf.js b/Libraries/LibJS/Tests/builtins/Object/Object.prototype.isPrototypeOf.js new file mode 100644 index 0000000000..f3f82174d2 --- /dev/null +++ b/Libraries/LibJS/Tests/builtins/Object/Object.prototype.isPrototypeOf.js @@ -0,0 +1,18 @@ +test("basic functionality", () => { + function A() {} + function B() {} + + A.prototype = new B(); + const C = new A(); + + expect(A.prototype.isPrototypeOf(C)).toBeTrue(); + expect(B.prototype.isPrototypeOf(C)).toBeTrue(); + + expect(A.isPrototypeOf(C)).toBeFalse(); + expect(B.isPrototypeOf(C)).toBeFalse(); + + const D = new Object(); + expect(Object.prototype.isPrototypeOf(D)).toBeTrue(); + expect(Function.prototype.isPrototypeOf(D.toString)).toBeTrue(); + expect(Array.prototype.isPrototypeOf([])).toBeTrue(); +}); |