ES6: Remove __proto__ setter poison pill
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 Feb 2014 16:09:45 +0000 (16:09 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 6 Feb 2014 16:09:45 +0000 (16:09 +0000)
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 <arv@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19165 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/messages.js
src/v8natives.js
test/mjsunit/proto-accessor.js [moved from test/mjsunit/proto-poison.js with 60% similarity]

index 08cb723..e9f1ae4 100644 (file)
@@ -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"],
index c1955cf..24b0c51 100644 (file)
@@ -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);
similarity index 60%
rename from test/mjsunit/proto-poison.js
rename to test/mjsunit/proto-accessor.js
index ca3b5d6..aca6ec5 100644 (file)
 // (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);