📄 jsexn.c
字号:
if (!name) return JS_FALSE; *rval = STRING_TO_JSVAL(name); if (!JS_GetProperty(cx, obj, js_message_str, &vp[0]) || !(message = js_ValueToSource(cx, vp[0]))) { return JS_FALSE; } vp[0] = STRING_TO_JSVAL(message); if (!JS_GetProperty(cx, obj, js_fileName_str, &vp[1]) || !(filename = js_ValueToSource(cx, vp[1]))) { return JS_FALSE; } vp[1] = STRING_TO_JSVAL(filename); if (!JS_GetProperty(cx, obj, js_lineNumber_str, &vp[2]) || !js_ValueToECMAUint32 (cx, vp[2], &lineno)) { return JS_FALSE; } if (lineno != 0) { lineno_as_str = js_ValueToString(cx, vp[2]); if (!lineno_as_str) return JS_FALSE; lineno_length = JSSTRING_LENGTH(lineno_as_str); } else { lineno_as_str = NULL; lineno_length = 0; } /* Magic 8, for the characters in ``(new ())''. */ name_length = JSSTRING_LENGTH(name); message_length = JSSTRING_LENGTH(message); length = 8 + name_length + message_length; filename_length = JSSTRING_LENGTH(filename); if (filename_length != 0) { /* append filename as ``, {filename}'' */ length += 2 + filename_length; if (lineno_as_str) { /* append lineno as ``, {lineno_as_str}'' */ length += 2 + lineno_length; } } else { if (lineno_as_str) { /* * no filename, but have line number, * need to append ``, "", {lineno_as_str}'' */ length += 6 + lineno_length; } } cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; *cp++ = '('; *cp++ = 'n'; *cp++ = 'e'; *cp++ = 'w'; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(name), name_length); cp += name_length; *cp++ = '('; if (message_length != 0) { js_strncpy(cp, JSSTRING_CHARS(message), message_length); cp += message_length; } if (filename_length != 0) { /* append filename as ``, {filename}'' */ *cp++ = ','; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(filename), filename_length); cp += filename_length; } else { if (lineno_as_str) { /* * no filename, but have line number, * need to append ``, "", {lineno_as_str}'' */ *cp++ = ','; *cp++ = ' '; *cp++ = '"'; *cp++ = '"'; } } if (lineno_as_str) { /* append lineno as ``, {lineno_as_str}'' */ *cp++ = ','; *cp++ = ' '; js_strncpy(cp, JSSTRING_CHARS(lineno_as_str), lineno_length); cp += lineno_length; } *cp++ = ')'; *cp++ = ')'; *cp = 0; result = js_NewString(cx, chars, length, 0); if (!result) { JS_free(cx, chars); return JS_FALSE; } *rval = STRING_TO_JSVAL(result); return JS_TRUE;}#endifstatic JSFunctionSpec exception_methods[] = {#if JS_HAS_TOSOURCE {js_toSource_str, exn_toSource, 0,0,3},#endif {js_toString_str, exn_toString, 0,0,0}, {0,0,0,0,0}};JSObject *js_InitExceptionClasses(JSContext *cx, JSObject *obj){ JSObject *obj_proto, *protos[JSEXN_LIMIT]; int i; /* * If lazy class initialization occurs for any Error subclass, then all * classes are initialized, starting with Error. To avoid reentry and * redundant initialization, we must not pass a null proto parameter to * js_NewObject below, when called for the Error superclass. We need to * ensure that Object.prototype is the proto of Error.prototype. * * See the equivalent code to ensure that parent_proto is non-null when * JS_InitClass calls js_NewObject, in jsapi.c. */ if (!js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object), &obj_proto)) { return NULL; } if (!js_EnterLocalRootScope(cx)) return NULL; /* Initialize the prototypes first. */ for (i = 0; exceptions[i].name != 0; i++) { JSAtom *atom; JSFunction *fun; JSObject *funobj; JSString *nameString; int protoIndex = exceptions[i].protoIndex; /* Make the prototype for the current constructor name. */ protos[i] = js_NewObject(cx, &js_ErrorClass, (protoIndex != JSEXN_NONE) ? protos[protoIndex] : obj_proto, obj); if (!protos[i]) break; /* So exn_finalize knows whether to destroy private data. */ OBJ_SET_SLOT(cx, protos[i], JSSLOT_PRIVATE, JSVAL_VOID); /* Make a constructor function for the current name. */ atom = cx->runtime->atomState.classAtoms[exceptions[i].key]; fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0); if (!fun) break; /* Make this constructor make objects of class Exception. */ fun->clasp = &js_ErrorClass; /* Extract the constructor object. */ funobj = fun->object; /* Make the prototype and constructor links. */ if (!js_SetClassPrototype(cx, funobj, protos[i], JSPROP_READONLY | JSPROP_PERMANENT)) { break; } /* proto bootstrap bit from JS_InitClass omitted. */ nameString = JS_NewStringCopyZ(cx, exceptions[i].name); if (!nameString) break; /* Add the name property to the prototype. */ if (!JS_DefineProperty(cx, protos[i], js_name_str, STRING_TO_JSVAL(nameString), NULL, NULL, JSPROP_ENUMERATE)) { break; } /* Finally, stash the constructor for later uses. */ if (!js_SetClassObject(cx, obj, exceptions[i].key, funobj)) break; } js_LeaveLocalRootScope(cx); if (exceptions[i].name) return NULL; /* * Add an empty message property. (To Exception.prototype only, * because this property will be the same for all the exception * protos.) */ if (!JS_DefineProperty(cx, protos[0], js_message_str, STRING_TO_JSVAL(cx->runtime->emptyString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } if (!JS_DefineProperty(cx, protos[0], js_fileName_str, STRING_TO_JSVAL(cx->runtime->emptyString), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } if (!JS_DefineProperty(cx, protos[0], js_lineNumber_str, INT_TO_JSVAL(0), NULL, NULL, JSPROP_ENUMERATE)) { return NULL; } /* * Add methods only to Exception.prototype, because ostensibly all * exception types delegate to that. */ if (!JS_DefineFunctions(cx, protos[0], exception_methods)) return NULL; return protos[0];}const JSErrorFormatString*js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale, const uintN errorNumber){ const JSErrorFormatString *errorString = NULL; if (cx->localeCallbacks && cx->localeCallbacks->localeGetErrorMessage) { errorString = cx->localeCallbacks ->localeGetErrorMessage(userRef, locale, errorNumber); } if (!errorString) errorString = js_GetErrorMessage(userRef, locale, errorNumber); return errorString;}#if defined ( DEBUG_mccabe ) && defined ( PRINTNAMES )/* For use below... get character strings for error name and exception name */static struct exnname { char *name; char *exception; } errortoexnname[] = {#define MSG_DEF(name, number, count, exception, format) \ {#name, #exception},#include "js.msg"#undef MSG_DEF};#endif /* DEBUG */JSBooljs_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp){ JSErrNum errorNumber; const JSErrorFormatString *errorString; JSExnType exn; jsval tv[4]; JSTempValueRooter tvr; JSBool ok; JSObject *errProto, *errObject; JSString *messageStr, *filenameStr; /* * Tell our caller to report immediately if cx has no active frames, or if * this report is just a warning. */ JS_ASSERT(reportp); if (!cx->fp || JSREPORT_IS_WARNING(reportp->flags)) return JS_FALSE; /* Find the exception index associated with this error. */ errorNumber = (JSErrNum) reportp->errorNumber; errorString = js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber); exn = errorString ? errorString->exnType : JSEXN_NONE; JS_ASSERT(exn < JSEXN_LIMIT);#if defined( DEBUG_mccabe ) && defined ( PRINTNAMES ) /* Print the error name and the associated exception name to stderr */ fprintf(stderr, "%s\t%s\n", errortoexnname[errorNumber].name, errortoexnname[errorNumber].exception);#endif /* * Return false (no exception raised) if no exception is associated * with the given error number. */ if (exn == JSEXN_NONE) return JS_FALSE; /* * Prevent runaway recursion, just as the Exception native constructor * must do, via cx->creatingException. If an out-of-memory error occurs, * no exception object will be created, but we don't assume that OOM is * the only kind of error that subroutines of this function called below * might raise. */ if (cx->creatingException) return JS_FALSE; /* After this point the control must flow through the label out. */ cx->creatingException = JS_TRUE; /* Protect the newly-created strings below from nesting GCs. */ memset(tv, 0, sizeof tv); JS_PUSH_TEMP_ROOT(cx, sizeof tv / sizeof tv[0], tv, &tvr); /* * Try to get an appropriate prototype by looking up the corresponding * exception constructor name in the scope chain of the current context's * top stack frame, or in the global object if no frame is active. */ ok = js_GetClassPrototype(cx, NULL, INT_TO_JSID(exceptions[exn].key), &errProto); if (!ok) goto out; tv[0] = OBJECT_TO_JSVAL(errProto); errObject = js_NewObject(cx, &js_ErrorClass, errProto, NULL); if (!errObject) { ok = JS_FALSE; goto out; } tv[1] = OBJECT_TO_JSVAL(errObject); messageStr = JS_NewStringCopyZ(cx, message); if (!messageStr) { ok = JS_FALSE; goto out; } tv[2] = STRING_TO_JSVAL(messageStr); filenameStr = JS_NewStringCopyZ(cx, reportp->filename); if (!filenameStr) { ok = JS_FALSE; goto out; } tv[3] = STRING_TO_JSVAL(filenameStr); ok = InitExnPrivate(cx, errObject, messageStr, filenameStr, reportp->lineno, reportp); if (!ok) goto out; JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject)); /* Flag the error report passed in to indicate an exception was raised. */ reportp->flags |= JSREPORT_EXCEPTION;out: JS_POP_TEMP_ROOT(cx, &tvr); cx->creatingException = JS_FALSE; return ok;}JSBooljs_ReportUncaughtException(JSContext *cx){ jsval exn; JSObject *exnObject; jsval vp[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; /* * 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); vp[0] = exn; memset(vp + 1, 0, sizeof vp - sizeof vp[0]); JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(vp), vp, &tvr); } 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 { if (exnObject) vp[1] = STRING_TO_JSVAL(str); bytes = js_GetStringBytes(cx->runtime, str); } 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, &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_lineNumber_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); }out: if (exnObject) JS_POP_TEMP_ROOT(cx, &tvr); return ok;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -