frame.scopeChain = NULL; ok = JS_TRUE; }  #if JS_HAS_EXCEPTIONS  if (!ok && frame.throwing) { fp->throwing = JS_TRUE; fp->exception = frame.exception; } #endif
frame.scopeChain = NULL; ok = JS_TRUE; }
js_Invoke(JSContext *cx, uintN argc, JSBool constructing){    JSStackFrame *fp, frame;    jsval *sp, *newsp;    jsval *vp, v;    JSObject *funobj, *parent, *thisp;    JSClass *clasp;    JSObjectOps *ops;    JSNative native;    JSFunction *fun;    JSScript *script;    uintN minargs, nvars;    void *mark;    intN nslots, nalloc, surplus;    JSBool ok;    /* Reach under args and this to find the callable on the stack. */    fp = cx->fp;    sp = fp->sp;    /*     * Set vp to the callable value's stack slot (it's where rval goes).     * Once vp is set, control must flow through label out2: to return.     * Set frame.rval early so native class and object ops can throw and     * return false, causing a goto out2 with ok set to false.     */    vp = sp - (2 + argc);    v = *vp;    frame.rval = JSVAL_VOID;    /* A callable must be an object reference. */    if (JSVAL_IS_PRIMITIVE(v))    	goto bad;    funobj = JSVAL_TO_OBJECT(v);    /* Load callable parent and this parameter for later. */    parent = OBJ_GET_PARENT(cx, funobj);    thisp = JSVAL_TO_OBJECT(vp[1]);    clasp = OBJ_GET_CLASS(cx, funobj);    if (clasp != &js_FunctionClass) {	/* Function is inlined, all other classes use object ops. */	ops = funobj->map->ops;	/* Try converting to function, for closure and API compatibility. */	ok = clasp->convert(cx, funobj, JSTYPE_FUNCTION, &v);	if (!ok)	    goto out2;	if (!JSVAL_IS_FUNCTION(cx, v)) {	    fun = NULL;	    script = NULL;	    minargs = nvars = 0;	} else {	    funobj = JSVAL_TO_OBJECT(v);            parent = OBJ_GET_PARENT(cx, funobj);	    fun = JS_GetPrivate(cx, funobj);            if (clasp != &js_ClosureClass) {                /* Make vp refer to funobj to keep it available as argv[-2]. */                *vp = v;                goto have_fun;            }            /* Closure invocation may need extra arg and local var slots. */            script = fun->script;            minargs = fun->nargs + fun->extra;            nvars = fun->nvars;	}	/* Try a call or construct native object op, using fun as fallback. */	native = constructing ? ops->construct : ops->call;	if (!native)	    goto bad;    } else {	/* Get private data and set derived locals from it. */	fun = JS_GetPrivate(cx, funobj);have_fun:	native = fun->call;	script = fun->script;	minargs = fun->nargs + fun->extra;	nvars = fun->nvars;	/* Handle bound method and dynamic scope special cases. */	if (fun->flags) {	    if (fun->flags & JSFUN_BOUND_METHOD)		thisp = parent;	    else		parent = NULL;        }    }    /* Initialize most of frame, except for thisp and scopeChain. */    frame.callobj = frame.argsobj = NULL;    frame.script = script;    frame.fun = fun;    frame.argc = argc;    frame.argv = sp - argc;    frame.nvars = nvars;    frame.vars = sp;    frame.down = fp;    frame.annotation = NULL;    frame.pc = NULL;    frame.sp = sp;    frame.sharpDepth = 0;    frame.sharpArray = NULL;    frame.constructing = constructing;    frame.overrides = 0;    frame.debugging = JS_FALSE;    frame.throwing = JS_FALSE;    frame.dormantNext = NULL;    /* Compute the 'this' parameter and store it in frame. */    if (thisp && OBJ_GET_CLASS(cx, thisp) != &js_CallClass) {	/* Some objects (e.g., With) delegate 'this' to another object. */	thisp = OBJ_THIS_OBJECT(cx, thisp);	if (!thisp) {	    ok = JS_FALSE;	    goto out2;	}	/* Default return value for a constructor is the new object. */        if (constructing)	    frame.rval = OBJECT_TO_JSVAL(thisp);    } else {    	/*    	 * ECMA requires "the global object", but in the presence of multiple    	 * top-level objects (windows, frames, or certain layers in the client    	 * object model), we prefer fun's parent.  An example that causes this    	 * code to run:    	 *    	 *   // in window w1    	 *   function f() { return this }    	 *   function g() { return f }    	 *    	 *   // in window w2    	 *   var h = w1.g()    	 *   alert(h() == w1)    	 *    	 * The alert should display "true".    	 */	PR_ASSERT(!constructing);        if (parent == NULL) {            parent = cx->globalObject;        } else {            /* walk up to find the top-level object */            JSObject *tmp;            thisp = parent;            while ((tmp = OBJ_GET_PARENT(cx, thisp)) != NULL)                thisp = tmp;        }    }    frame.thisp = thisp;    /* From here on, control must flow through label out: to return. */    cx->fp = &frame;    mark = PR_ARENA_MARK(&cx->stackPool);    /* Check for missing arguments expected by the function. */    nslots = (intN)((argc < minargs) ? minargs - argc : 0);    if (nslots) {	/* All arguments must be contiguous, so we may have to copy actuals. */	nalloc = nslots;	if ((pruword)(sp + nslots) > cx->stackPool.current->limit)	    nalloc += argc;	/* Take advantage of the surplus slots in the caller's frame depth. */	surplus = (jsval *)mark - sp;	PR_ASSERT(surplus >= 0);	nalloc -= surplus;	/* Check whether we have enough space in the caller's frame. */	if (nalloc > 0) {	    /* Need space for actuals plus missing formals minus surplus. */	    newsp = js_AllocStack(cx, (uintN)nalloc, NULL);	    if (!newsp) {		ok = JS_FALSE;		goto out;	    }	    /* If we couldn't allocate contiguous args, copy actuals now. */	    if (newsp != mark) {		if (argc)		    memcpy(newsp, frame.argv, argc * sizeof(jsval));		frame.argv = newsp;		frame.vars = frame.sp = newsp + argc;		RESTORE_SP(&frame);	    }	}	/* Advance frame.vars to make room for the missing args. */	frame.vars += nslots;	/* Push void to initialize missing args. */	while (--nslots >= 0)	    PUSH(JSVAL_VOID);    }    /* Now allocate stack space for local variables. */    nslots = (intN)frame.nvars;    if (nslots) {	surplus = (intN)((jsval *)cx->stackPool.current->avail - frame.vars);	if (surplus < nslots) {	    newsp = js_AllocStack(cx, (uintN)nslots, NULL);	    if (!newsp) {		ok = JS_FALSE;		goto out;	    }	    if (newsp != sp) {		/* NB: Discontinuity between argv and vars. */		frame.vars = frame.sp = newsp;		RESTORE_SP(&frame);	    }	}	/* Push void to initialize local variables. */	while (--nslots >= 0)	    PUSH(JSVAL_VOID);    }    /* Store the current sp in frame before calling fun. */    SAVE_SP(&frame);    /* Call the function, either a native method or an interpreted script. */    if (native) {	frame.scopeChain = fp->scopeChain;	ok = native(cx, thisp, argc, frame.argv, &frame.rval);    } else if (script) {	frame.scopeChain = funobj;	if (!parent) {#if JS_HAS_CALL_OBJECT	    /* Scope with a call object parented by cx's global object. */	    funobj = js_GetCallObject(cx, &frame, cx->globalObject, NULL);	    if (!funobj) {		ok = JS_FALSE;		goto out;	    }#else	    /* Bad old code slams globalObject directly into funobj. */	    OBJ_SET_PARENT(funobj, cx->globalObject);#endif	}	ok = js_Interpret(cx, &v);#if !JS_HAS_CALL_OBJECT	if (!parent)	    OBJ_SET_PARENT(funobj, NULL);#endif    } else {	/* fun might be onerror trying to report a syntax error in itself. */	frame.scopeChain = NULL;	ok = JS_TRUE;    }#if JS_HAS_EXCEPTIONS    /* Native or script returns JS_FALSE on error or uncaught exception */    if (!ok && frame.throwing) {	fp->throwing = JS_TRUE;	fp->exception = frame.exception;    }#endifout:    /*     * Checking frame.annotation limits the use of this hook for uses other     * than releasing annotations, but avoids one C function call for every     * JS function call.     */    if (frame.annotation &&	js_InterpreterHooks &&	js_InterpreterHooks->destroyFrame) {        js_InterpreterHooks->destroyFrame(cx, &frame);    }#if JS_HAS_CALL_OBJECT    /* If frame has a call object, sync values and clear back-pointer. */    if (frame.callobj)	ok &= js_PutCallObject(cx, &frame);#endif#if JS_HAS_ARGS_OBJECT    /* If frame has an arguments object, sync values clear back-pointer. */    if (frame.argsobj)	ok &= js_PutArgsObject(cx, &frame);#endif    /* Pop everything off the stack and restore cx->fp. */    PR_ARENA_RELEASE(&cx->stackPool, mark);    cx->fp = fp;out2:    /* Store the return value and restore sp just above it. */    *vp = frame.rval;    fp->sp = vp + 1;    return ok;bad:    js_ReportIsNotFunction(cx, vp, constructing);    ok = JS_FALSE;    goto out2;}