WScriptJsrt.cpp 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687
  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. if (HostConfigFlags::flags.$262)
  790. {
  791. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Broadcast", BroadcastCallback));
  792. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ReceiveBroadcast", ReceiveBroadcastCallback));
  793. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Report", ReportCallback));
  794. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetReport", GetReportCallback));
  795. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Leaving", LeavingCallback));
  796. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Sleep", SleepCallback));
  797. // OSX does build does not support $262 as filename
  798. const wchar_t $262[] =
  799. #include "262.js"
  800. ;
  801. JsValueRef $262ScriptRef;
  802. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateStringUtf16((uint16_t*)$262, _countof($262) - 1, &$262ScriptRef));
  803. JsValueRef fname;
  804. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString("$262", strlen("$262"), &fname));
  805. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsRun($262ScriptRef, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr));
  806. }
  807. Error:
  808. return hr == S_OK;
  809. }
  810. JsErrorCode WScriptJsrt::InitializeModuleCallbacks()
  811. {
  812. JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
  813. JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(nullptr, nullptr, &moduleRecord);
  814. if (errorCode == JsNoError)
  815. {
  816. errorCode = InitializeModuleInfo(nullptr, moduleRecord);
  817. }
  818. return errorCode;
  819. }
  820. bool WScriptJsrt::Uninitialize()
  821. {
  822. // moduleRecordMap is a global std::map, its destructor may access overridden
  823. // "operator delete" / global HeapAllocator::Instance. Clear it manually here
  824. // to avoid worrying about global destructor order.
  825. moduleRecordMap.clear();
  826. moduleDirMap.clear();
  827. scriptDirMap.clear();
  828. auto& threadData = GetRuntimeThreadLocalData().threadData;
  829. if (threadData && !threadData->children.empty())
  830. {
  831. LONG count = (LONG)threadData->children.size();
  832. std::vector<HANDLE> childrenHandles;
  833. //Clang does not support "for each" yet
  834. for(auto i = threadData->children.begin(); i!= threadData->children.end(); i++)
  835. {
  836. auto child = *i;
  837. childrenHandles.push_back(child->hThread);
  838. SetEvent(child->hevntShutdown);
  839. }
  840. DWORD waitRet = WaitForMultipleObjects(count, &childrenHandles[0], TRUE, INFINITE);
  841. Assert(waitRet == WAIT_OBJECT_0);
  842. for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
  843. {
  844. delete *i;
  845. }
  846. threadData->children.clear();
  847. }
  848. return true;
  849. }
  850. #if ENABLE_TTD
  851. void CALLBACK WScriptJsrt::JsContextBeforeCollectCallback(JsRef contextRef, void *data)
  852. {
  853. ChakraRTInterface::JsTTDNotifyContextDestroy(contextRef);
  854. }
  855. #endif
  856. JsValueRef __stdcall WScriptJsrt::LoadTextFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  857. {
  858. HRESULT hr = E_FAIL;
  859. JsValueRef returnValue = JS_INVALID_REFERENCE;
  860. JsErrorCode errorCode = JsNoError;
  861. const char* fileContent = nullptr;
  862. if (argumentCount < 2)
  863. {
  864. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  865. }
  866. else
  867. {
  868. AutoString fileName;
  869. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  870. if (errorCode == JsNoError)
  871. {
  872. UINT lengthBytes = 0;
  873. hr = Helpers::LoadScriptFromFile(*fileName, fileContent, &lengthBytes);
  874. if (FAILED(hr))
  875. {
  876. fwprintf(stderr, _u("Couldn't load file.\n"));
  877. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  878. }
  879. else
  880. {
  881. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(
  882. fileContent, lengthBytes, &returnValue));
  883. }
  884. }
  885. }
  886. Error:
  887. if (fileContent)
  888. {
  889. free((void*)fileContent);
  890. }
  891. return returnValue;
  892. }
  893. JsValueRef __stdcall WScriptJsrt::LoadBinaryFileCallback(JsValueRef callee,
  894. bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  895. {
  896. HRESULT hr = E_FAIL;
  897. JsValueRef returnValue = JS_INVALID_REFERENCE;
  898. JsErrorCode errorCode = JsNoError;
  899. if (argumentCount < 2)
  900. {
  901. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  902. }
  903. else
  904. {
  905. const char *fileContent;
  906. AutoString fileName;
  907. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  908. if (errorCode == JsNoError)
  909. {
  910. UINT lengthBytes = 0;
  911. hr = Helpers::LoadBinaryFile(*fileName, fileContent, lengthBytes);
  912. if (FAILED(hr))
  913. {
  914. fwprintf(stderr, _u("Couldn't load file.\n"));
  915. }
  916. else
  917. {
  918. JsValueRef arrayBuffer;
  919. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsCreateArrayBuffer(lengthBytes, &arrayBuffer), ErrorStillFree);
  920. BYTE* buffer;
  921. unsigned int bufferLength;
  922. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetArrayBufferStorage(arrayBuffer, &buffer, &bufferLength), ErrorStillFree);
  923. if (bufferLength < lengthBytes)
  924. {
  925. fwprintf(stderr, _u("Array buffer size is insufficient to store the binary file.\n"));
  926. }
  927. else
  928. {
  929. if (memcpy_s(buffer, bufferLength, (BYTE*)fileContent, lengthBytes) == 0)
  930. {
  931. returnValue = arrayBuffer;
  932. }
  933. }
  934. ErrorStillFree:
  935. HeapFree(GetProcessHeap(), 0, (void*)fileContent);
  936. }
  937. }
  938. }
  939. Error:
  940. return returnValue;
  941. }
  942. JsValueRef __stdcall WScriptJsrt::FlagCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  943. {
  944. HRESULT hr = E_FAIL;
  945. JsValueRef returnValue = JS_INVALID_REFERENCE;
  946. JsErrorCode errorCode = JsNoError;
  947. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  948. #if ENABLE_DEBUG_CONFIG_OPTIONS
  949. if (argumentCount > 1)
  950. {
  951. AutoString cmd;
  952. IfJsrtErrorSetGo(cmd.Initialize(arguments[1]));
  953. char16* argv[] = { nullptr, cmd.GetWideString() };
  954. ChakraRTInterface::SetConfigFlags(2, argv, nullptr);
  955. }
  956. #endif
  957. Error:
  958. return returnValue;
  959. }
  960. JsValueRef __stdcall WScriptJsrt::BroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  961. {
  962. HRESULT hr = E_FAIL;
  963. JsValueRef returnValue = JS_INVALID_REFERENCE;
  964. JsErrorCode errorCode = JsNoError;
  965. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  966. if (argumentCount > 1)
  967. {
  968. auto& threadData = GetRuntimeThreadLocalData().threadData;
  969. if (threadData)
  970. {
  971. ChakraRTInterface::JsGetSharedArrayBufferContent(arguments[1], &threadData->sharedContent);
  972. LONG count = (LONG)threadData->children.size();
  973. threadData->hSemaphore = CreateSemaphore(NULL, 0, count, NULL);
  974. if (threadData->hSemaphore)
  975. {
  976. //Clang does not support "for each" yet
  977. for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
  978. {
  979. auto child = *i;
  980. SetEvent(child->hevntReceivedBroadcast);
  981. }
  982. WaitForSingleObject(threadData->hSemaphore, INFINITE);
  983. CloseHandle(threadData->hSemaphore);
  984. threadData->hSemaphore = INVALID_HANDLE_VALUE;
  985. }
  986. else
  987. {
  988. fwprintf(stderr, _u("Couldn't create semaphore.\n"));
  989. fflush(stderr);
  990. }
  991. ChakraRTInterface::JsReleaseSharedArrayBufferContentHandle(threadData->sharedContent);
  992. }
  993. }
  994. Error:
  995. return returnValue;
  996. }
  997. JsValueRef __stdcall WScriptJsrt::ReceiveBroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  998. {
  999. HRESULT hr = E_FAIL;
  1000. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1001. JsErrorCode errorCode = JsNoError;
  1002. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1003. if (argumentCount > 1)
  1004. {
  1005. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1006. if (threadData)
  1007. {
  1008. if (threadData->receiveBroadcastCallbackFunc)
  1009. {
  1010. ChakraRTInterface::JsRelease(threadData->receiveBroadcastCallbackFunc, nullptr);
  1011. }
  1012. threadData->receiveBroadcastCallbackFunc = arguments[1];
  1013. ChakraRTInterface::JsAddRef(threadData->receiveBroadcastCallbackFunc, nullptr);
  1014. }
  1015. }
  1016. Error:
  1017. return returnValue;
  1018. }
  1019. JsValueRef __stdcall WScriptJsrt::ReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1020. {
  1021. HRESULT hr = E_FAIL;
  1022. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1023. JsErrorCode errorCode = JsNoError;
  1024. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1025. if (argumentCount > 1)
  1026. {
  1027. JsValueRef stringRef;
  1028. ChakraRTInterface::JsConvertValueToString(arguments[1], &stringRef);
  1029. AutoString autoStr(stringRef);
  1030. if (autoStr.GetError() == JsNoError)
  1031. {
  1032. std::string str(autoStr.GetString());
  1033. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1034. if (threadData && threadData->parent)
  1035. {
  1036. EnterCriticalSection(&threadData->parent->csReportQ);
  1037. threadData->parent->reportQ.push_back(str);
  1038. LeaveCriticalSection(&threadData->parent->csReportQ);
  1039. }
  1040. }
  1041. }
  1042. Error:
  1043. return returnValue;
  1044. }
  1045. JsValueRef __stdcall WScriptJsrt::GetReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1046. {
  1047. HRESULT hr = E_FAIL;
  1048. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1049. JsErrorCode errorCode = JsNoError;
  1050. IfJsrtErrorSetGo(ChakraRTInterface::JsGetNullValue(&returnValue));
  1051. if (argumentCount > 0)
  1052. {
  1053. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1054. if (threadData)
  1055. {
  1056. EnterCriticalSection(&threadData->csReportQ);
  1057. if (threadData->reportQ.size() > 0)
  1058. {
  1059. auto str = threadData->reportQ.front();
  1060. threadData->reportQ.pop_front();
  1061. ChakraRTInterface::JsCreateString(str.c_str(), str.size(), &returnValue);
  1062. }
  1063. LeaveCriticalSection(&threadData->csReportQ);
  1064. }
  1065. }
  1066. Error:
  1067. return returnValue;
  1068. }
  1069. JsValueRef __stdcall WScriptJsrt::LeavingCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1070. {
  1071. HRESULT hr = E_FAIL;
  1072. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1073. JsErrorCode errorCode = JsNoError;
  1074. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1075. if (argumentCount > 0)
  1076. {
  1077. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1078. if (threadData)
  1079. {
  1080. threadData->leaving = true;
  1081. }
  1082. }
  1083. Error:
  1084. return returnValue;
  1085. }
  1086. JsValueRef __stdcall WScriptJsrt::SleepCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1087. {
  1088. HRESULT hr = E_FAIL;
  1089. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1090. JsErrorCode errorCode = JsNoError;
  1091. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1092. if (argumentCount > 1)
  1093. {
  1094. double timeout = 0.0;
  1095. ChakraRTInterface::JsNumberToDouble(arguments[1], &timeout);
  1096. Sleep((DWORD)timeout);
  1097. }
  1098. Error:
  1099. return returnValue;
  1100. }
  1101. bool WScriptJsrt::PrintException(LPCSTR fileName, JsErrorCode jsErrorCode)
  1102. {
  1103. LPCWSTR errorTypeString = ConvertErrorCodeToMessage(jsErrorCode);
  1104. JsValueRef exception;
  1105. ChakraRTInterface::JsGetAndClearException(&exception);
  1106. if (HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
  1107. {
  1108. return false;
  1109. }
  1110. if (exception != nullptr)
  1111. {
  1112. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile || jsErrorCode == JsErrorCode::JsErrorScriptException)
  1113. {
  1114. AutoString errorMessage;
  1115. IfJsrtErrorFail(errorMessage.Initialize(exception), false);
  1116. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile)
  1117. {
  1118. JsPropertyIdRef linePropertyId = JS_INVALID_REFERENCE;
  1119. JsValueRef lineProperty = JS_INVALID_REFERENCE;
  1120. JsPropertyIdRef columnPropertyId = JS_INVALID_REFERENCE;
  1121. JsValueRef columnProperty = JS_INVALID_REFERENCE;
  1122. int line;
  1123. int column;
  1124. IfJsrtErrorFail(CreatePropertyIdFromString("line", &linePropertyId), false);
  1125. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, linePropertyId, &lineProperty), false);
  1126. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(lineProperty, &line), false);
  1127. IfJsrtErrorFail(CreatePropertyIdFromString("column", &columnPropertyId), false);
  1128. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, columnPropertyId, &columnProperty), false);
  1129. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(columnProperty, &column), false);
  1130. CHAR shortFileName[_MAX_PATH];
  1131. CHAR ext[_MAX_EXT];
  1132. _splitpath_s(fileName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  1133. fwprintf(stderr, _u("%ls\n\tat code (%S%S:%d:%d)\n"),
  1134. errorMessage.GetWideString(), shortFileName, ext, (int)line + 1,
  1135. (int)column + 1);
  1136. }
  1137. else
  1138. {
  1139. JsValueType propertyType = JsUndefined;
  1140. JsPropertyIdRef stackPropertyId = JS_INVALID_REFERENCE;
  1141. JsValueRef stackProperty = JS_INVALID_REFERENCE;
  1142. AutoString errorStack;
  1143. JsErrorCode errorCode = CreatePropertyIdFromString("stack", &stackPropertyId);
  1144. if (errorCode == JsErrorCode::JsNoError)
  1145. {
  1146. errorCode = ChakraRTInterface::JsGetProperty(exception, stackPropertyId, &stackProperty);
  1147. if (errorCode == JsErrorCode::JsNoError)
  1148. {
  1149. errorCode = ChakraRTInterface::JsGetValueType(stackProperty, &propertyType);
  1150. }
  1151. }
  1152. if (errorCode != JsErrorCode::JsNoError || propertyType == JsUndefined)
  1153. {
  1154. const char *fName = fileName != nullptr ? fileName : "(unknown)";
  1155. CHAR shortFileName[_MAX_PATH];
  1156. CHAR ext[_MAX_EXT];
  1157. _splitpath_s(fName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  1158. // do not mix char/wchar. print them separately
  1159. fprintf(stderr, "thrown at %s%s:\n^\n", shortFileName, ext);
  1160. fwprintf(stderr, _u("%ls\n"), errorMessage.GetWideString());
  1161. }
  1162. else
  1163. {
  1164. IfJsrtErrorFail(errorStack.Initialize(stackProperty), false);
  1165. fwprintf(stderr, _u("%ls\n"), errorStack.GetWideString());
  1166. }
  1167. }
  1168. }
  1169. else
  1170. {
  1171. fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
  1172. }
  1173. return true;
  1174. }
  1175. else
  1176. {
  1177. fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
  1178. }
  1179. return false;
  1180. }
  1181. void WScriptJsrt::AddMessageQueue(MessageQueue *_messageQueue)
  1182. {
  1183. Assert(messageQueue == nullptr);
  1184. messageQueue = _messageQueue;
  1185. }
  1186. WScriptJsrt::CallbackMessage::CallbackMessage(unsigned int time, JsValueRef function) : MessageBase(time), m_function(function)
  1187. {
  1188. JsErrorCode error = ChakraRTInterface::JsAddRef(m_function, nullptr);
  1189. if (error != JsNoError)
  1190. {
  1191. // Simply report a fatal error and exit because continuing from this point would result in inconsistent state
  1192. // and FailFast telemetry would not be useful.
  1193. wprintf(_u("FATAL ERROR: ChakraRTInterface::JsAddRef failed in WScriptJsrt::CallbackMessage::`ctor`. error=0x%x\n"), error);
  1194. exit(1);
  1195. }
  1196. }
  1197. WScriptJsrt::CallbackMessage::~CallbackMessage()
  1198. {
  1199. bool hasException = false;
  1200. ChakraRTInterface::JsHasException(&hasException);
  1201. if (hasException)
  1202. {
  1203. WScriptJsrt::PrintException("", JsErrorScriptException);
  1204. }
  1205. JsErrorCode errorCode = ChakraRTInterface::JsRelease(m_function, nullptr);
  1206. Assert(errorCode == JsNoError);
  1207. m_function = JS_INVALID_REFERENCE;
  1208. }
  1209. HRESULT WScriptJsrt::CallbackMessage::Call(LPCSTR fileName)
  1210. {
  1211. return CallFunction(fileName);
  1212. }
  1213. HRESULT WScriptJsrt::CallbackMessage::CallFunction(LPCSTR fileName)
  1214. {
  1215. HRESULT hr = S_OK;
  1216. JsValueRef global;
  1217. JsValueRef result;
  1218. JsValueRef stringValue;
  1219. JsValueType type;
  1220. JsErrorCode errorCode = JsNoError;
  1221. IfJsrtErrorHR(ChakraRTInterface::JsGetGlobalObject(&global));
  1222. IfJsrtErrorHR(ChakraRTInterface::JsGetValueType(m_function, &type));
  1223. if (type == JsString)
  1224. {
  1225. IfJsrtErrorHR(ChakraRTInterface::JsConvertValueToString(m_function, &stringValue));
  1226. JsValueRef fname;
  1227. ChakraRTInterface::JsCreateString("", strlen(""), &fname);
  1228. // Run the code
  1229. errorCode = ChakraRTInterface::JsRun(stringValue, JS_SOURCE_CONTEXT_NONE,
  1230. fname, JsParseScriptAttributeArrayBufferIsUtf16Encoded,
  1231. nullptr /*no result needed*/);
  1232. }
  1233. else
  1234. {
  1235. errorCode = ChakraRTInterface::JsCallFunction(m_function, &global, 1, &result);
  1236. }
  1237. if (errorCode != JsNoError)
  1238. {
  1239. hr = E_FAIL;
  1240. PrintException(fileName, errorCode);
  1241. }
  1242. Error:
  1243. return hr;
  1244. }
  1245. WScriptJsrt::ModuleMessage::ModuleMessage(JsModuleRecord module, JsValueRef specifier)
  1246. : MessageBase(0), moduleRecord(module), specifier(specifier)
  1247. {
  1248. ChakraRTInterface::JsAddRef(module, nullptr);
  1249. if (specifier != nullptr)
  1250. {
  1251. // nullptr specifier means a Promise to execute; non-nullptr means a "fetch" operation.
  1252. ChakraRTInterface::JsAddRef(specifier, nullptr);
  1253. }
  1254. }
  1255. WScriptJsrt::ModuleMessage::~ModuleMessage()
  1256. {
  1257. ChakraRTInterface::JsRelease(moduleRecord, nullptr);
  1258. if (specifier != nullptr)
  1259. {
  1260. ChakraRTInterface::JsRelease(specifier, nullptr);
  1261. }
  1262. }
  1263. HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
  1264. {
  1265. JsErrorCode errorCode;
  1266. JsValueRef result = JS_INVALID_REFERENCE;
  1267. HRESULT hr;
  1268. if (specifier == nullptr)
  1269. {
  1270. errorCode = ChakraRTInterface::JsModuleEvaluation(moduleRecord, &result);
  1271. if (errorCode != JsNoError)
  1272. {
  1273. PrintException(fileName, errorCode);
  1274. }
  1275. }
  1276. else
  1277. {
  1278. LPCSTR fileContent = nullptr;
  1279. AutoString specifierStr(specifier);
  1280. char fullPath[_MAX_PATH];
  1281. errorCode = specifierStr.GetError();
  1282. if (errorCode == JsNoError)
  1283. {
  1284. std::string specifierFullPath;
  1285. if (this->moduleRecord)
  1286. {
  1287. auto moduleDirEntry = moduleDirMap.find(this->moduleRecord);
  1288. if (moduleDirEntry != moduleDirMap.end())
  1289. {
  1290. specifierFullPath = moduleDirEntry->second;
  1291. }
  1292. }
  1293. specifierFullPath += *specifierStr;
  1294. if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
  1295. {
  1296. return JsErrorInvalidArgument;
  1297. }
  1298. hr = Helpers::LoadScriptFromFile(fullPath, fileContent);
  1299. if (FAILED(hr))
  1300. {
  1301. if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
  1302. {
  1303. fprintf(stderr, "Couldn't load file.\n");
  1304. }
  1305. LoadScript(nullptr, fullPath, nullptr, "module", true, WScriptJsrt::FinalizeFree);
  1306. }
  1307. else
  1308. {
  1309. LoadScript(nullptr, fullPath, fileContent, "module", true, WScriptJsrt::FinalizeFree);
  1310. }
  1311. }
  1312. }
  1313. return errorCode;
  1314. }
  1315. JsErrorCode WScriptJsrt::FetchImportedModuleHelper(JsModuleRecord referencingModule,
  1316. JsValueRef specifier, __out JsModuleRecord* dependentModuleRecord, LPCSTR refdir)
  1317. {
  1318. JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
  1319. AutoString specifierStr;
  1320. *dependentModuleRecord = nullptr;
  1321. if (specifierStr.Initialize(specifier) != JsNoError)
  1322. {
  1323. return specifierStr.GetError();
  1324. }
  1325. char fullPath[_MAX_PATH];
  1326. std::string specifierFullPath = refdir ? refdir : "";
  1327. specifierFullPath += *specifierStr;
  1328. if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
  1329. {
  1330. return JsErrorInvalidArgument;
  1331. }
  1332. auto moduleEntry = moduleRecordMap.find(std::string(fullPath));
  1333. if (moduleEntry != moduleRecordMap.end())
  1334. {
  1335. *dependentModuleRecord = moduleEntry->second;
  1336. return JsNoError;
  1337. }
  1338. JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(referencingModule, specifier, &moduleRecord);
  1339. if (errorCode == JsNoError)
  1340. {
  1341. char dir[_MAX_PATH];
  1342. moduleDirMap[moduleRecord] = std::string(GetDir(fullPath, dir));
  1343. InitializeModuleInfo(specifier, moduleRecord);
  1344. moduleRecordMap[std::string(fullPath)] = moduleRecord;
  1345. ModuleMessage* moduleMessage =
  1346. WScriptJsrt::ModuleMessage::Create(referencingModule, specifier);
  1347. if (moduleMessage == nullptr)
  1348. {
  1349. return JsErrorOutOfMemory;
  1350. }
  1351. WScriptJsrt::PushMessage(moduleMessage);
  1352. *dependentModuleRecord = moduleRecord;
  1353. }
  1354. return errorCode;
  1355. }
  1356. // Callback from chakracore to fetch dependent module. In the test harness,
  1357. // we are not doing any translation, just treat the specifier as fileName.
  1358. // While this call will come back directly from ParseModuleSource, the additional
  1359. // task are treated as Promise that will be executed later.
  1360. JsErrorCode WScriptJsrt::FetchImportedModule(_In_ JsModuleRecord referencingModule,
  1361. _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
  1362. {
  1363. auto moduleDirEntry = moduleDirMap.find(referencingModule);
  1364. if (moduleDirEntry != moduleDirMap.end())
  1365. {
  1366. std::string dir = moduleDirEntry->second;
  1367. return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord, dir.c_str());
  1368. }
  1369. return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord);
  1370. }
  1371. // Callback from chakracore to fetch module dynamically during runtime. In the test harness,
  1372. // we are not doing any translation, just treat the specifier as fileName.
  1373. // While this call will come back directly from runtime script or module code, the additional
  1374. // task can be scheduled asynchronously that executed later.
  1375. JsErrorCode WScriptJsrt::FetchImportedModuleFromScript(_In_ JsSourceContext dwReferencingSourceContext,
  1376. _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
  1377. {
  1378. // ch.exe assumes all imported source files are located at .
  1379. auto scriptDirEntry = scriptDirMap.find(dwReferencingSourceContext);
  1380. if (scriptDirEntry != scriptDirMap.end())
  1381. {
  1382. std::string dir = scriptDirEntry->second;
  1383. return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord, dir.c_str());
  1384. }
  1385. return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord);
  1386. }
  1387. // Callback from chakraCore when the module resolution is finished, either successfuly or unsuccessfully.
  1388. JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
  1389. {
  1390. if (exceptionVar != nullptr)
  1391. {
  1392. ChakraRTInterface::JsSetException(exceptionVar);
  1393. JsValueRef specifier = JS_INVALID_REFERENCE;
  1394. ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
  1395. AutoString fileName;
  1396. if (specifier != JS_INVALID_REFERENCE)
  1397. {
  1398. fileName.Initialize(specifier);
  1399. }
  1400. if (HostConfigFlags::flags.TraceHostCallbackIsEnabled)
  1401. {
  1402. printf("NotifyModuleReadyCallback(exception) %s\n", fileName.GetString());
  1403. }
  1404. PrintException(*fileName, JsErrorScriptException);
  1405. }
  1406. else
  1407. {
  1408. WScriptJsrt::ModuleMessage* moduleMessage =
  1409. WScriptJsrt::ModuleMessage::Create(referencingModule, nullptr);
  1410. if (moduleMessage == nullptr)
  1411. {
  1412. return JsErrorOutOfMemory;
  1413. }
  1414. WScriptJsrt::PushMessage(moduleMessage);
  1415. }
  1416. return JsNoError;
  1417. }
  1418. void WScriptJsrt::PromiseContinuationCallback(JsValueRef task, void *callbackState)
  1419. {
  1420. Assert(task != JS_INVALID_REFERENCE);
  1421. Assert(callbackState != JS_INVALID_REFERENCE);
  1422. MessageQueue * messageQueue = (MessageQueue *)callbackState;
  1423. WScriptJsrt::CallbackMessage *msg = new WScriptJsrt::CallbackMessage(0, task);
  1424. messageQueue->InsertSorted(msg);
  1425. }