static void ReportError(JSContext *cx, const char *message, JSErrorReport *reportp) { /* * Check the error report, and set a JavaScript-catchable exception * if the error is defined to have an associated exception. If an * exception is thrown, then the JSREPORT_EXCEPTION flag will be set * on the error report, and exception-aware hosts should ignore it. */ if (reportp && reportp->errorNumber == JSMSG_UNCAUGHT_EXCEPTION) reportp->flags |= JSREPORT_EXCEPTION; #if JS_HAS_ERROR_EXCEPTIONS /* * Call the error reporter only if an exception wasn't raised. * * If an exception was raised, then we call the debugErrorHook * (if present) to give it a chance to see the error before it * propagates out of scope. This is needed for compatability * with the old scheme. */ if (!js_ErrorToException(cx, message, reportp)) { js_ReportErrorAgain(cx, message, reportp); } else if (cx->runtime->debugErrorHook && cx->errorReporter) { JSDebugErrorHook hook = cx->runtime->debugErrorHook; /* test local in case debugErrorHook changed on another thread */ if (hook) hook(cx, message, reportp, cx->runtime->debugErrorHookData); } #else js_ReportErrorAgain(cx, message, reportp); #endif }
void js_ReportErrorVA(JSContext *cx, const char *format, va_list ap) { JSStackFrame *fp; JSErrorReport report, *reportp; char *last; fp = cx->fp; if (fp && fp->script && fp->pc) { report.filename = fp->script->filename; report.lineno = js_PCToLineNumber(fp->script, fp->pc); /* XXX should fetch line somehow */ report.linebuf = NULL; report.tokenptr = NULL; reportp = &report; } else { reportp = NULL; } last = PR_vsmprintf(format, ap); if (!last) return; js_ReportErrorAgain(cx, last, reportp); free(last); }
JSBool js_ReportUncaughtException(JSContext *cx) { JSObject *exnObject; JSString *str; jsval exn; JSErrorReport *reportp; const char *bytes; if (!JS_IsExceptionPending(cx)) return JS_FALSE; if (!JS_GetPendingException(cx, &exn)) return JS_FALSE; /* * Because js_ValueToString below could error and an exception object * could become unrooted, we root it here. */ if (JSVAL_IS_OBJECT(exn) && exn != JSVAL_NULL) { exnObject = JSVAL_TO_OBJECT(exn); if (!js_AddRoot(cx, &exnObject, "exn.report.root")) return JS_FALSE; } else { exnObject = NULL; } #if JS_HAS_ERROR_EXCEPTIONS reportp = js_ErrorFromException(cx, exn); #else reportp = NULL; #endif str = js_ValueToString(cx, exn); bytes = str ? js_GetStringBytes(str) : "null"; if (reportp == NULL) { /* * XXXmccabe todo: Instead of doing this, synthesize an error report * struct that includes the filename, lineno where the exception was * originally thrown. */ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNCAUGHT_EXCEPTION, bytes); } else { /* Flag the error as an exception. */ reportp->flags |= JSREPORT_EXCEPTION; js_ReportErrorAgain(cx, bytes, reportp); } if (exnObject != NULL) js_RemoveRoot(cx->runtime, &exnObject); return JS_TRUE; }
/* * This function is called up returning from Java back into JS as a result of * a thrown netscape.javascript.JSException, which itself must have been caused * by a JS error when Java called into JS. The original JS error is * reconstituted from the JSException and re-reported as a JS error. * * Returns JS_FALSE if an internal error occurs, JS_TRUE otherwise. */ JSBool jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception) { JSBool success; JSErrorReport report; const char *linebuf, *filename, *message, *tokenptr; jint lineno, token_index; jstring linebuf_jstr, filename_jstr, message_jstr; /* Initialize everything to NULL */ memset(&report, 0, sizeof(JSErrorReport)); success = JS_FALSE; filename_jstr = linebuf_jstr = message_jstr = NULL; filename = message = linebuf = tokenptr = NULL; lineno = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno); report.lineno = lineno; filename_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_filename); if ((*jEnv)->ExceptionOccurred(jEnv)) { jsj_UnexpectedJavaError(cx, jEnv, "Unable to access filename field of a JSException"); goto done; } if (filename_jstr) filename = (*jEnv)->GetStringUTFChars(jEnv, filename_jstr, 0); report.filename = filename; linebuf_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_source); if ((*jEnv)->ExceptionOccurred(jEnv)) { jsj_UnexpectedJavaError(cx, jEnv, "Unable to access source field of a JSException"); goto done; } if (linebuf_jstr) linebuf = (*jEnv)->GetStringUTFChars(jEnv, linebuf_jstr, 0); report.linebuf = linebuf; token_index = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno); report.tokenptr = linebuf + token_index; message_jstr = (*jEnv)->CallObjectMethod(jEnv, java_exception, jlThrowable_getMessage); if ((*jEnv)->ExceptionOccurred(jEnv)) { jsj_UnexpectedJavaError(cx, jEnv, "Unable to access message of a JSException"); goto done; } if (message_jstr) message = (*jEnv)->GetStringUTFChars(jEnv, message_jstr, 0); js_ReportErrorAgain(cx, message, &report); success = JS_TRUE; done: if (filename_jstr && filename) (*jEnv)->ReleaseStringUTFChars(jEnv, filename_jstr, filename); if (linebuf_jstr && linebuf) (*jEnv)->ReleaseStringUTFChars(jEnv, linebuf_jstr, linebuf); if (message_jstr && message) (*jEnv)->ReleaseStringUTFChars(jEnv, message_jstr, message); return success; }
JSBool js_ReportUncaughtException(JSContext *cx) { jsval exn; JSObject *exnObject; jsval roots[5]; JSTempValueRooter tvr; JSErrorReport *reportp, report; JSString *str; const char *bytes; JSBool ok; if (!JS_IsExceptionPending(cx)) return JS_TRUE; if (!JS_GetPendingException(cx, &exn)) return JS_FALSE; memset(roots, 0, sizeof roots); JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(roots), roots, &tvr); /* * 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, exn); if (!str) { bytes = "unknown (can't convert to string)"; } else { roots[1] = STRING_TO_JSVAL(str); bytes = js_GetStringBytes(cx, str); if (!bytes) { ok = JS_FALSE; goto out; } } ok = JS_TRUE; if (!reportp && exnObject && OBJ_GET_CLASS(cx, exnObject) == &js_ErrorClass) { const char *filename; uint32 lineno; ok = JS_GetProperty(cx, exnObject, js_message_str, &roots[2]); if (!ok) goto out; if (JSVAL_IS_STRING(roots[2])) { bytes = js_GetStringBytes(cx, JSVAL_TO_STRING(roots[2])); if (!bytes) { ok = JS_FALSE; goto out; } } ok = JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]); if (!ok) goto out; str = js_ValueToString(cx, roots[3]); if (!str) { ok = JS_FALSE; goto out; } filename = StringToFilename(cx, str); if (!filename) { ok = JS_FALSE; goto out; } ok = JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]); if (!ok) goto out; lineno = js_ValueToECMAUint32 (cx, &roots[4]); ok = !JSVAL_IS_NULL(roots[4]); if (!ok) goto out; reportp = &report; memset(&report, 0, sizeof report); report.filename = filename; report.lineno = (uintN) lineno; } 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); } out: JS_POP_TEMP_ROOT(cx, &tvr); return ok; }
JSBool js_ReportUncaughtException(JSContext *cx) { jsval exn, *vp; JSObject *exnObject; void *mark; JSErrorReport *reportp, report; JSString *str; const char *bytes; JSBool ok; if (!JS_IsExceptionPending(cx)) return JS_TRUE; if (!JS_GetPendingException(cx, &exn)) return JS_FALSE; /* * 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; vp = NULL; #ifdef __GNUC__ /* suppress bogus gcc warnings */ mark = NULL; #endif } else { exnObject = JSVAL_TO_OBJECT(exn); vp = js_AllocStack(cx, 5, &mark); if (!vp) { ok = JS_FALSE; goto out; } vp[0] = exn; } #if JS_HAS_ERROR_EXCEPTIONS reportp = js_ErrorFromException(cx, exn); #else reportp = NULL; #endif /* XXX L10N angels cry once again (see also jsemit.c, /L10N gaffes/) */ str = js_ValueToString(cx, exn); if (!str) { bytes = "unknown (can't convert to string)"; } else { if (vp) vp[1] = STRING_TO_JSVAL(str); bytes = js_GetStringBytes(str); } ok = JS_TRUE; if (!reportp && exnObject && OBJ_GET_CLASS(cx, exnObject) == &ExceptionClass) { const char *filename; uint32 lineno; ok = JS_GetProperty(cx, exnObject, js_message_str, &vp[2]); if (!ok) goto out; if (JSVAL_IS_STRING(vp[2])) bytes = JS_GetStringBytes(JSVAL_TO_STRING(vp[2])); ok = JS_GetProperty(cx, exnObject, js_filename_str, &vp[3]); if (!ok) goto out; str = js_ValueToString(cx, vp[3]); if (!str) { ok = JS_FALSE; goto out; } filename = StringToFilename(cx, str); ok = JS_GetProperty(cx, exnObject, js_lineno_str, &vp[4]); if (!ok) goto out; ok = js_ValueToECMAUint32 (cx, vp[4], &lineno); if (!ok) goto out; reportp = &report; memset(&report, 0, sizeof report); report.filename = filename; report.lineno = (uintN) lineno; } if (!reportp) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNCAUGHT_EXCEPTION, bytes); } else { /* Flag the error as an exception. */ reportp->flags |= JSREPORT_EXCEPTION; js_ReportErrorAgain(cx, bytes, reportp); } JS_ClearPendingException(cx); out: if (exnObject) js_FreeStack(cx, mark); return ok; }