Throw.h 8.1 KB

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