Fix hidden properties on object with frozen prototype.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 22 Aug 2013 13:51:32 +0000 (13:51 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 22 Aug 2013 13:51:32 +0000 (13:51 +0000)
This fixes a corner-case where a frozen prototype with existing hidden
properties might prevent setting hidden properties on another object.

R=rossberg@chromium.org
BUG=v8:2829

Review URL: https://codereview.chromium.org/22799021

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

src/objects.cc
src/objects.h
test/mjsunit/regress/regress-2829.js [new file with mode: 0644]

index 567a16d..686165e 100644 (file)
@@ -2163,7 +2163,6 @@ MaybeObject* JSObject::SetPropertyPostInterceptor(
     Object* value,
     PropertyAttributes attributes,
     StrictModeFlag strict_mode,
-    ExtensibilityCheck extensibility_check,
     StoreMode mode) {
   // Check local property, ignore interceptor.
   LookupResult result(GetIsolate());
@@ -2175,13 +2174,12 @@ MaybeObject* JSObject::SetPropertyPostInterceptor(
     return SetProperty(&result, name, value, attributes, strict_mode);
   }
   bool done = false;
-  MaybeObject* result_object;
-  result_object =
+  MaybeObject* result_object =
       SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
   if (done) return result_object;
   // Add a new real property.
   return AddProperty(name, value, attributes, strict_mode,
-                     MAY_BE_STORE_FROM_KEYED, extensibility_check,
+                     MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK,
                      OPTIMAL_REPRESENTATION, mode);
 }
 
@@ -2824,8 +2822,7 @@ MaybeObject* JSObject::SetPropertyWithInterceptor(
       this_handle->SetPropertyPostInterceptor(*name_handle,
                                               *value_handle,
                                               attributes,
-                                              strict_mode,
-                                              PERFORM_EXTENSIBILITY_CHECK);
+                                              strict_mode);
   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   return raw_result;
 }
@@ -4030,7 +4027,8 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
     Object* value_raw,
     PropertyAttributes attributes,
     ValueType value_type,
-    StoreMode mode) {
+    StoreMode mode,
+    ExtensibilityCheck extensibility_check) {
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -4058,7 +4056,8 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
         value_raw,
         attributes,
         value_type,
-        mode);
+        mode,
+        extensibility_check);
   }
 
   // Check for accessor in prototype chain removed here in clone.
@@ -4066,7 +4065,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
     // Neither properties nor transitions found.
     return AddProperty(
         name_raw, value_raw, attributes, kNonStrictMode,
-        MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type, mode);
+        MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode);
   }
 
   // From this point on everything needs to be handlified.
@@ -4923,12 +4922,12 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
   }
 
   MaybeObject* store_result =
-      SetPropertyPostInterceptor(GetHeap()->hidden_string(),
-                                 hashtable,
-                                 DONT_ENUM,
-                                 kNonStrictMode,
-                                 OMIT_EXTENSIBILITY_CHECK,
-                                 FORCE_FIELD);
+      SetLocalPropertyIgnoreAttributes(GetHeap()->hidden_string(),
+                                       hashtable,
+                                       DONT_ENUM,
+                                       OPTIMAL_REPRESENTATION,
+                                       ALLOW_AS_CONSTANT,
+                                       OMIT_EXTENSIBILITY_CHECK);
   if (store_result->IsFailure()) return store_result;
   return hashtable;
 }
@@ -4956,12 +4955,12 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
     }
   }
   MaybeObject* store_result =
-      SetPropertyPostInterceptor(GetHeap()->hidden_string(),
-                                 value,
-                                 DONT_ENUM,
-                                 kNonStrictMode,
-                                 OMIT_EXTENSIBILITY_CHECK,
-                                 FORCE_FIELD);
+      SetLocalPropertyIgnoreAttributes(GetHeap()->hidden_string(),
+                                       value,
+                                       DONT_ENUM,
+                                       OPTIMAL_REPRESENTATION,
+                                       ALLOW_AS_CONSTANT,
+                                       OMIT_EXTENSIBILITY_CHECK);
   if (store_result->IsFailure()) return store_result;
   return this;
 }
@@ -15307,6 +15306,7 @@ MaybeObject* ObjectHashSet::Add(Object* key) {
   int hash;
   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
     if (maybe_hash->IsFailure()) return maybe_hash;
+    ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash);
     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
   }
   int entry = FindEntry(key);
@@ -15368,6 +15368,7 @@ MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
   int hash;
   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
     if (maybe_hash->IsFailure()) return maybe_hash;
+    ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash);
     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
   }
   int entry = FindEntry(key);
index 8597d45..5e395b9 100644 (file)
@@ -2159,7 +2159,6 @@ class JSObject: public JSReceiver {
       Object* value,
       PropertyAttributes attributes,
       StrictModeFlag strict_mode,
-      ExtensibilityCheck extensibility_check,
       StoreMode mode = ALLOW_AS_CONSTANT);
 
   static Handle<Object> SetLocalPropertyIgnoreAttributes(
@@ -2197,7 +2196,8 @@ class JSObject: public JSReceiver {
       Object* value,
       PropertyAttributes attributes,
       ValueType value_type = OPTIMAL_REPRESENTATION,
-      StoreMode mode = ALLOW_AS_CONSTANT);
+      StoreMode mode = ALLOW_AS_CONSTANT,
+      ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK);
 
   // Retrieve a value in a normalized object given a lookup result.
   // Handles the special representation of JS global objects.
diff --git a/test/mjsunit/regress/regress-2829.js b/test/mjsunit/regress/regress-2829.js
new file mode 100644 (file)
index 0000000..a046ae0
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-collections
+
+(function test1() {
+  var wm1 = new WeakMap();
+  wm1.set(Object.prototype, 23);
+  assertTrue(wm1.has(Object.prototype));
+  Object.freeze(Object.prototype);
+
+  var wm2 = new WeakMap();
+  var o = {};
+  wm2.set(o, 42);
+  assertEquals(42, wm2.get(o));
+})();
+
+(function test2() {
+  var wm1 = new WeakMap();
+  var o1 = {};
+  wm1.set(o1, 23);
+  assertTrue(wm1.has(o1));
+  Object.freeze(o1);
+
+  var wm2 = new WeakMap();
+  var o2 = Object.create(o1);
+  wm2.set(o2, 42);
+  assertEquals(42, wm2.get(o2));
+})();