Пример #1
0
// Even with autoJSAPIOwnsErrorReporting, the JS engine still sends warning
// reports to the JSErrorReporter as soon as they are generated. These go
// directly to the console, so we can handle them easily here.
//
// Eventually, SpiderMonkey will have a special-purpose callback for warnings
// only.
void
WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep)
{
  MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
  if (!NS_IsMainThread()) {
    // Reporting a warning on workers is a bit complicated because we have to
    // climb our parent chain until we get to the main thread.  So go ahead and
    // just go through the worker ReportError codepath here.
    //
    // That said, it feels like we should be able to short-circuit things a bit
    // here by posting an appropriate runnable to the main thread directly...
    // Worth looking into sometime.
    workers::WorkerPrivate* worker = workers::GetWorkerPrivateFromContext(aCx);
    MOZ_ASSERT(worker);

    worker->ReportError(aCx, aMessage, aRep);
    return;
  }

  RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
  nsGlobalWindow* win = xpc::CurrentWindowOrNull(aCx);
  xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
                  win ? win->AsInner()->WindowID() : 0);
  xpcReport->LogToConsole();
}
Пример #2
0
static void
error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
{
	unsigned char *strict, *exception, *warning, *error;
	struct string msg;

	if (!init_string(&msg)) goto reported;

	strict	  = JSREPORT_IS_STRICT(report->flags) ? " strict" : "";
	exception = JSREPORT_IS_EXCEPTION(report->flags) ? " exception" : "";
	warning   = JSREPORT_IS_WARNING(report->flags) ? " warning" : "";
	error	  = !report->flags ? " error" : "";

	add_format_to_string(&msg, "A client script raised the following%s%s%s%s",
			strict, exception, warning, error);

	add_to_string(&msg, ":\n\n");
	add_to_string(&msg, message);

	if (report->linebuf && report->tokenptr) {
		int pos = report->tokenptr - report->linebuf;

		add_format_to_string(&msg, "\n\n%s\n.%*s^%*s.",
			       report->linebuf,
			       pos - 2, " ",
			       strlen(report->linebuf) - pos - 1, " ");
	}

	alert_smjs_error(msg.source);
	done_string(&msg);

reported:
	JS_ClearPendingException(ctx);
}
Пример #3
0
//---------------------------------------------------------------------------
void printError(JSContext *cx, const char *message, JSErrorReport *report) {
    char *cstr = 0;
    int  where;

    fprintf(stderr, "JSERROR: %s:%d:\n    %s\n",
            (report->filename ? report->filename : "NULL"),
            report->lineno,
            message);
    if (report->linebuf) {
        cstr = (char *)report->linebuf;
        fprintf(stderr, "    \"%s\"\n", cstr);
        if (report->tokenptr) {
            where = report->tokenptr - report->linebuf;
            /* Todo: 80 */
            if ((where >= 0) && (where < 80)) {
                where += 6;
                while (--where > 0) fputc(' ', stderr);
                fprintf(stderr, "^\n");
            }
        }
    }
    fprintf(stderr, "    Flags:");
    if (JSREPORT_IS_WARNING(report->flags)) fprintf(stderr, " WARNING");
    if (JSREPORT_IS_EXCEPTION(report->flags)) fprintf(stderr, " EXCEPTION");
    if (JSREPORT_IS_STRICT(report->flags)) fprintf(stderr, " STRICT");
    fprintf(stderr, " (Error number: %d)\n", report->errorNumber);
    /* print exception object */
    //printJSException(cx);
}
Пример #4
0
void MozJSImplScope::_reportError(JSContext* cx, const char* message, JSErrorReport* report) {
    auto scope = getScope(cx);

    if (!JSREPORT_IS_WARNING(report->flags)) {
        str::stream ss;
        ss << message;

        // TODO: something far more elaborate that mimics the stack printing from v8
        JS::RootedValue excn(cx);
        if (JS_GetPendingException(cx, &excn) && excn.isObject()) {
            JS::RootedValue stack(cx);

            ObjectWrapper(cx, excn).getValue("stack", &stack);

            auto str = ValueWriter(cx, stack).toString();

            if (str.empty()) {
                ss << " @" << report->filename << ":" << report->lineno << ":" << report->column
                   << "\n";
            } else {
                ss << " :\n" << str;
            }
        }

        scope->_status = Status(
            JSErrorReportToStatus(cx, report, ErrorCodes::JSInterpreterFailure, message).code(),
            ss);
    }
}
Пример #5
0
static void
PACWarningReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aReport)
{
  MOZ_ASSERT(aReport);
  MOZ_ASSERT(JSREPORT_IS_WARNING(aReport->flags));

  PACLogErrorOrWarning(NS_LITERAL_STRING("Warning"), aReport);
}
Пример #6
0
void
couch_error(JSContext* cx, const char* mesg, JSErrorReport* report)
{
    if(!report || !JSREPORT_IS_WARNING(report->flags))
    {
        fprintf(stderr, "[couchjs] %s\n", mesg);
    }
}
Пример #7
0
/*
 * The arguments from ap need to be packaged up into an array and stored
 * into the report struct.
 *
 * The format string addressed by the error number may contain operands
 * identified by the format {N}, where N is a decimal digit. Each of these
 * is to be replaced by the Nth argument from the va_list. The complete
 * message is placed into reportp->ucmessage converted to a JSString.
 *
 * Returns true if the expansion succeeds (can fail if out of memory).
 */
JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
                        void *userRef, const uintN errorNumber,
                        char **messagep, JSErrorReport *reportp,
                        JSBool *warningp, JSBool charArgs, va_list ap)
{
    const JSErrorFormatString *efs;
    int i;
    int argCount;

    *warningp = JSREPORT_IS_WARNING(reportp->flags);
    if (*warningp && JS_HAS_WERROR_OPTION(cx)) {
        reportp->flags &= ~JSREPORT_WARNING;
        *warningp = JS_FALSE;
    }

    *messagep = NULL;

    /* Most calls supply js_GetErrorMessage; if this is so, assume NULL. */
    if (!callback || callback == js_GetErrorMessage)
        efs = js_GetLocalizedErrorMessage(cx, userRef, NULL, errorNumber);
    else
        efs = callback(userRef, NULL, errorNumber);
    if (efs) {
        size_t totalArgsLength = 0;
        size_t argLengths[10]; /* only {0} thru {9} supported */
        argCount = efs->argCount;
        JS_ASSERT(argCount <= 10);
        if (argCount > 0) {
            /*
             * Gather the arguments into an array, and accumulate
             * their sizes. We allocate 1 more than necessary and
             * null it out to act as the caboose when we free the
             * pointers later.
             */
            reportp->messageArgs = (const jschar **)
                JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
            if (!reportp->messageArgs)
                return JS_FALSE;
            reportp->messageArgs[argCount] = NULL;
            for (i = 0; i < argCount; i++) {
                if (charArgs) {
                    char *charArg = va_arg(ap, char *);
                    size_t charArgLength = strlen(charArg);
                    reportp->messageArgs[i]
                        = js_InflateString(cx, charArg, &charArgLength);
                    if (!reportp->messageArgs[i])
                        goto error;
                } else {
                    reportp->messageArgs[i] = va_arg(ap, jschar *);
                }
                argLengths[i] = js_strlen(reportp->messageArgs[i]);
                totalArgsLength += argLengths[i];
            }
            /* NULL-terminate for easy copying. */
            reportp->messageArgs[i] = NULL;
        }
void JS_DLL_CALLBACK
mozJSLoaderErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep)
{
    nsresult rv;

    /* Use the console service to register the error. */
    nsCOMPtr<nsIConsoleService> consoleService =
        do_GetService(NS_CONSOLESERVICE_CONTRACTID);

    /*
     * Make an nsIScriptError, populate it with information from this
     * error, then log it with the console service.  The UI can then
     * poll the service to update the Error console.
     */
    nsCOMPtr<nsIScriptError> errorObject = 
        do_CreateInstance(NS_SCRIPTERROR_CONTRACTID);
    
    if (consoleService && errorObject) {
        /*
         * Got an error object; prepare appropriate-width versions of
         * various arguments to it.
         */
        nsAutoString fileUni;
        fileUni.AssignWithConversion(rep->filename);

        PRUint32 column = rep->uctokenptr - rep->uclinebuf;

        rv = errorObject->Init(reinterpret_cast<const PRUnichar*>
                                               (rep->ucmessage),
                               fileUni.get(),
                               reinterpret_cast<const PRUnichar*>
                                               (rep->uclinebuf),
                               rep->lineno, column, rep->flags,
                               "component javascript");
        if (NS_SUCCEEDED(rv)) {
            rv = consoleService->LogMessage(errorObject);
            if (NS_SUCCEEDED(rv)) {
                // We're done!  Skip return to fall thru to stderr
                // printout, for the benefit of those invoking the
                // browser with -console
                // return;
            }
        }
    }

    /*
     * If any of the above fails for some reason, fall back to
     * printing to stderr.
     */
#ifdef DEBUG
    fprintf(stderr, "JS Component Loader: %s %s:%d\n"
            "                     %s\n",
            JSREPORT_IS_WARNING(rep->flags) ? "WARNING" : "ERROR",
            rep->filename, rep->lineno,
            message ? message : "<no message>");
#endif
}
Пример #9
0
// Even with autoJSAPIOwnsErrorReporting, the JS engine still sends warning
// reports to the JSErrorReporter as soon as they are generated. These go
// directly to the console, so we can handle them easily here.
//
// Eventually, SpiderMonkey will have a special-purpose callback for warnings
// only.
void
WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep)
{
  MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
  nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
  nsPIDOMWindow* win = xpc::CurrentWindowOrNull(aCx);
  xpcReport->Init(aRep, aMessage, nsContentUtils::IsCallerChrome(),
                  win ? win->WindowID() : 0);
  xpcReport->LogToConsole();
}
Пример #10
0
// Even with dontReportUncaught, the JS engine still sends warning reports
// to the JSErrorReporter as soon as they are generated. These go directly to
// the console, so we can handle them easily here.
//
// Eventually, SpiderMonkey will have a special-purpose callback for warnings only.
void
WarningOnlyErrorReporter(JSContext* aCx, const char* aMessage, JSErrorReport* aRep)
{
  MOZ_ASSERT(JSREPORT_IS_WARNING(aRep->flags));
  nsRefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
  const char* category = nsContentUtils::IsCallerChrome() ? "chrome javascript"
                                                          : "content javascript";
  nsPIDOMWindow* win = xpc::WindowGlobalOrNull(JS::CurrentGlobalOrNull(aCx));
  xpcReport->Init(aRep, aMessage, category, win ? win->WindowID() : 0);
  xpcReport->LogToConsole();
}
Пример #11
0
static void
error_reporter(JSContext *ctx, const char *message, JSErrorReport *report)
{
	struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);
	struct session *ses = interpreter->vs->doc_view->session;
	struct terminal *term;
	unsigned char *strict, *exception, *warning, *error;
	struct string msg;

	assert(interpreter && interpreter->vs && interpreter->vs->doc_view
	       && ses && ses->tab);
	if_assert_failed goto reported;

	term = ses->tab->term;

