Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
jsiter.h File Reference
#include "jsprvtd.h"
#include "jspubtd.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.


struct  JSGenerator


#define JSITER_ENUMERATE   0x1 /* for-in compatible hidden default iterator */
#define JSITER_FOREACH   0x2 /* return [key, value] pair rather than key */
#define JSITER_KEYVALUE   0x4 /* destructuring for-in wants [key, value] */
#define FRAME_TO_GENERATOR(fp)   ((JSGenerator *) ((uint8 *)(fp) - offsetof(JSGenerator, frame)))


typedef enum JSGeneratorState JSGeneratorState


enum  JSGeneratorState {


void js_CloseNativeIterator (JSContext *cx, JSObject *iterobj)
void js_CloseIteratorState (JSContext *cx, JSObject *iterobj)
JSBool js_ValueToIterator (JSContext *cx, uintN flags, jsval *vp)
JSBool js_CallIteratorNext (JSContext *cx, JSObject *iterobj, jsval *rval)
JSObjectjs_NewGenerator (JSContext *cx, JSStackFrame *fp)
JSBool js_CloseGeneratorObject (JSContext *cx, JSGenerator *gen)
JSObjectjs_InitIteratorClasses (JSContext *cx, JSObject *obj)


JSClass js_GeneratorClass
JSClass js_IteratorClass
JSClass js_StopIterationClass

Class Documentation

struct JSGenerator

Definition at line 87 of file jsiter.h.

Collaboration diagram for JSGenerator:
Class Members
JSArena arena
JSStackFrame frame
JSGenerator * next
JSObject * obj
jsval stack
JSGeneratorState state

Define Documentation

#define FRAME_TO_GENERATOR (   fp)    ((JSGenerator *) ((uint8 *)(fp) - offsetof(JSGenerator, frame)))

Definition at line 96 of file jsiter.h.

#define JSITER_ENUMERATE   0x1 /* for-in compatible hidden default iterator */

Definition at line 48 of file jsiter.h.

#define JSITER_FOREACH   0x2 /* return [key, value] pair rather than key */

Definition at line 49 of file jsiter.h.

#define JSITER_KEYVALUE   0x4 /* destructuring for-in wants [key, value] */

Definition at line 50 of file jsiter.h.

Typedef Documentation

Enumeration Type Documentation


Definition at line 79 of file jsiter.h.

    JSGEN_NEWBORN,  /* not yet started */
    JSGEN_OPEN,     /* started by a .next() or .send(undefined) call */
    JSGEN_RUNNING,  /* currently executing via .next(), etc., call */
    JSGEN_CLOSING,  /* close method is doing asynchronous return */
    JSGEN_CLOSED    /* closed, cannot be started or closed again */
} JSGeneratorState;

Function Documentation

JSBool js_CallIteratorNext ( JSContext cx,
JSObject iterobj,
jsval rval 

Definition at line 595 of file jsiter.c.

    uintN flags;

    /* Fast path for native iterators */
    if (OBJ_GET_CLASS(cx, iterobj) == &js_IteratorClass) {
        flags = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_FLAGS));
        if (flags & JSITER_ENUMERATE)
            return CallEnumeratorNext(cx, iterobj, flags, rval);

         * Call next directly as all the methods of the native iterator are
         * read-only and permanent.
        if (!IteratorNextImpl(cx, iterobj, rval))
            return JS_FALSE;
    } else {
        jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);

        if (!JS_GetMethodById(cx, iterobj, id, &iterobj, rval))
            return JS_FALSE;
        if (!js_InternalCall(cx, iterobj, *rval, 0, NULL, rval)) {
            /* Check for StopIteration. */
            if (!cx->throwing ||
                JSVAL_IS_PRIMITIVE(cx->exception) ||
                OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(cx->exception))
                    != &js_StopIterationClass) {
                return JS_FALSE;

            /* Inline JS_ClearPendingException(cx). */
            cx->throwing = JS_FALSE;
            cx->exception = JSVAL_VOID;
            *rval = JSVAL_HOLE;
            return JS_TRUE;

    return JS_TRUE;

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 923 of file jsiter.c.

    /* We pass null as rval since SendToGenerator never uses it with CLOSE. */
    return SendToGenerator(cx, JSGENOP_CLOSE, gen->obj, gen, JSVAL_VOID, NULL);

Here is the call graph for this function:

Here is the caller graph for this function:

void js_CloseIteratorState ( JSContext cx,
JSObject iterobj 

Definition at line 85 of file jsiter.c.

    jsval *slots;
    jsval state, parent;
    JSObject *iterable;

    JS_ASSERT(JS_InstanceOf(cx, iterobj, &js_IteratorClass, NULL));
    slots = iterobj->slots;

    /* Avoid double work if js_CloseNativeIterator was called on obj. */
    state = slots[JSSLOT_ITER_STATE];
    if (JSVAL_IS_NULL(state))

    /* Protect against failure to fully initialize obj. */
    parent = slots[JSSLOT_PARENT];
    if (!JSVAL_IS_PRIMITIVE(parent)) {
        iterable = JSVAL_TO_OBJECT(parent);
            OBJECT_IS_XML(cx, iterable)) {
            ((JSXMLObjectOps *) iterable->map->ops)->
                enumerateValues(cx, iterable, JSENUMERATE_DESTROY, &state,
                                NULL, NULL);
        } else
            OBJ_ENUMERATE(cx, iterable, JSENUMERATE_DESTROY, &state, NULL);

Here is the call graph for this function:

Here is the caller graph for this function:

void js_CloseNativeIterator ( JSContext cx,
JSObject iterobj 

Definition at line 323 of file jsiter.c.

    uintN flags;

     * If this iterator is not an instance of the native default iterator
     * class, leave it to be GC'ed.
    if (!JS_InstanceOf(cx, iterobj, &js_IteratorClass, NULL))

     * If this iterator was not created by js_ValueToIterator called from the
     * for-in loop code in js_Interpret, leave it to be GC'ed.
    flags = JSVAL_TO_INT(OBJ_GET_SLOT(cx, iterobj, JSSLOT_ITER_FLAGS));
    if (!(flags & JSITER_ENUMERATE))

    js_CloseIteratorState(cx, iterobj);

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1055 of file jsiter.c.

    JSObject *proto, *stop;

    /* Idempotency required: we initialize several things, possibly lazily. */
    if (!js_GetClassObject(cx, obj, JSProto_StopIteration, &stop))
        return NULL;
    if (stop)
        return stop;

    proto = JS_InitClass(cx, obj, NULL, &js_IteratorClass, Iterator, 2,
                         NULL, iterator_methods, NULL, NULL);
    if (!proto)
        return NULL;
    proto->slots[JSSLOT_ITER_STATE] = JSVAL_NULL;

    /* Initialize the generator internals if configured. */
    if (!JS_InitClass(cx, obj, NULL, &js_GeneratorClass, NULL, 0,
                      NULL, generator_methods, NULL, NULL)) {
        return NULL;

    return JS_InitClass(cx, obj, NULL, &js_StopIterationClass, NULL, 0,
                        NULL, NULL, NULL, NULL);

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 714 of file jsiter.c.

    JSObject *obj;
    uintN argc, nargs, nvars, depth, nslots;
    JSGenerator *gen;
    jsval *newsp;

    /* After the following return, failing control flow must goto bad. */
    obj = js_NewObject(cx, &js_GeneratorClass, NULL, NULL);
    if (!obj)
        return NULL;

    /* Load and compute stack slot counts. */
    argc = fp->argc;
    nargs = JS_MAX(argc, fp->fun->nargs);
    nvars = fp->nvars;
    depth = fp->script->depth;
    nslots = 2 + nargs + nvars + 2 * depth;

    /* Allocate obj's private data struct. */
    gen = (JSGenerator *)
          JS_malloc(cx, sizeof(JSGenerator) + (nslots - 1) * sizeof(jsval));
    if (!gen)
        goto bad;

    gen->obj = obj;

    /* Steal away objects reflecting fp and point them at gen->frame. */
    gen->frame.callobj = fp->callobj;
    if (fp->callobj) {
        JS_SetPrivate(cx, fp->callobj, &gen->frame);
        fp->callobj = NULL;
    gen->frame.argsobj = fp->argsobj;
    if (fp->argsobj) {
        JS_SetPrivate(cx, fp->argsobj, &gen->frame);
        fp->argsobj = NULL;

    /* These two references can be shared with fp until it goes away. */
    gen->frame.varobj = fp->varobj;
    gen->frame.thisp = fp->thisp;

    /* Copy call-invariant script and function references. */
    gen->frame.script = fp->script;
    gen->frame.callee = fp->callee;
    gen-> = fp->fun;

    /* Use newsp to carve space out of gen->stack. */
    newsp = gen->stack;
    gen-> = NULL;
    gen->arena.base = (jsuword) newsp;
    gen->arena.limit = gen->arena.avail = (jsuword) (newsp + nslots);

#define COPY_STACK_ARRAY(vec,cnt,num)                                         \
    JS_BEGIN_MACRO                                                            \
        gen->frame.cnt = cnt;                                                 \
        gen->frame.vec = newsp;                                               \
        newsp += (num);                                                       \
        memcpy(gen->frame.vec, fp->vec, (num) * sizeof(jsval));               \

    /* Copy argv, rval, and vars. */
    *newsp++ = fp->argv[-2];
    *newsp++ = fp->argv[-1];
    COPY_STACK_ARRAY(argv, argc, nargs);
    gen->frame.rval = fp->rval;
    COPY_STACK_ARRAY(vars, nvars, nvars);


    /* Initialize or copy virtual machine state. */
    gen->frame.down = NULL;
    gen->frame.annotation = NULL;
    gen->frame.scopeChain = fp->scopeChain;
    gen->frame.pc = fp->pc;

    /* Allocate generating pc and operand stack space. */
    gen->frame.spbase = gen->frame.sp = newsp + depth;

    /* Copy remaining state (XXX sharp* and xml* should be local vars). */
    gen->frame.sharpDepth = 0;
    gen->frame.sharpArray = NULL;
    gen->frame.flags = fp->flags | JSFRAME_GENERATOR;
    gen->frame.dormantNext = NULL;
    gen->frame.xmlNamespace = NULL;
    gen->frame.blockChain = NULL;

    /* Note that gen is newborn. */
    gen->state = JSGEN_NEWBORN;

    if (!JS_SetPrivate(cx, obj, gen)) {
        JS_free(cx, gen);
        goto bad;

     * Register with GC to ensure that suspended finally blocks will be
     * executed.
    js_RegisterGenerator(cx, gen);
    return obj;

    cx->weakRoots.newborn[GCX_OBJECT] = NULL;
    return NULL;

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool js_ValueToIterator ( JSContext cx,
uintN  flags,
jsval vp 

Definition at line 350 of file jsiter.c.

    JSObject *obj;
    JSTempValueRooter tvr;
    const JSAtom *atom;
    JSBool ok;
    JSObject *iterobj;
    jsval arg;
    JSString *str;

                          JSITER_FOREACH |

    /* JSITER_KEYVALUE must always come with JSITER_FOREACH */
    JS_ASSERT(!(flags & JSITER_KEYVALUE) || (flags & JSITER_FOREACH));

    /* XXX work around old valueOf call hidden beneath js_ValueToObject */
    if (!JSVAL_IS_PRIMITIVE(*vp)) {
        obj = JSVAL_TO_OBJECT(*vp);
    } else {
         * Enumerating over null and undefined gives an empty enumerator.
         * This is contrary to ECMA-262 9.9 ToObject, invoked from step 3 of
         * the first production in 12.6.4 and step 4 of the second production,
         * but it's "web JS" compatible.
        if ((flags & JSITER_ENUMERATE)) {
            if (!js_ValueToObject(cx, *vp, &obj))
                return JS_FALSE;
            if (!obj)
                goto default_iter;
        } else {
            obj = js_ValueToNonNullObject(cx, *vp);
            if (!obj)
                return JS_FALSE;

    JS_PUSH_TEMP_ROOT_OBJECT(cx, obj, &tvr);

    atom = cx->runtime->atomState.iteratorAtom;
    if (OBJECT_IS_XML(cx, obj)) {
        if (!js_GetXMLFunction(cx, obj, ATOM_TO_JSID(atom), vp))
            goto bad;
    } else
        if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(atom), vp))
            goto bad;

    if (JSVAL_IS_VOID(*vp)) {
         * Fail over to the default enumerating native iterator.
         * Create iterobj with a NULL parent to ensure that we use the correct
         * scope chain to lookup the iterator's constructor. Since we use the
         * parent slot to keep track of the iterable, we must fix it up after.
        iterobj = js_NewObject(cx, &js_IteratorClass, NULL, NULL);
        if (!iterobj)
            goto bad;

        /* Store iterobj in *vp to protect it from GC (callers must root vp). */
        *vp = OBJECT_TO_JSVAL(iterobj);

        if (!InitNativeIterator(cx, iterobj, obj, flags))
            goto bad;
    } else {
        arg = BOOLEAN_TO_JSVAL((flags & JSITER_FOREACH) == 0);
        if (!js_InternalInvoke(cx, obj, *vp, JSINVOKE_ITERATOR, 1, &arg, vp))
            goto bad;
        if (JSVAL_IS_PRIMITIVE(*vp)) {
            str = js_DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, *vp, NULL);
            if (str) {
                JS_ReportErrorNumberUC(cx, js_GetErrorMessage, NULL,
            goto bad;

    ok = JS_TRUE;
    if (obj)
        JS_POP_TEMP_ROOT(cx, &tvr);
    return ok;
    ok = JS_FALSE;
    goto out;

Here is the call graph for this function:

Here is the caller graph for this function:

Variable Documentation

Definition at line 695 of file jsiter.c.

Definition at line 116 of file jsiter.c.

Definition at line 644 of file jsiter.c.