JavascriptExceptionOperators.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 _M_AMD64
  7. extern "C" void *amd64_CallWithFakeFrame(void *target,
  8. void *frame,
  9. size_t spillSize,
  10. size_t argsSize,
  11. void *arg0 = nullptr) throw(...);
  12. #elif defined(_M_ARM)
  13. extern "C" void *arm_CallEhFrame(void *target, void *framePtr, void *localsPtr, size_t argsSize) throw(...);
  14. extern "C" void *arm_CallCatch(void *target, void *framePtr, void *localsPtr, size_t argsSize, void *catchObj) throw(...);
  15. #elif defined(_M_ARM64)
  16. extern "C" void *arm64_CallEhFrame(void *target, void *framePtr, void *localsPtr, size_t argsSize) throw(...);
  17. extern "C" void *arm64_CallCatch(void *target, void *framePtr, void *localsPtr, size_t argsSize, void *catchObj) throw(...);
  18. #endif
  19. namespace Js
  20. {
  21. class JavascriptExceptionContext;
  22. class JavascriptExceptionOperators /* All static */
  23. {
  24. public:
  25. static const uint64 DefaultStackTraceLimit = 10;
  26. static const uint64 MaxStackTraceLimit = _UI64_MAX;
  27. // AutoCatchHandlerExists tracks where an exception will be caught and not propagated out.
  28. // It should be included wherever an exception is caught and swallowed.
  29. class AutoCatchHandlerExists
  30. {
  31. private:
  32. bool m_previousCatchHandlerExists;
  33. bool m_previousCatchHandlerToUserCodeStatus;
  34. ThreadContext* m_threadContext;
  35. void FetchNonUserCodeStatus(ScriptContext *scriptContext);
  36. public:
  37. AutoCatchHandlerExists(ScriptContext* scriptContext, bool isPromiseHandled = true);
  38. ~AutoCatchHandlerExists();
  39. };
  40. class TryHandlerAddrOfReturnAddrStack
  41. {
  42. private:
  43. void * m_prevTryHandlerAddrOfReturnAddr;
  44. ThreadContext* m_threadContext;
  45. public:
  46. TryHandlerAddrOfReturnAddrStack(ScriptContext* scriptContext, void *addrOfReturnAddr);
  47. ~TryHandlerAddrOfReturnAddrStack();
  48. };
  49. class HasBailedOutPtrStack
  50. {
  51. private:
  52. bool * m_prevHasBailedOutPtr;
  53. ThreadContext* m_threadContext;
  54. public:
  55. HasBailedOutPtrStack(ScriptContext* scriptContext, bool *hasBailedOutPtr);
  56. ~HasBailedOutPtrStack();
  57. };
  58. class PendingFinallyExceptionStack
  59. {
  60. private:
  61. ThreadContext* m_threadContext;
  62. public:
  63. PendingFinallyExceptionStack(ScriptContext* scriptContext, Js::JavascriptExceptionObject *exceptionObj);
  64. ~PendingFinallyExceptionStack();
  65. };
  66. static void __declspec(noreturn) OP_Throw(Var object, ScriptContext* scriptContext);
  67. static void __declspec(noreturn) Throw(Var object, ScriptContext* scriptContext);
  68. static void __declspec(noreturn) ThrowExceptionObject(Js::JavascriptExceptionObject* exceptionObject, ScriptContext* scriptContext, bool considerPassingToDebugger = false, PVOID returnAddress = NULL, bool resetStack = false);
  69. static void __declspec(noreturn) RethrowExceptionObject(Js::JavascriptExceptionObject* exceptionObject, ScriptContext* scriptContext, bool considerPassingToDebugger = false);
  70. static void __declspec(noreturn) DoThrow(JavascriptExceptionObject* exceptionObject, ScriptContext* scriptContext);
  71. static void __declspec(noreturn) DoThrowCheckClone(JavascriptExceptionObject* exceptionObject, ScriptContext* scriptContext);
  72. #ifdef _M_X64
  73. static void *OP_TryCatch(void *try_, void *catch_, void *frame, size_t spillSize, size_t argsSize, int hasBailedOutOffset, ScriptContext *scriptContext);
  74. static void *OP_TryFinally(void *try_, void *finally_, void *frame, size_t spillSize, size_t argsSize, int hasBailedOutOffset, ScriptContext *scriptContext);
  75. static void *OP_TryFinallyNoOpt(void *try_, void *finally_, void *frame, size_t spillSize, size_t argsSize, ScriptContext *scriptContext);
  76. #elif defined(_M_ARM32_OR_ARM64)
  77. static void* OP_TryCatch(void* continuationAddr, void* handlerAddr, void* framePtr, void *localsPtr, size_t argsSize, int hasBailedOutOffset, ScriptContext* scriptContext);
  78. static void* OP_TryFinally(void* continuationAddr, void* handlerAddr, void* framePtr, void *localsPtr, size_t argsSize, int hasBailedOutOffset, ScriptContext* scriptContext);
  79. static void* OP_TryFinallyNoOpt(void* continuationAddr, void* handlerAddr, void* framePtr, void *localsPtr, size_t argsSize, ScriptContext* scriptContext);
  80. #else
  81. static void* OP_TryCatch(void* continuationAddr, void* handlerAddr, void* framePtr, int hasBailedOutOffset, ScriptContext* scriptContext);
  82. static void* OP_TryFinally(void* continuationAddr, void* handlerAddr, void* framePtr, int hasBailedOutOffset, ScriptContext* scriptContext);
  83. static void* OP_TryFinallyNoOpt(void* continuationAddr, void* handlerAddr, void* framePtr, ScriptContext* scriptContext);
  84. #endif
  85. #if defined(DBG) && defined(_M_IX86)
  86. static void DbgCheckEHChain();
  87. #endif
  88. static JavascriptExceptionObject* GetOutOfMemoryExceptionObject(ScriptContext* scriptContext);
  89. static Var OP_RuntimeTypeError(MessageId messageId, ScriptContext* scriptContext);
  90. static Var OP_RuntimeRangeError(MessageId messageId, ScriptContext* scriptContext);
  91. static Var OP_RuntimeReferenceError(MessageId messageId, ScriptContext* scriptContext);
  92. static Var OP_WebAssemblyRuntimeError(MessageId messageId, ScriptContext* scriptContext);
  93. static void __declspec(noreturn) ThrowOutOfMemory(ScriptContext* scriptContext);
  94. static void __declspec(noreturn) ThrowStackOverflow(ScriptContext* scriptContext, PVOID returnAddress);
  95. static uint64 GetStackTraceLimit(Var thrownObject, ScriptContext* scriptContext);
  96. static Var ThrowTypeErrorRestrictedPropertyAccessor(RecyclableObject* function, CallInfo callInfo, ...);
  97. static Var StackTraceAccessor(RecyclableObject* function, CallInfo callInfo, ...);
  98. static void WalkStackForExceptionContext(ScriptContext& scriptContext, JavascriptExceptionContext& exceptionContext, Var thrownObject, uint64 stackCrawlLimit, PVOID returnAddress, bool isThrownException = true, bool resetSatck = false);
  99. #if ENABLE_NATIVE_CODEGEN
  100. static void WalkStackForCleaningUpInlineeInfo(ScriptContext *scriptContext, PVOID returnAddress, PVOID tryCatchFrameAddr);
  101. #endif
  102. static void AddStackTraceToObject(Var obj, JavascriptExceptionContext::StackTrace* stackTrace, ScriptContext& scriptContext, bool isThrownException = true, bool resetSatck = false);
  103. static uint64 StackCrawlLimitOnThrow(Var thrownObject, ScriptContext& scriptContext);
  104. class EntryInfo
  105. {
  106. public:
  107. static FunctionInfo StackTraceAccessor;
  108. // For strict mode
  109. static FunctionInfo ThrowTypeErrorRestrictedPropertyAccessor;
  110. };
  111. private:
  112. static JavascriptFunction * WalkStackForExceptionContextInternal(ScriptContext& scriptContext, JavascriptExceptionContext& exceptionContext, Var thrownObject, uint32& callerByteCodeOffset,
  113. uint64 stackCrawlLimit, PVOID returnAddress, bool isThrownException, bool resetStack = false);
  114. static void ThrowExceptionObjectInternal(Js::JavascriptExceptionObject * exceptionObject, ScriptContext* scriptContext, bool fillExceptionContext, bool considerPassingToDebugger, PVOID returnAddress, bool resetStack);
  115. static BOOL GetCaller(JavascriptStackWalker& walker, _Out_opt_ JavascriptFunction*& jsFunc);
  116. static void DumpStackTrace(JavascriptExceptionContext& exceptionContext, bool isThrownException = true);
  117. static JavascriptExceptionContext::StackTrace* TrimStackTraceForThrownObject(JavascriptExceptionContext::StackTrace* stackTraceOriginal, Var thrownObject, ScriptContext& scriptContext);
  118. static void AppendExternalFrameToStackTrace(CompoundString* bs, LPCWSTR functionName, LPCWSTR fileName, ULONG lineNumber, LONG characterPosition);
  119. static void AppendLibraryFrameToStackTrace(CompoundString* bs, LPCWSTR functionName);
  120. static bool IsErrorInstance(Var thrownObject);
  121. static bool CrawlStackForWER(Js::ScriptContext& scriptContext);
  122. static void DispatchExceptionToDebugger(Js::JavascriptExceptionObject * exceptionObject, ScriptContext* scriptContext);
  123. };
  124. } // namespace Js