1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef INCLUDE_V8_EXCEPTION_H_ 6 #define INCLUDE_V8_EXCEPTION_H_ 7 8 #include <stddef.h> 9 10 #include "v8-local-handle.h" // NOLINT(build/include_directory) 11 #include "v8config.h" // NOLINT(build/include_directory) 12 13 namespace v8 { 14 15 class Context; 16 class Isolate; 17 class Message; 18 class StackTrace; 19 class String; 20 class Value; 21 22 namespace internal { 23 class Isolate; 24 class ThreadLocalTop; 25 } // namespace internal 26 27 /** 28 * Create new error objects by calling the corresponding error object 29 * constructor with the message. 30 */ 31 class V8_EXPORT Exception { 32 public: 33 static Local<Value> RangeError(Local<String> message); 34 static Local<Value> ReferenceError(Local<String> message); 35 static Local<Value> SyntaxError(Local<String> message); 36 static Local<Value> TypeError(Local<String> message); 37 static Local<Value> WasmCompileError(Local<String> message); 38 static Local<Value> WasmLinkError(Local<String> message); 39 static Local<Value> WasmRuntimeError(Local<String> message); 40 static Local<Value> Error(Local<String> message); 41 42 /** 43 * Creates an error message for the given exception. 44 * Will try to reconstruct the original stack trace from the exception value, 45 * or capture the current stack trace if not available. 46 */ 47 static Local<Message> CreateMessage(Isolate* isolate, Local<Value> exception); 48 49 /** 50 * Returns the original stack trace that was captured at the creation time 51 * of a given exception, or an empty handle if not available. 52 */ 53 static Local<StackTrace> GetStackTrace(Local<Value> exception); 54 }; 55 56 /** 57 * An external exception handler. 58 */ 59 class V8_EXPORT TryCatch { 60 public: 61 /** 62 * Creates a new try/catch block and registers it with v8. Note that 63 * all TryCatch blocks should be stack allocated because the memory 64 * location itself is compared against JavaScript try/catch blocks. 65 */ 66 explicit TryCatch(Isolate* isolate); 67 68 /** 69 * Unregisters and deletes this try/catch block. 70 */ 71 ~TryCatch(); 72 73 /** 74 * Returns true if an exception has been caught by this try/catch block. 75 */ 76 bool HasCaught() const; 77 78 /** 79 * For certain types of exceptions, it makes no sense to continue execution. 80 * 81 * If CanContinue returns false, the correct action is to perform any C++ 82 * cleanup needed and then return. If CanContinue returns false and 83 * HasTerminated returns true, it is possible to call 84 * CancelTerminateExecution in order to continue calling into the engine. 85 */ 86 bool CanContinue() const; 87 88 /** 89 * Returns true if an exception has been caught due to script execution 90 * being terminated. 91 * 92 * There is no JavaScript representation of an execution termination 93 * exception. Such exceptions are thrown when the TerminateExecution 94 * methods are called to terminate a long-running script. 95 * 96 * If such an exception has been thrown, HasTerminated will return true, 97 * indicating that it is possible to call CancelTerminateExecution in order 98 * to continue calling into the engine. 99 */ 100 bool HasTerminated() const; 101 102 /** 103 * Throws the exception caught by this TryCatch in a way that avoids 104 * it being caught again by this same TryCatch. As with ThrowException 105 * it is illegal to execute any JavaScript operations after calling 106 * ReThrow; the caller must return immediately to where the exception 107 * is caught. 108 */ 109 Local<Value> ReThrow(); 110 111 /** 112 * Returns the exception caught by this try/catch block. If no exception has 113 * been caught an empty handle is returned. 114 */ 115 Local<Value> Exception() const; 116 117 /** 118 * Returns the .stack property of an object. If no .stack 119 * property is present an empty handle is returned. 120 */ 121 V8_WARN_UNUSED_RESULT static MaybeLocal<Value> StackTrace( 122 Local<Context> context, Local<Value> exception); 123 124 /** 125 * Returns the .stack property of the thrown object. If no .stack property is 126 * present or if this try/catch block has not caught an exception, an empty 127 * handle is returned. 128 */ 129 V8_WARN_UNUSED_RESULT MaybeLocal<Value> StackTrace( 130 Local<Context> context) const; 131 132 /** 133 * Returns the message associated with this exception. If there is 134 * no message associated an empty handle is returned. 135 */ 136 Local<v8::Message> Message() const; 137 138 /** 139 * Clears any exceptions that may have been caught by this try/catch block. 140 * After this method has been called, HasCaught() will return false. Cancels 141 * the scheduled exception if it is caught and ReThrow() is not called before. 142 * 143 * It is not necessary to clear a try/catch block before using it again; if 144 * another exception is thrown the previously caught exception will just be 145 * overwritten. However, it is often a good idea since it makes it easier 146 * to determine which operation threw a given exception. 147 */ 148 void Reset(); 149 150 /** 151 * Set verbosity of the external exception handler. 152 * 153 * By default, exceptions that are caught by an external exception 154 * handler are not reported. Call SetVerbose with true on an 155 * external exception handler to have exceptions caught by the 156 * handler reported as if they were not caught. 157 */ 158 void SetVerbose(bool value); 159 160 /** 161 * Returns true if verbosity is enabled. 162 */ 163 bool IsVerbose() const; 164 165 /** 166 * Set whether or not this TryCatch should capture a Message object 167 * which holds source information about where the exception 168 * occurred. True by default. 169 */ 170 void SetCaptureMessage(bool value); 171 172 TryCatch(const TryCatch&) = delete; 173 void operator=(const TryCatch&) = delete; 174 175 private: 176 // Declaring operator new and delete as deleted is not spec compliant. 177 // Therefore declare them private instead to disable dynamic alloc 178 void* operator new(size_t size); 179 void* operator new[](size_t size); 180 void operator delete(void*, size_t); 181 void operator delete[](void*, size_t); 182 183 /** 184 * There are cases when the raw address of C++ TryCatch object cannot be 185 * used for comparisons with addresses into the JS stack. The cases are: 186 * 1) ARM, ARM64 and MIPS simulators which have separate JS stack. 187 * 2) Address sanitizer allocates local C++ object in the heap when 188 * UseAfterReturn mode is enabled. 189 * This method returns address that can be used for comparisons with 190 * addresses into the JS stack. When neither simulator nor ASAN's 191 * UseAfterReturn is enabled, then the address returned will be the address 192 * of the C++ try catch handler itself. 193 */ JSStackComparableAddressPrivate()194 internal::Address JSStackComparableAddressPrivate() { 195 return js_stack_comparable_address_; 196 } 197 198 void ResetInternal(); 199 200 internal::Isolate* isolate_; 201 TryCatch* next_; 202 void* exception_; 203 void* message_obj_; 204 internal::Address js_stack_comparable_address_; 205 bool is_verbose_ : 1; 206 bool can_continue_ : 1; 207 bool capture_message_ : 1; 208 bool rethrow_ : 1; 209 bool has_terminated_ : 1; 210 211 friend class internal::Isolate; 212 friend class internal::ThreadLocalTop; 213 }; 214 215 } // namespace v8 216 217 #endif // INCLUDE_V8_EXCEPTION_H_ 218