Don't re-use cached iterators that have suppressed deleted properties (bug 633409, r=gal).

This commit is contained in:
David Anderson 2011-02-11 14:21:14 -08:00
Родитель 6a8a09e0cc
Коммит 40116825f5
5 изменённых файлов: 38 добавлений и 7 удалений

Просмотреть файл

@ -0,0 +1,13 @@
// vim: set ts=4 sw=4 tw=99 et:
x = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 };
for (i in x)
delete x.d;
x = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 };
y = [];
for (i in x)
y.push(i)
assertEq(y[3], "d");

Просмотреть файл

@ -0,0 +1,13 @@
// vim: set ts=4 sw=4 tw=99 et:
var o1 = {p1: 1};
var o2 = {p1: 1, p2: 2};
for(var x in o1) {
for(var y in o2) {
delete o2.p2;
}
}
/* Don't fail cx->enumerators == obj assert, see bug comment #31 */

Просмотреть файл

@ -590,7 +590,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
JSObject *proto = obj->getProto();
if (last) {
NativeIterator *lastni = last->getNativeIterator();
if (!(lastni->flags & JSITER_ACTIVE) &&
if (!(lastni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
obj->isNative() &&
obj->shape() == lastni->shapes_array[0] &&
proto && proto->isNative() &&
@ -627,7 +627,7 @@ GetIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
JSObject *iterobj = cx->compartment->nativeIterCache.get(key);
if (iterobj) {
NativeIterator *ni = iterobj->getNativeIterator();
if (!(ni->flags & JSITER_ACTIVE) &&
if (!(ni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
ni->shapes_key == key &&
ni->shapes_length == shapes.length() &&
Compare(ni->shapes_array, shapes.begin(), ni->shapes_length)) {
@ -882,6 +882,10 @@ SuppressDeletedPropertyHelper(JSContext *cx, JSObject *obj, IdPredicate predicat
memmove(idp, idp + 1, (props_end - (idp + 1)) * sizeof(jsid));
ni->props_end = ni->end() - 1;
}
/* Don't reuse modified native iterators. */
ni->flags |= JSITER_UNREUSABLE;
if (predicate.matchesAtMostOne())
break;
}

Просмотреть файл

@ -63,7 +63,8 @@
* For cacheable native iterators, whether the iterator is currently active.
* Not serialized by XDR.
*/
#define JSITER_ACTIVE 0x1000
#define JSITER_ACTIVE 0x1000
#define JSITER_UNREUSABLE 0x2000
namespace js {

Просмотреть файл

@ -4032,7 +4032,8 @@ mjit::Compiler::iter(uintN flags)
/* Test for active iterator. */
Address flagsAddr(nireg, offsetof(NativeIterator, flags));
masm.load32(flagsAddr, T1);
Jump activeIterator = masm.branchTest32(Assembler::NonZero, T1, Imm32(JSITER_ACTIVE));
Jump activeIterator = masm.branchTest32(Assembler::NonZero, T1,
Imm32(JSITER_ACTIVE|JSITER_UNREUSABLE));
stubcc.linkExit(activeIterator, Uses(1));
/* Compare shape of object with iterator. */
@ -4224,9 +4225,8 @@ mjit::Compiler::iterEnd()
Address flagAddr(T1, offsetof(NativeIterator, flags));
masm.loadPtr(flagAddr, T2);
/* Test for (flags == ENUMERATE | ACTIVE). */
Jump notEnumerate = masm.branch32(Assembler::NotEqual, T2,
Imm32(JSITER_ENUMERATE | JSITER_ACTIVE));
/* Test for a normal enumerate iterator. */
Jump notEnumerate = masm.branchTest32(Assembler::Zero, T2, Imm32(JSITER_ENUMERATE));
stubcc.linkExit(notEnumerate, Uses(1));
/* Clear active bit. */