From 0ecd03ab4cd04062858ce5a2cf6eec6f685721e1 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Thu, 22 Aug 2013 13:51:32 +0000 Subject: [PATCH] Fix hidden properties on object with frozen prototype. 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 | 43 +++++++++++++++-------------- src/objects.h | 4 +-- test/mjsunit/regress/regress-2829.js | 53 ++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 test/mjsunit/regress/regress-2829.js diff --git a/src/objects.cc b/src/objects.cc index 567a16d..686165e 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -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); diff --git a/src/objects.h b/src/objects.h index 8597d45..5e395b9 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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 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 index 0000000..a046ae0 --- /dev/null +++ b/test/mjsunit/regress/regress-2829.js @@ -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)); +})(); -- 2.7.4