/* * This function is used to convert function arguments and return value (jsval) * into the following based on each value's type tag: * * jsval returned * ------------------- * STRING -> char * * INT -> int * DOUBLE -> double * * BOOLEAN -> int * OBJECT -> void * * * All are presented as void * for DTrace consumers to use, after shifting or * masking out the JavaScript type bits. This allows D scripts to use ints and * booleans directly and copyinstr() for string arguments, when types are known * beforehand. * * This is used by the function-args and function-rval probes, which also * provide raw (unmasked) jsvals should type info be useful from D scripts. */ void * jsdtrace_jsvaltovoid(JSContext *cx, jsval argval) { JSType type = TYPEOF(cx, argval); switch (type) { case JSTYPE_NULL: case JSTYPE_VOID: return JS_TYPE_STR(type); case JSTYPE_BOOLEAN: return (void *)JSVAL_TO_BOOLEAN(argval); case JSTYPE_STRING: return (void *)js_GetStringBytes(cx, JSVAL_TO_STRING(argval)); case JSTYPE_NUMBER: if (JSVAL_IS_INT(argval)) return (void *)JSVAL_TO_INT(argval); return JSVAL_TO_DOUBLE(argval); default: return JSVAL_TO_GCTHING(argval); } /* NOTREACHED */ }
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; }
char * jsdtrace_function_name(JSContext *cx, JSStackFrame *fp, JSFunction *fun) { JSAtom *atom; JSFrameRegs *regs; JSScript *script; jsbytecode *pc; char *name; atom = FUN_ATOM(fun); if (!atom) { if (fp->fun != fun || !fp->down) return dempty; regs = fp->down->regs; if (!regs) return dempty; /* * An anonymous function called from an active script or interpreted * function: try to fetch the variable or property name by which the * anonymous function was invoked. */ pc = regs->pc; script = fp->down->script; switch ((JSOp) *pc) { case JSOP_CALL: case JSOP_EVAL: JS_ASSERT(fp->argv == regs->sp - (int)GET_ARGC(pc)); /* * FIXME bug 422864: update this code to use the pc stack from the * decompiler. */ break; } switch ((JSOp) *pc) { case JSOP_CALLNAME: case JSOP_CALLPROP: case JSOP_NAME: case JSOP_SETNAME: case JSOP_GETPROP: case JSOP_SETPROP: GET_ATOM_FROM_BYTECODE(script, pc, 0, atom); break; case JSOP_CALLELEM: case JSOP_GETELEM: case JSOP_SETELEM: case JSOP_CALLGVAR: case JSOP_GETGVAR: case JSOP_SETGVAR: case JSOP_CALLVAR: case JSOP_CALLARG: case JSOP_CALLLOCAL: /* FIXME: try to recover a name from these ops. */ /* FALL THROUGH */ default: return dempty; } } name = (char *)js_GetStringBytes(cx, ATOM_TO_STRING(atom)); return name ? name : dempty; }
static const char * StringToFilename(JSContext *cx, JSString *str) { return js_GetStringBytes(cx, str); }
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; }