#ifdef CONFIG_LEDS
	set_led_value(ses->status.ecmascript_led, 'J');
#endif

	if (!get_opt_bool("ecmascript.error_reporting", ses)
	    || !init_string(&msg))
		goto reported;

	strict	  = JSREPORT_IS_STRICT(report->flags) ? " strict" : "";
	exception = JSREPORT_IS_EXCEPTION(report->flags) ? " exception" : "";
	warning   = JSREPORT_IS_WARNING(report->flags) ? " warning" : "";
	error	  = !report->flags ? " error" : "";

	add_format_to_string(&msg, _("A script embedded in the current "
			"document raised the following%s%s%s%s", term),
			strict, exception, warning, error);

	add_to_string(&msg, ":\n\n");
	add_to_string(&msg, message);

	if (report->linebuf && report->tokenptr) {
		int pos = report->tokenptr - report->linebuf;

		add_format_to_string(&msg, "\n\n%s\n.%*s^%*s.",
			       report->linebuf,
			       pos - 2, " ",
			       strlen(report->linebuf) - pos - 1, " ");
	}

	info_box(term, MSGBOX_FREE_TEXT, N_("JavaScript Error"), ALIGN_CENTER,
		 msg.source);

reported:
	/* Im clu'les. --pasky */
	JS_ClearPendingException(ctx);
}
Пример #12
0
static void output_message(JSContext *cx, gpsee_runtime_t *grt, const char *er_pfx, const char *log_message, JSErrorReport *report, int printOnTTY)
{
  if (grt->errorLogger)
    grt->errorLogger(cx, er_pfx, log_message);
  else
  {
    if (JSREPORT_IS_WARNING(report->flags))
      gpsee_log(cx, GLOG_NOTTY_INFO, "%s %s", er_pfx, log_message);
    else
      gpsee_log(cx, GLOG_NOTTY_NOTICE, "%s %s", er_pfx, log_message);
  }

  if (printOnTTY)
    gpsee_fprintf(cx, stderr, "%s %s\n", er_pfx, log_message);

  return;
}
Пример #13
0
JSBool
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
{
    char *message;
    jschar *ucmessage;
    size_t messagelen;
    JSStackFrame *fp;
    JSErrorReport report;
    JSBool warning;

    if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
        return JS_TRUE;

    message = JS_vsmprintf(format, ap);
    if (!message)
        return JS_FALSE;
    messagelen = strlen(message);

    memset(&report, 0, sizeof (struct JSErrorReport));
    report.flags = flags;
    report.errorNumber = JSMSG_USER_DEFINED_ERROR;
    report.ucmessage = ucmessage = js_InflateString(cx, message, &messagelen);

    /* Find the top-most active script frame, for best line number blame. */
    for (fp = cx->fp; fp; fp = fp->down) {
        if (fp->regs) {
            report.filename = fp->script->filename;
            report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
            break;
        }
    }

    warning = JSREPORT_IS_WARNING(report.flags);
    if (warning && JS_HAS_WERROR_OPTION(cx)) {
        report.flags &= ~JSREPORT_WARNING;
        warning = JS_FALSE;
    }

    ReportError(cx, message, &report);
    free(message);
    JS_free(cx, ucmessage);
    return warning;
}
Пример #14
0
void MozJSImplScope::_reportError(JSContext* cx, const char* message, JSErrorReport* report) {
    auto scope = getScope(cx);

    if (!JSREPORT_IS_WARNING(report->flags)) {
        str::stream ss;
        ss << message;

        // TODO: something far more elaborate that mimics the stack printing from v8
        JS::RootedValue excn(cx);
        if (JS_GetPendingException(cx, &excn) && excn.isObject()) {
            JS::RootedValue stack(cx);

            ObjectWrapper(cx, excn).getValue("stack", &stack);

            ss << " :\n" << ValueWriter(cx, stack).toString();
        }

        scope->_status =
            Status(report->errorNumber ? static_cast<ErrorCodes::Error>(report->errorNumber)
                                       : ErrorCodes::JSInterpreterFailure,
                   ss);
    }
}
Пример #15
0
JSBool
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
{
    JSStackFrame *fp;
    JSErrorReport report, *reportp;
    char *last;
    JSBool warning;

    if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
        return JS_TRUE;

    /* Find the top-most active script frame, for best line number blame. */
    for (fp = cx->fp; fp && (!fp->script || !fp->pc); fp = fp->down)
        continue;

    reportp = &report;
    memset(reportp, 0, sizeof (struct JSErrorReport));
    report.flags = flags;
    if (fp) {
        report.filename = fp->script->filename;
        report.lineno = js_PCToLineNumber(fp->script, fp->pc);
        /* XXX should fetch line somehow */
    }
    last = JS_vsmprintf(format, ap);
    if (!last)
        return JS_FALSE;

    ReportError(cx, last, reportp);
    free(last);

    warning = JSREPORT_IS_WARNING(reportp->flags);
    if (warning && JS_HAS_WERROR_OPTION(cx)) {
        reportp->flags &= ~JSREPORT_WARNING;
        warning = JS_FALSE;
    }
    return warning;
}
Пример #16
0
JSBool
js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
{
    char *last;
    JSStackFrame *fp;
    JSErrorReport report;
    JSBool warning;

    if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
        return JS_TRUE;

    last = JS_vsmprintf(format, ap);
    if (!last)
        return JS_FALSE;

    memset(&report, 0, sizeof (struct JSErrorReport));
    report.flags = flags;

    /* Find the top-most active script frame, for best line number blame. */
    for (fp = cx->fp; fp; fp = fp->down) {
        if (fp->script && fp->pc) {
            report.filename = fp->script->filename;
            report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
            break;
        }
    }

    warning = JSREPORT_IS_WARNING(report.flags);
    if (warning && JS_HAS_WERROR_OPTION(cx)) {
        report.flags &= ~JSREPORT_WARNING;
        warning = JS_FALSE;
    }

    ReportError(cx, last, &report);
    free(last);
    return warning;
}
Пример #17
0
static void
gjs_console_error_reporter(JSContext *cx, const char *message, JSErrorReport *report)
{
    int i, j, k, n;
    char *prefix, *tmp;
    const char *ctmp;

    if (!report) {
        fprintf(stderr, "%s\n", message);
        return;
    }

    prefix = NULL;
    if (report->filename)
        prefix = g_strdup_printf("%s:", report->filename);
    if (report->lineno) {
        tmp = prefix;
        prefix = g_strdup_printf("%s%u: ", tmp ? tmp : "", report->lineno);
        g_free(tmp);
    }
    if (JSREPORT_IS_WARNING(report->flags)) {
        tmp = prefix;
        prefix = g_strdup_printf("%s%swarning: ",
                                 tmp ? tmp : "",
                                 JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
        g_free(tmp);
    }

    /* embedded newlines -- argh! */
    while ((ctmp = strchr(message, '\n')) != NULL) {
        ctmp++;
        if (prefix)
            fputs(prefix, stderr);
        fwrite(message, 1, ctmp - message, stderr);
        message = ctmp;
    }

    /* If there were no filename or lineno, the prefix might be empty */
    if (prefix)
        fputs(prefix, stderr);
    fputs(message, stderr);

    if (!report->linebuf) {
        fputc('\n', stderr);
        goto out;
    }

    /* report->linebuf usually ends with a newline. */
    n = strlen(report->linebuf);
    fprintf(stderr, ":\n%s%s%s%s",
            prefix,
            report->linebuf,
            (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
            prefix);
    n = ((char*)report->tokenptr) - ((char*) report->linebuf);
    for (i = j = 0; i < n; i++) {
        if (report->linebuf[i] == '\t') {
            for (k = (j + 8) & ~7; j < k; j++) {
                fputc('.', stderr);
            }
            continue;
        }
        fputc('.', stderr);
        j++;
    }
    fputs("^\n", stderr);
 out:
    g_free(prefix);
}
Пример #18
0
JSBool
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
{
    JSErrNum errorNumber;
    JSExnType exn;
    JSBool ok;
    JSObject *errProto, *errObject;
    JSString *messageStr, *filenameStr;
    uintN lineno;
    JSExnPrivate *privateData;

    /* Find the exception index associated with this error. */
    JS_ASSERT(reportp);
    if (JSREPORT_IS_WARNING(reportp->flags))
        return JS_FALSE;
    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;
    }

    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));

    /* Set the generated Exception object as the current exception. */
    JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));

    /* Flag the error report passed in to indicate an exception was raised. */
    reportp->flags |= JSREPORT_EXCEPTION;

