зеркало из https://github.com/mozilla/gecko-dev.git
new Iterator() always constructs the default iterator. bug=354945 r=brendan
This commit is contained in:
Родитель
19c7d67134
Коммит
6fea546cc2
111
js/src/jsiter.c
111
js/src/jsiter.c
|
@ -122,10 +122,43 @@ JSClass js_IteratorClass = {
|
|||
};
|
||||
|
||||
static JSBool
|
||||
Iterator(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
InitNativeIterator(JSContext *cx, JSObject *iterobj, JSObject *obj, uintN flags)
|
||||
{
|
||||
jsval state;
|
||||
JSBool ok;
|
||||
|
||||
JS_ASSERT(JSVAL_TO_PRIVATE(iterobj->slots[JSSLOT_CLASS]) ==
|
||||
&js_IteratorClass);
|
||||
|
||||
/* Initialize iterobj in case of enumerate hook failure. */
|
||||
iterobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj);
|
||||
iterobj->slots[JSSLOT_ITER_STATE] = JSVAL_NULL;
|
||||
iterobj->slots[JSSLOT_ITER_FLAGS] = INT_TO_JSVAL(flags);
|
||||
if (!js_RegisterCloseableIterator(cx, iterobj))
|
||||
return JS_FALSE;
|
||||
|
||||
ok =
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, obj))
|
||||
? ((JSXMLObjectOps *) obj->map->ops)->
|
||||
enumerateValues(cx, obj, JSENUMERATE_INIT, &state, NULL, NULL)
|
||||
:
|
||||
#endif
|
||||
OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
||||
iterobj->slots[JSSLOT_ITER_STATE] = state;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Iterator(JSContext *cx, JSObject *iterobj, uintN argc, jsval *argv, jsval *rval)
|
||||
{
|
||||
JSObject *obj;
|
||||
JSBool keyonly;
|
||||
jsid id;
|
||||
jsval fval;
|
||||
const jsid id = ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom);
|
||||
|
||||
/* XXX work around old valueOf call hidden beneath js_ValueToObject */
|
||||
if (!JSVAL_IS_PRIMITIVE(argv[0])) {
|
||||
|
@ -134,8 +167,17 @@ Iterator(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
obj = js_ValueToNonNullObject(cx, argv[0]);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
argv[0] = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
||||
if (cx->fp->flags & JSFRAME_CONSTRUCTING) {
|
||||
keyonly = JS_FALSE;
|
||||
return js_ValueToBoolean(cx, argv[1], &keyonly) &&
|
||||
InitNativeIterator(cx, iterobj, obj,
|
||||
keyonly ? 0 : JSITER_FOREACH);
|
||||
}
|
||||
|
||||
id = ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom);
|
||||
return JS_GetMethodById(cx, obj, id, &obj, &fval) &&
|
||||
js_InternalCall(cx, obj, fval, argc - 1, argv + 1, rval);
|
||||
}
|
||||
|
@ -287,8 +329,6 @@ JSBool
|
|||
js_NewNativeIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp)
|
||||
{
|
||||
JSObject *iterobj;
|
||||
jsval state;
|
||||
JSBool ok;
|
||||
|
||||
/*
|
||||
* Create iterobj with a NULL parent to ensure that we use the correct
|
||||
|
@ -302,26 +342,7 @@ js_NewNativeIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp)
|
|||
/* Store iterobj in *vp to protect it from GC (callers must root vp). */
|
||||
*vp = OBJECT_TO_JSVAL(iterobj);
|
||||
|
||||
/* Initialize iterobj in case of enumerate hook failure. */
|
||||
iterobj->slots[JSSLOT_PARENT] = OBJECT_TO_JSVAL(obj);
|
||||
iterobj->slots[JSSLOT_ITER_STATE] = JSVAL_NULL;
|
||||
iterobj->slots[JSSLOT_ITER_FLAGS] = INT_TO_JSVAL(flags);
|
||||
if (!js_RegisterCloseableIterator(cx, iterobj))
|
||||
return JS_FALSE;
|
||||
|
||||
ok =
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
((flags & JSITER_FOREACH) && OBJECT_IS_XML(cx, obj))
|
||||
? ((JSXMLObjectOps *) obj->map->ops)->
|
||||
enumerateValues(cx, obj, JSENUMERATE_INIT, &state, NULL, NULL)
|
||||
:
|
||||
#endif
|
||||
OBJ_ENUMERATE(cx, obj, JSENUMERATE_INIT, &state, NULL);
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
||||
iterobj->slots[JSSLOT_ITER_STATE] = state;
|
||||
return JS_TRUE;
|
||||
return InitNativeIterator(cx, iterobj, obj, flags);
|
||||
}
|
||||
|
||||
uintN
|
||||
|
@ -363,23 +384,6 @@ js_CloseNativeIterator(JSContext *cx, JSObject *iterobj)
|
|||
js_CloseIteratorState(cx, iterobj);
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DefaultIterator(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSBool keyonly;
|
||||
|
||||
if (OBJ_GET_CLASS(cx, obj) == &js_IteratorClass) {
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
keyonly = JS_FALSE;
|
||||
if (argc != 0 && !js_ValueToBoolean(cx, argv[0], &keyonly))
|
||||
return JS_FALSE;
|
||||
return js_NewNativeIterator(cx, obj, keyonly ? 0 : JSITER_FOREACH, rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inline expansion of Iterator, with extra logic to constrain the result of
|
||||
* ToObject(v).__iterator__.
|
||||
|
@ -402,29 +406,26 @@ js_ValueToIterator(JSContext *cx, jsval v, uintN flags)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
|
||||
|
||||
JS_PUSH_SINGLE_TEMP_ROOT(cx, obj, &tvr);
|
||||
if (!JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), &obj, &fval))
|
||||
goto bad;
|
||||
if (JSVAL_IS_VOID(fval)) {
|
||||
/* Fail over to the default native iterator, called directly. */
|
||||
if (!js_DefaultIterator(cx, obj, 1, &arg, &rval))
|
||||
/* Fail over to the default enumerating native iterator. */
|
||||
if (!js_NewNativeIterator(cx, obj,
|
||||
(flags & JSITER_FOREACH) | JSITER_ENUMERATE,
|
||||
&rval)) {
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
|
||||
if (!js_InternalInvoke(cx, obj, fval, JSINVOKE_ITERATOR, 1, &arg,
|
||||
&rval)) {
|
||||
goto bad;
|
||||
}
|
||||
if (JSVAL_IS_PRIMITIVE(rval))
|
||||
goto bad_iterator;
|
||||
iterobj = JSVAL_TO_OBJECT(rval);
|
||||
JS_ASSERT(OBJ_GET_CLASS(cx, iterobj) == &js_IteratorClass);
|
||||
iterobj->slots[JSSLOT_ITER_FLAGS] |= INT_TO_JSVAL(JSITER_ENUMERATE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!js_InternalInvoke(cx, obj, fval, JSINVOKE_ITERATOR, 1, &arg, &rval))
|
||||
goto bad;
|
||||
|
||||
if (JSVAL_IS_PRIMITIVE(rval))
|
||||
goto bad_iterator;
|
||||
|
||||
iterobj = JSVAL_TO_OBJECT(rval);
|
||||
|
||||
out:
|
||||
|
|
|
@ -61,10 +61,6 @@ js_CloseNativeIterator(JSContext *cx, JSObject *iterobj);
|
|||
extern void
|
||||
js_CloseIteratorState(JSContext *cx, JSObject *iterobj);
|
||||
|
||||
extern JSBool
|
||||
js_DefaultIterator(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
extern JSObject *
|
||||
js_ValueToIterator(JSContext *cx, jsval v, uintN flags);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче