if ((sprop->attrs & JSPROP_ENUMERATE) &&
if (( #ifdef DUMP_CALL_TABLE (cx->options & JSOPTION_LOGCALL_TOSOURCE) || #endif (sprop->attrs & JSPROP_ENUMERATE)) &&
js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,             jsval *statep, jsid *idp){    JSObject *proto_obj;    JSClass *clasp;    JSEnumerateOp enumerate;    JSScopeProperty *sprop, *lastProp;    jsint i, length;    JSScope *scope;    JSIdArray *ida;    JSNativeIteratorState *state;    clasp = OBJ_GET_CLASS(cx, obj);    enumerate = clasp->enumerate;    if (clasp->flags & JSCLASS_NEW_ENUMERATE)        return ((JSNewEnumerateOp) enumerate)(cx, obj, enum_op, statep, idp);    switch (enum_op) {    case JSENUMERATE_INIT:        if (!enumerate(cx, obj))            goto init_error;        length = 0;        /*         * The set of all property ids is pre-computed when the iterator         * is initialized so as to avoid problems with properties being         * deleted during the iteration.         */        JS_LOCK_OBJ(cx, obj);        scope = OBJ_SCOPE(obj);        /*         * If this object shares a scope with its prototype, don't enumerate         * its properties.  Otherwise they will be enumerated a second time         * when the prototype object is enumerated.         */        proto_obj = OBJ_GET_PROTO(cx, obj);        if (proto_obj && scope == OBJ_SCOPE(proto_obj)) {            ida = js_NewIdArray(cx, 0);            if (!ida) {                JS_UNLOCK_OBJ(cx, obj);                goto init_error;            }        } else {            /* Object has a private scope; Enumerate all props in scope. */            for (sprop = lastProp = SCOPE_LAST_PROP(scope); sprop;                 sprop = sprop->parent) {                if ((sprop->attrs & JSPROP_ENUMERATE) &&                    !(sprop->flags & SPROP_IS_ALIAS) &&                    (!SCOPE_HAD_MIDDLE_DELETE(scope) ||                     SCOPE_HAS_PROPERTY(scope, sprop))) {                    length++;                }            }            ida = js_NewIdArray(cx, length);            if (!ida) {                JS_UNLOCK_OBJ(cx, obj);                goto init_error;            }            i = length;            for (sprop = lastProp; sprop; sprop = sprop->parent) {                if ((sprop->attrs & JSPROP_ENUMERATE) &&                    !(sprop->flags & SPROP_IS_ALIAS) &&                    (!SCOPE_HAD_MIDDLE_DELETE(scope) ||                     SCOPE_HAS_PROPERTY(scope, sprop))) {                    JS_ASSERT(i > 0);                    ida->vector[--i] = sprop->id;                }            }        }        JS_UNLOCK_OBJ(cx, obj);        state = (JSNativeIteratorState *)            JS_malloc(cx, sizeof(JSNativeIteratorState));        if (!state) {            JS_DestroyIdArray(cx, ida);            goto init_error;        }        state->ida = ida;        state->next_index = 0;        *statep = PRIVATE_TO_JSVAL(state);        if (idp)            *idp = INT_TO_JSVAL(length);        return JS_TRUE;    case JSENUMERATE_NEXT:        state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep);        ida = state->ida;        length = ida->length;        if (state->next_index != length) {            *idp = ida->vector[state->next_index++];            return JS_TRUE;        }        /* Fall through ... */    case JSENUMERATE_DESTROY:        state = (JSNativeIteratorState *) JSVAL_TO_PRIVATE(*statep);        JS_DestroyIdArray(cx, state->ida);        JS_free(cx, state);        *statep = JSVAL_NULL;        return JS_TRUE;    default:        JS_ASSERT(0);        return JS_FALSE;    }init_error:    *statep = JSVAL_NULL;    return JS_FALSE;}