out:
    cx->creatingException = JS_FALSE;
    return ok;
}
Пример #19
0
my_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
    int i, j, k, n;
    char *prefix = NULL, *tmp;
    const char *ctmp;

    if (!report) {
        fprintf(gErrFile, "%s\n", message);
        return;
    }

    /* Conditionally ignore reported warnings. */
    if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
        return;

    if (report->filename)
        prefix = JS_smprintf("%s:", report->filename);
    if (report->lineno) {
        tmp = prefix;
        prefix = JS_smprintf("%s%u: ", tmp ? tmp : "", report->lineno);
        JS_free(cx, tmp);
    }
    if (JSREPORT_IS_WARNING(report->flags)) {
        tmp = prefix;
        prefix = JS_smprintf("%s%swarning: ",
                             tmp ? tmp : "",
                             JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
        JS_free(cx, tmp);
    }

    /* embedded newlines -- argh! */
    while ((ctmp = strchr(message, '\n')) != 0) {
        ctmp++;
        if (prefix) fputs(prefix, gErrFile);
        fwrite(message, 1, ctmp - message, gErrFile);
        message = ctmp;
    }
    /* If there were no filename or lineno, the prefix might be empty */
    if (prefix)
        fputs(prefix, gErrFile);
    fputs(message, gErrFile);

    if (!report->linebuf) {
        fputc('\n', gErrFile);
        goto out;
    }

    fprintf(gErrFile, ":\n%s%s\n%s", prefix, report->linebuf, prefix);
    n = report->tokenptr - report->linebuf;
    for (i = j = 0; i < n; i++) {
        if (report->linebuf[i] == '\t') {
            for (k = (j + 8) & ~7; j < k; j++) {
                fputc('.', gErrFile);
            }
            continue;
        }
        fputc('.', gErrFile);
        j++;
    }
    fputs("^\n", gErrFile);
 out:
    if (!JSREPORT_IS_WARNING(report->flags))
        gExitCode = EXITCODE_RUNTIME_ERROR;
    JS_free(cx, prefix);
}
Пример #20
0
bool
PrintError(JSContext *cx, FILE *file, const char *message, JSErrorReport *report,
           bool reportWarnings)
{
    if (!report) {
        fprintf(file, "%s\n", message);
        fflush(file);
        return false;
    }

    /* Conditionally ignore reported warnings. */
    if (JSREPORT_IS_WARNING(report->flags) && !reportWarnings)
        return false;

    char *prefix = NULL;
    if (report->filename)
        prefix = JS_smprintf("%s:", report->filename);
    if (report->lineno) {
        char *tmp = prefix;
        prefix = JS_smprintf("%s%u:%u ", tmp ? tmp : "", report->lineno, report->column);
        JS_free(cx, tmp);
    }
    if (JSREPORT_IS_WARNING(report->flags)) {
        char *tmp = prefix;
        prefix = JS_smprintf("%s%swarning: ",
                             tmp ? tmp : "",
                             JSREPORT_IS_STRICT(report->flags) ? "strict " : "");
        JS_free(cx, tmp);
    }

    /* embedded newlines -- argh! */
    const char *ctmp;
    while ((ctmp = strchr(message, '\n')) != 0) {
        ctmp++;
        if (prefix)
            fputs(prefix, file);
        fwrite(message, 1, ctmp - message, file);
        message = ctmp;
    }

    /* If there were no filename or lineno, the prefix might be empty */
    if (prefix)
        fputs(prefix, file);
    fputs(message, file);

    if (report->linebuf) {
        /* report->linebuf usually ends with a newline. */
        int n = strlen(report->linebuf);
        fprintf(file, ":\n%s%s%s%s",
                prefix,
                report->linebuf,
                (n > 0 && report->linebuf[n-1] == '\n') ? "" : "\n",
                prefix);
        n = report->tokenptr - report->linebuf;
        for (int i = 0, j = 0; i < n; i++) {
            if (report->linebuf[i] == '\t') {
                for (int k = (j + 8) & ~7; j < k; j++) {
                    fputc('.', file);
                }
                continue;
            }
            fputc('.', file);
            j++;
        }
        fputc('^', file);
    }
    fputc('\n', file);
    fflush(file);
    JS_free(cx, prefix);
    return true;
}
Пример #21
0
/*
 * The arguments from ap need to be packaged up into an array and stored
 * into the report struct.
 *
 * The format string addressed by the error number may contain operands
 * identified by the format {N}, where N is a decimal digit. Each of these
 * is to be replaced by the Nth argument from the va_list. The complete
 * message is placed into reportp->ucmessage converted to a JSString.
 *
 * Returns true if the expansion succeeds (can fail if out of memory).
 */
