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; }