diff --git a/js/src/jsiter.c b/js/src/jsiter.c index 2c13d298a441..7c2982060974 100644 --- a/js/src/jsiter.c +++ b/js/src/jsiter.c @@ -76,6 +76,33 @@ extern const char js_throw_str[]; /* from jsscan.h */ #error JS_INITIAL_NSLOTS must be greater than JSSLOT_ITER_FLAGS. #endif +static uint32 +iterator_mark(JSContext *cx, JSObject *obj, void *arg) +{ + jsval state, parent; + JSObject *iterable; + + /* Avoid double work if js_CloseNativeIterator was called on obj. */ + state = obj->slots[JSSLOT_ITER_STATE]; + if (JSVAL_IS_VOID(state)) + return 0; + + parent = obj->slots[JSSLOT_PARENT]; + if (!JSVAL_IS_NULL(state) && !JSVAL_IS_PRIMITIVE(parent)) { + iterable = JSVAL_TO_OBJECT(parent); +#if JS_HAS_XML_SUPPORT + if ((JSVAL_TO_INT(obj->slots[JSSLOT_ITER_FLAGS]) & JSITER_FOREACH) && + OBJECT_IS_XML(cx, iterable)) { + ((JSXMLObjectOps *) iterable->map->ops)-> + enumerateValues(cx, iterable, JSENUMERATE_MARK, &state, + NULL, NULL); + } else +#endif + OBJ_ENUMERATE(cx, iterable, JSENUMERATE_MARK, &state, NULL); + } + return 0; +} + static void iterator_close(JSContext *cx, JSObject *obj) { @@ -110,7 +137,8 @@ JSExtendedClass js_IteratorClass = { JSCLASS_HAS_CACHED_PROTO(JSProto_Iterator), JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, - JSCLASS_NO_OPTIONAL_MEMBERS }, + NULL, NULL, NULL, NULL, + NULL, NULL, iterator_mark, NULL }, NULL, NULL, NULL, iterator_close, JSCLASS_NO_RESERVED_MEMBERS }; diff --git a/js/src/jsobj.c b/js/src/jsobj.c index e658b5feaf05..aa94cdd9dbfa 100644 --- a/js/src/jsobj.c +++ b/js/src/jsobj.c @@ -3793,6 +3793,22 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, JS_free(cx, state); *statep = JSVAL_NULL; break; + + case JSENUMERATE_MARK: + state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep); + ida = state->ida; + length = ida->length; + for (i = 0; i < length; i++) { + jsid id; + + id = ida->vector[i]; + if (JSID_IS_ATOM(id)) { + GC_MARK_ATOM(cx, JSID_TO_ATOM(id)); + } else if (JSID_IS_OBJECT(id)) { + GC_MARK(cx, JSID_TO_OBJECT(id), "ida->vector[i]"); + } + } + break; } return JS_TRUE; } diff --git a/js/src/jspubtd.h b/js/src/jspubtd.h index e6e0871c2cd8..6fb0abd19647 100644 --- a/js/src/jspubtd.h +++ b/js/src/jspubtd.h @@ -119,7 +119,8 @@ typedef enum JSAccessMode { typedef enum JSIterateOp { JSENUMERATE_INIT, /* Create new iterator state */ JSENUMERATE_NEXT, /* Iterate once */ - JSENUMERATE_DESTROY /* Destroy iterator state */ + JSENUMERATE_DESTROY, /* Destroy iterator state */ + JSENUMERATE_MARK /* mark opaque iterator state */ } JSIterateOp; /* Struct typedefs. */ diff --git a/js/src/jsxml.c b/js/src/jsxml.c index ff97665f4770..868f8efa0a19 100644 --- a/js/src/jsxml.c +++ b/js/src/jsxml.c @@ -5151,6 +5151,9 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, } *statep = JSVAL_NULL; break; + + case JSENUMERATE_MARK: + break; } return JS_TRUE; } @@ -5310,6 +5313,9 @@ xml_enumerateValues(JSContext *cx, JSObject *obj, JSIterateOp enum_op, } *statep = JSVAL_NULL; break; + + case JSENUMERATE_MARK: + break; } return JS_TRUE; }