📄 jsexn.c
字号:
* 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,0},#endif {js_toString_str, exn_toString, 0,0,0}, {0,0,0,0,0}};JSObject *js_InitExceptionClasses(JSContext *cx, JSObject *obj){ int i; JSObject *protos[JSEXN_LIMIT]; /* Initialize the prototypes first. */ for (i = 0; exceptions[i].name != 0; i++) { JSAtom *atom; JSFunction *fun; JSString *nameString; int protoIndex = exceptions[i].protoIndex; /* Make the prototype for the current constructor name. */ protos[i] = js_NewObject(cx, &ExceptionClass, (protoIndex != JSEXN_NONE) ? protos[protoIndex] : NULL, obj); if (!protos[i]) return NULL; /* So exn_finalize knows whether to destroy private data. */ OBJ_SET_SLOT(cx, protos[i], JSSLOT_PRIVATE, JSVAL_VOID); atom = js_Atomize(cx, exceptions[i].name, strlen(exceptions[i].name), 0); if (!atom) return NULL; /* Make a constructor function for the current name. */ fun = js_DefineFunction(cx, obj, atom, exceptions[i].native, 3, 0); if (!fun) return NULL; /* Make this constructor make objects of class Exception. */ fun->clasp = &ExceptionClass; /* Make the prototype and constructor links. */ if (!js_SetClassPrototype(cx, fun->object, protos[i], JSPROP_READONLY | JSPROP_PERMANENT)) { return NULL; } /* proto bootstrap bit from JS_InitClass omitted. */ nameString = JS_NewStringCopyZ(cx, exceptions[i].name); if (!nameString) return NULL; /* Add the name property to the prototype. */ if (!JS_DefineProperty(cx, protos[i], js_name_str, STRING_TO_JSVAL(nameString), NULL, NULL, JSPROP_ENUMERATE)) { 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_lineno_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];}static JSExnType errorToExceptionNum[] = {#define MSG_DEF(name, number, count, exception, format) \ exception,#include "js.msg"#undef MSG_DEF};#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; JSExnType exn; JSBool ok; JSObject *errProto, *errObject; JSString *messageStr, *filenameStr; uintN lineno; JSExnPrivate *privateData; /* * 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; exn = errorToExceptionNum[errorNumber]; 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; cx->creatingException = JS_TRUE; /* * 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. * * XXXbe hack around JSCLASS_NEW_RESOLVE code in js_LookupProperty that * checks cx->fp, cx->fp->pc, and js_CodeSpec[*cx->fp->pc] in order * to compute resolve flags such as JSRESOLVE_ASSIGNING. The bug * is that this "internal" js_GetClassPrototype call may trigger a * resolve of exceptions[exn].name if the global object uses a lazy * standard class resolver (see JS_ResolveStandardClass), but the * current frame and bytecode end up affecting the resolve flags. */ { JSStackFrame *fp = cx->fp; jsbytecode *pc = NULL; if (fp) { pc = fp->pc; fp->pc = NULL; } ok = js_GetClassPrototype(cx, exceptions[exn].name, &errProto); if (pc) fp->pc = pc; if (!ok) goto out; } errObject = js_NewObject(cx, &ExceptionClass, errProto, NULL); if (!errObject) { ok = JS_FALSE; goto out; } /* * Set the generated Exception object early, so it won't be GC'd by a last * ditch attempt to collect garbage, or a GC that otherwise nests or races * under any of the following calls. If one of the following calls fails, * it will overwrite this exception object with one of its own (except in * case of OOM errors, of course). */ JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject)); messageStr = JS_NewStringCopyZ(cx, message); if (!messageStr) { ok = JS_FALSE; goto out; } if (reportp) { filenameStr = JS_NewStringCopyZ(cx, reportp->filename); if (!filenameStr) { ok = JS_FALSE; goto out; } lineno = reportp->lineno; } else { filenameStr = cx->runtime->emptyString; lineno = 0; } ok = InitExceptionObject(cx, errObject, messageStr, filenameStr, lineno); if (!ok) goto out; /* * Construct a new copy of the error report struct, and store it in the * exception object's private data. We can't use the error report struct * that was passed in, because it's stack-allocated, and also because it * may point to transient data in the JSTokenStream. */ privateData = exn_newPrivate(cx, reportp); if (!privateData) { ok = JS_FALSE; goto out; } OBJ_SET_SLOT(cx, errObject, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(privateData)); /* Flag the error report passed in to indicate an exception was raised. */ reportp->flags |= JSREPORT_EXCEPTION;out: cx->creatingException = JS_FALSE; return ok;}#endif /* JS_HAS_ERROR_EXCEPTIONS */#if JS_HAS_EXCEPTIONSJSBooljs_ReportUncaughtException(JSContext *cx){ JSObject *exnObject; JSString *str; jsval exn; JSErrorReport *reportp; const char *bytes; 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. */ if (JSVAL_IS_PRIMITIVE(exn)) { exnObject = NULL; } else { exnObject = JSVAL_TO_OBJECT(exn); if (!js_AddRoot(cx, &exnObject, "exn.report.root")) return JS_FALSE; }#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); JS_ClearPendingException(cx); return JS_TRUE;}#endif /* JS_HAS_EXCEPTIONS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -