new Iterator() always constructs the default iterator. bug=354945 r=brendan

This commit is contained in:
igor.bukanov%gmail.com 2006-10-01 00:17:15 +00:00
Родитель 19c7d67134
Коммит 6fea546cc2
2 изменённых файлов: 56 добавлений и 59 удалений

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

@ -122,10 +122,43 @@ JSClass js_IteratorClass = {
}; };
static JSBool 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; jsval fval;
const jsid id = ATOM_TO_JSID(cx->runtime->atomState.iteratorAtom);
/* XXX work around old valueOf call hidden beneath js_ValueToObject */ /* XXX work around old valueOf call hidden beneath js_ValueToObject */
if (!JSVAL_IS_PRIMITIVE(argv[0])) { 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]); obj = js_ValueToNonNullObject(cx, argv[0]);
if (!obj) if (!obj)
return JS_FALSE; 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) && return JS_GetMethodById(cx, obj, id, &obj, &fval) &&
js_InternalCall(cx, obj, fval, argc - 1, argv + 1, rval); 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) js_NewNativeIterator(JSContext *cx, JSObject *obj, uintN flags, jsval *vp)
{ {
JSObject *iterobj; JSObject *iterobj;
jsval state;
JSBool ok;
/* /*
* Create iterobj with a NULL parent to ensure that we use the correct * 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). */ /* Store iterobj in *vp to protect it from GC (callers must root vp). */
*vp = OBJECT_TO_JSVAL(iterobj); *vp = OBJECT_TO_JSVAL(iterobj);
/* Initialize iterobj in case of enumerate hook failure. */ return InitNativeIterator(cx, iterobj, obj, flags);
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;
} }
uintN uintN
@ -363,23 +384,6 @@ js_CloseNativeIterator(JSContext *cx, JSObject *iterobj)
js_CloseIteratorState(cx, 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 * Inline expansion of Iterator, with extra logic to constrain the result of
* ToObject(v).__iterator__. * ToObject(v).__iterator__.
@ -402,29 +406,26 @@ js_ValueToIterator(JSContext *cx, jsval v, uintN flags)
return NULL; return NULL;
} }
arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
JS_PUSH_SINGLE_TEMP_ROOT(cx, obj, &tvr); JS_PUSH_SINGLE_TEMP_ROOT(cx, obj, &tvr);
if (!JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), &obj, &fval)) if (!JS_GetMethodById(cx, obj, ATOM_TO_JSID(atom), &obj, &fval))
goto bad; goto bad;
if (JSVAL_IS_VOID(fval)) { if (JSVAL_IS_VOID(fval)) {
/* Fail over to the default native iterator, called directly. */ /* Fail over to the default enumerating native iterator. */
if (!js_DefaultIterator(cx, obj, 1, &arg, &rval)) if (!js_NewNativeIterator(cx, obj,
(flags & JSITER_FOREACH) | JSITER_ENUMERATE,
&rval)) {
goto bad; 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)) if (JSVAL_IS_PRIMITIVE(rval))
goto bad_iterator; 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); iterobj = JSVAL_TO_OBJECT(rval);
out: out:

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

@ -61,10 +61,6 @@ js_CloseNativeIterator(JSContext *cx, JSObject *iterobj);
extern void extern void
js_CloseIteratorState(JSContext *cx, JSObject *iterobj); js_CloseIteratorState(JSContext *cx, JSObject *iterobj);
extern JSBool
js_DefaultIterator(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
extern JSObject * extern JSObject *
js_ValueToIterator(JSContext *cx, jsval v, uintN flags); js_ValueToIterator(JSContext *cx, jsval v, uintN flags);