Throw.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #ifdef STACK_BACK_TRACE
  7. class StackBackTrace;
  8. #endif
  9. namespace Js {
  10. class ScriptContext;
  11. class Throw
  12. {
  13. public:
  14. static void __declspec(noreturn) OutOfMemory();
  15. static void __declspec(noreturn) StackOverflow(ScriptContext *scriptContext, PVOID returnAddress);
  16. static void __declspec(noreturn) NotImplemented();
  17. static void __declspec(noreturn) InternalError();
  18. static void __declspec(noreturn) FatalInternalError();
  19. static void __declspec(noreturn) FatalProjectionError();
  20. static void CheckAndThrowOutOfMemory(BOOLEAN status);
  21. static bool ReportAssert(__in LPSTR fileName, uint lineNumber, __in LPSTR error, __in LPSTR message);
  22. static void LogAssert();
  23. #ifdef GENERATE_DUMP
  24. static int GenerateDump(PEXCEPTION_POINTERS exceptInfo, LPCWSTR filePath, int ret = EXCEPTION_CONTINUE_SEARCH, bool needLock = false);
  25. static void GenerateDump(LPCWSTR filePath, bool terminate = false, bool needLock = false);
  26. static void GenerateDumpForAssert(LPCWSTR filePath);
  27. private:
  28. static CriticalSection csGenerateDump;
  29. #ifdef STACK_BACK_TRACE
  30. __declspec(thread) static StackBackTrace * stackBackTrace;
  31. static const int StackToSkip = 2;
  32. static const int StackTraceDepth = 40;
  33. #endif
  34. #endif
  35. };
  36. // Info: Verify the result or throw catastrophic
  37. // Parameters: HRESULT
  38. inline void VerifyOkCatastrophic(__in HRESULT hr)
  39. {
  40. if (hr == E_OUTOFMEMORY)
  41. {
  42. Js::Throw::OutOfMemory();
  43. }
  44. else if (FAILED(hr))
  45. {
  46. Js::Throw::FatalProjectionError();
  47. }
  48. }
  49. // Info: Verify the result or throw catastrophic
  50. // Parameters: bool
  51. template<typename TCheck>
  52. inline void VerifyCatastrophic(__in TCheck result)
  53. {
  54. if (!result)
  55. {
  56. Assert(false);
  57. Js::Throw::FatalProjectionError();
  58. }
  59. }
  60. } // namespace Js
  61. #define BEGIN_TRANSLATE_TO_HRESULT(type) \
  62. {\
  63. try \
  64. { \
  65. AUTO_HANDLED_EXCEPTION_TYPE(type);
  66. #define BEGIN_TRANSLATE_TO_HRESULT_NESTED(type) \
  67. {\
  68. try \
  69. { \
  70. AUTO_NESTED_HANDLED_EXCEPTION_TYPE(type);
  71. #define BEGIN_TRANSLATE_OOM_TO_HRESULT BEGIN_TRANSLATE_TO_HRESULT(ExceptionType_OutOfMemory)
  72. #define BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED BEGIN_TRANSLATE_TO_HRESULT_NESTED(ExceptionType_OutOfMemory)
  73. #define END_TRANSLATE_OOM_TO_HRESULT(hr) \
  74. } \
  75. catch (Js::OutOfMemoryException) \
  76. { \
  77. hr = E_OUTOFMEMORY; \
  78. }\
  79. }
  80. #define END_TRANSLATE_OOM_TO_HRESULT_AND_EXCEPTION_OBJECT(hr, scriptContext, exceptionObject) \
  81. } \
  82. catch(Js::OutOfMemoryException) \
  83. { \
  84. hr = E_OUTOFMEMORY; \
  85. *exceptionObject = Js::JavascriptExceptionOperators::GetOutOfMemoryExceptionObject(scriptContext); \
  86. } \
  87. }
  88. #define BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT BEGIN_TRANSLATE_TO_HRESULT((ExceptionType)(ExceptionType_OutOfMemory | ExceptionType_StackOverflow))
  89. #define BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT_NESTED BEGIN_TRANSLATE_TO_HRESULT_NESTED((ExceptionType)(ExceptionType_OutOfMemory | ExceptionType_StackOverflow))
  90. #define BEGIN_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT BEGIN_TRANSLATE_TO_HRESULT((ExceptionType)(ExceptionType_OutOfMemory | ExceptionType_StackOverflow | ExceptionType_JavascriptException))
  91. #define BEGIN_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED BEGIN_TRANSLATE_TO_HRESULT_NESTED((ExceptionType)(ExceptionType_OutOfMemory | ExceptionType_StackOverflow | ExceptionType_JavascriptException))
  92. #define END_TRANSLATE_KNOWN_EXCEPTION_TO_HRESULT(hr) \
  93. } \
  94. catch (Js::InternalErrorException) \
  95. { \
  96. hr = E_FAIL; \
  97. } \
  98. catch (Js::OutOfMemoryException) \
  99. { \
  100. hr = E_OUTOFMEMORY; \
  101. } \
  102. catch (Js::StackOverflowException) \
  103. { \
  104. hr = VBSERR_OutOfStack; \
  105. } \
  106. catch (Js::NotImplementedException) \
  107. { \
  108. hr = E_NOTIMPL; \
  109. } \
  110. catch (Js::ScriptAbortException) \
  111. { \
  112. hr = E_ABORT; \
  113. } \
  114. catch (Js::AsmJsParseException) \
  115. { \
  116. hr = JSERR_AsmJsCompileError; \
  117. }
  118. #define CATCH_UNHANDLED_EXCEPTION(hr) \
  119. catch (...) \
  120. { \
  121. AssertMsg(FALSE, "invalid exception thrown and didn't get handled"); \
  122. hr = E_FAIL; \
  123. } \
  124. }
  125. #define END_TRANSLATE_EXCEPTION_TO_HRESULT(hr) \
  126. END_TRANSLATE_KNOWN_EXCEPTION_TO_HRESULT(hr)\
  127. CATCH_UNHANDLED_EXCEPTION(hr)
  128. #define END_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr) \
  129. Assert(!JsUtil::ExternalApi::IsScriptActiveOnCurrentThreadContext()); \
  130. END_TRANSLATE_KNOWN_EXCEPTION_TO_HRESULT(hr) \
  131. END_TRANSLATE_ERROROBJECT_TO_HRESULT(hr) \
  132. CATCH_UNHANDLED_EXCEPTION(hr)
  133. // Use this version if execution is in script (use rarely)
  134. #define END_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_INSCRIPT(hr) \
  135. Assert(JsUtil::ExternalApi::IsScriptActiveOnCurrentThreadContext()); \
  136. END_TRANSLATE_KNOWN_EXCEPTION_TO_HRESULT(hr) \
  137. END_TRANSLATE_ERROROBJECT_TO_HRESULT_INSCRIPT(hr) \
  138. CATCH_UNHANDLED_EXCEPTION(hr)
  139. #define END_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NOASSERT(hr) \
  140. END_TRANSLATE_KNOWN_EXCEPTION_TO_HRESULT(hr) \
  141. END_TRANSLATE_ERROROBJECT_TO_HRESULT(hr) \
  142. CATCH_UNHANDLED_EXCEPTION(hr)
  143. #define END_TRANSLATE_ERROROBJECT_TO_HRESULT_EX(hr, GetRuntimeErrorFunc) \
  144. catch(Js::JavascriptExceptionObject * exceptionObject) \
  145. { \
  146. GET_RUNTIME_ERROR_IMPL(hr, GetRuntimeErrorFunc, exceptionObject); \
  147. }
  148. #define GET_RUNTIME_ERROR_IMPL(hr, GetRuntimeErrorFunc, exceptionObject) \
  149. { \
  150. Js::Var errorObject = exceptionObject->GetThrownObject(nullptr); \
  151. if (errorObject != nullptr && (Js::JavascriptError::Is(errorObject) || \
  152. Js::JavascriptError::IsRemoteError(errorObject))) \
  153. { \
  154. hr = GetRuntimeErrorFunc(Js::RecyclableObject::FromVar(errorObject), nullptr); \
  155. } \
  156. else \
  157. { \
  158. AssertMsg(errorObject == nullptr, "errorObject should be NULL"); \
  159. hr = E_OUTOFMEMORY; \
  160. } \
  161. }
  162. #define GET_RUNTIME_ERROR(hr, exceptionObject) \
  163. GET_RUNTIME_ERROR_IMPL(hr, Js::JavascriptError::GetRuntimeErrorWithScriptEnter, exceptionObject)
  164. #define END_TRANSLATE_ERROROBJECT_TO_HRESULT(hr) \
  165. END_TRANSLATE_ERROROBJECT_TO_HRESULT_EX(hr, Js::JavascriptError::GetRuntimeErrorWithScriptEnter)
  166. #define END_GET_ERROROBJECT(hr, scriptContext, exceptionObject) \
  167. catch (Js::JavascriptExceptionObject * _exceptionObject) \
  168. { \
  169. BEGIN_TRANSLATE_OOM_TO_HRESULT_NESTED \
  170. exceptionObject = _exceptionObject; \
  171. exceptionObject = exceptionObject->CloneIfStaticExceptionObject(scriptContext); \
  172. END_TRANSLATE_OOM_TO_HRESULT(hr) \
  173. }
  174. #define CATCH_STATIC_JAVASCRIPT_EXCEPTION_OBJECT \
  175. catch (Js::OutOfMemoryException) \
  176. { \
  177. return JsErrorOutOfMemory; \
  178. } catch (Js::StackOverflowException) \
  179. { \
  180. return JsErrorOutOfMemory; \
  181. } \
  182. #define CATCH_OTHER_EXCEPTIONS \
  183. catch (JsrtExceptionBase& e) \
  184. { \
  185. return e.GetJsErrorCode(); \
  186. } \
  187. catch (Js::ExceptionBase) \
  188. { \
  189. AssertMsg(false, "Unexpected engine exception."); \
  190. return JsErrorFatal; \
  191. } \
  192. catch (...) \
  193. { \
  194. AssertMsg(false, "Unexpected non-engine exception."); \
  195. return JsErrorFatal; \
  196. }
  197. // Use this version if execution is in script (use rarely)
  198. #define END_TRANSLATE_ERROROBJECT_TO_HRESULT_INSCRIPT(hr) \
  199. END_TRANSLATE_ERROROBJECT_TO_HRESULT_EX(hr, Js::JavascriptError::GetRuntimeError)
  200. #define TRANSLATE_EXCEPTION_TO_HRESULT_ENTRY(ex) \
  201. } \
  202. catch (ex) \
  203. {
  204. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  205. #define RAISE_FATL_INTERNAL_ERROR_IFFAILED(hr) if (hr != S_OK) Js::Throw::FatalInternalError();
  206. #else
  207. #define RAISE_FATL_INTERNAL_ERROR_IFFAILED(hr)
  208. #endif