WScriptJsrt.cpp 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "stdafx.h"
  6. #include <vector>
  7. #if defined(_X86_) || defined(_M_IX86)
  8. #define CPU_ARCH_TEXT "x86"
  9. #elif defined(_AMD64_) || defined(_IA64_) || defined(_M_AMD64) || defined(_M_IA64)
  10. #define CPU_ARCH_TEXT "x86_64"
  11. #elif defined(_ARM_) || defined(_M_ARM)
  12. #define CPU_ARCH_TEXT "ARM"
  13. #elif defined(_ARM64_) || defined(_M_ARM64)
  14. #define CPU_ARCH_TEXT "ARM64"
  15. #endif
  16. // do not change the order below
  17. // otherwise, i.e. android system can be marked as posix? etc..
  18. #ifdef _WIN32
  19. #define DEST_PLATFORM_TEXT "win32"
  20. #else // ! _WIN32
  21. #if defined(__APPLE__)
  22. #ifdef __IOS__
  23. #define DEST_PLATFORM_TEXT "ios"
  24. #else // ! iOS
  25. #define DEST_PLATFORM_TEXT "darwin"
  26. #endif // iOS ?
  27. #elif defined(__ANDROID__)
  28. #define DEST_PLATFORM_TEXT "android"
  29. #elif defined(__linux__)
  30. #define DEST_PLATFORM_TEXT "posix"
  31. #elif defined(__FreeBSD__) || defined(__unix__)
  32. #define DEST_PLATFORM_TEXT "bsd"
  33. #endif // FreeBSD or unix ?
  34. #endif // _WIN32 ?
  35. MessageQueue* WScriptJsrt::messageQueue = nullptr;
  36. std::map<std::string, JsModuleRecord> WScriptJsrt::moduleRecordMap;
  37. std::map<JsModuleRecord, std::string> WScriptJsrt::moduleDirMap;
  38. std::map<DWORD_PTR, std::string> WScriptJsrt::scriptDirMap;
  39. DWORD_PTR WScriptJsrt::sourceContext = 0;
  40. #define ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString) \
  41. JsErrorCode errorCode = JsNoError; \
  42. do \
  43. { \
  44. const char *outOfMemoryString = \
  45. "Failed to convert wide string. Out of memory?";\
  46. \
  47. char *errorMessageNarrow; \
  48. if (FAILED(WideStringToNarrowDynamic(errorMessage, &errorMessageNarrow))) \
  49. { \
  50. errorCode = ChakraRTInterface::JsCreateString(outOfMemoryString, \
  51. strlen(outOfMemoryString), &errorMessageString); \
  52. } \
  53. else \
  54. { \
  55. errorCode = ChakraRTInterface::JsCreateString(errorMessageNarrow, \
  56. strlen(errorMessageNarrow), &errorMessageString); \
  57. free(errorMessageNarrow); \
  58. } \
  59. } \
  60. while(0)
  61. DWORD_PTR WScriptJsrt::GetNextSourceContext()
  62. {
  63. return sourceContext++;
  64. }
  65. void WScriptJsrt::RegisterScriptDir(DWORD_PTR sourceContext, LPCSTR fullDirNarrow)
  66. {
  67. char dir[_MAX_PATH];
  68. scriptDirMap[sourceContext] = std::string(GetDir(fullDirNarrow, dir));
  69. }
  70. bool WScriptJsrt::CreateArgumentsObject(JsValueRef *argsObject)
  71. {
  72. LPWSTR *argv = HostConfigFlags::argsVal;
  73. JsValueRef retArr;
  74. Assert(argsObject);
  75. *argsObject = nullptr;
  76. IfJsrtErrorFail(ChakraRTInterface::JsCreateArray(HostConfigFlags::argsCount, &retArr), false);
  77. for (int i = 0; i < HostConfigFlags::argsCount; i++)
  78. {
  79. JsValueRef value;
  80. JsValueRef index;
  81. char *argNarrow;
  82. if (FAILED(WideStringToNarrowDynamic(argv[i], &argNarrow)))
  83. {
  84. return false;
  85. }
  86. JsErrorCode errCode = ChakraRTInterface::JsCreateString(
  87. argNarrow,
  88. strlen(argNarrow), &value);
  89. free(argNarrow);
  90. IfJsrtErrorFail(errCode, false);
  91. IfJsrtErrorFail(ChakraRTInterface::JsDoubleToNumber(i, &index), false);
  92. IfJsrtErrorFail(ChakraRTInterface::JsSetIndexedProperty(retArr, index, value), false);
  93. }
  94. *argsObject = retArr;
  95. return true;
  96. }
  97. JsValueRef __stdcall WScriptJsrt::EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  98. {
  99. for (unsigned int i = 1; i < argumentCount; i++)
  100. {
  101. JsValueRef strValue;
  102. JsErrorCode error = ChakraRTInterface::JsConvertValueToString(arguments[i], &strValue);
  103. if (error == JsNoError)
  104. {
  105. AutoString str(strValue);
  106. if (str.GetError() == JsNoError)
  107. {
  108. if (i > 1)
  109. {
  110. wprintf(_u(" "));
  111. }
  112. wprintf(_u("%ls"), str.GetWideString());
  113. }
  114. }
  115. if (error == JsErrorScriptException)
  116. {
  117. return nullptr;
  118. }
  119. }
  120. wprintf(_u("\n"));
  121. fflush(stdout);
  122. JsValueRef undefinedValue;
  123. if (ChakraRTInterface::JsGetUndefinedValue(&undefinedValue) == JsNoError)
  124. {
  125. return undefinedValue;
  126. }
  127. else
  128. {
  129. return nullptr;
  130. }
  131. }
  132. JsValueRef __stdcall WScriptJsrt::QuitCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  133. {
  134. int exitCode = 0;
  135. if (argumentCount > 1)
  136. {
  137. double exitCodeDouble;
  138. IfJsrtErrorFail(ChakraRTInterface::JsNumberToDouble(arguments[1], &exitCodeDouble), JS_INVALID_REFERENCE);
  139. exitCode = (int)exitCodeDouble;
  140. }
  141. ExitProcess(exitCode);
  142. }
  143. JsValueRef __stdcall WScriptJsrt::LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  144. {
  145. return LoadScriptFileHelper(callee, arguments, argumentCount, false);
  146. }
  147. // needed because of calling convention differences between _stdcall and _cdecl
  148. void CHAKRA_CALLBACK WScriptJsrt::FinalizeFree(void* addr)
  149. {
  150. free(addr);
  151. }
  152. JsValueRef WScriptJsrt::LoadScriptFileHelper(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, bool isSourceModule)
  153. {
  154. HRESULT hr = E_FAIL;
  155. JsValueRef returnValue = JS_INVALID_REFERENCE;
  156. JsErrorCode errorCode = JsNoError;
  157. LPCWSTR errorMessage = _u("");
  158. if (argumentCount < 2 || argumentCount > 4)
  159. {
  160. errorCode = JsErrorInvalidArgument;
  161. errorMessage = _u("Need more or fewer arguments for WScript.LoadScript");
  162. }
  163. else
  164. {
  165. LPCSTR fileContent;
  166. AutoString fileName(arguments[1]);
  167. IfJsrtErrorSetGo(fileName.GetError());
  168. AutoString scriptInjectType;
  169. if (argumentCount > 2)
  170. {
  171. IfJsrtErrorSetGo(scriptInjectType.Initialize(arguments[2]));
  172. }
  173. if (errorCode == JsNoError)
  174. {
  175. hr = Helpers::LoadScriptFromFile(*fileName, fileContent);
  176. if (FAILED(hr))
  177. {
  178. fwprintf(stderr, _u("Couldn't load file.\n"));
  179. }
  180. else
  181. {
  182. returnValue = LoadScript(callee, *fileName, fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree);
  183. }
  184. }
  185. }
  186. Error:
  187. if (errorCode != JsNoError)
  188. {
  189. JsValueRef errorObject;
  190. JsValueRef errorMessageString;
  191. if (wcscmp(errorMessage, _u("")) == 0) {
  192. errorMessage = ConvertErrorCodeToMessage(errorCode);
  193. }
  194. ERROR_MESSAGE_TO_STRING(errCode, errorMessage, errorMessageString);
  195. ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  196. ChakraRTInterface::JsSetException(errorObject);
  197. }
  198. return returnValue;
  199. }
  200. JsValueRef __stdcall WScriptJsrt::LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  201. {
  202. return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, false);
  203. }
  204. JsValueRef __stdcall WScriptJsrt::LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  205. {
  206. return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, true);
  207. }
  208. JsValueRef WScriptJsrt::LoadScriptHelper(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState, bool isSourceModule)
  209. {
  210. HRESULT hr = E_FAIL;
  211. JsErrorCode errorCode = JsNoError;
  212. LPCWSTR errorMessage = _u("");
  213. JsValueRef returnValue = JS_INVALID_REFERENCE;
  214. if (argumentCount < 2 || argumentCount > 4)
  215. {
  216. errorCode = JsErrorInvalidArgument;
  217. errorMessage = _u("Need more or fewer arguments for WScript.LoadScript");
  218. }
  219. else
  220. {
  221. AutoString fileContent;
  222. char *fileNameNarrow = nullptr;
  223. AutoString fileName;
  224. AutoString scriptInjectType;
  225. char fileNameBuffer[MAX_PATH];
  226. IfJsrtErrorSetGo(fileContent.Initialize(arguments[1]));
  227. // ExternalArrayBuffer Finalize will clean this up
  228. // but only if we actually register a finalizecallback for this
  229. fileContent.MakePersistent();
  230. if (argumentCount > 2)
  231. {
  232. IfJsrtErrorSetGo(scriptInjectType.Initialize(arguments[2]));
  233. if (argumentCount > 3)
  234. {
  235. IfJsrtErrorSetGo(fileName.Initialize(arguments[3]));
  236. fileNameNarrow = *fileName;
  237. }
  238. }
  239. if (!fileNameNarrow && isSourceModule)
  240. {
  241. sprintf_s(fileNameBuffer, MAX_PATH, "moduleScript%i.js", (int)sourceContext);
  242. fileNameNarrow = fileNameBuffer;
  243. }
  244. if (*fileContent)
  245. {
  246. // TODO: This is CESU-8. How to tell the engine?
  247. // TODO: How to handle this source (script) life time?
  248. returnValue = LoadScript(callee, fileNameNarrow, *fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree);
  249. }
  250. }
  251. Error:
  252. if (errorCode != JsNoError)
  253. {
  254. JsValueRef errorObject;
  255. JsValueRef errorMessageString;
  256. if (wcscmp(errorMessage, _u("")) == 0) {
  257. errorMessage = ConvertErrorCodeToMessage(errorCode);
  258. }
  259. ERROR_MESSAGE_TO_STRING(errCode, errorMessage, errorMessageString);
  260. ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  261. ChakraRTInterface::JsSetException(errorObject);
  262. }
  263. return returnValue;
  264. }
  265. JsErrorCode WScriptJsrt::InitializeModuleInfo(JsValueRef specifier, JsModuleRecord moduleRecord)
  266. {
  267. JsErrorCode errorCode = JsNoError;
  268. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_FetchImportedModuleCallback, (void*)WScriptJsrt::FetchImportedModule);
  269. if (errorCode == JsNoError)
  270. {
  271. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_FetchImportedModuleFromScriptCallback, (void*)WScriptJsrt::FetchImportedModuleFromScript);
  272. if (errorCode == JsNoError)
  273. {
  274. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_NotifyModuleReadyCallback, (void*)WScriptJsrt::NotifyModuleReadyCallback);
  275. if (errorCode == JsNoError)
  276. {
  277. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_HostDefined, specifier);
  278. }
  279. }
  280. }
  281. IfJsrtErrorFailLogAndRetErrorCode(errorCode);
  282. return JsNoError;
  283. }
  284. char* WScriptJsrt::GetDir(LPCSTR fullPathNarrow, __out_ecount(260) char* const fullDirNarrow)
  285. {
  286. char dir[_MAX_DIR];
  287. _splitpath_s(fullPathNarrow, fullDirNarrow, _MAX_DRIVE, dir, _MAX_DIR, nullptr, 0, nullptr, 0);
  288. strcat_s(fullDirNarrow, _MAX_PATH, dir);
  289. return fullDirNarrow;
  290. }
  291. JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName)
  292. {
  293. DWORD_PTR dwSourceCookie = WScriptJsrt::GetNextSourceContext();
  294. JsModuleRecord requestModule = JS_INVALID_REFERENCE;
  295. LPCSTR moduleRecordKey = fullName ? fullName : fileName;
  296. auto moduleRecordEntry = moduleRecordMap.find(std::string(moduleRecordKey));
  297. JsErrorCode errorCode = JsNoError;
  298. // we need to create a new moduleRecord if the specifier (fileName) is not found;
  299. // otherwise we'll use the old one.
  300. if (moduleRecordEntry == moduleRecordMap.end())
  301. {
  302. JsValueRef specifier;
  303. errorCode = ChakraRTInterface::JsCreateString(
  304. fileName, strlen(fileName), &specifier);
  305. if (errorCode == JsNoError)
  306. {
  307. errorCode = ChakraRTInterface::JsInitializeModuleRecord(
  308. nullptr, specifier, &requestModule);
  309. }
  310. if (errorCode == JsNoError)
  311. {
  312. errorCode = InitializeModuleInfo(specifier, requestModule);
  313. }
  314. if (errorCode == JsNoError)
  315. {
  316. if (fullName)
  317. {
  318. char dir[_MAX_PATH];
  319. moduleDirMap[requestModule] = std::string(GetDir(fullName, dir));
  320. }
  321. moduleRecordMap[std::string(moduleRecordKey)] = requestModule;
  322. }
  323. }
  324. else
  325. {
  326. requestModule = moduleRecordEntry->second;
  327. }
  328. IfJsrtErrorFailLogAndRetErrorCode(errorCode);
  329. JsValueRef errorObject = JS_INVALID_REFERENCE;
  330. // ParseModuleSource is sync, while additional fetch & evaluation are async.
  331. unsigned int fileContentLength = (fileContent == nullptr) ? 0 : (unsigned int)strlen(fileContent);
  332. errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
  333. fileContentLength, JsParseModuleSourceFlags_DataIsUTF8, &errorObject);
  334. if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE && fileContent != nullptr && !HostConfigFlags::flags.IgnoreScriptErrorCode)
  335. {
  336. ChakraRTInterface::JsSetException(errorObject);
  337. return errorCode;
  338. }
  339. return JsNoError;
  340. }
  341. JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
  342. LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback)
  343. {
  344. HRESULT hr = E_FAIL;
  345. JsErrorCode errorCode = JsNoError;
  346. LPCWSTR errorMessage = _u("Internal error.");
  347. JsValueRef returnValue = JS_INVALID_REFERENCE;
  348. JsErrorCode innerErrorCode = JsNoError;
  349. JsContextRef currentContext = JS_INVALID_REFERENCE;
  350. JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
  351. void *callbackArg = (finalizeCallback != nullptr ? (void*)fileContent : nullptr);
  352. char fullPath[_MAX_PATH];
  353. IfJsrtErrorSetGo(ChakraRTInterface::JsGetCurrentContext(&currentContext));
  354. IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime));
  355. if (fileName == nullptr)
  356. {
  357. fileName = "script.js";
  358. }
  359. if (_fullpath(fullPath, fileName, _MAX_PATH) == nullptr)
  360. {
  361. goto Error;
  362. }
  363. // this is called with LoadModuleCallback method as well where caller pass in a string that should be
  364. // treated as a module source text instead of opening a new file.
  365. if (isSourceModule || (strcmp(scriptInjectType, "module") == 0))
  366. {
  367. errorCode = LoadModuleFromString(fileName, fileContent, fullPath);
  368. }
  369. else if (strcmp(scriptInjectType, "self") == 0)
  370. {
  371. JsContextRef calleeContext;
  372. IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
  373. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(calleeContext));
  374. JsValueRef scriptSource;
  375. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContent,
  376. (unsigned int)strlen(fileContent), finalizeCallback, callbackArg, &scriptSource));
  377. JsValueRef fname;
  378. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(fullPath,
  379. strlen(fullPath), &fname));
  380. JsSourceContext sourceContext = GetNextSourceContext();
  381. RegisterScriptDir(sourceContext, fullPath);
  382. errorCode = ChakraRTInterface::JsRun(scriptSource, sourceContext,
  383. fname, JsParseScriptAttributeNone, &returnValue);
  384. if(errorCode == JsNoError)
  385. {
  386. errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
  387. }
  388. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(currentContext));
  389. }
  390. else if (strcmp(scriptInjectType, "samethread") == 0)
  391. {
  392. JsValueRef newContext = JS_INVALID_REFERENCE;
  393. // Create a new context and set it as the current context
  394. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateContext(runtime, &newContext));
  395. #if ENABLE_TTD
  396. //We need this here since this context is created in record
  397. IfJsrtErrorSetGo(ChakraRTInterface::JsSetObjectBeforeCollectCallback(newContext, nullptr, WScriptJsrt::JsContextBeforeCollectCallback));
  398. #endif
  399. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(newContext));
  400. IfJsErrorFailLog(ChakraRTInterface::JsSetPromiseContinuationCallback(PromiseContinuationCallback, (void*)messageQueue));
  401. // Initialize the host objects
  402. Initialize();
  403. JsValueRef scriptSource;
  404. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContent,
  405. (unsigned int)strlen(fileContent), finalizeCallback, callbackArg, &scriptSource));
  406. JsValueRef fname;
  407. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(fullPath,
  408. strlen(fullPath), &fname));
  409. JsSourceContext sourceContext = GetNextSourceContext();
  410. RegisterScriptDir(sourceContext, fullPath);
  411. errorCode = ChakraRTInterface::JsRun(scriptSource, sourceContext,
  412. fname, JsParseScriptAttributeNone, &returnValue);
  413. if (errorCode == JsNoError)
  414. {
  415. errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
  416. }
  417. // Set the context back to the old one
  418. ChakraRTInterface::JsSetCurrentContext(currentContext);
  419. }
  420. else if (strcmp(scriptInjectType, "crossthread") == 0)
  421. {
  422. auto& threadData = GetRuntimeThreadLocalData().threadData;
  423. if (threadData == nullptr)
  424. {
  425. threadData = new RuntimeThreadData();
  426. }
  427. RuntimeThreadData* child = new RuntimeThreadData();
  428. child->initialSource = fileContent;
  429. threadData->children.push_back(child);
  430. child->parent = threadData;
  431. // TODO: need to add a switch in case we don't need to wait for
  432. // child initial script completion
  433. ResetEvent(threadData->hevntInitialScriptCompleted);
  434. child->hThread = ::CreateThread(NULL, NULL, [](void* param) -> DWORD
  435. {
  436. return ((RuntimeThreadData*)param)->ThreadProc();
  437. }, (void*)child, NULL, NULL);
  438. WaitForSingleObject(threadData->hevntInitialScriptCompleted, INFINITE);
  439. }
  440. else
  441. {
  442. errorCode = JsErrorInvalidArgument;
  443. errorMessage = _u("Unsupported argument type inject type.");
  444. }
  445. Error:
  446. JsValueRef value = returnValue;
  447. if (errorCode != JsNoError)
  448. {
  449. if (innerErrorCode != JsNoError)
  450. {
  451. // Failed to retrieve the inner error message, so set a custom error string
  452. errorMessage = ConvertErrorCodeToMessage(errorCode);
  453. }
  454. JsValueRef error = JS_INVALID_REFERENCE;
  455. JsValueRef messageProperty = JS_INVALID_REFERENCE;
  456. ERROR_MESSAGE_TO_STRING(errCode, errorMessage, messageProperty);
  457. if (errCode == JsNoError)
  458. {
  459. errCode = ChakraRTInterface::JsCreateError(messageProperty, &error);
  460. if (errCode == JsNoError)
  461. {
  462. bool hasException = false;
  463. errorCode = ChakraRTInterface::JsHasException(&hasException);
  464. if (errorCode == JsNoError && !hasException)
  465. {
  466. errCode = ChakraRTInterface::JsSetException(error);
  467. }
  468. else if (errCode == JsNoError)
  469. {
  470. errCode = JsErrorInExceptionState;
  471. }
  472. }
  473. }
  474. ChakraRTInterface::JsDoubleToNumber(errorCode, &value);
  475. }
  476. _flushall();
  477. return value;
  478. }
  479. JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  480. {
  481. LPCWSTR errorMessage = _u("invalid call to WScript.SetTimeout");
  482. JsValueRef function;
  483. JsValueRef timerId;
  484. unsigned int time;
  485. double tmp;
  486. CallbackMessage *msg = nullptr;
  487. if (argumentCount != 3)
  488. {
  489. goto Error;
  490. }
  491. function = arguments[1];
  492. IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[2], &tmp));
  493. time = static_cast<int>(tmp);
  494. msg = new CallbackMessage(time, function);
  495. messageQueue->InsertSorted(msg);
  496. IfJsrtError(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(msg->GetId()), &timerId));
  497. return timerId;
  498. Error:
  499. JsValueRef errorObject;
  500. JsValueRef errorMessageString;
  501. ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString);
  502. if (errorCode != JsNoError)
  503. {
  504. errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  505. if (errorCode != JsNoError)
  506. {
  507. ChakraRTInterface::JsSetException(errorObject);
  508. }
  509. }
  510. return JS_INVALID_REFERENCE;
  511. }
  512. JsValueRef WScriptJsrt::ClearTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  513. {
  514. LPCWSTR errorMessage = _u("invalid call to WScript.ClearTimeout");
  515. if (argumentCount != 2)
  516. {
  517. goto Error;
  518. }
  519. unsigned int timerId;
  520. double tmp;
  521. JsValueRef undef;
  522. JsValueRef global;
  523. IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[1], &tmp));
  524. timerId = static_cast<int>(tmp);
  525. messageQueue->RemoveById(timerId);
  526. IfJsrtError(ChakraRTInterface::JsGetGlobalObject(&global));
  527. IfJsrtError(ChakraRTInterface::JsGetUndefinedValue(&undef));
  528. return undef;
  529. Error:
  530. JsValueRef errorObject;
  531. JsValueRef errorMessageString;
  532. ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString);
  533. if (errorCode != JsNoError)
  534. {
  535. errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  536. if (errorCode != JsNoError)
  537. {
  538. ChakraRTInterface::JsSetException(errorObject);
  539. }
  540. }
  541. return JS_INVALID_REFERENCE;
  542. }
  543. template <class DebugOperationFunc>
  544. void QueueDebugOperation(JsValueRef function, const DebugOperationFunc& operation)
  545. {
  546. WScriptJsrt::PushMessage(WScriptJsrt::CallbackMessage::Create(function, operation));
  547. }
  548. JsValueRef WScriptJsrt::AttachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  549. {
  550. LPCWSTR errorMessage = _u("WScript.Attach requires a function, like WScript.Attach(foo);");
  551. JsValueType argumentType = JsUndefined;
  552. if (argumentCount != 2)
  553. {
  554. goto Error;
  555. }
  556. IfJsrtError(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType));
  557. if (argumentType != JsFunction)
  558. {
  559. goto Error;
  560. }
  561. QueueDebugOperation(arguments[1], [](WScriptJsrt::CallbackMessage& msg)
  562. {
  563. JsContextRef currentContext = JS_INVALID_REFERENCE;
  564. ChakraRTInterface::JsGetCurrentContext(&currentContext);
  565. JsRuntimeHandle currentRuntime = JS_INVALID_RUNTIME_HANDLE;
  566. ChakraRTInterface::JsGetRuntime(currentContext, &currentRuntime);
  567. Debugger* debugger = Debugger::GetDebugger(currentRuntime);
  568. debugger->StartDebugging(currentRuntime);
  569. debugger->SourceRunDown();
  570. return msg.CallFunction("");
  571. });
  572. Error:
  573. JsValueRef errorObject;
  574. JsValueRef errorMessageString;
  575. ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString);
  576. if (errorCode != JsNoError)
  577. {
  578. errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  579. if (errorCode != JsNoError)
  580. {
  581. ChakraRTInterface::JsSetException(errorObject);
  582. }
  583. }
  584. return JS_INVALID_REFERENCE;
  585. }
  586. JsValueRef WScriptJsrt::DetachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  587. {
  588. LPCWSTR errorMessage = _u("WScript.Detach requires a function, like WScript.Detach(foo);");
  589. JsValueType argumentType = JsUndefined;
  590. if (argumentCount != 2)
  591. {
  592. goto Error;
  593. }
  594. IfJsrtError(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType));
  595. if (argumentType != JsFunction)
  596. {
  597. goto Error;
  598. }
  599. QueueDebugOperation(arguments[1], [](WScriptJsrt::CallbackMessage& msg)
  600. {
  601. JsContextRef currentContext = JS_INVALID_REFERENCE;
  602. ChakraRTInterface::JsGetCurrentContext(&currentContext);
  603. JsRuntimeHandle currentRuntime = JS_INVALID_RUNTIME_HANDLE;
  604. ChakraRTInterface::JsGetRuntime(currentContext, &currentRuntime);
  605. if (Debugger::debugger != nullptr)
  606. {
  607. Debugger* debugger = Debugger::GetDebugger(currentRuntime);
  608. debugger->StopDebugging(currentRuntime);
  609. }
  610. return msg.CallFunction("");
  611. });
  612. Error:
  613. JsValueRef errorObject;
  614. JsValueRef errorMessageString;
  615. ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString);
  616. if (errorCode != JsNoError)
  617. {
  618. errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  619. if (errorCode != JsNoError)
  620. {
  621. ChakraRTInterface::JsSetException(errorObject);
  622. }
  623. }
  624. return JS_INVALID_REFERENCE;
  625. }
  626. JsValueRef WScriptJsrt::DumpFunctionPositionCallback(JsValueRef callee, bool isConstructCall, JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
  627. {
  628. JsValueRef functionPosition = JS_INVALID_REFERENCE;
  629. if (argumentCount > 1)
  630. {
  631. if (ChakraRTInterface::JsDiagGetFunctionPosition(arguments[1], &functionPosition) != JsNoError)
  632. {
  633. // If we can't get the functionPosition pass undefined
  634. IfJsErrorFailLogAndRet(ChakraRTInterface::JsGetUndefinedValue(&functionPosition));
  635. }
  636. if (Debugger::debugger != nullptr)
  637. {
  638. Debugger::debugger->DumpFunctionPosition(functionPosition);
  639. }
  640. }
  641. return JS_INVALID_REFERENCE;
  642. }
  643. JsValueRef WScriptJsrt::RequestAsyncBreakCallback(JsValueRef callee, bool isConstructCall,
  644. JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
  645. {
  646. if (Debugger::debugger != nullptr && !Debugger::debugger->IsDetached())
  647. {
  648. IfJsErrorFailLogAndRet(ChakraRTInterface::JsDiagRequestAsyncBreak(Debugger::GetRuntime()));
  649. }
  650. else
  651. {
  652. Helpers::LogError(_u("RequestAsyncBreak can only be called when debugger is attached"));
  653. }
  654. return JS_INVALID_REFERENCE;
  655. }
  656. JsValueRef WScriptJsrt::EmptyCallback(JsValueRef callee, bool isConstructCall,
  657. JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
  658. {
  659. return JS_INVALID_REFERENCE;
  660. }
  661. bool WScriptJsrt::CreateNamedFunction(const char* nameString, JsNativeFunction callback,
  662. JsValueRef* functionVar)
  663. {
  664. JsValueRef nameVar;
  665. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  666. nameString, strlen(nameString), &nameVar), false);
  667. IfJsrtErrorFail(ChakraRTInterface::JsCreateNamedFunction(nameVar, callback,
  668. nullptr, functionVar), false);
  669. return true;
  670. }
  671. bool WScriptJsrt::InstallObjectsOnObject(JsValueRef object, const char* name,
  672. JsNativeFunction nativeFunction)
  673. {
  674. JsValueRef propertyValueRef;
  675. JsPropertyIdRef propertyId;
  676. IfJsrtErrorFail(CreatePropertyIdFromString(name, &propertyId), false);
  677. CreateNamedFunction(name, nativeFunction, &propertyValueRef);
  678. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(object, propertyId,
  679. propertyValueRef, true), false);
  680. return true;
  681. }
  682. bool WScriptJsrt::Initialize()
  683. {
  684. HRESULT hr = S_OK;
  685. char CH_BINARY_LOCATION[2048];
  686. #ifdef CHAKRA_STATIC_LIBRARY
  687. const char* LINK_TYPE = "static";
  688. #else
  689. const char* LINK_TYPE = "shared";
  690. #endif
  691. JsValueRef wscript;
  692. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&wscript), false);
  693. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Echo", EchoCallback));
  694. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Quit", QuitCallback));
  695. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScriptFile", LoadScriptFileCallback));
  696. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScript", LoadScriptCallback));
  697. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadModule", LoadModuleCallback));
  698. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SetTimeout", SetTimeoutCallback));
  699. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ClearTimeout", ClearTimeoutCallback));
  700. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Attach", AttachCallback));
  701. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Detach", DetachCallback));
  702. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "DumpFunctionPosition", DumpFunctionPositionCallback));
  703. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "RequestAsyncBreak", RequestAsyncBreakCallback));
  704. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadBinaryFile", LoadBinaryFileCallback));
  705. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadTextFile", LoadTextFileCallback));
  706. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Flag", FlagCallback));
  707. // ToDo Remove
  708. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Edit", EmptyCallback));
  709. // Platform
  710. JsValueRef platformObject;
  711. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&platformObject), false);
  712. JsPropertyIdRef platformProperty;
  713. IfJsrtErrorFail(CreatePropertyIdFromString("Platform", &platformProperty), false);
  714. // Set CPU arch
  715. JsPropertyIdRef archProperty;
  716. IfJsrtErrorFail(CreatePropertyIdFromString("ARCH", &archProperty), false);
  717. JsValueRef archValue;
  718. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  719. CPU_ARCH_TEXT, strlen(CPU_ARCH_TEXT), &archValue), false);
  720. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, archProperty,
  721. archValue, true), false);
  722. // Set Build Type
  723. JsPropertyIdRef buildProperty;
  724. IfJsrtErrorFail(CreatePropertyIdFromString("BUILD_TYPE", &buildProperty), false);
  725. JsValueRef buildValue;
  726. #ifdef _DEBUG
  727. #define BUILD_TYPE_STRING_CH "Debug" // (O0)
  728. #elif defined(ENABLE_DEBUG_CONFIG_OPTIONS)
  729. #define BUILD_TYPE_STRING_CH "Test" // (O3 with debug config options)
  730. #else
  731. #define BUILD_TYPE_STRING_CH "Release" // (O3)
  732. #endif
  733. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  734. BUILD_TYPE_STRING_CH, strlen(BUILD_TYPE_STRING_CH), &buildValue), false);
  735. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, buildProperty,
  736. buildValue, true), false);
  737. #undef BUILD_TYPE_STRING_CH
  738. // Set Link Type [static / shared]
  739. JsPropertyIdRef linkProperty;
  740. IfJsrtErrorFail(CreatePropertyIdFromString("LINK_TYPE", &linkProperty), false);
  741. JsValueRef linkValue;
  742. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  743. LINK_TYPE, strlen(LINK_TYPE), &linkValue), false);
  744. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, linkProperty,
  745. linkValue, true), false);
  746. // Set Binary Location
  747. JsValueRef binaryPathValue;
  748. PlatformAgnostic::SystemInfo::GetBinaryLocation(CH_BINARY_LOCATION, sizeof(CH_BINARY_LOCATION));
  749. JsPropertyIdRef binaryPathProperty;
  750. IfJsrtErrorFail(CreatePropertyIdFromString("BINARY_PATH", &binaryPathProperty), false);
  751. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  752. CH_BINARY_LOCATION,
  753. strlen(CH_BINARY_LOCATION), &binaryPathValue), false);
  754. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(
  755. platformObject, binaryPathProperty, binaryPathValue, true), false);
  756. // Set destination OS
  757. JsPropertyIdRef osProperty;
  758. IfJsrtErrorFail(CreatePropertyIdFromString("OS", &osProperty), false);
  759. JsValueRef osValue;
  760. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  761. DEST_PLATFORM_TEXT, strlen(DEST_PLATFORM_TEXT), &osValue), false);
  762. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, osProperty,
  763. osValue, true), false);
  764. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, platformProperty,
  765. platformObject, true), false);
  766. JsValueRef argsObject;
  767. if (!CreateArgumentsObject(&argsObject))
  768. {
  769. return false;
  770. }
  771. JsPropertyIdRef argsName;
  772. IfJsrtErrorFail(CreatePropertyIdFromString("Arguments", &argsName), false);
  773. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, argsName, argsObject, true), false);
  774. JsPropertyIdRef wscriptName;
  775. IfJsrtErrorFail(CreatePropertyIdFromString("WScript", &wscriptName), false);
  776. JsValueRef global;
  777. IfJsrtErrorFail(ChakraRTInterface::JsGetGlobalObject(&global), false);
  778. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, wscriptName, wscript, true), false);
  779. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "print", EchoCallback));
  780. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "read", LoadTextFileCallback));
  781. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "readbuffer", LoadBinaryFileCallback));
  782. JsValueRef console;
  783. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&console), false);
  784. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(console, "log", EchoCallback));
  785. JsPropertyIdRef consoleName;
  786. IfJsrtErrorFail(CreatePropertyIdFromString("console", &consoleName), false);
  787. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, consoleName, console, true), false);
  788. IfJsrtErrorFail(InitializeModuleCallbacks(), false);
  789. // When the command-line argument `-Test262` is set,
  790. // WScript will have the extra support API below and $262 will be
  791. // added to global scope
  792. if (HostConfigFlags::flags.Test262)
  793. {
  794. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Broadcast", BroadcastCallback));
  795. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ReceiveBroadcast", ReceiveBroadcastCallback));
  796. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Report", ReportCallback));
  797. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetReport", GetReportCallback));
  798. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Leaving", LeavingCallback));
  799. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Sleep", SleepCallback));
  800. // $262
  801. const char Test262[] =
  802. #include "262.js"
  803. ;
  804. JsValueRef Test262ScriptRef;
  805. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString(Test262, strlen(Test262), &Test262ScriptRef));
  806. JsValueRef fname;
  807. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString("262", strlen("262"), &fname));
  808. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsRun(Test262ScriptRef, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr));
  809. }
  810. Error:
  811. return hr == S_OK;
  812. }
  813. JsErrorCode WScriptJsrt::InitializeModuleCallbacks()
  814. {
  815. JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
  816. JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(nullptr, nullptr, &moduleRecord);
  817. if (errorCode == JsNoError)
  818. {
  819. errorCode = InitializeModuleInfo(nullptr, moduleRecord);
  820. }
  821. return errorCode;
  822. }
  823. bool WScriptJsrt::Uninitialize()
  824. {
  825. // moduleRecordMap is a global std::map, its destructor may access overrided
  826. // "operator delete" / global HeapAllocator::Instance. Clear it manually here
  827. // to avoid worrying about global destructor order.
  828. moduleRecordMap.clear();
  829. moduleDirMap.clear();
  830. scriptDirMap.clear();
  831. auto& threadData = GetRuntimeThreadLocalData().threadData;
  832. if (threadData && !threadData->children.empty())
  833. {
  834. LONG count = (LONG)threadData->children.size();
  835. std::vector<HANDLE> childrenHandles;
  836. //Clang does not support "for each" yet
  837. for(auto i = threadData->children.begin(); i!= threadData->children.end(); i++)
  838. {
  839. auto child = *i;
  840. childrenHandles.push_back(child->hThread);
  841. SetEvent(child->hevntShutdown);
  842. }
  843. DWORD waitRet = WaitForMultipleObjects(count, &childrenHandles[0], TRUE, INFINITE);
  844. Assert(waitRet == WAIT_OBJECT_0);
  845. for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
  846. {
  847. delete *i;
  848. }
  849. threadData->children.clear();
  850. }
  851. return true;
  852. }
  853. #if ENABLE_TTD
  854. void CALLBACK WScriptJsrt::JsContextBeforeCollectCallback(JsRef contextRef, void *data)
  855. {
  856. ChakraRTInterface::JsTTDNotifyContextDestroy(contextRef);
  857. }
  858. #endif
  859. JsValueRef __stdcall WScriptJsrt::LoadTextFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  860. {
  861. HRESULT hr = E_FAIL;
  862. JsValueRef returnValue = JS_INVALID_REFERENCE;
  863. JsErrorCode errorCode = JsNoError;
  864. const char* fileContent = nullptr;
  865. if (argumentCount < 2)
  866. {
  867. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  868. }
  869. else
  870. {
  871. AutoString fileName;
  872. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  873. if (errorCode == JsNoError)
  874. {
  875. UINT lengthBytes = 0;
  876. hr = Helpers::LoadScriptFromFile(*fileName, fileContent, &lengthBytes);
  877. if (FAILED(hr))
  878. {
  879. fwprintf(stderr, _u("Couldn't load file.\n"));
  880. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  881. }
  882. else
  883. {
  884. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(
  885. fileContent, lengthBytes, &returnValue));
  886. }
  887. }
  888. }
  889. Error:
  890. if (fileContent)
  891. {
  892. free((void*)fileContent);
  893. }
  894. return returnValue;
  895. }
  896. JsValueRef __stdcall WScriptJsrt::LoadBinaryFileCallback(JsValueRef callee,
  897. bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  898. {
  899. HRESULT hr = E_FAIL;
  900. JsValueRef returnValue = JS_INVALID_REFERENCE;
  901. JsErrorCode errorCode = JsNoError;
  902. if (argumentCount < 2)
  903. {
  904. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  905. }
  906. else
  907. {
  908. const char *fileContent;
  909. AutoString fileName;
  910. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  911. if (errorCode == JsNoError)
  912. {
  913. UINT lengthBytes = 0;
  914. hr = Helpers::LoadBinaryFile(*fileName, fileContent, lengthBytes);
  915. if (FAILED(hr))
  916. {
  917. fwprintf(stderr, _u("Couldn't load file.\n"));
  918. }
  919. else
  920. {
  921. JsValueRef arrayBuffer;
  922. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsCreateArrayBuffer(lengthBytes, &arrayBuffer), ErrorStillFree);
  923. BYTE* buffer;
  924. unsigned int bufferLength;
  925. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetArrayBufferStorage(arrayBuffer, &buffer, &bufferLength), ErrorStillFree);
  926. if (bufferLength < lengthBytes)
  927. {
  928. fwprintf(stderr, _u("Array buffer size is insufficient to store the binary file.\n"));
  929. }
  930. else
  931. {
  932. if (memcpy_s(buffer, bufferLength, (BYTE*)fileContent, lengthBytes) == 0)
  933. {
  934. returnValue = arrayBuffer;
  935. }
  936. }
  937. ErrorStillFree:
  938. HeapFree(GetProcessHeap(), 0, (void*)fileContent);
  939. }
  940. }
  941. }
  942. Error:
  943. return returnValue;
  944. }
  945. JsValueRef __stdcall WScriptJsrt::FlagCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  946. {
  947. HRESULT hr = E_FAIL;
  948. JsValueRef returnValue = JS_INVALID_REFERENCE;
  949. JsErrorCode errorCode = JsNoError;
  950. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  951. #if ENABLE_DEBUG_CONFIG_OPTIONS
  952. if (argumentCount > 1)
  953. {
  954. AutoString cmd;
  955. IfJsrtErrorSetGo(cmd.Initialize(arguments[1]));
  956. char16* argv[] = { nullptr, cmd.GetWideString() };
  957. ChakraRTInterface::SetConfigFlags(2, argv, nullptr);
  958. }
  959. #endif
  960. Error:
  961. return returnValue;
  962. }
  963. JsValueRef __stdcall WScriptJsrt::BroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  964. {
  965. HRESULT hr = E_FAIL;
  966. JsValueRef returnValue = JS_INVALID_REFERENCE;
  967. JsErrorCode errorCode = JsNoError;
  968. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  969. if (argumentCount > 1)
  970. {
  971. auto& threadData = GetRuntimeThreadLocalData().threadData;
  972. if (threadData)
  973. {
  974. ChakraRTInterface::JsGetSharedArrayBufferContent(arguments[1], &threadData->sharedContent);
  975. LONG count = (LONG)threadData->children.size();
  976. threadData->hSemaphore = CreateSemaphore(NULL, 0, count, NULL);
  977. if (threadData->hSemaphore)
  978. {
  979. //Clang does not support "for each" yet
  980. for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
  981. {
  982. auto child = *i;
  983. SetEvent(child->hevntReceivedBroadcast);
  984. }
  985. WaitForSingleObject(threadData->hSemaphore, INFINITE);
  986. CloseHandle(threadData->hSemaphore);
  987. threadData->hSemaphore = INVALID_HANDLE_VALUE;
  988. }
  989. else
  990. {
  991. fwprintf(stderr, _u("Couldn't create semaphore.\n"));
  992. fflush(stderr);
  993. }
  994. ChakraRTInterface::JsReleaseSharedArrayBufferContentHandle(threadData->sharedContent);
  995. }
  996. }
  997. Error:
  998. return returnValue;
  999. }
  1000. JsValueRef __stdcall WScriptJsrt::ReceiveBroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1001. {
  1002. HRESULT hr = E_FAIL;
  1003. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1004. JsErrorCode errorCode = JsNoError;
  1005. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1006. if (argumentCount > 1)
  1007. {
  1008. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1009. if (threadData)
  1010. {
  1011. if (threadData->receiveBroadcastCallbackFunc)
  1012. {
  1013. ChakraRTInterface::JsRelease(threadData->receiveBroadcastCallbackFunc, nullptr);
  1014. }
  1015. threadData->receiveBroadcastCallbackFunc = arguments[1];
  1016. ChakraRTInterface::JsAddRef(threadData->receiveBroadcastCallbackFunc, nullptr);
  1017. }
  1018. }
  1019. Error:
  1020. return returnValue;
  1021. }
  1022. JsValueRef __stdcall WScriptJsrt::ReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1023. {
  1024. HRESULT hr = E_FAIL;
  1025. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1026. JsErrorCode errorCode = JsNoError;
  1027. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1028. if (argumentCount > 1)
  1029. {
  1030. JsValueRef stringRef;
  1031. ChakraRTInterface::JsConvertValueToString(arguments[1], &stringRef);
  1032. AutoString autoStr(stringRef);
  1033. if (autoStr.GetError() == JsNoError)
  1034. {
  1035. std::string str(autoStr.GetString());
  1036. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1037. if (threadData && threadData->parent)
  1038. {
  1039. EnterCriticalSection(&threadData->parent->csReportQ);
  1040. threadData->parent->reportQ.push_back(str);
  1041. LeaveCriticalSection(&threadData->parent->csReportQ);
  1042. }
  1043. }
  1044. }
  1045. Error:
  1046. return returnValue;
  1047. }
  1048. JsValueRef __stdcall WScriptJsrt::GetReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1049. {
  1050. HRESULT hr = E_FAIL;
  1051. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1052. JsErrorCode errorCode = JsNoError;
  1053. IfJsrtErrorSetGo(ChakraRTInterface::JsGetNullValue(&returnValue));
  1054. if (argumentCount > 0)
  1055. {
  1056. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1057. if (threadData)
  1058. {
  1059. EnterCriticalSection(&threadData->csReportQ);
  1060. if (threadData->reportQ.size() > 0)
  1061. {
  1062. auto str = threadData->reportQ.front();
  1063. threadData->reportQ.pop_front();
  1064. ChakraRTInterface::JsCreateString(str.c_str(), str.size(), &returnValue);
  1065. }
  1066. LeaveCriticalSection(&threadData->csReportQ);
  1067. }
  1068. }
  1069. Error:
  1070. return returnValue;
  1071. }
  1072. JsValueRef __stdcall WScriptJsrt::LeavingCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1073. {
  1074. HRESULT hr = E_FAIL;
  1075. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1076. JsErrorCode errorCode = JsNoError;
  1077. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1078. if (argumentCount > 0)
  1079. {
  1080. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1081. if (threadData)
  1082. {
  1083. threadData->leaving = true;
  1084. }
  1085. }
  1086. Error:
  1087. return returnValue;
  1088. }
  1089. JsValueRef __stdcall WScriptJsrt::SleepCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1090. {
  1091. HRESULT hr = E_FAIL;
  1092. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1093. JsErrorCode errorCode = JsNoError;
  1094. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1095. if (argumentCount > 1)
  1096. {
  1097. double timeout = 0.0;
  1098. ChakraRTInterface::JsNumberToDouble(arguments[1], &timeout);
  1099. Sleep((DWORD)timeout);
  1100. }
  1101. Error:
  1102. return returnValue;
  1103. }
  1104. bool WScriptJsrt::PrintException(LPCSTR fileName, JsErrorCode jsErrorCode)
  1105. {
  1106. LPCWSTR errorTypeString = ConvertErrorCodeToMessage(jsErrorCode);
  1107. JsValueRef exception;
  1108. ChakraRTInterface::JsGetAndClearException(&exception);
  1109. if (HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
  1110. {
  1111. return false;
  1112. }
  1113. if (exception != nullptr)
  1114. {
  1115. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile || jsErrorCode == JsErrorCode::JsErrorScriptException)
  1116. {
  1117. AutoString errorMessage;
  1118. IfJsrtErrorFail(errorMessage.Initialize(exception), false);
  1119. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile)
  1120. {
  1121. JsPropertyIdRef linePropertyId = JS_INVALID_REFERENCE;
  1122. JsValueRef lineProperty = JS_INVALID_REFERENCE;
  1123. JsPropertyIdRef columnPropertyId = JS_INVALID_REFERENCE;
  1124. JsValueRef columnProperty = JS_INVALID_REFERENCE;
  1125. int line;
  1126. int column;
  1127. IfJsrtErrorFail(CreatePropertyIdFromString("line", &linePropertyId), false);
  1128. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, linePropertyId, &lineProperty), false);
  1129. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(lineProperty, &line), false);
  1130. IfJsrtErrorFail(CreatePropertyIdFromString("column", &columnPropertyId), false);
  1131. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, columnPropertyId, &columnProperty), false);
  1132. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(columnProperty, &column), false);
  1133. CHAR shortFileName[_MAX_PATH];
  1134. CHAR ext[_MAX_EXT];
  1135. _splitpath_s(fileName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  1136. fwprintf(stderr, _u("%ls\n\tat code (%S%S:%d:%d)\n"),
  1137. errorMessage.GetWideString(), shortFileName, ext, (int)line + 1,
  1138. (int)column + 1);
  1139. }
  1140. else
  1141. {
  1142. JsValueType propertyType = JsUndefined;
  1143. JsPropertyIdRef stackPropertyId = JS_INVALID_REFERENCE;
  1144. JsValueRef stackProperty = JS_INVALID_REFERENCE;
  1145. AutoString errorStack;
  1146. JsErrorCode errorCode = CreatePropertyIdFromString("stack", &stackPropertyId);
  1147. if (errorCode == JsErrorCode::JsNoError)
  1148. {
  1149. errorCode = ChakraRTInterface::JsGetProperty(exception, stackPropertyId, &stackProperty);
  1150. if (errorCode == JsErrorCode::JsNoError)
  1151. {
  1152. errorCode = ChakraRTInterface::JsGetValueType(stackProperty, &propertyType);
  1153. }
  1154. }
  1155. if (errorCode != JsErrorCode::JsNoError || propertyType == JsUndefined)
  1156. {
  1157. const char *fName = fileName != nullptr ? fileName : "(unknown)";
  1158. CHAR shortFileName[_MAX_PATH];
  1159. CHAR ext[_MAX_EXT];
  1160. _splitpath_s(fName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  1161. // do not mix char/wchar. print them separately
  1162. fprintf(stderr, "thrown at %s%s:\n^\n", shortFileName, ext);
  1163. fwprintf(stderr, _u("%ls\n"), errorMessage.GetWideString());
  1164. }
  1165. else
  1166. {
  1167. IfJsrtErrorFail(errorStack.Initialize(stackProperty), false);
  1168. fwprintf(stderr, _u("%ls\n"), errorStack.GetWideString());
  1169. }
  1170. }
  1171. }
  1172. else
  1173. {
  1174. fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
  1175. }
  1176. return true;
  1177. }
  1178. else
  1179. {
  1180. fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
  1181. }
  1182. return false;
  1183. }
  1184. void WScriptJsrt::AddMessageQueue(MessageQueue *_messageQueue)
  1185. {
  1186. Assert(messageQueue == nullptr);
  1187. messageQueue = _messageQueue;
  1188. }
  1189. WScriptJsrt::CallbackMessage::CallbackMessage(unsigned int time, JsValueRef function) : MessageBase(time), m_function(function)
  1190. {
  1191. JsErrorCode error = ChakraRTInterface::JsAddRef(m_function, nullptr);
  1192. if (error != JsNoError)
  1193. {
  1194. // Simply report a fatal error and exit because continuing from this point would result in inconsistent state
  1195. // and FailFast telemetry would not be useful.
  1196. wprintf(_u("FATAL ERROR: ChakraRTInterface::JsAddRef failed in WScriptJsrt::CallbackMessage::`ctor`. error=0x%x\n"), error);
  1197. exit(1);
  1198. }
  1199. }
  1200. WScriptJsrt::CallbackMessage::~CallbackMessage()
  1201. {
  1202. bool hasException = false;
  1203. ChakraRTInterface::JsHasException(&hasException);
  1204. if (hasException)
  1205. {
  1206. WScriptJsrt::PrintException("", JsErrorScriptException);
  1207. }
  1208. JsErrorCode errorCode = ChakraRTInterface::JsRelease(m_function, nullptr);
  1209. Assert(errorCode == JsNoError);
  1210. m_function = JS_INVALID_REFERENCE;
  1211. }
  1212. HRESULT WScriptJsrt::CallbackMessage::Call(LPCSTR fileName)
  1213. {
  1214. return CallFunction(fileName);
  1215. }
  1216. HRESULT WScriptJsrt::CallbackMessage::CallFunction(LPCSTR fileName)
  1217. {
  1218. HRESULT hr = S_OK;
  1219. JsValueRef global;
  1220. JsValueRef result;
  1221. JsValueRef stringValue;
  1222. JsValueType type;
  1223. JsErrorCode errorCode = JsNoError;
  1224. IfJsrtErrorHR(ChakraRTInterface::JsGetGlobalObject(&global));
  1225. IfJsrtErrorHR(ChakraRTInterface::JsGetValueType(m_function, &type));
  1226. if (type == JsString)
  1227. {
  1228. IfJsrtErrorHR(ChakraRTInterface::JsConvertValueToString(m_function, &stringValue));
  1229. JsValueRef fname;
  1230. ChakraRTInterface::JsCreateString("", strlen(""), &fname);
  1231. // Run the code
  1232. errorCode = ChakraRTInterface::JsRun(stringValue, JS_SOURCE_CONTEXT_NONE,
  1233. fname, JsParseScriptAttributeArrayBufferIsUtf16Encoded,
  1234. nullptr /*no result needed*/);
  1235. }
  1236. else
  1237. {
  1238. errorCode = ChakraRTInterface::JsCallFunction(m_function, &global, 1, &result);
  1239. }
  1240. if (errorCode != JsNoError)
  1241. {
  1242. hr = E_FAIL;
  1243. PrintException(fileName, errorCode);
  1244. }
  1245. Error:
  1246. return hr;
  1247. }
  1248. WScriptJsrt::ModuleMessage::ModuleMessage(JsModuleRecord module, JsValueRef specifier)
  1249. : MessageBase(0), moduleRecord(module), specifier(specifier)
  1250. {
  1251. ChakraRTInterface::JsAddRef(module, nullptr);
  1252. if (specifier != nullptr)
  1253. {
  1254. // nullptr specifier means a Promise to execute; non-nullptr means a "fetch" operation.
  1255. ChakraRTInterface::JsAddRef(specifier, nullptr);
  1256. }
  1257. }
  1258. WScriptJsrt::ModuleMessage::~ModuleMessage()
  1259. {
  1260. ChakraRTInterface::JsRelease(moduleRecord, nullptr);
  1261. if (specifier != nullptr)
  1262. {
  1263. ChakraRTInterface::JsRelease(specifier, nullptr);
  1264. }
  1265. }
  1266. HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
  1267. {
  1268. JsErrorCode errorCode;
  1269. JsValueRef result = JS_INVALID_REFERENCE;
  1270. HRESULT hr;
  1271. if (specifier == nullptr)
  1272. {
  1273. errorCode = ChakraRTInterface::JsModuleEvaluation(moduleRecord, &result);
  1274. if (errorCode != JsNoError)
  1275. {
  1276. PrintException(fileName, errorCode);
  1277. }
  1278. }
  1279. else
  1280. {
  1281. LPCSTR fileContent = nullptr;
  1282. AutoString specifierStr(specifier);
  1283. char fullPath[_MAX_PATH];
  1284. errorCode = specifierStr.GetError();
  1285. if (errorCode == JsNoError)
  1286. {
  1287. std::string specifierFullPath;
  1288. if (this->moduleRecord)
  1289. {
  1290. auto moduleDirEntry = moduleDirMap.find(this->moduleRecord);
  1291. if (moduleDirEntry != moduleDirMap.end())
  1292. {
  1293. specifierFullPath = moduleDirEntry->second;
  1294. }
  1295. }
  1296. specifierFullPath += *specifierStr;
  1297. if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
  1298. {
  1299. return JsErrorInvalidArgument;
  1300. }
  1301. hr = Helpers::LoadScriptFromFile(fullPath, fileContent);
  1302. if (FAILED(hr))
  1303. {
  1304. if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
  1305. {
  1306. fprintf(stderr, "Couldn't load file.\n");
  1307. }
  1308. LoadScript(nullptr, fullPath, nullptr, "module", true, WScriptJsrt::FinalizeFree);
  1309. }
  1310. else
  1311. {
  1312. LoadScript(nullptr, fullPath, fileContent, "module", true, WScriptJsrt::FinalizeFree);
  1313. }
  1314. }
  1315. }
  1316. return errorCode;
  1317. }
  1318. JsErrorCode WScriptJsrt::FetchImportedModuleHelper(JsModuleRecord referencingModule,
  1319. JsValueRef specifier, __out JsModuleRecord* dependentModuleRecord, LPCSTR refdir)
  1320. {
  1321. JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
  1322. AutoString specifierStr;
  1323. *dependentModuleRecord = nullptr;
  1324. if (specifierStr.Initialize(specifier) != JsNoError)
  1325. {
  1326. return specifierStr.GetError();
  1327. }
  1328. char fullPath[_MAX_PATH];
  1329. std::string specifierFullPath = refdir ? refdir : "";
  1330. specifierFullPath += *specifierStr;
  1331. if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
  1332. {
  1333. return JsErrorInvalidArgument;
  1334. }
  1335. auto moduleEntry = moduleRecordMap.find(std::string(fullPath));
  1336. if (moduleEntry != moduleRecordMap.end())
  1337. {
  1338. *dependentModuleRecord = moduleEntry->second;
  1339. return JsNoError;
  1340. }
  1341. JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(referencingModule, specifier, &moduleRecord);
  1342. if (errorCode == JsNoError)
  1343. {
  1344. char dir[_MAX_PATH];
  1345. moduleDirMap[moduleRecord] = std::string(GetDir(fullPath, dir));
  1346. InitializeModuleInfo(specifier, moduleRecord);
  1347. moduleRecordMap[std::string(fullPath)] = moduleRecord;
  1348. ModuleMessage* moduleMessage =
  1349. WScriptJsrt::ModuleMessage::Create(referencingModule, specifier);
  1350. if (moduleMessage == nullptr)
  1351. {
  1352. return JsErrorOutOfMemory;
  1353. }
  1354. WScriptJsrt::PushMessage(moduleMessage);
  1355. *dependentModuleRecord = moduleRecord;
  1356. }
  1357. return errorCode;
  1358. }
  1359. // Callback from chakracore to fetch dependent module. In the test harness,
  1360. // we are not doing any translation, just treat the specifier as fileName.
  1361. // While this call will come back directly from ParseModuleSource, the additional
  1362. // task are treated as Promise that will be executed later.
  1363. JsErrorCode WScriptJsrt::FetchImportedModule(_In_ JsModuleRecord referencingModule,
  1364. _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
  1365. {
  1366. auto moduleDirEntry = moduleDirMap.find(referencingModule);
  1367. if (moduleDirEntry != moduleDirMap.end())
  1368. {
  1369. std::string dir = moduleDirEntry->second;
  1370. return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord, dir.c_str());
  1371. }
  1372. return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord);
  1373. }
  1374. // Callback from chakracore to fetch module dynamically during runtime. In the test harness,
  1375. // we are not doing any translation, just treat the specifier as fileName.
  1376. // While this call will come back directly from runtime script or module code, the additional
  1377. // task can be scheduled asynchronously that executed later.
  1378. JsErrorCode WScriptJsrt::FetchImportedModuleFromScript(_In_ JsSourceContext dwReferencingSourceContext,
  1379. _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
  1380. {
  1381. // ch.exe assumes all imported source files are located at .
  1382. auto scriptDirEntry = scriptDirMap.find(dwReferencingSourceContext);
  1383. if (scriptDirEntry != scriptDirMap.end())
  1384. {
  1385. std::string dir = scriptDirEntry->second;
  1386. return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord, dir.c_str());
  1387. }
  1388. return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord);
  1389. }
  1390. // Callback from chakraCore when the module resolution is finished, either successfuly or unsuccessfully.
  1391. JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
  1392. {
  1393. if (exceptionVar != nullptr)
  1394. {
  1395. ChakraRTInterface::JsSetException(exceptionVar);
  1396. JsValueRef specifier = JS_INVALID_REFERENCE;
  1397. ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
  1398. AutoString fileName;
  1399. if (specifier != JS_INVALID_REFERENCE)
  1400. {
  1401. fileName.Initialize(specifier);
  1402. }
  1403. if (HostConfigFlags::flags.TraceHostCallbackIsEnabled)
  1404. {
  1405. printf("NotifyModuleReadyCallback(exception) %s\n", fileName.GetString());
  1406. }
  1407. PrintException(*fileName, JsErrorScriptException);
  1408. }
  1409. else
  1410. {
  1411. WScriptJsrt::ModuleMessage* moduleMessage =
  1412. WScriptJsrt::ModuleMessage::Create(referencingModule, nullptr);
  1413. if (moduleMessage == nullptr)
  1414. {
  1415. return JsErrorOutOfMemory;
  1416. }
  1417. WScriptJsrt::PushMessage(moduleMessage);
  1418. }
  1419. return JsNoError;
  1420. }
  1421. void WScriptJsrt::PromiseContinuationCallback(JsValueRef task, void *callbackState)
  1422. {
  1423. Assert(task != JS_INVALID_REFERENCE);
  1424. Assert(callbackState != JS_INVALID_REFERENCE);
  1425. MessageQueue * messageQueue = (MessageQueue *)callbackState;
  1426. WScriptJsrt::CallbackMessage *msg = new WScriptJsrt::CallbackMessage(0, task);
  1427. messageQueue->InsertSorted(msg);
  1428. }