argsrc = js_ValueToSource(cx, fp->argv[i]);
v = fp->argv[i]; if (JSVAL_IS_FUNCTION(cx, v)) { argsrc = JS_GetFunctionId(JS_ValueToFunction(cx, v)); if (!argsrc) argsrc = js_ValueToSource(cx, v); } else { argsrc = js_ValueToString(cx, v); }
InitExceptionObject(JSContext *cx, JSObject *obj, JSString *message,                    JSString *filename, uintN lineno){    JSCheckAccessOp checkAccess;    JSErrorReporter older;    JSExceptionState *state;    jschar *stackbuf;    size_t stacklen, stackmax;    JSStackFrame *fp;    jsval callerid, v;    JSBool ok;    JSString *argsrc, *stack;    uintN i, ulineno;    const char *cp;    char ulnbuf[11];    if (!JS_DefineProperty(cx, obj, js_message_str, STRING_TO_JSVAL(message),                           NULL, NULL, JSPROP_ENUMERATE)) {        return JS_FALSE;    }    if (!JS_DefineProperty(cx, obj, js_filename_str,                           STRING_TO_JSVAL(filename),                           NULL, NULL, JSPROP_ENUMERATE)) {        return JS_FALSE;    }    if (!JS_DefineProperty(cx, obj, js_lineno_str,                           INT_TO_JSVAL(lineno),                           NULL, NULL, JSPROP_ENUMERATE)) {        return JS_FALSE;    }    /*     * Set the 'stack' property.     *     * First, set aside any error reporter for cx and save its exception state     * so we can suppress any checkAccess failures.  Such failures should stop     * the backtrace procedure, not result in a failure of this constructor.     */    checkAccess = cx->runtime->checkObjectAccess;    if (checkAccess) {        older = JS_SetErrorReporter(cx, NULL);        state = JS_SaveExceptionState(cx);    }#ifdef __GNUC__         /* suppress bogus gcc warnings */    else {        older = NULL;        state = NULL;    }#endif    callerid = ATOM_KEY(cx->runtime->atomState.callerAtom);    /*     * Prepare to allocate a jschar buffer at stackbuf, where stacklen indexes     * the next free jschar slot, and with room for at most stackmax non-null     * jschars.  If stackbuf is non-null, it always contains an extra slot for     * the null terminator we'll store at the end, as a backstop.     *     * All early returns must goto done after this point, till the after-loop     * cleanup code has run!     */    stackbuf = NULL;    stacklen = stackmax = 0;    ok = JS_TRUE;#define APPEND_CHAR_TO_STACK(c)                                               \    JS_BEGIN_MACRO                                                            \        if (stacklen == stackmax) {                                           \            void *ptr_;                                                       \            stackmax = stackmax ? 2 * stackmax : 64;                          \            ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar));   \            if (!ptr_) {                                                      \                ok = JS_FALSE;                                                \                goto done;                                                    \            }                                                                 \            stackbuf = ptr_;                                                  \        }                                                                     \        stackbuf[stacklen++] = (c);                                           \    JS_END_MACRO#define APPEND_STRING_TO_STACK(str)                                           \    JS_BEGIN_MACRO                                                            \        JSString *str_ = str;                                                 \        size_t length_ = JSSTRING_LENGTH(str_);                               \        if (stacklen + length_ > stackmax) {                                  \            void *ptr_;                                                       \            stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_));            \            ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar));   \            if (!ptr_) {                                                      \                ok = JS_FALSE;                                                \                goto done;                                                    \            }                                                                 \            stackbuf = ptr_;                                                  \        }                                                                     \        js_strncpy(stackbuf + stacklen, JSSTRING_CHARS(str_), length_);       \        stacklen += length_;                                                  \    JS_END_MACRO    for (fp = cx->fp; fp; fp = fp->down) {        if (checkAccess) {            v = (fp->fun && fp->argv) ? fp->argv[-2] : JSVAL_NULL;            if (!JSVAL_IS_PRIMITIVE(v)) {                ok = checkAccess(cx, fp->fun->object, callerid, JSACC_READ, &v);                if (!ok) {                    ok = JS_TRUE;                    break;                }            }        }        if (fp->fun) {            if (fp->fun->atom)                APPEND_STRING_TO_STACK(ATOM_TO_STRING(fp->fun->atom));            APPEND_CHAR_TO_STACK('(');            for (i = 0; i < fp->argc; i++) {                argsrc = js_ValueToSource(cx, fp->argv[i]);                if (!argsrc) {                    ok = JS_FALSE;                    goto done;                }                if (i > 0)                    APPEND_CHAR_TO_STACK(',');                APPEND_STRING_TO_STACK(argsrc);            }            APPEND_CHAR_TO_STACK(')');        }        APPEND_CHAR_TO_STACK('@');        if (fp->script && fp->script->filename) {            for (cp = fp->script->filename; *cp; cp++)                APPEND_CHAR_TO_STACK(*cp);        }        APPEND_CHAR_TO_STACK(':');        if (fp->script && fp->pc) {            ulineno = js_PCToLineNumber(fp->script, fp->pc);            JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", ulineno);            for (cp = ulnbuf; *cp; cp++)                APPEND_CHAR_TO_STACK(*cp);        } else {            APPEND_CHAR_TO_STACK('0');        }        APPEND_CHAR_TO_STACK('\n');    }#undef APPEND_CHAR_TO_STACK#undef APPEND_STRING_TO_STACKdone:    if (checkAccess) {        if (ok)            JS_RestoreExceptionState(cx, state);        else            JS_DropExceptionState(cx, state);        JS_SetErrorReporter(cx, older);    }    if (!ok) {        JS_free(cx, stackbuf);        return JS_FALSE;    }    if (!stackbuf) {        stack = cx->runtime->emptyString;    } else {        /* NB: if stackbuf was allocated, it has room for the terminator. */        JS_ASSERT(stacklen <= stackmax);        if (stacklen < stackmax) {            /*             * Realloc can fail when shrinking on some FreeBSD versions, so             * don't use JS_realloc here; simply let the oversized allocation             * be owned by the string in that rare case.             */            void *shrunk = realloc(stackbuf, (stacklen+1) * sizeof(jschar));            if (shrunk)                stackbuf = shrunk;        }        stackbuf[stacklen] = 0;        stack = js_NewString(cx, stackbuf, stacklen, 0);        if (!stack) {            JS_free(cx, stackbuf);            return JS_FALSE;        }    }    return JS_DefineProperty(cx, obj, js_stack_str,                             STRING_TO_JSVAL(stack),                             NULL, NULL, JSPROP_ENUMERATE);}