Remove LIFO invariants from the enumerator list (bug 831626, r=billm).
This commit is contained in:
@@ -434,13 +434,30 @@ NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVe
|
||||
ni->props_array[i].init(str);
|
||||
}
|
||||
}
|
||||
ni->next_ = NULL;
|
||||
ni->prev_ = NULL;
|
||||
return ni;
|
||||
}
|
||||
|
||||
NativeIterator *
|
||||
NativeIterator::allocateSentinel(JSContext *cx)
|
||||
{
|
||||
NativeIterator *ni = (NativeIterator *)js_malloc(sizeof(NativeIterator));
|
||||
if (!ni)
|
||||
return NULL;
|
||||
|
||||
PodZero(ni);
|
||||
|
||||
ni->next_ = ni;
|
||||
ni->prev_ = ni;
|
||||
return ni;
|
||||
}
|
||||
|
||||
inline void
|
||||
NativeIterator::init(RawObject obj, unsigned flags, uint32_t slength, uint32_t key)
|
||||
NativeIterator::init(RawObject obj, RawObject iterObj, unsigned flags, uint32_t slength, uint32_t key)
|
||||
{
|
||||
this->obj.init(obj);
|
||||
this->iterObj_ = iterObj;
|
||||
this->flags = flags;
|
||||
this->shapes_array = (Shape **) this->props_end;
|
||||
this->shapes_length = slength;
|
||||
@@ -452,8 +469,7 @@ RegisterEnumerator(JSContext *cx, PropertyIteratorObject *iterobj, NativeIterato
|
||||
{
|
||||
/* Register non-escaping native enumerators (for-in) with the current context. */
|
||||
if (ni->flags & JSITER_ENUMERATE) {
|
||||
ni->next = cx->enumerators;
|
||||
cx->enumerators = iterobj;
|
||||
ni->link(cx->compartment->enumerators);
|
||||
|
||||
JS_ASSERT(!(ni->flags & JSITER_ACTIVE));
|
||||
ni->flags |= JSITER_ACTIVE;
|
||||
@@ -479,7 +495,7 @@ VectorToKeyIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoIdVecto
|
||||
NativeIterator *ni = NativeIterator::allocateIterator(cx, slength, keys);
|
||||
if (!ni)
|
||||
return false;
|
||||
ni->init(obj, flags, slength, key);
|
||||
ni->init(obj, iterobj, flags, slength, key);
|
||||
|
||||
if (slength) {
|
||||
/*
|
||||
@@ -531,7 +547,7 @@ js::VectorToValueIterator(JSContext *cx, HandleObject obj, unsigned flags, AutoI
|
||||
NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, keys);
|
||||
if (!ni)
|
||||
return false;
|
||||
ni->init(obj, flags, 0, 0);
|
||||
ni->init(obj, iterobj, flags, 0, 0);
|
||||
|
||||
iterobj->setNativeIterator(ni);
|
||||
vp.setObject(*iterobj);
|
||||
@@ -1011,8 +1027,7 @@ js::CloseIterator(JSContext *cx, HandleObject obj)
|
||||
NativeIterator *ni = obj->asPropertyIterator().getNativeIterator();
|
||||
|
||||
if (ni->flags & JSITER_ENUMERATE) {
|
||||
JS_ASSERT(cx->enumerators == obj);
|
||||
cx->enumerators = ni->next;
|
||||
ni->unlink();
|
||||
|
||||
JS_ASSERT(ni->flags & JSITER_ACTIVE);
|
||||
ni->flags &= ~JSITER_ACTIVE;
|
||||
@@ -1048,10 +1063,8 @@ js::UnwindIteratorForUncatchableException(JSContext *cx, RawObject obj)
|
||||
{
|
||||
if (obj->isPropertyIterator()) {
|
||||
NativeIterator *ni = obj->asPropertyIterator().getNativeIterator();
|
||||
if (ni->flags & JSITER_ENUMERATE) {
|
||||
JS_ASSERT(cx->enumerators == obj);
|
||||
cx->enumerators = ni->next;
|
||||
}
|
||||
if (ni->flags & JSITER_ENUMERATE)
|
||||
ni->unlink();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1076,10 +1089,11 @@ template<typename StringPredicate>
|
||||
static bool
|
||||
SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate predicate)
|
||||
{
|
||||
RootedPropertyIteratorObject iterobj(cx, cx->enumerators);
|
||||
while (iterobj) {
|
||||
NativeIterator *enumeratorList = cx->compartment->enumerators;
|
||||
NativeIterator *ni = enumeratorList->next();
|
||||
|
||||
while (ni != enumeratorList) {
|
||||
again:
|
||||
NativeIterator *ni = iterobj->getNativeIterator();
|
||||
/* This only works for identified surpressed keys, not values. */
|
||||
if (ni->isKeyIter() && ni->obj == obj && ni->props_cursor < ni->props_end) {
|
||||
/* Check whether id is still to come. */
|
||||
@@ -1087,6 +1101,12 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
|
||||
HeapPtr<JSFlatString> *props_end = ni->end();
|
||||
for (HeapPtr<JSFlatString> *idp = props_cursor; idp < props_end; ++idp) {
|
||||
if (predicate(*idp)) {
|
||||
/*
|
||||
* Root the iterobj. This loop can GC, so we want to make sure that if
|
||||
* the GC removes any elements from the list, it won't remove this one.
|
||||
*/
|
||||
AutoObjectRooter iterRoot(cx, ni->iterObj());
|
||||
|
||||
/*
|
||||
* Check whether another property along the prototype chain
|
||||
* became visible as a result of this deletion.
|
||||
@@ -1149,7 +1169,7 @@ SuppressDeletedPropertyHelper(JSContext *cx, HandleObject obj, StringPredicate p
|
||||
}
|
||||
}
|
||||
}
|
||||
iterobj = ni->next;
|
||||
ni = ni->next();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1467,7 +1487,6 @@ js_NewGenerator(JSContext *cx)
|
||||
/* Initialize JSGenerator. */
|
||||
gen->obj.init(obj);
|
||||
gen->state = JSGEN_NEWBORN;
|
||||
gen->enumerators = NULL;
|
||||
gen->fp = genfp;
|
||||
gen->prevGenerator = NULL;
|
||||
|
||||
@@ -1563,14 +1582,10 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, HandleObject obj,
|
||||
gen->regs = cx->regs();
|
||||
|
||||
cx->enterGenerator(gen); /* OOM check above. */
|
||||
RootedPropertyIteratorObject enumerators(cx, cx->enumerators);
|
||||
cx->enumerators = gen->enumerators;
|
||||
|
||||
RootedScript script(cx, fp->script());
|
||||
ok = RunScript(cx, script, fp);
|
||||
|
||||
gen->enumerators = cx->enumerators;
|
||||
cx->enumerators = enumerators;
|
||||
cx->leaveGenerator(gen);
|
||||
}
|
||||
|
||||
@@ -1783,7 +1798,7 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
|
||||
NativeIterator *ni = NativeIterator::allocateIterator(cx, 0, blank);
|
||||
if (!ni)
|
||||
return false;
|
||||
ni->init(NULL, 0 /* flags */, 0, 0);
|
||||
ni->init(NULL, NULL, 0 /* flags */, 0, 0);
|
||||
|
||||
iteratorProto->asPropertyIterator().setNativeIterator(ni);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user