📄 jsexn.c
字号:
* the backtrace procedure, not result in a failure of this constructor. */ checkAccess = cx->runtime->checkObjectAccess; if (checkAccess) { older = JS_SetErrorReporter(cx, NULL); state = JS_SaveExceptionState(cx); }#ifdef __GNUC__ /* suppress bogus gcc warnings */ else { older = NULL; state = NULL; }#endif callerid = ATOM_KEY(cx->runtime->atomState.callerAtom); /* * Prepare to allocate a jschar buffer at stackbuf, where stacklen indexes * the next free jschar slot, and with room for at most stackmax non-null * jschars. If stackbuf is non-null, it always contains an extra slot for * the null terminator we'll store at the end, as a backstop. * * All early returns must goto done after this point, till the after-loop * cleanup code has run! */ stackbuf = NULL; stacklen = stackmax = 0; ok = JS_TRUE;#define APPEND_CHAR_TO_STACK(c) \ JS_BEGIN_MACRO \ if (stacklen == stackmax) { \ void *ptr_; \ stackmax = stackmax ? 2 * stackmax : 64; \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) { \ ok = JS_FALSE; \ goto done; \ } \ stackbuf = ptr_; \ } \ stackbuf[stacklen++] = (c); \ JS_END_MACRO#define APPEND_STRING_TO_STACK(str) \ JS_BEGIN_MACRO \ JSString *str_ = str; \ size_t length_ = JSSTRING_LENGTH(str_); \ if (stacklen + length_ > stackmax) { \ void *ptr_; \ stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_)); \ ptr_ = JS_realloc(cx, stackbuf, (stackmax+1) * sizeof(jschar)); \ if (!ptr_) { \ ok = JS_FALSE; \ goto done; \ } \ stackbuf = ptr_; \ } \ js_strncpy(stackbuf + stacklen, JSSTRING_CHARS(str_), length_); \ stacklen += length_; \ JS_END_MACRO for (fp = cx->fp; fp; fp = fp->down) { if (checkAccess) { v = (fp->fun && fp->argv) ? fp->argv[-2] : JSVAL_NULL; if (!JSVAL_IS_PRIMITIVE(v)) { ok = checkAccess(cx, fp->fun->object, callerid, JSACC_READ, &v); if (!ok) { ok = JS_TRUE; break; } } } if (fp->fun) { if (fp->fun->atom) APPEND_STRING_TO_STACK(ATOM_TO_STRING(fp->fun->atom)); APPEND_CHAR_TO_STACK('('); for (i = 0; i < fp->argc; i++) { /* Avoid toSource bloat and fallibility for object types. */ v = fp->argv[i]; if (JSVAL_IS_PRIMITIVE(v)) { argsrc = js_ValueToSource(cx, v); } else if (JSVAL_IS_FUNCTION(cx, v)) { /* XXX Avoid function decompilation bloat for now. */ argsrc = JS_GetFunctionId(JS_ValueToFunction(cx, v)); if (!argsrc) argsrc = js_ValueToSource(cx, v); } else { /* XXX Avoid toString on objects, it takes too long and uses too much memory, for too many classes (see Mozilla bug 166743). */ char buf[100]; JS_snprintf(buf, sizeof buf, "[object %s]", OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v))->name); argsrc = JS_NewStringCopyZ(cx, buf); } if (!argsrc) { ok = JS_FALSE; goto done; } if (i > 0) APPEND_CHAR_TO_STACK(','); APPEND_STRING_TO_STACK(argsrc); } APPEND_CHAR_TO_STACK(')'); } APPEND_CHAR_TO_STACK('@'); if (fp->script && fp->script->filename) { for (cp = fp->script->filename; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } APPEND_CHAR_TO_STACK(':'); if (fp->script && fp->pc) { ulineno = js_PCToLineNumber(cx, fp->script, fp->pc); JS_snprintf(ulnbuf, sizeof ulnbuf, "%u", ulineno); for (cp = ulnbuf; *cp; cp++) APPEND_CHAR_TO_STACK(*cp); } else { APPEND_CHAR_TO_STACK('0'); } APPEND_CHAR_TO_STACK('\n'); }#undef APPEND_CHAR_TO_STACK#undef APPEND_STRING_TO_STACKdone: if (checkAccess) { if (ok) JS_RestoreExceptionState(cx, state); else JS_DropExceptionState(cx, state); JS_SetErrorReporter(cx, older); } if (!ok) { JS_free(cx, stackbuf); return JS_FALSE; } if (!stackbuf) { stack = cx->runtime->emptyString; } else { /* NB: if stackbuf was allocated, it has room for the terminator. */ JS_ASSERT(stacklen <= stackmax); if (stacklen < stackmax) { /* * Realloc can fail when shrinking on some FreeBSD versions, so * don't use JS_realloc here; simply let the oversized allocation * be owned by the string in that rare case. */ void *shrunk = realloc(stackbuf, (stacklen+1) * sizeof(jschar)); if (shrunk) stackbuf = shrunk; } stackbuf[stacklen] = 0; stack = js_NewString(cx, stackbuf, stacklen, 0); if (!stack) { JS_free(cx, stackbuf); return JS_FALSE; } } return JS_DefineProperty(cx, obj, js_stack_str, STRING_TO_JSVAL(stack), NULL, NULL, JSPROP_ENUMERATE);}static JSBoolException(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSBool ok; jsval pval; int32 lineno; JSString *message, *filename; if (cx->creatingException) return JS_FALSE; cx->creatingException = JS_TRUE; if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) { /* * ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when * called as functions, without operator new. But as we do not give * each constructor a distinct JSClass, whose .name member is used by * js_NewObject to find the class prototype, we must get the class * prototype ourselves. */ ok = OBJ_GET_PROPERTY(cx, JSVAL_TO_OBJECT(argv[-2]), (jsid)cx->runtime->atomState.classPrototypeAtom, &pval); if (!ok) goto out; obj = js_NewObject(cx, &ExceptionClass, JSVAL_TO_OBJECT(pval), NULL); if (!obj) { ok = JS_FALSE; goto out; } *rval = OBJECT_TO_JSVAL(obj); } /* * If it's a new object of class Exception, then null out the private * data so that the finalizer doesn't attempt to free it. */ if (OBJ_GET_CLASS(cx, obj) == &ExceptionClass) OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, JSVAL_VOID); /* Set the 'message' property. */ if (argc != 0) { message = js_ValueToString(cx, argv[0]); if (!message) { ok = JS_FALSE; goto out; } argv[0] = STRING_TO_JSVAL(message); } else { message = cx->runtime->emptyString; } /* Set the 'fileName' property. */ if (argc > 1) { filename = js_ValueToString(cx, argv[1]); if (!filename) { ok = JS_FALSE; goto out; } argv[1] = STRING_TO_JSVAL(filename); } else { filename = cx->runtime->emptyString; } /* Set the 'lineNumber' property. */ if (argc > 2) { ok = js_ValueToInt32(cx, argv[2], &lineno); if (!ok) goto out; } else { lineno = 0; } ok = InitExceptionObject(cx, obj, message, filename, lineno);out: cx->creatingException = JS_FALSE; return ok;}/* * Convert to string. * * This method only uses JavaScript-modifiable properties name, message. It * is left to the host to check for private data and report filename and line * number information along with this message. */static JSBoolexn_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ jsval v; JSString *name, *message, *result; jschar *chars, *cp; size_t name_length, message_length, length; if (!OBJ_GET_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.nameAtom, &v)) return JS_FALSE; name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString; if (!JS_GetProperty(cx, obj, js_message_str, &v)) return JS_FALSE; message = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString; if (JSSTRING_LENGTH(message) != 0) { name_length = JSSTRING_LENGTH(name); message_length = JSSTRING_LENGTH(message); length = (name_length ? name_length + 2 : 0) + message_length; cp = chars = (jschar*) JS_malloc(cx, (length + 1) * sizeof(jschar)); if (!chars) return JS_FALSE; if (name_length) { js_strncpy(cp, JSSTRING_CHARS(name), name_length); cp += name_length; *cp++ = ':'; *cp++ = ' '; } js_strncpy(cp, JSSTRING_CHARS(message), message_length); cp += message_length; *cp = 0; result = js_NewString(cx, chars, length, 0); if (!result) { JS_free(cx, chars); return JS_FALSE; } } else { result = name; } *rval = STRING_TO_JSVAL(result); return JS_TRUE;}#if JS_HAS_TOSOURCE/* * Return a string that may eval to something similar to the original object. */static JSBoolexn_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ jsval v; JSString *name, *message, *filename, *lineno_as_str, *result; int32 lineno; size_t lineno_length, name_length, message_length, filename_length, length; jschar *chars, *cp; if (!OBJ_GET_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.nameAtom, &v)) return JS_FALSE; name = js_ValueToString(cx, v); if (!name) return JS_FALSE; if (!JS_GetProperty(cx, obj, js_message_str, &v) || !(message = js_ValueToSource(cx, v))) { return JS_FALSE; } if (!JS_GetProperty(cx, obj, js_filename_str, &v) || !(filename = js_ValueToSource(cx, v))) { return JS_FALSE; } if (!JS_GetProperty(cx, obj, js_lineno_str, &v) || !js_ValueToInt32 (cx, v, &lineno)) { return JS_FALSE; } if (lineno != 0) { if (!(lineno_as_str = js_ValueToString(cx, v))) { 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) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -