From 01f5601129c517ffa76eb3bfa5f7bd73778cb8c8 Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Thu, 6 Feb 2014 16:09:45 +0000 Subject: [PATCH] ES6: Remove __proto__ setter poison pill http://people.mozilla.org/~jorendorff/es6-draft.html#sec-set-object.prototype.__proto__ The __proto__ setter should be reusable on other objects. BUG=v8:2804 LOG=y R=rossberg@chromium.org Review URL: https://codereview.chromium.org/103343005 Patch from Erik Arvidsson . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19165 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/messages.js | 1 - src/v8natives.js | 11 +--- .../mjsunit/{proto-poison.js => proto-accessor.js} | 60 +++++++++++++++++----- 3 files changed, 49 insertions(+), 23 deletions(-) rename test/mjsunit/{proto-poison.js => proto-accessor.js} (60%) diff --git a/src/messages.js b/src/messages.js index 08cb723..e9f1ae4 100644 --- a/src/messages.js +++ b/src/messages.js @@ -104,7 +104,6 @@ var kMessages = { observe_perform_non_string: ["Invalid non-string changeType"], observe_perform_non_function: ["Cannot perform non-function"], observe_notify_non_notifier: ["notify called on non-notifier object"], - proto_poison_pill: ["Generic use of __proto__ accessor not allowed"], not_typed_array: ["this is not a typed array."], invalid_argument: ["invalid_argument"], data_view_not_array_buffer: ["First argument to DataView constructor must be an ArrayBuffer"], diff --git a/src/v8natives.js b/src/v8natives.js index c1955cf..24b0c51 100644 --- a/src/v8natives.js +++ b/src/v8natives.js @@ -397,8 +397,7 @@ function FromPropertyDescriptor(desc) { } // Must be an AccessorDescriptor then. We never return a generic descriptor. return { get: desc.getGet(), - set: desc.getSet() === ObjectSetProto ? ObjectPoisonProto - : desc.getSet(), + set: desc.getSet(), enumerable: desc.isEnumerable(), configurable: desc.isConfigurable() }; } @@ -1397,12 +1396,6 @@ function ObjectSetProto(obj) { } -// Harmony __proto__ poison pill. -function ObjectPoisonProto(obj) { - throw MakeTypeError("proto_poison_pill", []); -} - - function ObjectConstructor(x) { if (%_IsConstructCall()) { if (x == null) return this; @@ -1422,8 +1415,6 @@ function SetUpObject() { %SetNativeFlag($Object); %SetCode($Object, ObjectConstructor); - %FunctionSetName(ObjectPoisonProto, "__proto__"); - %FunctionRemovePrototype(ObjectPoisonProto); %SetExpectedNumberOfProperties($Object, 4); %SetProperty($Object.prototype, "constructor", $Object, DONT_ENUM); diff --git a/test/mjsunit/proto-poison.js b/test/mjsunit/proto-accessor.js similarity index 60% rename from test/mjsunit/proto-poison.js rename to test/mjsunit/proto-accessor.js index ca3b5d6..aca6ec5 100644 --- a/test/mjsunit/proto-poison.js +++ b/test/mjsunit/proto-accessor.js @@ -25,21 +25,57 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Check that the __proto__ accessor is properly poisoned when extracted -// from Object.prototype using the property descriptor. var desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); assertEquals("function", typeof desc.get); assertEquals("function", typeof desc.set); assertDoesNotThrow("desc.get.call({})"); -assertThrows("desc.set.call({})", TypeError); +assertDoesNotThrow("desc.set.call({}, {})"); + + +var obj = {}; +var obj2 = {}; +desc.set.call(obj, obj2); +assertEquals(obj.__proto__, obj2); +assertEquals(desc.get.call(obj), obj2); + + +// Check that any redefinition of the __proto__ accessor works. +Object.defineProperty(Object.prototype, "__proto__", { + get: function() { + return 42; + } +}); +assertEquals({}.__proto__, 42); +assertEquals(desc.get.call({}), Object.prototype); + + +var desc2 = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); +assertEquals(desc2.get.call({}), 42); +assertDoesNotThrow("desc2.set.call({})"); + -// Check that any redefinition of the __proto__ accessor causes poising -// to cease and the accessor to be extracted normally. -Object.defineProperty(Object.prototype, "__proto__", { get:function(){} }); -desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); -assertDoesNotThrow("desc.get.call({})"); -assertThrows("desc.set.call({})", TypeError); Object.defineProperty(Object.prototype, "__proto__", { set:function(x){} }); -desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); -assertDoesNotThrow("desc.get.call({})"); -assertDoesNotThrow("desc.set.call({})"); +var desc3 = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__"); +assertDoesNotThrow("desc3.get.call({})"); +assertDoesNotThrow("desc3.set.call({})"); + + +Object.defineProperty(Object.prototype, "__proto__", { set: undefined }); +assertThrows(function() { + "use strict"; + var o = {}; + var p = {}; + o.__proto__ = p; +}, TypeError); + + +assertTrue(delete Object.prototype.__proto__); +var o = {}; +var p = {}; +o.__proto__ = p; +assertEquals(Object.getPrototypeOf(o), Object.prototype); +var desc4 = Object.getOwnPropertyDescriptor(o, "__proto__"); +assertTrue(desc4.configurable); +assertTrue(desc4.enumerable); +assertTrue(desc4.writable); +assertEquals(desc4.value, p); -- 2.7.4