JSBool
js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
                        void *userRef, const uintN errorNumber,
                        char **messagep, JSErrorReport *reportp,
                        JSBool *warningp, JSBool charArgs, va_list ap)
{
    const JSErrorFormatString *efs;
    int i;
    int argCount;

    *warningp = JSREPORT_IS_WARNING(reportp->flags);
    if (*warningp && JS_HAS_WERROR_OPTION(cx)) {
        reportp->flags &= ~JSREPORT_WARNING;
        *warningp = JS_FALSE;
    }

    *messagep = NULL;
    if (callback) {
        efs = callback(userRef, NULL, errorNumber);
        if (efs) {
            size_t totalArgsLength = 0;
            size_t argLengths[10]; /* only {0} thru {9} supported */
            argCount = efs->argCount;
            JS_ASSERT(argCount <= 10);
            if (argCount > 0) {
                /*
                 * Gather the arguments into an array, and accumulate
                 * their sizes. We allocate 1 more than necessary and
                 * null it out to act as the caboose when we free the
                 * pointers later.
                 */
                reportp->messageArgs = (const jschar **)
                    JS_malloc(cx, sizeof(jschar *) * (argCount + 1));
                if (!reportp->messageArgs)
                    return JS_FALSE;
                reportp->messageArgs[argCount] = NULL;
                for (i = 0; i < argCount; i++) {
                    if (charArgs) {
                        char *charArg = va_arg(ap, char *);
                        reportp->messageArgs[i]
                            = js_InflateString(cx, charArg, strlen(charArg));
                        if (!reportp->messageArgs[i])
                            goto error;
                    }
                    else
                        reportp->messageArgs[i] = va_arg(ap, jschar *);
                    argLengths[i] = js_strlen(reportp->messageArgs[i]);
                    totalArgsLength += argLengths[i];
                }
                /* NULL-terminate for easy copying. */
                reportp->messageArgs[i] = NULL;
            }
            /*
             * Parse the error format, substituting the argument X
             * for {X} in the format.
             */
            if (argCount > 0) {
                if (efs->format) {
                    const char *fmt;
                    const jschar *arg;
                    jschar *out;
                    int expandedArgs = 0;
                    size_t expandedLength
                        = strlen(efs->format)
                            - (3 * argCount) /* exclude the {n} */
                            + totalArgsLength;
                    /*
                     * Note - the above calculation assumes that each argument
                     * is used once and only once in the expansion !!!
                     */
                    reportp->ucmessage = out = (jschar *)
                        JS_malloc(cx, (expandedLength + 1) * sizeof(jschar));
                    if (!out)
                        goto error;
                    fmt = efs->format;
                    while (*fmt) {
                        if (*fmt == '{') {
                            if (isdigit(fmt[1])) {
                                int d = JS7_UNDEC(fmt[1]);
                                JS_ASSERT(expandedArgs < argCount);
                                arg = reportp->messageArgs[d];
                                js_strncpy(out, arg, argLengths[d]);
                                out += argLengths[d];
                                fmt += 3;
                                expandedArgs++;
                                continue;
                            }
                        }
                        /*
                         * is this kosher?
                         */
                        *out++ = (unsigned char)(*fmt++);
                    }
                    JS_ASSERT(expandedArgs == argCount);
                    *out = 0;
                    *messagep =
                        js_DeflateString(cx, reportp->ucmessage,
                                         (size_t)(out - reportp->ucmessage));
                    if (!*messagep)
                        goto error;
                }
            } else {
                /*
                 * Zero arguments: the format string (if it exists) is the
                 * entire message.
                 */
                if (efs->format) {
                    *messagep = JS_strdup(cx, efs->format);
                    if (!*messagep)
                        goto error;
                    reportp->ucmessage
                        = js_InflateString(cx, *messagep, strlen(*messagep));
                    if (!reportp->ucmessage)
                        goto error;
                }
            }
        }
Пример #22
0
JSBool
js_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 ? (JSExnType) 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, via cx->generatingError.  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->generatingError)
        return JS_FALSE;

    /* After this point the control must flow through the label out. */
    cx->generatingError = JS_TRUE;

    /* Protect the newly-created strings below from nesting GCs. */
    memset(tv, 0, sizeof tv);
    JS_PUSH_TEMP_ROOT(cx, JS_ARRAY_LENGTH(tv), 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, 0);
    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->generatingError = JS_FALSE;
    return ok;
}
Пример #23
0
JSBool
js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp)
{
    JSErrNum errorNumber;
    JSExnType exn;
    JSBool ok;
    JSObject *errProto, *errObject;
    JSString *messageStr, *filenameStr;
    uintN lineno;
    JSExnPrivate *privateData;
    const JSErrorFormatString *errorString;

    /*
     * 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;
    cx->creatingException = JS_TRUE;

    /* Protect the newly-created strings below from nesting GCs. */
    ok = js_EnterLocalRootScope(cx);
    if (!ok)
        goto out;

    /*
     * 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, exceptions[exn].name, &errProto);
    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:
    js_LeaveLocalRootScope(cx);
    cx->creatingException = JS_FALSE;
    return ok;
}
Пример #24
0
/** Error Reporter for Spidermonkey. Used to report warnings and
 *  uncaught exceptions.
 */
void gpsee_errorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
  const char 		*ctmp;
  char			er_filename[64];
  char			er_exception[16];
  char			er_warning[16];
  char			er_number[16];
  char			er_lineno[16];
  char			er_charno[16];
  char			er_pfx[64];
  gpsee_runtime_t 	*grt = JS_GetRuntimePrivate(JS_GetRuntime(cx));
  int                   printOnTTY = 0;

  if (grt->errorReport == er_none)
    return;

  if (!report)
  {
    gpsee_log(cx, GLOG_NOTICE, "JS error from unknown source: %s\n", message);
    return;
  }

  /* Conditionally ignore reported warnings. */
  if (JSREPORT_IS_WARNING(report->flags))
  {
    if (grt->errorReport & er_noWarnings)
      return;

    if (cfg_bool_value(cfg, "gpsee_report_warnings") == cfg_false)
      return;

    if (gpsee_verbosity(0) >= GPSEE_WARNING_OUTPUT_VERBOSITY)
      printOnTTY = 1 && gpsee_isatty(STDERR_FILENO);
  }
  else
    if (gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY)
      printOnTTY = 1 && gpsee_isatty(STDERR_FILENO);

  if (report->filename)
  {
    const char *bn = strrchr(report->filename, '/');

    if (bn)
      bn += 1;
    else
      bn = report->filename;

    snprintf(er_filename, sizeof(er_filename), "in %s ", bn);
  }
  else
    er_filename[0] = (char)0;

  if (report->lineno)
    snprintf(er_lineno, sizeof(er_lineno), "line %u ", report->lineno);
  else
    er_lineno[0] = (char)0;

  if (report->tokenptr && report->linebuf)
    snprintf(er_charno, sizeof(er_charno), "ch %ld ", (long int)(report->tokenptr - report->linebuf));
  else
    er_charno[0] = (char)0;

  er_warning[0] = (char)0;

  if (JSREPORT_IS_EXCEPTION(report->flags))
  {
    snprintf(er_exception, sizeof(er_exception), "exception ");
    if (!grt->exitType)
      grt->exitType = et_exception;
  }
  else
  {
    er_exception[0] = (char)0;

    if (JSREPORT_IS_WARNING(report->flags))
      snprintf(er_warning, sizeof(er_warning), "%swarning ", (JSREPORT_IS_STRICT(report->flags) ? "strict " : ""));
  }

  if (report->errorNumber)     
    snprintf(er_number, sizeof(er_number), "#%i ", report->errorNumber);
  else
    er_number[0] = (char)0;

  snprintf(er_pfx, sizeof(er_pfx), "JS %s%s%s%s" "%s" "%s%s%s" "-",
	   er_warning, er_exception, ((er_exception[0] || er_warning[0]) ? "" : "error "), er_number,	/* error 69 */
	   er_filename,											/* in myprog.js */
	   ((er_lineno[0] || er_charno[0]) ? "at " :""), er_lineno, er_charno				/* at line 12, ch 34 */
	   );

  /* embedded newlines -- log each separately */
  while ((ctmp = strchr(message, '\n')) != 0)
  {
    char log_message[strlen(message)];

    ctmp++;
    strncpy(log_message, message, ctmp-message);
    log_message[ctmp - message] = (char)0;
    output_message(cx, grt, er_pfx, log_message, report, printOnTTY);
    message = ctmp;

    memset(er_pfx, ' ', strlen(er_pfx));
    er_pfx[0] = '|';   
  }
  
  output_message(cx, grt, er_pfx, message, report, printOnTTY);
}
Пример #25
0
JSBool
js_ReportCompileErrorNumber(JSContext *cx, JSTokenStream *ts,
                            JSCodeGenerator *cg, uintN flags,
                            const uintN errorNumber, ...)
{
    va_list ap;
    JSErrorReporter onError;
    JSErrorReport report;
    jschar *tokenptr;
    JSString *linestr = NULL;
    char *message;
    JSBool warning;

    if ((flags & JSREPORT_STRICT) && !JS_HAS_STRICT_OPTION(cx))
        return JS_TRUE;

    memset(&report, 0, sizeof (struct JSErrorReport));
    report.flags = flags;
    report.errorNumber = errorNumber;
    message = NULL;

    va_start(ap, errorNumber);
    if (!js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL,
                                 errorNumber, &message, &report, &warning,
                                 JS_TRUE, ap)) {
        return JS_FALSE;
    }
    va_end(ap);

    js_AddRoot(cx, &linestr, "error line buffer");

    JS_ASSERT(!ts || ts->linebuf.limit < ts->linebuf.base + JS_LINE_LIMIT);
    onError = cx->errorReporter;
    if (onError) {
        /* 
         * We are typically called with non-null ts and null cg from jsparse.c.
         * We can be called with null ts from the regexp compilation functions.
         * The code generator (jsemit.c) may pass null ts and non-null cg.
         */
        if (ts) {
            report.filename = ts->filename;
            report.lineno = ts->lineno;
            linestr = js_NewStringCopyN(cx, ts->linebuf.base,
                                        ts->linebuf.limit - ts->linebuf.base,
                                        0);
            report.linebuf = linestr
                ? JS_GetStringBytes(linestr)
                : NULL;
            tokenptr =
                ts->tokens[(ts->cursor + ts->lookahead) & NTOKENS_MASK].ptr;
            report.tokenptr = linestr
                ? report.linebuf + (tokenptr - ts->linebuf.base)
                : NULL;
            report.uclinebuf = linestr
                ? JS_GetStringChars(linestr)
                : NULL;
            report.uctokenptr = linestr
                ? report.uclinebuf + (tokenptr - ts->linebuf.base)
                : NULL;
        } else if (cg) {
            report.filename = cg->filename;
            report.lineno = cg->currentLine;
        }

#if JS_HAS_ERROR_EXCEPTIONS
        /*
         * If there's a runtime exception type associated with this error
         * number, set that as the pending exception.  For errors occuring at
         * compile time, this is very likely to be a JSEXN_SYNTAXERR.
         *
         * If an exception is thrown but not caught, the JSREPORT_EXCEPTION
         * flag will be set in report.flags.  Proper behavior for an error
         * reporter is to ignore a report with this flag for all but top-level
         * compilation errors.  The exception will remain pending, and so long
         * as the non-top-level "load", "eval", or "compile" native function
         * returns false, the top-level reporter will eventually receive the
         * uncaught exception report.
         * 
         * XXX it'd probably be best if there was only one call to this
         * function, but there seem to be two error reporter call points.
         */

        /*
         * Only try to raise an exception if there isn't one already set -
         * otherwise the exception will describe only the last compile error,
         * which is likely spurious.
         */
        if (!(ts && (ts->flags & TSF_ERROR)))
            if (js_ErrorToException(cx, message, &report))
                onError = NULL;

        /*
         * Suppress any compiletime errors that don't occur at the top level.
         * This may still fail, as interplevel may be zero in contexts where we
         * don't really want to call the error reporter, as when js is called
         * by other code which could catch the error.
         */
        if (cx->interpLevel != 0)
            onError = NULL;
#endif
        if (cx->runtime->debugErrorHook && onError) {
            JSDebugErrorHook hook = cx->runtime->debugErrorHook;
            /* test local in case debugErrorHook changed on another thread */
            if (hook && !hook(cx, message, &report,
                              cx->runtime->debugErrorHookData)) {
                onError = NULL;
            }
        }
        if (onError)
            (*onError)(cx, message, &report);
    }
    if (message)
        JS_free(cx, message);
    if (report.messageArgs) {
        int i = 0;
        while (report.messageArgs[i])
            JS_free(cx, (void *)report.messageArgs[i++]);
        JS_free(cx, (void *)report.messageArgs);
    }
    if (report.ucmessage)
        JS_free(cx, (void *)report.ucmessage);

    js_RemoveRoot(cx->runtime, &linestr);

    if (ts && !JSREPORT_IS_WARNING(flags)) {
        /* Set the error flag to suppress spurious reports. */
        ts->flags |= TSF_ERROR;
    }
    return warning;
}