diff --git a/Libraries/LibJS/Runtime/Object.cpp b/Libraries/LibJS/Runtime/Object.cpp index e028047a7f..e62c68cfaa 100644 --- a/Libraries/LibJS/Runtime/Object.cpp +++ b/Libraries/LibJS/Runtime/Object.cpp @@ -69,15 +69,18 @@ const Object* Object::prototype() const return shape().prototype(); } -void Object::set_prototype(Object* new_prototype) +bool Object::set_prototype(Object* new_prototype) { if (prototype() == new_prototype) - return; + return true; + if (!m_is_extensible) + return false; if (shape().is_unique()) { shape().set_prototype_without_transition(new_prototype); - return; + return true; } m_shape = m_shape->create_prototype_transition(new_prototype); + return true; } bool Object::has_prototype(const Object* prototype) const diff --git a/Libraries/LibJS/Runtime/Object.h b/Libraries/LibJS/Runtime/Object.h index 0500eb0a26..3263b225ad 100644 --- a/Libraries/LibJS/Runtime/Object.h +++ b/Libraries/LibJS/Runtime/Object.h @@ -95,7 +95,7 @@ public: Object* prototype(); const Object* prototype() const; - void set_prototype(Object*); + bool set_prototype(Object* prototype); bool has_prototype(const Object* prototype) const; bool is_extensible() const { return m_is_extensible; } diff --git a/Libraries/LibJS/Runtime/ObjectConstructor.cpp b/Libraries/LibJS/Runtime/ObjectConstructor.cpp index 23b247d6b7..a4882889b4 100644 --- a/Libraries/LibJS/Runtime/ObjectConstructor.cpp +++ b/Libraries/LibJS/Runtime/ObjectConstructor.cpp @@ -112,7 +112,10 @@ Value ObjectConstructor::set_prototype_of(Interpreter& interpreter) interpreter.throw_exception("Prototype must be null or object"); return {}; } - object->set_prototype(prototype); + if (!object->set_prototype(prototype)) { + interpreter.throw_exception("Can't set prototype of non-extensible object"); + return {}; + } return object; } diff --git a/Libraries/LibJS/Tests/Object.setPrototypeOf.js b/Libraries/LibJS/Tests/Object.setPrototypeOf.js index ddc404263b..09039275ee 100644 --- a/Libraries/LibJS/Tests/Object.setPrototypeOf.js +++ b/Libraries/LibJS/Tests/Object.setPrototypeOf.js @@ -11,7 +11,17 @@ try { }); o = {}; - assert(Object.setPrototypeOf(o, {}) === o); + p = {}; + assert(Object.setPrototypeOf(o, p) === o); + + Object.preventExtensions(o); + assertThrowsError(() => { + Object.setPrototypeOf(o, {}); + }, { + error: TypeError, + message: "Can't set prototype of non-extensible object" + }); + assert(Object.setPrototypeOf(o, p) === o); console.log("PASS"); } catch (e) {