HRESULT RunScript(const char* fileName, LPCWSTR fileContents, BYTE *bcBuffer, char *fullPath) { HRESULT hr = S_OK; MessageQueue * messageQueue = new MessageQueue(); WScriptJsrt::AddMessageQueue(messageQueue); LPWSTR fullPathWide = nullptr; IfJsErrorFailLog(ChakraRTInterface::JsSetPromiseContinuationCallback(PromiseContinuationCallback, (void*)messageQueue)); Assert(fileContents != nullptr || bcBuffer != nullptr); // TODO: Remove this code in a future iteration once Utf8 versions of the Jsrt API is implemented IfFailGo(Helpers::NarrowStringToWideDynamic(fullPath, &fullPathWide)); JsErrorCode runScript; if (bcBuffer != nullptr) { runScript = ChakraRTInterface::JsRunSerializedScript(fileContents, bcBuffer, WScriptJsrt::GetNextSourceContext(), fullPathWide, nullptr /*result*/); } else { runScript = ChakraRTInterface::JsRunScript(fileContents, WScriptJsrt::GetNextSourceContext(), fullPathWide, nullptr /*result*/); } free(fullPathWide); if (runScript != JsNoError) { WScriptJsrt::PrintException(fileName, runScript); } else { // Repeatedly flush the message queue until it's empty. It is necessary to loop on this // because setTimeout can add scripts to execute. do { IfFailGo(messageQueue->ProcessAll(fileName)); } while (!messageQueue->IsEmpty()); } Error: if (messageQueue != nullptr) { messageQueue->RemoveAll(); delete messageQueue; } return hr; }
HRESULT RunScript(const char* fileName, LPCSTR fileContents, BYTE *bcBuffer, char *fullPath) { HRESULT hr = S_OK; MessageQueue * messageQueue = new MessageQueue(); WScriptJsrt::AddMessageQueue(messageQueue); IfJsErrorFailLog(ChakraRTInterface::JsSetPromiseContinuationCallback(PromiseContinuationCallback, (void*)messageQueue)); if(strlen(fileName) >= 14 && strcmp(fileName + strlen(fileName) - 14, "ttdSentinal.js") == 0) { #if !ENABLE_TTD wprintf(_u("Sential js file is only ok when in TTDebug mode!!!\n")); return E_FAIL; #else if(!doTTDebug) { wprintf(_u("Sential js file is only ok when in TTDebug mode!!!\n")); return E_FAIL; } ChakraRTInterface::JsTTDStart(); try { JsTTDMoveMode moveMode = (JsTTDMoveMode)(JsTTDMoveMode::JsTTDMoveKthEvent | ((int64) startEventCount) << 32); int64_t snapEventTime = -1; int64_t nextEventTime = -2; while(true) { JsErrorCode error = ChakraRTInterface::JsTTDGetSnapTimeTopLevelEventMove(chRuntime, moveMode, &nextEventTime, &snapEventTime, nullptr); if(error != JsNoError) { if(error == JsErrorCategoryUsage) { wprintf(_u("Start time not in log range.\n")); } return error; } IfFailedReturn(ChakraRTInterface::JsTTDMoveToTopLevelEvent(chRuntime, moveMode, snapEventTime, nextEventTime)); JsErrorCode res = ChakraRTInterface::JsTTDReplayExecution(&moveMode, &nextEventTime); //handle any uncaught exception by immediately time-traveling to the throwing line in the debugger -- in replay just report and exit if(res == JsErrorCategoryScript) { wprintf(_u("An unhandled script exception occoured!!!\n")); ExitProcess(0); } if(nextEventTime == -1) { wprintf(_u("\nReached end of Execution -- Exiting.\n")); break; } } } catch(...) { wprintf(_u("Terminal exception in Replay -- exiting.\n")); ExitProcess(0); } #endif } else { Assert(fileContents != nullptr || bcBuffer != nullptr); JsErrorCode runScript; JsValueRef fname; IfJsErrorFailLog(ChakraRTInterface::JsCreateStringUtf8((const uint8_t*)fullPath, strlen(fullPath), &fname)); if(bcBuffer != nullptr) { runScript = ChakraRTInterface::JsRunSerialized( bcBuffer, DummyJsSerializedScriptLoadUtf8Source, reinterpret_cast<JsSourceContext>(fileContents), // Use source ptr as sourceContext fname, nullptr /*result*/); } else { JsValueRef scriptSource; IfJsErrorFailLog(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContents, (unsigned int)strlen(fileContents), [](void *data) { free(data); }, nullptr, &scriptSource)); #if ENABLE_TTD if(doTTRecord) { ChakraRTInterface::JsTTDStart(); } runScript = ChakraRTInterface::JsRun(scriptSource, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr /*result*/); if (runScript == JsErrorCategoryUsage) { wprintf(_u("FATAL ERROR: Core was compiled without ENABLE_TTD is defined. CH is trying to use TTD interface\n")); abort(); } #else runScript = ChakraRTInterface::JsRun(scriptSource, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr /*result*/); #endif } //Do a yield after the main script body executes ChakraRTInterface::JsTTDNotifyYield(); if(runScript != JsNoError) { WScriptJsrt::PrintException(fileName, runScript); } else { // Repeatedly flush the message queue until it's empty. It is necessary to loop on this // because setTimeout can add scripts to execute. do { IfFailGo(messageQueue->ProcessAll(fileName)); } while(!messageQueue->IsEmpty()); } } Error: #if ENABLE_TTD if(doTTRecord) { ChakraRTInterface::JsTTDEmitRecording(); ChakraRTInterface::JsTTDStop(); } #endif if (messageQueue != nullptr) { messageQueue->RemoveAll(); // clean up possible pinned exception object on exit to avoid potential leak bool hasException; if (ChakraRTInterface::JsHasException(&hasException) == JsNoError && hasException) { JsValueRef exception = JS_INVALID_REFERENCE; ChakraRTInterface::JsGetAndClearException(&exception); } delete messageQueue; } return hr; }
HRESULT RunScript(const char* fileName, LPCWSTR fileContents, BYTE *bcBuffer, char *fullPath) { HRESULT hr = S_OK; MessageQueue * messageQueue = new MessageQueue(); WScriptJsrt::AddMessageQueue(messageQueue); LPWSTR fullPathWide = nullptr; IfJsErrorFailLog(ChakraRTInterface::JsSetPromiseContinuationCallback(PromiseContinuationCallback, (void*)messageQueue)); if(strlen(fileName) >= 14 && strcmp(fileName + strlen(fileName) - 14, "ttdSentinal.js") == 0) { #if !ENABLE_TTD wprintf(_u("Sential js file is only ok when in TTDebug mode!!!\n")); return E_FAIL; #else if(!doTTDebug) { wprintf(_u("Sential js file is only ok when in TTDebug mode!!!\n")); return E_FAIL; } ChakraRTInterface::JsTTDStartTimeTravelDebugging(); try { INT64 snapEventTime = -1; INT64 nextEventTime = -2; while(true) { IfJsErrorFailLog(ChakraRTInterface::JsTTDPrepContextsForTopLevelEventMove(chRuntime, nextEventTime, &snapEventTime)); ChakraRTInterface::JsTTDMoveToTopLevelEvent(snapEventTime, nextEventTime); JsErrorCode res = ChakraRTInterface::JsTTDReplayExecution(&nextEventTime); //handle any uncaught exception by immediately time-traveling to the throwing line if(res == JsErrorCategoryScript) { wprintf(_u("An unhandled script exception occoured!!!\n")); ExitProcess(0); } if(nextEventTime == -1) { wprintf(_u("\nReached end of Execution -- Exiting.\n")); break; } } } catch(...) { wprintf(_u("Terminal exception in Replay -- exiting.")); ExitProcess(0); } #endif } else { Assert(fileContents != nullptr || bcBuffer != nullptr); // TODO: Remove this code in a future iteration once Utf8 versions of the Jsrt API is implemented IfFailGo(Helpers::NarrowStringToWideDynamic(fullPath, &fullPathWide)); JsErrorCode runScript; if(bcBuffer != nullptr) { runScript = ChakraRTInterface::JsRunSerializedScript(fileContents, bcBuffer, WScriptJsrt::GetNextSourceContext(), fullPathWide, nullptr /*result*/); } else { #if ENABLE_TTD if(doTTRecord) { ChakraRTInterface::JsTTDStartTimeTravelRecording(); } runScript = ChakraRTInterface::JsTTDRunScript(-1, fileContents, WScriptJsrt::GetNextSourceContext(), fullPathWide, nullptr /*result*/); #else runScript = ChakraRTInterface::JsRunScript(fileContents, WScriptJsrt::GetNextSourceContext(), fullPathWide, nullptr /*result*/); #endif } free(fullPathWide); //Do a yield after the main script body executes ChakraRTInterface::JsTTDNotifyYield(); if(runScript != JsNoError) { WScriptJsrt::PrintException(fileName, runScript); } else { // Repeatedly flush the message queue until it's empty. It is necessary to loop on this // because setTimeout can add scripts to execute. do { IfFailGo(messageQueue->ProcessAll(fileName)); } while(!messageQueue->IsEmpty()); } } Error: #if ENABLE_TTD if(doTTRecord) { ChakraRTInterface::JsTTDStopTimeTravelRecording(); } #endif if (messageQueue != nullptr) { messageQueue->RemoveAll(); delete messageQueue; } return hr; }