Ensure that iterators are closed when an exception is thrown (bug 729797, r=luke).

This commit is contained in:
David Anderson
2012-02-27 17:01:52 -08:00
parent e9c2c12a73
commit bdae2ae7b1
6 changed files with 42 additions and 30 deletions

View File

@@ -829,7 +829,7 @@ Iterator(JSContext *cx, uintN argc, Value *vp)
bool keyonly = argc >= 2 ? js_ValueToBoolean(argv[1]) : false;
uintN flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
*vp = argc >= 1 ? argv[0] : UndefinedValue();
return js_ValueToIterator(cx, flags, vp);
return ValueToIterator(cx, flags, vp);
}
JSBool
@@ -871,12 +871,19 @@ static JSFunctionSpec iterator_methods[] = {
JS_FS_END
};
#if JS_HAS_GENERATORS
static JSBool
CloseGenerator(JSContext *cx, JSObject *genobj);
#endif
namespace js {
/*
* Call ToObject(v).__iterator__(keyonly) if ToObject(v).__iterator__ exists.
* Otherwise construct the default iterator.
*/
JS_FRIEND_API(JSBool)
js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
JSBool
ValueToIterator(JSContext *cx, uintN flags, Value *vp)
{
/* JSITER_KEYVALUE must always come with JSITER_FOREACH */
JS_ASSERT_IF(flags & JSITER_KEYVALUE, flags & JSITER_FOREACH);
@@ -914,13 +921,8 @@ js_ValueToIterator(JSContext *cx, uintN flags, Value *vp)
return GetIterator(cx, obj, flags, vp);
}
#if JS_HAS_GENERATORS
static JSBool
CloseGenerator(JSContext *cx, JSObject *genobj);
#endif
JS_FRIEND_API(JSBool)
js_CloseIterator(JSContext *cx, JSObject *obj)
bool
CloseIterator(JSContext *cx, JSObject *obj)
{
cx->iterValue.setMagic(JS_NO_ITER_VALUE);
@@ -950,6 +952,19 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
return JS_TRUE;
}
bool
UnwindIteratorForException(JSContext *cx, JSObject *obj)
{
Value v = cx->getPendingException();
cx->clearPendingException();
if (!CloseIterator(cx, obj))
return false;
cx->setPendingException(v);
return true;
}
} // namespace js
/*
* Suppress enumeration of deleted properties. This function must be called
* when a property is deleted and there might be active enumerators.