if (!js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL, errorNumber, &message, &report, &warning, JS_TRUE, ap)) { return JS_FALSE; }
warning = ReportCompileErrorNumber(cx, handle, flags, errorNumber, &report, JS_TRUE, ap);
js_ReportCompileErrorNumber(JSContext *cx, void *handle, uintN flags,                            uintN errorNumber, ...){    va_list ap;    JSErrorReport report;    JSString *linestr = NULL;    JSTokenStream *ts = NULL;    JSCodeGenerator *cg = NULL;#if JS_HAS_XML_SUPPORT    JSParseNode *pn = NULL;#endif    JSErrorReporter onError;    JSTokenPos *tp;    JSStackFrame *fp;    uintN index;    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");    switch (flags & JSREPORT_HANDLE) {      case JSREPORT_TS:        ts = handle;        break;      case JSREPORT_CG:        cg = handle;        break;#if JS_HAS_XML_SUPPORT      case JSREPORT_PN:        pn = handle;        ts = pn->pn_ts;        break;#endif    }    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.         */        do {            if (ts) {                report.filename = ts->filename;#if JS_HAS_XML_SUPPORT                if (pn) {                    report.lineno = pn->pn_pos.begin.lineno;                    if (report.lineno != ts->lineno)                        break;                }#endif                report.lineno = ts->lineno;                linestr = js_NewStringCopyN(cx, ts->linebuf.base,                                            PTRDIFF(ts->linebuf.limit,                                                    ts->linebuf.base,                                                    jschar),                                            0);                report.linebuf = linestr                                 ? JS_GetStringBytes(linestr)                                 : NULL;                tp = &ts->tokens[(ts->cursor+ts->lookahead) & NTOKENS_MASK].pos;#if JS_HAS_XML_SUPPORT                if (pn)                    tp = &pn->pn_pos;#endif                index = (tp->begin.lineno == tp->end.lineno)                        ? tp->begin.index - ts->linepos                        : 0;                report.tokenptr = linestr ? report.linebuf + index : NULL;                report.uclinebuf = linestr ? JS_GetStringChars(linestr) : NULL;                report.uctokenptr = linestr ? report.uclinebuf + index : NULL;                break;            }            if (cg) {                report.filename = cg->filename;                report.lineno = CG_CURRENT_LINE(cg);                break;            }            /*             * If we can't find out where the error was based on the current frame,             * see if the next frame has a script/pc combo we can use.             */            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;                }            }        } while (0);#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 compile-time 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;}