diff options
author | Linus Groh <mail@linusgroh.de> | 2021-07-04 23:48:47 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-07-05 00:53:57 +0100 |
commit | cb20baebaef4aeb53e3914dafa5699f365f14925 (patch) | |
tree | bf968dea7483576b9629e70d17ad57730a0120a6 /Userland | |
parent | fac8f9a94d98baa435cc6ad4ee6fe9bab93ae87f (diff) | |
download | serenity-cb20baebaef4aeb53e3914dafa5699f365f14925.zip |
LibJS: Make ObjectPrototype an immutable prototype exotic object
To make this happen, this patch implements the SetImmutablePrototype
abstract operation (as a method on Object) and then overrides
[[SetPrototypeOf]] on ObjectPrototype.
Diffstat (limited to 'Userland')
5 files changed, 41 insertions, 0 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Object.cpp b/Userland/Libraries/LibJS/Runtime/Object.cpp index fcd6c9c35b..6850e7198a 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.cpp +++ b/Userland/Libraries/LibJS/Runtime/Object.cpp @@ -870,6 +870,26 @@ MarkedValueList Object::internal_own_property_keys() const return keys; } +// 10.4.7.2 SetImmutablePrototype ( O, V ), https://tc39.es/ecma262/#sec-set-immutable-prototype +bool Object::set_immutable_prototype(Object* prototype) +{ + auto& vm = this->vm(); + + // 1. Assert: Either Type(V) is Object or Type(V) is Null. + + // 2. Let current be ? O.[[GetPrototypeOf]](). + auto* current = internal_get_prototype_of(); + if (vm.exception()) + return {}; + + // 3. If SameValue(V, current) is true, return true. + if (prototype == current) + return true; + + // 4. Return false. + return false; +} + Optional<ValueAndAttributes> Object::storage_get(PropertyName const& property_name, CallNativeProperty call_native_property) const { VERIFY(property_name.is_valid()); diff --git a/Userland/Libraries/LibJS/Runtime/Object.h b/Userland/Libraries/LibJS/Runtime/Object.h index 6659a886f1..29bfdc7800 100644 --- a/Userland/Libraries/LibJS/Runtime/Object.h +++ b/Userland/Libraries/LibJS/Runtime/Object.h @@ -100,6 +100,10 @@ public: virtual bool internal_delete(PropertyName const&); virtual MarkedValueList internal_own_property_keys() const; + // 10.4.7 Immutable Prototype Exotic Objects, https://tc39.es/ecma262/#sec-immutable-prototype-exotic-objects + + bool set_immutable_prototype(Object* prototype); + // 20.1 Object Objects, https://tc39.es/ecma262/#sec-object-objects Object* define_properties(Value properties); diff --git a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp index 367ed5d815..21b1a2747f 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.cpp @@ -50,6 +50,12 @@ ObjectPrototype::~ObjectPrototype() { } +// 10.4.7.1 [[SetPrototypeOf]] ( V ), https://tc39.es/ecma262/#sec-immutable-prototype-exotic-objects-setprototypeof-v +bool ObjectPrototype::internal_set_prototype_of(Object* prototype) +{ + return set_immutable_prototype(prototype); +} + // 20.1.3.2 Object.prototype.hasOwnProperty ( V ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::has_own_property) { diff --git a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.h b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.h index 36dd061705..969ea442dd 100644 --- a/Userland/Libraries/LibJS/Runtime/ObjectPrototype.h +++ b/Userland/Libraries/LibJS/Runtime/ObjectPrototype.h @@ -18,6 +18,10 @@ public: virtual void initialize(GlobalObject&) override; virtual ~ObjectPrototype() override; + // 10.4.7 Immutable Prototype Exotic Objects, https://tc39.es/ecma262/#sec-immutable-prototype-exotic-objects + + virtual bool internal_set_prototype_of(Object* prototype) override; + // public to serve as intrinsic function %Object.prototype.toString% JS_DECLARE_NATIVE_FUNCTION(to_string); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.prototype.js b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.prototype.js index eab7093b3b..7f06f7eb13 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Object/Object.prototype.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Object/Object.prototype.js @@ -3,3 +3,10 @@ test("basic functionality", () => { Object.prototype.foo = 123; expect(o.foo).toBe(123); }); + +test("is an immutable prototype exotic object", () => { + const p = Object.create(null); + expect(() => { + Object.setPrototypeOf(Object.prototype, p); + }).toThrowWithMessage(TypeError, "Object's [[SetPrototypeOf]] method returned false"); +}); |