ErrorReporting.h (8435B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_ErrorReporting_h 8 #define vm_ErrorReporting_h 9 10 #include <stdarg.h> 11 12 #include "jsfriendapi.h" // for ScriptEnvironmentPreparer 13 14 #include "js/CharacterEncoding.h" // JS::ConstUTF8CharsZ 15 #include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin 16 #include "js/ErrorReport.h" // for JSErrorNotes, JSErrorReport 17 #include "js/UniquePtr.h" // for UniquePtr 18 #include "js/Utility.h" // for UniqueTwoByteChars 19 20 namespace js { 21 22 class FrontendContext; 23 24 /** 25 * Use this type instead of JSContext when the object is only used for its 26 * ability to allocate memory (via its MallocProvider methods). 27 */ 28 using JSAllocator = JSContext; 29 30 /** 31 * Metadata for a compilation error (or warning) at a particular offset, or at 32 * no offset (i.e. with respect to a script overall). 33 */ 34 struct ErrorMetadata { 35 // The file/URL where the error occurred. 36 JS::ConstUTF8CharsZ filename; 37 38 // The line and column numbers where the error occurred. If the error 39 // is with respect to the entire script and not with respect to a 40 // particular location, these will both be zero. 41 42 // Line number (1-origin). 43 uint32_t lineNumber; 44 45 // Column number in UTF-16 code units. 46 JS::ColumnNumberOneOrigin columnNumber; 47 48 // If the error occurs at a particular location, context surrounding the 49 // location of the error: the line that contained the error, or a small 50 // portion of it if the line is long. (If the error occurs within a 51 // regular expression, this context is based upon its pattern characters.) 52 // 53 // This information is provided on a best-effort basis: code populating 54 // ErrorMetadata instances isn't obligated to supply this. 55 JS::UniqueTwoByteChars lineOfContext; 56 57 // If |lineOfContext| is provided, we show only a portion (a "window") of 58 // the line around the erroneous token -- the first char in the token, plus 59 // |lineOfContextRadius| chars before it and |lineOfContextRadius - 1| 60 // chars after it. This is because for a very long line, the full line is 61 // (a) not that helpful, and (b) wastes a lot of memory. See bug 634444. 62 static constexpr size_t lineOfContextRadius = 60; 63 64 // If |lineOfContext| is non-null, its length. 65 size_t lineLength; 66 67 // If |lineOfContext| is non-null, the offset within it of the token that 68 // triggered the error. 69 size_t tokenOffset; 70 71 // Whether the error is "muted" because it derives from a cross-origin 72 // load. See the comment in TransitiveCompileOptions in jsapi.h for 73 // details. 74 bool isMuted; 75 }; 76 77 class CompileError : public JSErrorReport { 78 public: 79 bool throwError(JSContext* cx); 80 }; 81 82 class MOZ_STACK_CLASS ReportExceptionClosure final 83 : public ScriptEnvironmentPreparer::Closure { 84 JS::HandleValue exn_; 85 86 public: 87 explicit ReportExceptionClosure(JS::HandleValue exn) : exn_(exn) {} 88 89 bool operator()(JSContext* cx) override; 90 }; 91 92 /** Send a JSErrorReport to the warningReporter callback. */ 93 extern void CallWarningReporter(JSContext* cx, JSErrorReport* report); 94 95 /** 96 * Report a compile error during script processing prior to execution of the 97 * script. 98 */ 99 extern void ReportCompileErrorLatin1VA(FrontendContext* fc, 100 ErrorMetadata&& metadata, 101 UniquePtr<JSErrorNotes> notes, 102 unsigned errorNumber, va_list* args); 103 104 extern void ReportCompileErrorUTF8VA(FrontendContext* fc, 105 ErrorMetadata&& metadata, 106 UniquePtr<JSErrorNotes> notes, 107 unsigned errorNumber, va_list* args); 108 109 extern void ReportCompileErrorLatin1(FrontendContext* fc, 110 ErrorMetadata&& metadata, 111 UniquePtr<JSErrorNotes> notes, 112 unsigned errorNumber, ...); 113 114 extern void ReportCompileErrorUTF8(FrontendContext* fc, 115 ErrorMetadata&& metadata, 116 UniquePtr<JSErrorNotes> notes, 117 unsigned errorNumber, ...); 118 119 /** 120 * Report a compile warning during script processing prior to execution of the 121 * script. Returns true if the warning was successfully reported, false if an 122 * error occurred. 123 */ 124 [[nodiscard]] extern bool ReportCompileWarning(FrontendContext* fc, 125 ErrorMetadata&& metadata, 126 UniquePtr<JSErrorNotes> notes, 127 unsigned errorNumber, 128 va_list* args); 129 130 class GlobalObject; 131 132 /** 133 * Report the given error Value to the given global. The JSContext is not 134 * assumed to be in any particular realm, but the global and error are 135 * expected to be same-compartment. 136 */ 137 extern void ReportErrorToGlobal(JSContext* cx, 138 JS::Handle<js::GlobalObject*> global, 139 JS::HandleValue error); 140 141 enum class IsWarning { No, Yes }; 142 143 /** 144 * Report an exception, using printf-style APIs to generate the error 145 * message. 146 */ 147 extern bool ReportErrorVA(JSContext* cx, IsWarning isWarning, 148 const char* format, ErrorArgumentsType argumentsType, 149 va_list ap) MOZ_FORMAT_PRINTF(3, 0); 150 151 extern bool ReportErrorNumberVA(JSContext* cx, IsWarning isWarning, 152 JSErrorCallback callback, void* userRef, 153 const unsigned errorNumber, 154 ErrorArgumentsType argumentsType, va_list ap); 155 156 extern bool ReportErrorNumberUCArray(JSContext* cx, IsWarning isWarning, 157 JSErrorCallback callback, void* userRef, 158 const unsigned errorNumber, 159 const char16_t** args); 160 161 extern bool ReportErrorNumberUTF8Array(JSContext* cx, IsWarning isWarning, 162 JSErrorCallback callback, void* userRef, 163 const unsigned errorNumber, 164 const char** args); 165 166 extern bool ExpandErrorArgumentsVA(FrontendContext* fc, 167 JSErrorCallback callback, void* userRef, 168 const unsigned errorNumber, 169 const char16_t** messageArgs, 170 ErrorArgumentsType argumentsType, 171 JSErrorReport* reportp, va_list ap); 172 173 extern bool ExpandErrorArgumentsVA(FrontendContext* fc, 174 JSErrorCallback callback, void* userRef, 175 const unsigned errorNumber, 176 const char** messageArgs, 177 ErrorArgumentsType argumentsType, 178 JSErrorReport* reportp, va_list ap); 179 180 /* 181 * For cases when we do not have an arguments array. 182 */ 183 extern bool ExpandErrorArgumentsVA(FrontendContext* fc, 184 JSErrorCallback callback, void* userRef, 185 const unsigned errorNumber, 186 ErrorArgumentsType argumentsType, 187 JSErrorReport* reportp, va_list ap); 188 189 extern bool ExpandErrorArgumentsVA(FrontendContext* fc, 190 JSErrorCallback callback, void* userRef, 191 const unsigned errorNumber, 192 const char16_t** messageArgs, 193 ErrorArgumentsType argumentsType, 194 JSErrorNotes::Note* notep, va_list ap); 195 196 /* 197 * If there is a pending exception, print it to stderr and clear it. Otherwise 198 * do nothing. 199 * 200 * For reporting bugs or unexpected errors in testing functions. 201 */ 202 extern void MaybePrintAndClearPendingException(JSContext* cx); 203 204 } // namespace js 205 206 #endif /* vm_ErrorReporting_h */