[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-release / js / ErrorReport.h
blob6dd16aec7baacffaa77a73a744941370e5743845
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /*
7 * Error-reporting APIs.
9 * Despite the types and structures defined here existing in js/public,
10 * significant parts of their heritage date back to distant SpiderMonkey past,
11 * and they are not all universally well-thought-out as ideal,
12 * intended-to-be-permanent API. We may eventually replace this with something
13 * more consistent with ECMAScript the language and less consistent with
14 * '90s-era JSAPI inventions, but it's doubtful this will happen any time soon.
17 #ifndef js_ErrorReport_h
18 #define js_ErrorReport_h
20 #include "mozilla/Assertions.h" // MOZ_ASSERT
22 #include <iterator> // std::input_iterator_tag, std::iterator
23 #include <stdarg.h>
24 #include <stddef.h> // size_t
25 #include <stdint.h> // int16_t, uint16_t
26 #include <string.h> // strlen
28 #include "jstypes.h" // JS_PUBLIC_API
30 #include "js/AllocPolicy.h"
31 #include "js/CharacterEncoding.h" // JS::ConstUTF8CharsZ
32 #include "js/RootingAPI.h" // JS::HandleObject, JS::RootedObject
33 #include "js/UniquePtr.h" // js::UniquePtr
34 #include "js/Vector.h" // js::Vector
36 struct JS_PUBLIC_API JSContext;
37 class JS_PUBLIC_API JSString;
39 namespace JS {
40 class ExceptionStack;
42 namespace js {
43 class SystemAllocPolicy;
46 /**
47 * Possible exception types. These types are part of a JSErrorFormatString
48 * structure. They define which error to throw in case of a runtime error.
50 * JSEXN_WARN is used for warnings, that are not strictly errors but are handled
51 * using the generalized error reporting mechanism. (One side effect of this
52 * type is to not prepend 'Error:' to warning messages.) This value can go away
53 * if we ever decide to use an entirely separate mechanism for warnings.
55 enum JSExnType {
56 JSEXN_ERR,
57 JSEXN_FIRST = JSEXN_ERR,
58 JSEXN_INTERNALERR,
59 JSEXN_AGGREGATEERR,
60 JSEXN_EVALERR,
61 JSEXN_RANGEERR,
62 JSEXN_REFERENCEERR,
63 JSEXN_SYNTAXERR,
64 JSEXN_TYPEERR,
65 JSEXN_URIERR,
66 JSEXN_DEBUGGEEWOULDRUN,
67 JSEXN_WASMCOMPILEERROR,
68 JSEXN_WASMLINKERROR,
69 JSEXN_WASMRUNTIMEERROR,
70 JSEXN_ERROR_LIMIT,
71 JSEXN_WARN = JSEXN_ERROR_LIMIT,
72 JSEXN_NOTE,
73 JSEXN_LIMIT
76 struct JSErrorFormatString {
77 /** The error message name in ASCII. */
78 const char* name;
80 /** The error format string in ASCII. */
81 const char* format;
83 /** The number of arguments to expand in the formatted error message. */
84 uint16_t argCount;
86 /** One of the JSExnType constants above. */
87 int16_t exnType;
90 using JSErrorCallback =
91 const JSErrorFormatString* (*)(void* userRef, const unsigned errorNumber);
93 /**
94 * Base class that implements parts shared by JSErrorReport and
95 * JSErrorNotes::Note.
97 class JSErrorBase {
98 private:
99 // The (default) error message.
100 // If ownsMessage_ is true, the it is freed in destructor.
101 JS::ConstUTF8CharsZ message_;
103 public:
104 // Source file name, URL, etc., or null.
105 const char* filename;
107 // Unique identifier for the script source.
108 unsigned sourceId;
110 // Source line number.
111 unsigned lineno;
113 // Zero-based column index in line.
114 unsigned column;
116 // the error number, e.g. see js/public/friend/ErrorNumbers.msg.
117 unsigned errorNumber;
119 // Points to JSErrorFormatString::name.
120 // This string must never be freed.
121 const char* errorMessageName;
123 private:
124 bool ownsMessage_ : 1;
126 public:
127 JSErrorBase()
128 : filename(nullptr),
129 sourceId(0),
130 lineno(0),
131 column(0),
132 errorNumber(0),
133 errorMessageName(nullptr),
134 ownsMessage_(false) {}
136 ~JSErrorBase() { freeMessage(); }
138 public:
139 const JS::ConstUTF8CharsZ message() const { return message_; }
141 void initOwnedMessage(const char* messageArg) {
142 initBorrowedMessage(messageArg);
143 ownsMessage_ = true;
145 void initBorrowedMessage(const char* messageArg) {
146 MOZ_ASSERT(!message_);
147 message_ = JS::ConstUTF8CharsZ(messageArg, strlen(messageArg));
150 JSString* newMessageString(JSContext* cx);
152 private:
153 void freeMessage();
157 * Notes associated with JSErrorReport.
159 class JSErrorNotes {
160 public:
161 class Note final : public JSErrorBase {};
163 private:
164 // Stores pointers to each note.
165 js::Vector<js::UniquePtr<Note>, 1, js::SystemAllocPolicy> notes_;
167 public:
168 JSErrorNotes();
169 ~JSErrorNotes();
171 // Add an note to the given position.
172 bool addNoteASCII(JSContext* cx, const char* filename, unsigned sourceId,
173 unsigned lineno, unsigned column,
174 JSErrorCallback errorCallback, void* userRef,
175 const unsigned errorNumber, ...);
176 bool addNoteLatin1(JSContext* cx, const char* filename, unsigned sourceId,
177 unsigned lineno, unsigned column,
178 JSErrorCallback errorCallback, void* userRef,
179 const unsigned errorNumber, ...);
180 bool addNoteUTF8(JSContext* cx, const char* filename, unsigned sourceId,
181 unsigned lineno, unsigned column,
182 JSErrorCallback errorCallback, void* userRef,
183 const unsigned errorNumber, ...);
185 JS_PUBLIC_API size_t length();
187 // Create a deep copy of notes.
188 js::UniquePtr<JSErrorNotes> copy(JSContext* cx);
190 class iterator final {
191 private:
192 js::UniquePtr<Note>* note_;
194 public:
195 using iterator_category = std::input_iterator_tag;
196 using value_type = js::UniquePtr<Note>;
197 using difference_type = ptrdiff_t;
198 using pointer = value_type*;
199 using reference = value_type&;
201 explicit iterator(js::UniquePtr<Note>* note = nullptr) : note_(note) {}
203 bool operator==(iterator other) const { return note_ == other.note_; }
204 bool operator!=(iterator other) const { return !(*this == other); }
205 iterator& operator++() {
206 note_++;
207 return *this;
209 reference operator*() { return *note_; }
212 JS_PUBLIC_API iterator begin();
213 JS_PUBLIC_API iterator end();
217 * Describes a single error or warning that occurs in the execution of script.
219 class JSErrorReport : public JSErrorBase {
220 private:
221 // Offending source line without final '\n'.
222 // If ownsLinebuf_ is true, the buffer is freed in destructor.
223 const char16_t* linebuf_;
225 // Number of chars in linebuf_. Does not include trailing '\0'.
226 size_t linebufLength_;
228 // The 0-based offset of error token in linebuf_.
229 size_t tokenOffset_;
231 public:
232 // Associated notes, or nullptr if there's no note.
233 js::UniquePtr<JSErrorNotes> notes;
235 // One of the JSExnType constants.
236 int16_t exnType;
238 // See the comment in TransitiveCompileOptions.
239 bool isMuted : 1;
241 // This error report is actually a warning.
242 bool isWarning_ : 1;
244 private:
245 bool ownsLinebuf_ : 1;
247 public:
248 JSErrorReport()
249 : linebuf_(nullptr),
250 linebufLength_(0),
251 tokenOffset_(0),
252 notes(nullptr),
253 exnType(0),
254 isMuted(false),
255 isWarning_(false),
256 ownsLinebuf_(false) {}
258 ~JSErrorReport() { freeLinebuf(); }
260 public:
261 const char16_t* linebuf() const { return linebuf_; }
262 size_t linebufLength() const { return linebufLength_; }
263 size_t tokenOffset() const { return tokenOffset_; }
264 void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
265 size_t tokenOffsetArg) {
266 initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
267 ownsLinebuf_ = true;
269 void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg,
270 size_t tokenOffsetArg);
272 bool isWarning() const { return isWarning_; }
274 private:
275 void freeLinebuf();
278 namespace JS {
280 struct MOZ_STACK_CLASS JS_PUBLIC_API ErrorReportBuilder {
281 explicit ErrorReportBuilder(JSContext* cx);
282 ~ErrorReportBuilder();
284 enum SniffingBehavior { WithSideEffects, NoSideEffects };
287 * Generate a JSErrorReport from the provided thrown value.
289 * If the value is a (possibly wrapped) Error object, the JSErrorReport will
290 * be exactly initialized from the Error object's information, without
291 * observable side effects. (The Error object's JSErrorReport is reused, if
292 * it has one.)
294 * Otherwise various attempts are made to derive JSErrorReport information
295 * from |exnStack| and from the current execution state. This process is
296 * *definitely* inconsistent with any standard, and particulars of the
297 * behavior implemented here generally shouldn't be relied upon.
299 * If the value of |sniffingBehavior| is |WithSideEffects|, some of these
300 * attempts *may* invoke user-configurable behavior when the exception is an
301 * object: converting it to a string, detecting and getting its properties,
302 * accessing its prototype chain, and others are possible. Users *must*
303 * tolerate |ErrorReportBuilder::init| potentially having arbitrary effects.
304 * Any exceptions thrown by these operations will be caught and silently
305 * ignored, and "default" values will be substituted into the JSErrorReport.
307 * But if the value of |sniffingBehavior| is |NoSideEffects|, these attempts
308 * *will not* invoke any observable side effects. The JSErrorReport will
309 * simply contain fewer, less precise details.
311 * Unlike some functions involved in error handling, this function adheres
312 * to the usual JSAPI return value error behavior.
314 bool init(JSContext* cx, const JS::ExceptionStack& exnStack,
315 SniffingBehavior sniffingBehavior);
317 JSErrorReport* report() const { return reportp; }
319 const JS::ConstUTF8CharsZ toStringResult() const { return toStringResult_; }
321 private:
322 // More or less an equivalent of JS_ReportErrorNumber/js::ReportErrorNumberVA
323 // but fills in an ErrorReport instead of reporting it. Uses varargs to
324 // make it simpler to call js::ExpandErrorArgumentsVA.
326 // Returns false if we fail to actually populate the ErrorReport
327 // for some reason (probably out of memory).
328 bool populateUncaughtExceptionReportUTF8(JSContext* cx,
329 JS::HandleObject stack, ...);
330 bool populateUncaughtExceptionReportUTF8VA(JSContext* cx,
331 JS::HandleObject stack,
332 va_list ap);
334 // Reports exceptions from add-on scopes to telemetry.
335 void ReportAddonExceptionToTelemetry(JSContext* cx);
337 // We may have a provided JSErrorReport, so need a way to represent that.
338 JSErrorReport* reportp;
340 // Or we may need to synthesize a JSErrorReport one of our own.
341 JSErrorReport ownedReport;
343 // Root our exception value to keep a possibly borrowed |reportp| alive.
344 JS::RootedObject exnObject;
346 // And for our filename.
347 JS::UniqueChars filename;
349 // We may have a result of error.toString().
350 // FIXME: We should not call error.toString(), since it could have side
351 // effect (see bug 633623).
352 JS::ConstUTF8CharsZ toStringResult_;
353 JS::UniqueChars toStringResultBytesStorage;
356 // Writes a full report to a file descriptor. Does nothing for JSErrorReports
357 // which are warnings, unless reportWarnings is set.
358 extern JS_PUBLIC_API void PrintError(FILE* file, JSErrorReport* report,
359 bool reportWarnings);
361 extern JS_PUBLIC_API void PrintError(FILE* file,
362 const JS::ErrorReportBuilder& builder,
363 bool reportWarnings);
365 } // namespace JS
368 * There are four encoding variants for the error reporting API:
369 * UTF-8
370 * JSAPI's default encoding for error handling. Use this when the encoding
371 * of the error message, format string, and arguments is UTF-8.
372 * ASCII
373 * Equivalent to UTF-8, but also asserts that the error message, format
374 * string, and arguments are all ASCII. Because ASCII is a subset of UTF-8,
375 * any use of this encoding variant *could* be replaced with use of the
376 * UTF-8 variant. This variant exists solely to double-check the
377 * developer's assumption that all these strings truly are ASCII, given that
378 * UTF-8 and ASCII strings regrettably have the same C++ type.
379 * UC = UTF-16
380 * Use this when arguments are UTF-16. The format string must be UTF-8.
381 * Latin1 (planned to be removed)
382 * In this variant, all strings are interpreted byte-for-byte as the
383 * corresponding Unicode codepoint. This encoding may *safely* be used on
384 * any null-terminated string, regardless of its encoding. (You shouldn't
385 * *actually* be uncertain, but in the real world, a string's encoding -- if
386 * promised at all -- may be more...aspirational...than reality.) This
387 * encoding variant will eventually be removed -- work to convert your uses
388 * to UTF-8 as you're able.
391 namespace JS {
392 const uint16_t MaxNumErrorArguments = 10;
396 * Report an exception represented by the sprintf-like conversion of format
397 * and its arguments.
399 extern JS_PUBLIC_API void JS_ReportErrorASCII(JSContext* cx, const char* format,
400 ...) MOZ_FORMAT_PRINTF(2, 3);
402 extern JS_PUBLIC_API void JS_ReportErrorLatin1(JSContext* cx,
403 const char* format, ...)
404 MOZ_FORMAT_PRINTF(2, 3);
406 extern JS_PUBLIC_API void JS_ReportErrorUTF8(JSContext* cx, const char* format,
407 ...) MOZ_FORMAT_PRINTF(2, 3);
410 * Use an errorNumber to retrieve the format string, args are char*
412 extern JS_PUBLIC_API void JS_ReportErrorNumberASCII(
413 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
414 const unsigned errorNumber, ...);
416 extern JS_PUBLIC_API void JS_ReportErrorNumberASCIIVA(
417 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
418 const unsigned errorNumber, va_list ap);
420 extern JS_PUBLIC_API void JS_ReportErrorNumberLatin1(
421 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
422 const unsigned errorNumber, ...);
424 #ifdef va_start
425 extern JS_PUBLIC_API void JS_ReportErrorNumberLatin1VA(
426 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
427 const unsigned errorNumber, va_list ap);
428 #endif
430 extern JS_PUBLIC_API void JS_ReportErrorNumberUTF8(
431 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
432 const unsigned errorNumber, ...);
434 #ifdef va_start
435 extern JS_PUBLIC_API void JS_ReportErrorNumberUTF8VA(
436 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
437 const unsigned errorNumber, va_list ap);
438 #endif
441 * args is null-terminated. That is, a null char* means there are no
442 * more args. The number of args must match the number expected for
443 * errorNumber for the given JSErrorCallback.
445 extern JS_PUBLIC_API void JS_ReportErrorNumberUTF8Array(
446 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
447 const unsigned errorNumber, const char** args);
450 * Use an errorNumber to retrieve the format string, args are char16_t*
452 extern JS_PUBLIC_API void JS_ReportErrorNumberUC(JSContext* cx,
453 JSErrorCallback errorCallback,
454 void* userRef,
455 const unsigned errorNumber,
456 ...);
458 extern JS_PUBLIC_API void JS_ReportErrorNumberUCArray(
459 JSContext* cx, JSErrorCallback errorCallback, void* userRef,
460 const unsigned errorNumber, const char16_t** args);
463 * Complain when out of memory.
465 extern MOZ_COLD JS_PUBLIC_API void JS_ReportOutOfMemory(JSContext* cx);
467 extern JS_PUBLIC_API bool JS_ExpandErrorArgumentsASCII(
468 JSContext* cx, JSErrorCallback errorCallback, const unsigned errorNumber,
469 JSErrorReport* reportp, ...);
472 * Complain when an allocation size overflows the maximum supported limit.
474 extern JS_PUBLIC_API void JS_ReportAllocationOverflow(JSContext* cx);
476 namespace JS {
478 extern JS_PUBLIC_API bool CreateError(
479 JSContext* cx, JSExnType type, HandleObject stack, HandleString fileName,
480 uint32_t lineNumber, uint32_t columnNumber, JSErrorReport* report,
481 HandleString message, MutableHandleValue rval);
483 } /* namespace JS */
485 #endif /* js_ErrorReport_h */