Esempio n. 1
0
JSBool
js_ReportUncaughtException(JSContext *cx)
{
    jsval exn;
    JSObject *exnObject;
    jsval roots[5];
    JSErrorReport *reportp, report;
    JSString *str;
    const char *bytes;

    if (!JS_IsExceptionPending(cx))
        return true;

    if (!JS_GetPendingException(cx, &exn))
        return false;

    PodArrayZero(roots);
    AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(roots), Valueify(roots));

    /*
     * Because js_ValueToString below could error and an exception object
     * could become unrooted, we must root exnObject.  Later, if exnObject is
     * non-null, we need to root other intermediates, so allocate an operand
     * stack segment to protect all of these values.
     */
    if (JSVAL_IS_PRIMITIVE(exn)) {
        exnObject = NULL;
    } else {
        exnObject = JSVAL_TO_OBJECT(exn);
        roots[0] = exn;
    }

    JS_ClearPendingException(cx);
    reportp = js_ErrorFromException(cx, exn);

    /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */
    str = js_ValueToString(cx, Valueify(exn));
    JSAutoByteString bytesStorage;
    if (!str) {
        bytes = "unknown (can't convert to string)";
    } else {
        roots[1] = STRING_TO_JSVAL(str);
        if (!bytesStorage.encode(cx, str))
            return false;
        bytes = bytesStorage.ptr();
    }

    JSAutoByteString filename;
    if (!reportp && exnObject && exnObject->getClass() == &js_ErrorClass) {
        if (!JS_GetProperty(cx, exnObject, js_message_str, &roots[2]))
            return false;
        if (JSVAL_IS_STRING(roots[2])) {
            bytesStorage.clear();
            if (!bytesStorage.encode(cx, str))
                return false;
            bytes = bytesStorage.ptr();
        }

        if (!JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]))
            return false;
        str = js_ValueToString(cx, Valueify(roots[3]));
        if (!str || !filename.encode(cx, str))
            return false;

        if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]))
            return false;
        uint32_t lineno;
        if (!ValueToECMAUint32(cx, Valueify(roots[4]), &lineno))
            return false;

        reportp = &report;
        PodZero(&report);
        report.filename = filename.ptr();
        report.lineno = (uintN) lineno;
        if (JSVAL_IS_STRING(roots[2])) {
            JSFixedString *fixed = JSVAL_TO_STRING(roots[2])->ensureFixed(cx);
            if (!fixed)
                return false;
            report.ucmessage = fixed->chars();
        }
    }

    if (!reportp) {
        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                             JSMSG_UNCAUGHT_EXCEPTION, bytes);
    } else {
        /* Flag the error as an exception. */
        reportp->flags |= JSREPORT_EXCEPTION;

        /* Pass the exception object. */
        JS_SetPendingException(cx, exn);
        js_ReportErrorAgain(cx, bytes, reportp);
        JS_ClearPendingException(cx);
    }

    return true;
}