ok = CheckEvalAccess(cx, scopeobj, principals);
ok = js_CheckPrincipalsAccess(cx, scopeobj, principals, js_eval_str);
obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){    JSStackFrame *fp, *caller;    JSBool indirectCall;    JSObject *scopeobj;    JSString *str;    const char *file;    uintN line;    JSPrincipals *principals;    JSScript *script;    JSBool ok;#if JS_HAS_EVAL_THIS_SCOPE    JSObject *callerScopeChain = NULL, *callerVarObj = NULL;    JSBool setCallerScopeChain = JS_FALSE, setCallerVarObj = JS_FALSE;#endif    fp = cx->fp;    caller = JS_GetScriptedCaller(cx, fp);    indirectCall = (caller && caller->pc && *caller->pc != JSOP_EVAL);    if (JS_VERSION_IS_ECMA(cx) &&        indirectCall &&        !JS_ReportErrorFlagsAndNumber(cx,                                      JSREPORT_WARNING | JSREPORT_STRICT,                                      js_GetErrorMessage, NULL,                                      JSMSG_BAD_INDIRECT_CALL,                                      js_eval_str)) {        return JS_FALSE;    }    if (!JSVAL_IS_STRING(argv[0])) {        *rval = argv[0];        return JS_TRUE;    }#if JS_HAS_SCRIPT_OBJECT    /*     * Script.prototype.compile/exec and Object.prototype.eval all take an     * optional trailing argument that overrides the scope object.     */    scopeobj = NULL;    if (argc >= 2) {        if (!js_ValueToObject(cx, argv[1], &scopeobj))            return JS_FALSE;        argv[1] = OBJECT_TO_JSVAL(scopeobj);    }    if (!scopeobj)#endif    {#if JS_HAS_EVAL_THIS_SCOPE        /* If obj.eval(str), emulate 'with (obj) eval(str)' in the caller. */        if (indirectCall) {            callerScopeChain = caller->scopeChain;            if (obj != callerScopeChain) {                if (!CheckEvalAccess(cx, obj, caller->script->principals))                    return JS_FALSE;                scopeobj = js_NewObject(cx, &js_WithClass, obj,                                        callerScopeChain);                if (!scopeobj)                    return JS_FALSE;                /* Set fp->scopeChain too, for the compiler. */                caller->scopeChain = fp->scopeChain = scopeobj;                setCallerScopeChain = JS_TRUE;            }            callerVarObj = caller->varobj;            if (obj != callerVarObj) {                /* Set fp->varobj too, for the compiler. */                caller->varobj = fp->varobj = obj;                setCallerVarObj = JS_TRUE;            }        }        /* From here on, control must exit through label out with ok set. */#endif#if JS_BUG_EVAL_THIS_SCOPE        /* An old version used the object in which eval was found for scope. */        scopeobj = obj;#else        /* Compile using caller's current scope object. */        if (caller)            scopeobj = caller->scopeChain;#endif    }    /* Ensure we compile this eval with the right object in the scope chain. */    OBJ_TO_INNER_OBJECT(cx, scopeobj);    if (!scopeobj)        return JS_FALSE;    if (!js_CheckScopeChainValidity(cx, scopeobj, js_eval_str))        return JS_FALSE;    str = JSVAL_TO_STRING(argv[0]);    if (caller) {        file = caller->script->filename;        line = js_PCToLineNumber(cx, caller->script, caller->pc);        principals = JS_EvalFramePrincipals(cx, fp, caller);    } else {        file = NULL;        line = 0;        principals = NULL;    }    /*     * Set JSFRAME_EVAL on fp and any frames (e.g., fun_call if eval.call was     * invoked) between fp and its scripted caller, to help the compiler easily     * find the same caller whose scope and var obj we've set.     *     * XXX this nonsense could, and perhaps should, go away with a better way     * to pass params to the compiler than via the top-most frame.     */    do {        fp->flags |= JSFRAME_EVAL;    } while ((fp = fp->down) != caller);    script = JS_CompileUCScriptForPrincipals(cx, scopeobj, principals,                                             JSSTRING_CHARS(str),                                             JSSTRING_LENGTH(str),                                             file, line);    if (!script) {        ok = JS_FALSE;        goto out;    }#if !JS_BUG_EVAL_THIS_SCOPE#if JS_HAS_SCRIPT_OBJECT    if (argc < 2)#endif    {        /* Execute using caller's new scope object (might be a Call object). */        if (caller)            scopeobj = caller->scopeChain;    }#endif    /*     * Belt-and-braces: check that the lesser of eval's principals and the     * caller's principals has access to scopeobj.     */    ok = CheckEvalAccess(cx, scopeobj, principals);    if (!ok)        goto out;    ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);    JS_DestroyScript(cx, script);out:#if JS_HAS_EVAL_THIS_SCOPE    /* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */    if (setCallerScopeChain)        caller->scopeChain = callerScopeChain;    if (setCallerVarObj)        caller->varobj = callerVarObj;#endif    return ok;}