diff options
Diffstat (limited to 'js/src')
-rw-r--r-- | js/src/vm/ErrorReporting.cpp | 124 | ||||
-rw-r--r-- | js/src/vm/ErrorReporting.h | 91 |
2 files changed, 215 insertions, 0 deletions
diff --git a/js/src/vm/ErrorReporting.cpp b/js/src/vm/ErrorReporting.cpp new file mode 100644 index 000000000..5877f3a4b --- /dev/null +++ b/js/src/vm/ErrorReporting.cpp @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "vm/ErrorReporting.h" + +#include "mozilla/Move.h" + +#include <stdarg.h> + +#include "jscntxt.h" +#include "jsexn.h" + +using mozilla::Move; + +using JS::UniqueTwoByteChars; + +void +CallWarningReporter(JSContext* cx, JSErrorReport* reportp) +{ + MOZ_ASSERT(reportp); + MOZ_ASSERT(JSREPORT_IS_WARNING(reportp->flags)); + + if (JS::WarningReporter warningReporter = cx->runtime()->warningReporter) + warningReporter(cx, reportp); +} + +void +CompileError::throwError(JSContext* cx) +{ + if (JSREPORT_IS_WARNING(flags)) { + CallWarningReporter(cx, this); + return; + } + + // 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. + ErrorToException(cx, this, nullptr, nullptr); +} + +bool +ReportCompileWarning(JSContext* cx, ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes, + unsigned flags, unsigned errorNumber, va_list args) +{ + // On the main thread, report the error immediately. When compiling off + // thread, save the error so that the thread finishing the parse can report + // it later. + CompileError tempErr; + CompileError* err = &tempErr; + if (!cx->isJSContext() && !cx->addPendingCompileError(&err)) { + return false; + } + + err->notes = Move(notes); + err->flags = flags; + err->errorNumber = errorNumber; + + err->filename = metadata.filename; + err->lineno = metadata.lineNumber; + err->column = metadata.columnNumber; + err->isMuted = metadata.isMuted; + + if (UniqueTwoByteChars lineOfContext = Move(metadata.lineOfContext)) + err->initOwnedLinebuf(lineOfContext.release(), metadata.lineLength, metadata.tokenOffset); + + if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr, errorNumber, + nullptr, ArgumentsAreLatin1, err, args)) + { + return false; + } + + if (cx->isJSContext()) { + err->throwError(cx->asJSContext()); + } + + return true; +} + +void +ReportCompileError(JSContext* cx, ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes, + unsigned flags, unsigned errorNumber, va_list args) +{ + // On the main thread, report the error immediately. When compiling off + // thread, save the error so that the thread finishing the parse can report + // it later. + CompileError tempErr; + CompileError* err = &tempErr; + if (!cx->isJSContext() && !cx->addPendingCompileError(&err)) { + return; + } + + err->notes = Move(notes); + err->flags = flags; + err->errorNumber = errorNumber; + + err->filename = metadata.filename; + err->lineno = metadata.lineNumber; + err->column = metadata.columnNumber; + err->isMuted = metadata.isMuted; + + if (UniqueTwoByteChars lineOfContext = Move(metadata.lineOfContext)) + err->initOwnedLinebuf(lineOfContext.release(), metadata.lineLength, metadata.tokenOffset); + + if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr, errorNumber, + nullptr, ArgumentsAreLatin1, err, args)) + { + return; + } + + if (cx->isJSContext()) { + err->throwError(cx->asJSContext()); + } +} diff --git a/js/src/vm/ErrorReporting.h b/js/src/vm/ErrorReporting.h new file mode 100644 index 000000000..02bbe2c63 --- /dev/null +++ b/js/src/vm/ErrorReporting.h @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef vm_ErrorReporting_h +#define vm_ErrorReporting_h + +#include "mozilla/Move.h" + +#include <stdarg.h> + +#include "jsapi.h" // for JSErrorNotes, JSErrorReport + +#include "js/UniquePtr.h" // for UniquePtr +#include "js/Utility.h" // for UniqueTwoByteChars + +struct JSContext; + +namespace js { + +/** + * Metadata for a compilation error (or warning) at a particular offset, or at + * no offset (i.e. with respect to a script overall). + */ +struct ErrorMetadata +{ + // The file/URL where the error occurred. + const char* filename; + + // The line and column numbers where the error occurred. If the error + // is with respect to the entire script and not with respect to a + // particular location, these will both be zero. + uint32_t lineNumber; + uint32_t columnNumber; + + // If the error occurs at a particular location, context surrounding the + // location of the error: the line that contained the error, or a small + // portion of it if the line is long. + // + // This information is provided on a best-effort basis: code populating + // ErrorMetadata instances isn't obligated to supply this. + JS::UniqueTwoByteChars lineOfContext; + + // If |lineOfContext| is non-null, its length. + size_t lineLength; + + // If |lineOfContext| is non-null, the offset within it of the token that + // triggered the error. + size_t tokenOffset; + + // Whether the error is "muted" because it derives from a cross-origin + // load. See the comment in TransitiveCompileOptions in jsapi.h for + // details. + bool isMuted; +}; + +class CompileError : public JSErrorReport +{ + public: + void throwError(JSContext* cx); +}; + +/** Send a JSErrorReport to the warningReporter callback. */ +extern void +CallWarningReporter(JSContext* cx, JSErrorReport* report); + +/** + * Report a compile error during script processing prior to execution of the + * script. + */ +extern void +ReportCompileError(ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes, + unsigned flags, unsigned errorNumber, va_list args); + +/** + * Report a compile warning during script processing prior to execution of the + * script. Returns true if the warning was successfully reported, false if an + * error occurred. + * + * This function DOES NOT respect an existing werror option. If the caller + * wishes such option to be respected, it must do so itself. + */ +extern MOZ_MUST_USE bool +ReportCompileWarning(JSContext* cx, ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes, + unsigned flags, unsigned errorNumber, va_list args); + +} // namespace js + +#endif /* vm_ErrorReporting_h */ |