author | Nicholas Nethercote <nnethercote@mozilla.com> |
Wed, 13 Jun 2012 23:23:01 -0700 | |
changeset 106445 | a977ac53a195ee750973025594a945e9c37d65a9 |
parent 106444 | 000eb13cb3bafedfc910025e90abf2d0f5a74ad8 |
child 106446 | b3820743259201b5eadc2fdfbda4cb14e2a80a59 |
push id | 23447 |
push user | danderson@mozilla.com |
push date | Tue, 11 Sep 2012 17:34:27 +0000 |
treeherder | mozilla-central@fdfaef738a00 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jwalden |
bugs | 634800 |
milestone | 16.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -390,55 +390,73 @@ TokenStream::TokenBuf::findEOLMax(const n++; } return p; } bool TokenStream::reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned errorNumber, va_list ap) { - JSErrorReport report; - char *message; - jschar *windowChars; - char *windowBytes; - bool warning; - JSBool ok; - const TokenPos *tp; - unsigned i; + class ReportManager + { + JSContext *cx; + JSErrorReport *report; + bool hasCharArgs; + + public: + char *message; + + ReportManager(JSContext *cx, JSErrorReport *report, bool hasCharArgs) + : cx(cx), report(report), hasCharArgs(hasCharArgs), message(NULL) + {} + + ~ReportManager() { + cx->free_((void*)report->uclinebuf); + cx->free_((void*)report->linebuf); + cx->free_(message); + cx->free_((void*)report->ucmessage); + + if (report->messageArgs) { + if (hasCharArgs) { + unsigned i = 0; + while (report->messageArgs[i]) + cx->free_((void *)report->messageArgs[i++]); + } + cx->free_((void *)report->messageArgs); + } + } + }; if (JSREPORT_IS_STRICT(flags) && !cx->hasStrictOption()) return true; - warning = JSREPORT_IS_WARNING(flags); + bool warning = JSREPORT_IS_WARNING(flags); if (warning && cx->hasWErrorOption()) { flags &= ~JSREPORT_WARNING; warning = false; } + const TokenPos *const tp = pn ? &pn->pn_pos : ¤tToken().pos; + + JSErrorReport report; PodZero(&report); report.flags = flags; report.errorNumber = errorNumber; - message = NULL; - windowChars = NULL; - windowBytes = NULL; - - MUST_FLOW_THROUGH("out"); - ok = js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL, - errorNumber, &message, &report, - !(flags & JSREPORT_UC), ap); - if (!ok) { - warning = false; - goto out; - } - report.filename = filename; report.originPrincipals = originPrincipals; + report.lineno = tp->begin.lineno; - tp = pn ? &pn->pn_pos : ¤tToken().pos; - report.lineno = tp->begin.lineno; + bool hasCharArgs = !(flags & JSREPORT_UC); + + ReportManager mgr(cx, &report, hasCharArgs); + + if (!js_ExpandErrorArguments(cx, js_GetErrorMessage, NULL, errorNumber, &mgr.message, &report, + hasCharArgs, ap)) { + return false; + } /* * Given a token, T, that we want to complain about: if T's (starting) * lineno doesn't match TokenStream's lineno, that means we've scanned past * the line that T starts on, which makes it hard to print some or all of * T's (starting) line for context. * * So we don't even try, leaving report.linebuf and friends zeroed. This @@ -464,35 +482,27 @@ TokenStream::reportCompileErrorNumberVA( // Find EOL, or truncate at the back if necessary. const jschar *windowLimit = userbuf.findEOLMax(tokptr, windowRadius); size_t windowLength = windowLimit - windowBase; JS_ASSERT(windowLength <= windowRadius * 2); // Create the windowed strings. StringBuffer windowBuf(cx); - if (!windowBuf.append(windowBase, windowLength) || !windowBuf.append((jschar)0)) { - warning = false; - goto out; - } - windowChars = windowBuf.extractWellSized(); - if (!windowChars) { - warning = false; - goto out; - } - windowBytes = DeflateString(cx, windowChars, windowLength); - if (!windowBytes) { - warning = false; - goto out; - } + if (!windowBuf.append(windowBase, windowLength) || !windowBuf.append((jschar)0)) + return false; // Unicode and char versions of the window into the offending source // line, without final \n. - report.linebuf = windowBytes; - report.uclinebuf = windowChars; + report.uclinebuf = windowBuf.extractWellSized(); + if (!report.uclinebuf) + return false; + report.linebuf = DeflateString(cx, report.uclinebuf, windowLength); + if (!report.linebuf) + return false; // The lineno check above means we should only see single-line tokens here. JS_ASSERT(tp->begin.lineno == tp->end.lineno); report.tokenptr = report.linebuf + windowIndex; report.uctokenptr = report.uclinebuf + windowIndex; } /* @@ -503,47 +513,30 @@ TokenStream::reportCompileErrorNumberVA( * 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. */ - if (!js_ErrorToException(cx, message, &report, NULL, NULL)) { + if (!js_ErrorToException(cx, mgr.message, &report, NULL, NULL)) { /* * If debugErrorHook is present then we give it a chance to veto * sending the error on to the regular error reporter. */ bool reportError = true; - if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) - reportError = hook(cx, message, &report, cx->runtime->debugHooks.debugErrorHookData); + if (JSDebugErrorHook hook = cx->runtime->debugHooks.debugErrorHook) { + reportError = hook(cx, mgr.message, &report, + cx->runtime->debugHooks.debugErrorHookData); + } /* Report the error */ if (reportError && cx->errorReporter) - cx->errorReporter(cx, message, &report); - } - - out: - if (windowBytes) - cx->free_(windowBytes); - if (windowChars) - cx->free_(windowChars); - if (message) - cx->free_(message); - if (report.ucmessage) - cx->free_((void *)report.ucmessage); - - if (report.messageArgs) { - if (!(flags & JSREPORT_UC)) { - i = 0; - while (report.messageArgs[i]) - cx->free_((void *)report.messageArgs[i++]); - } - cx->free_((void *)report.messageArgs); + cx->errorReporter(cx, mgr.message, &report); } return warning; } bool js::ReportStrictModeError(JSContext *cx, TokenStream *ts, ParseNode *pn, unsigned errorNumber, ...) {
--- a/js/src/frontend/TokenStream.h +++ b/js/src/frontend/TokenStream.h @@ -495,17 +495,20 @@ class TokenStream bool isStrictMode() const { return strictModeGetter ? strictModeGetter->get() : false; } bool isXMLTagMode() const { return !!(flags & TSF_XMLTAGMODE); } bool isXMLOnlyMode() const { return !!(flags & TSF_XMLONLYMODE); } bool isUnexpectedEOF() const { return !!(flags & TSF_UNEXPECTED_EOF); } bool isEOF() const { return !!(flags & TSF_EOF); } bool hasOctalCharacterEscape() const { return flags & TSF_OCTAL_CHAR; } - bool reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned errorNumber, va_list ap); + // Return false if we should stop compiling, either because (a) we issued + // an error message, or (b) something went wrong, such as an OOM. + bool reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned errorNumber, + va_list ap); private: static JSAtom *atomize(JSContext *cx, CharBuffer &cb); bool putIdentInTokenbuf(const jschar *identStart); /* * Enables flags in the associated tokenstream for the object lifetime. * Useful for lexically-scoped flag toggles.