Beispiel #1
0
/*
 * 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 */
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
static const char *
StringToFilename(JSContext *cx, JSString *str)
{
    return js_GetStringBytes(cx, str);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}