diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index bfa4fc3a5ac..18a33fda580 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -86,7 +86,7 @@ js_GenerateShape(JSContext *cx, bool gcLocked) */ rt->shapeGen = SHAPE_OVERFLOW_BIT; shape = SHAPE_OVERFLOW_BIT; - + #ifdef JS_THREADSAFE Conditionally lockIf(!gcLocked, rt); #endif @@ -851,8 +851,10 @@ JSObject::putProperty(JSContext *cx, jsid id, * care which slot, copy shape->slot into slot so we can match shape, * if all other members match. */ - if (!(attrs & JSPROP_SHARED) && slot == SHAPE_INVALID_SLOT && containsSlot(shape->slot)) - slot = shape->slot; + bool hadSlot = !shape->isAlias() && containsSlot(shape->slot); + uint32 oldSlot = shape->slot; + if (!(attrs & JSPROP_SHARED) && slot == SHAPE_INVALID_SLOT && hadSlot) + slot = oldSlot; if (shape->matchesParamsAfterId(getter, setter, slot, attrs, flags, shortid)) { METER(redundantPuts); return shape; @@ -929,6 +931,17 @@ JSObject::putProperty(JSContext *cx, jsid id, lastProp->maybeHash(cx); } + /* + * Can't fail now, so free the previous incarnation's slot if the new + * shape has no slot. But we do not need to free oldSlot (and must not, + * as trying to will botch an assertion in JSObject::freeSlot) if the + * new lastProp (shape here) has a slotSpan that does not cover it. + */ + if (hadSlot && !shape->hasSlot() && oldSlot < shape->slotSpan) { + freeSlot(cx, oldSlot); + JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals); + } + CHECK_SHAPE_CONSISTENCY(this); METER(puts); return shape; diff --git a/js/src/tests/js1_8_5/regress/jstests.list b/js/src/tests/js1_8_5/regress/jstests.list index 44ad09d1158..a24259fccba 100644 --- a/js/src/tests/js1_8_5/regress/jstests.list +++ b/js/src/tests/js1_8_5/regress/jstests.list @@ -40,3 +40,5 @@ fails-if(!xulRuntime.shell) script regress-595365-2.js script regress-569464.js script regress-596103.js script regress-597870.js +script regress-597945-1.js +script regress-597945-2.js diff --git a/js/src/tests/js1_8_5/regress/regress-597945-1.js b/js/src/tests/js1_8_5/regress/regress-597945-1.js new file mode 100644 index 00000000000..db632a4ce09 --- /dev/null +++ b/js/src/tests/js1_8_5/regress/regress-597945-1.js @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function b(foo) { + delete foo.d + delete foo.w + foo.d = true + foo.w = Object + delete Object.defineProperty(foo, "d", ({ + set: Math.w + })); {} +} +for each(e in [arguments, arguments]) { + try { + b(e)('') + } catch (e) {} +} + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/js1_8_5/regress/regress-597945-2.js b/js/src/tests/js1_8_5/regress/regress-597945-2.js new file mode 100644 index 00000000000..99f4f816a3b --- /dev/null +++ b/js/src/tests/js1_8_5/regress/regress-597945-2.js @@ -0,0 +1,13 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var a = {d: true, w: true}; +Object.defineProperty(a, "d", {set: undefined}); +delete a.d; +delete a.w; +a.d = true; + +reportCompare(0, 0, "ok");