From 7624bdbe590e7e9179d0cf5776f3955b62f26420 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Thu, 29 Dec 2011 05:44:10 -0600 Subject: [PATCH] Bug 713944 - Assert that a data descriptor referenced in the property cache was writable only if the property cache entry was a hit. If it wasn't, the descriptor might have been made writable in the interim -- and if the cache entry was for finding the property along the prototype chain, the shape key used for the entry lookup would be invariant across the data descriptor's mutation. This also fixes bug 643847. r=jorendorff --- js/src/jsinterp.cpp | 8 ++-- js/src/tests/ecma_5/Object/jstests.list | 1 + .../proto-property-change-writability-set.js | 44 +++++++++++++++++++ 3 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 js/src/tests/ecma_5/Object/proto-property-change-writability-set.js diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 61bd303acaca..882ec1c9ace1 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -3161,11 +3161,13 @@ BEGIN_CASE(JSOP_SETMETHOD) * on a prototype property that has a setter. */ const Shape *shape = entry->prop; - JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable()); - JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit()); if (entry->isOwnPropertyHit() || - ((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) { + ((obj2 = obj->getProto()) && obj2->lastProperty() == entry->pshape)) + { + JS_ASSERT_IF(shape->isDataDescriptor(), shape->writable()); + JS_ASSERT_IF(shape->hasSlot(), entry->isOwnPropertyHit()); + #ifdef DEBUG if (entry->isOwnPropertyHit()) { JS_ASSERT(obj->nativeContains(cx, *shape)); diff --git a/js/src/tests/ecma_5/Object/jstests.list b/js/src/tests/ecma_5/Object/jstests.list index 320b23ce59b5..3bad7957e167 100644 --- a/js/src/tests/ecma_5/Object/jstests.list +++ b/js/src/tests/ecma_5/Object/jstests.list @@ -38,6 +38,7 @@ skip-if(!xulRuntime.shell) script 15.2.3.6-dictionary-redefinition-8-of-8.js # u script 15.2.3.6-define-over-method.js script mutation-prevention-methods.js script object-toString-01.js +script proto-property-change-writability-set.js script vacuous-accessor-unqualified-name.js script add-property-non-extensible.js skip-if(!xulRuntime.shell) script freeze-global-eval-const.js # uses evalcx diff --git a/js/src/tests/ecma_5/Object/proto-property-change-writability-set.js b/js/src/tests/ecma_5/Object/proto-property-change-writability-set.js new file mode 100644 index 000000000000..f9b0eebd48e6 --- /dev/null +++ b/js/src/tests/ecma_5/Object/proto-property-change-writability-set.js @@ -0,0 +1,44 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributors: + * Gary Kwong + * Jeff Walden + * Jason Orendorff + */ + +var accDesc = { set: function() {} }; +var dataDesc = { value: 3 }; + +function f() +{ + constructor = {}; +} +function g() +{ + constructor = {}; +} + +Object.defineProperty(Object.prototype, "constructor", accDesc); +f(); +Object.defineProperty(Object.prototype, "constructor", dataDesc); +assertEq(constructor, 3); +f(); +assertEq(constructor, 3); +g(); +assertEq(constructor, 3); + + + +var a = { p1: 1, p2: 2 }; +var b = Object.create(a); +Object.defineProperty(a, "p1", {set: function () {}}); +for (var i = 0; i < 2; i++) +{ + b.p1 = {}; + Object.defineProperty(a, "p1", {value: 3}); +} +assertEq(b.p1, 3); +assertEq(a.p1, 3); + +reportCompare(true, true);