2
0

WScriptJsrt.cpp 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241
  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 "PlatformAgnostic/ChakraICU.h"
  7. #include <vector>
  8. #if defined(_X86_) || defined(_M_IX86)
  9. #define CPU_ARCH_TEXT "x86"
  10. #elif defined(_AMD64_) || defined(_IA64_) || defined(_M_AMD64) || defined(_M_IA64)
  11. #define CPU_ARCH_TEXT "x86_64"
  12. #elif defined(_ARM_) || defined(_M_ARM)
  13. #define CPU_ARCH_TEXT "ARM"
  14. #elif defined(_ARM64_) || defined(_M_ARM64)
  15. #define CPU_ARCH_TEXT "ARM64"
  16. #endif
  17. // do not change the order below
  18. // otherwise, i.e. android system can be marked as posix? etc..
  19. #ifdef _WIN32
  20. #define DEST_PLATFORM_TEXT "win32"
  21. #else // ! _WIN32
  22. #if defined(__APPLE__)
  23. #ifdef __IOS__
  24. #define DEST_PLATFORM_TEXT "ios"
  25. #else // ! iOS
  26. #define DEST_PLATFORM_TEXT "darwin"
  27. #endif // iOS ?
  28. #elif defined(__ANDROID__)
  29. #define DEST_PLATFORM_TEXT "android"
  30. #elif defined(__linux__)
  31. #define DEST_PLATFORM_TEXT "posix"
  32. #elif defined(__FreeBSD__) || defined(__unix__)
  33. #define DEST_PLATFORM_TEXT "bsd"
  34. #endif // FreeBSD or unix ?
  35. #endif // _WIN32 ?
  36. #pragma prefast(disable:26444, "This warning unfortunately raises false positives when auto is used for declaring the type of an iterator in a loop.")
  37. #ifdef HAS_ICU
  38. #define INTL_LIBRARY_TEXT "icu"
  39. #elif defined(_WIN32)
  40. #define INTL_LIBRARY_TEXT "winglob"
  41. #else
  42. #define INTL_LIBRARY_TEXT ""
  43. #endif
  44. struct ArrayBufferTransferInfo {
  45. byte* buffer;
  46. uint length;
  47. ArrayBufferFreeFn freeFn;
  48. };
  49. struct SerializerBlob
  50. {
  51. void *data;
  52. size_t dataLength;
  53. std::vector<ArrayBufferTransferInfo> transferableArrays;
  54. };
  55. MessageQueue* WScriptJsrt::messageQueue = nullptr;
  56. std::map<std::string, JsModuleRecord> WScriptJsrt::moduleRecordMap;
  57. std::map<JsModuleRecord, std::string> WScriptJsrt::moduleDirMap;
  58. std::map<JsModuleRecord, ModuleState> WScriptJsrt::moduleErrMap;
  59. std::map<DWORD_PTR, std::string> WScriptJsrt::scriptDirMap;
  60. DWORD_PTR WScriptJsrt::sourceContext = 0;
  61. #define ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString) \
  62. JsErrorCode errorCode = JsNoError; \
  63. do \
  64. { \
  65. const char *outOfMemoryString = \
  66. "Failed to convert wide string. Out of memory?";\
  67. \
  68. char *errorMessageNarrow; \
  69. if (FAILED(WideStringToNarrowDynamic(errorMessage, &errorMessageNarrow))) \
  70. { \
  71. errorCode = ChakraRTInterface::JsCreateString(outOfMemoryString, \
  72. strlen(outOfMemoryString), &errorMessageString); \
  73. } \
  74. else \
  75. { \
  76. errorCode = ChakraRTInterface::JsCreateString(errorMessageNarrow, \
  77. strlen(errorMessageNarrow), &errorMessageString); \
  78. free(errorMessageNarrow); \
  79. } \
  80. } \
  81. while(0)
  82. DWORD_PTR WScriptJsrt::GetNextSourceContext()
  83. {
  84. return sourceContext++;
  85. }
  86. void WScriptJsrt::RegisterScriptDir(DWORD_PTR sourceContext, LPCSTR fullDirNarrow)
  87. {
  88. GetDir(fullDirNarrow, &scriptDirMap[sourceContext]);
  89. }
  90. bool WScriptJsrt::CreateArgumentsObject(JsValueRef *argsObject)
  91. {
  92. LPWSTR *argv = HostConfigFlags::argsVal;
  93. JsValueRef retArr;
  94. Assert(argsObject);
  95. *argsObject = nullptr;
  96. IfJsrtErrorFail(ChakraRTInterface::JsCreateArray(HostConfigFlags::argsCount, &retArr), false);
  97. for (int i = 0; i < HostConfigFlags::argsCount; i++)
  98. {
  99. JsValueRef value;
  100. JsValueRef index;
  101. char *argNarrow;
  102. if (FAILED(WideStringToNarrowDynamic(argv[i], &argNarrow)))
  103. {
  104. return false;
  105. }
  106. JsErrorCode errCode = ChakraRTInterface::JsCreateString(
  107. argNarrow,
  108. strlen(argNarrow), &value);
  109. free(argNarrow);
  110. IfJsrtErrorFail(errCode, false);
  111. IfJsrtErrorFail(ChakraRTInterface::JsDoubleToNumber(i, &index), false);
  112. IfJsrtErrorFail(ChakraRTInterface::JsSetIndexedProperty(retArr, index, value), false);
  113. }
  114. *argsObject = retArr;
  115. return true;
  116. }
  117. JsValueRef __stdcall WScriptJsrt::EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  118. {
  119. for (unsigned int i = 1; i < argumentCount; i++)
  120. {
  121. JsValueRef strValue;
  122. JsErrorCode error = ChakraRTInterface::JsConvertValueToString(arguments[i], &strValue);
  123. if (error == JsNoError)
  124. {
  125. AutoString str(strValue);
  126. if (str.GetError() == JsNoError)
  127. {
  128. if (i > 1)
  129. {
  130. wprintf(_u(" "));
  131. }
  132. charcount_t len;
  133. LPWSTR ws = str.GetWideString(&len);
  134. LPWSTR wsNoNull = new WCHAR[((size_t)len) + 1];
  135. charcount_t newIndex = 0;
  136. for (charcount_t j = 0; j < len; j++)
  137. {
  138. if (ws[j] != _u('\0'))
  139. {
  140. wsNoNull[newIndex++] = ws[j];
  141. }
  142. }
  143. wsNoNull[newIndex] = _u('\0');
  144. wprintf(_u("%s"), wsNoNull);
  145. delete[] wsNoNull;
  146. }
  147. }
  148. if (error == JsErrorScriptException)
  149. {
  150. return nullptr;
  151. }
  152. }
  153. wprintf(_u("\n"));
  154. fflush(stdout);
  155. JsValueRef undefinedValue;
  156. if (ChakraRTInterface::JsGetUndefinedValue(&undefinedValue) == JsNoError)
  157. {
  158. return undefinedValue;
  159. }
  160. else
  161. {
  162. return nullptr;
  163. }
  164. }
  165. JsValueRef __stdcall WScriptJsrt::QuitCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  166. {
  167. int exitCode = 0;
  168. if (argumentCount > 1)
  169. {
  170. double exitCodeDouble;
  171. IfJsrtErrorFail(ChakraRTInterface::JsNumberToDouble(arguments[1], &exitCodeDouble), JS_INVALID_REFERENCE);
  172. exitCode = (int)exitCodeDouble;
  173. }
  174. ExitProcess(exitCode);
  175. }
  176. JsValueRef __stdcall WScriptJsrt::LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  177. {
  178. return LoadScriptFileHelper(callee, arguments, argumentCount, false);
  179. }
  180. // needed because of calling convention differences between _stdcall and _cdecl
  181. void CHAKRA_CALLBACK WScriptJsrt::FinalizeFree(void* addr)
  182. {
  183. free(addr);
  184. }
  185. JsValueRef WScriptJsrt::LoadScriptFileHelper(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, bool isSourceModule)
  186. {
  187. HRESULT hr = E_FAIL;
  188. JsValueRef returnValue = JS_INVALID_REFERENCE;
  189. JsErrorCode errorCode = JsNoError;
  190. LPCWSTR errorMessage = _u("");
  191. if (argumentCount < 2 || argumentCount > 4)
  192. {
  193. errorCode = JsErrorInvalidArgument;
  194. errorMessage = _u("Need more or fewer arguments for WScript.LoadScript");
  195. }
  196. else
  197. {
  198. LPCSTR fileContent;
  199. AutoString fileName(arguments[1]);
  200. IfJsrtErrorSetGo(fileName.GetError());
  201. AutoString scriptInjectType;
  202. if (argumentCount > 2)
  203. {
  204. IfJsrtErrorSetGo(scriptInjectType.Initialize(arguments[2]));
  205. }
  206. if (errorCode == JsNoError)
  207. {
  208. hr = Helpers::LoadScriptFromFile(*fileName, fileContent);
  209. if (FAILED(hr))
  210. {
  211. fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
  212. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  213. return returnValue;
  214. }
  215. returnValue = LoadScript(callee, *fileName, fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree, true);
  216. }
  217. }
  218. Error:
  219. SetExceptionIf(errorCode, errorMessage);
  220. return returnValue;
  221. }
  222. void WScriptJsrt::SetExceptionIf(JsErrorCode errorCode, LPCWSTR errorMessage)
  223. {
  224. if (errorCode != JsNoError)
  225. {
  226. // If the exception is already is set - no need to create a new exception.
  227. bool hasException = false;
  228. if (!(ChakraRTInterface::JsHasException(&hasException) == JsNoError && hasException))
  229. {
  230. JsValueRef errorObject;
  231. JsValueRef errorMessageString;
  232. if (wcscmp(errorMessage, _u("")) == 0)
  233. {
  234. errorMessage = ConvertErrorCodeToMessage(errorCode);
  235. }
  236. ERROR_MESSAGE_TO_STRING(errCode, errorMessage, errorMessageString);
  237. ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  238. ChakraRTInterface::JsSetException(errorObject);
  239. }
  240. }
  241. }
  242. byte * CHAKRA_CALLBACK ReallocateBufferMemory(void * state, byte *oldBuffer, size_t newSize, size_t *allocatedSize)
  243. {
  244. void* data = realloc((void*)oldBuffer, newSize);
  245. if (allocatedSize)
  246. {
  247. *allocatedSize = newSize;
  248. }
  249. return (byte*)data;
  250. }
  251. bool CHAKRA_CALLBACK WriteHostObject(void * state, JsValueRef data)
  252. {
  253. // Not implemented
  254. return true;
  255. }
  256. JsValueRef __stdcall WScriptJsrt::SerializeObject(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  257. {
  258. JsErrorCode errorCode = JsNoError;
  259. LPCWSTR errorMessage = _u("");
  260. JsValueRef returnValue = JS_INVALID_REFERENCE;
  261. HRESULT hr = S_OK;
  262. JsValueRef *transferVarsArray = nullptr;
  263. int transferVarsCount = 0;
  264. if (argumentCount < 2)
  265. {
  266. errorCode = JsErrorInvalidArgument;
  267. errorMessage = _u("Need an argument for WScript.Serialize");
  268. }
  269. else
  270. {
  271. JsValueRef rootObject = arguments[1];
  272. JsValueRef transferArray = nullptr;
  273. if (argumentCount > 2)
  274. {
  275. JsValueType argumentType = JsUndefined;
  276. transferArray = arguments[2];
  277. IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(transferArray, &argumentType));
  278. if (argumentType != JsUndefined)
  279. {
  280. if (argumentType != JsArray)
  281. {
  282. errorCode = JsErrorInvalidArgument;
  283. goto Error;
  284. }
  285. JsPropertyIdRef lengthPropId;
  286. JsValueRef arrayLengthObj = JS_INVALID_REFERENCE;
  287. int arrayLength = 0;
  288. IfJsrtErrorSetGo(CreatePropertyIdFromString("length", &lengthPropId));
  289. IfJsrtErrorSetGo(ChakraRTInterface::JsGetProperty(transferArray, lengthPropId, &arrayLengthObj));
  290. IfJsrtErrorSetGo(ChakraRTInterface::JsNumberToInt(arrayLengthObj, &arrayLength));
  291. if (arrayLength > 0)
  292. {
  293. transferVarsArray = new JsValueRef[arrayLength];
  294. if (transferVarsArray == nullptr)
  295. {
  296. errorCode = JsErrorOutOfMemory;
  297. goto Error;
  298. }
  299. for (int i = 0; i < arrayLength; i++)
  300. {
  301. JsValueRef index;
  302. JsValueRef value = JS_INVALID_REFERENCE;
  303. JsValueType jsType = JsUndefined;
  304. IfJsrtErrorSetGo(ChakraRTInterface::JsIntToNumber(i, &index));
  305. IfJsrtErrorSetGo(ChakraRTInterface::JsGetIndexedProperty(transferArray, index, &value));
  306. IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(value, &jsType));
  307. if (jsType == JsArrayBuffer)
  308. {
  309. *(transferVarsArray + transferVarsCount) = value;
  310. transferVarsCount++;
  311. }
  312. }
  313. }
  314. }
  315. }
  316. JsVarSerializerHandle serializerHandle = nullptr;
  317. // This memory will be claimed at WScriptJsrt::Deserialize.
  318. SerializerBlob *blob = new SerializerBlob();
  319. IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializer(ReallocateBufferMemory, WriteHostObject, nullptr, &serializerHandle));
  320. IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerSetTransferableVars(serializerHandle, transferVarsArray, transferVarsCount));
  321. IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerWriteValue(serializerHandle, rootObject));
  322. IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerReleaseData(serializerHandle, (byte**)&blob->data, &blob->dataLength));
  323. for (int i = 0; i < transferVarsCount; i++)
  324. {
  325. JsValueRef arrayBuffer = transferVarsArray[i];
  326. ArrayBufferTransferInfo bufferInfo;
  327. IfJsrtErrorSetGo(ChakraRTInterface::JsGetArrayBufferStorage(arrayBuffer, &bufferInfo.buffer, &bufferInfo.length));
  328. IfJsrtErrorSetGo(ChakraRTInterface::JsExternalizeArrayBuffer(arrayBuffer));
  329. IfJsrtErrorSetGo(ChakraRTInterface::JsGetArrayBufferFreeFunction(arrayBuffer, &bufferInfo.freeFn));
  330. blob->transferableArrays.push_back(bufferInfo);
  331. IfJsrtErrorSetGo(ChakraRTInterface::JsDetachArrayBuffer(arrayBuffer));
  332. }
  333. errorCode = ChakraRTInterface::JsCreateExternalArrayBuffer((void*)blob, sizeof(SerializerBlob), nullptr, nullptr, &returnValue);
  334. IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerFree(serializerHandle));
  335. }
  336. Error:
  337. SetExceptionIf(errorCode, errorMessage);
  338. if (transferVarsArray)
  339. {
  340. delete[] transferVarsArray;
  341. }
  342. return returnValue;
  343. }
  344. JsValueRef CHAKRA_CALLBACK ReadHostObject(void * state)
  345. {
  346. Assert(false); // TBD
  347. return nullptr;
  348. }
  349. JsValueRef CHAKRA_CALLBACK GetSharedArrayBufferFromId(void * state, uint32_t id)
  350. {
  351. Assert(false); // TBD
  352. return nullptr;
  353. }
  354. JsValueRef CHAKRA_CALLBACK GetWasmModuleFromId(void * state, uint32_t transfer_id)
  355. {
  356. Assert(false); // TBD
  357. return nullptr;
  358. }
  359. struct BufferFreeFunctionState {
  360. ArrayBufferFreeFn freeFn;
  361. void* buffer;
  362. };
  363. void CHAKRA_CALLBACK BufferFreeFunction(void * state)
  364. {
  365. BufferFreeFunctionState* bufferState = (BufferFreeFunctionState*)state;
  366. if (!bufferState)
  367. {
  368. return;
  369. }
  370. if (bufferState->freeFn)
  371. {
  372. bufferState->freeFn(bufferState->buffer);
  373. }
  374. delete bufferState;
  375. }
  376. JsValueRef __stdcall WScriptJsrt::Deserialize(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  377. {
  378. JsErrorCode errorCode = JsNoError;
  379. LPCWSTR errorMessage = _u("");
  380. JsValueRef returnValue = JS_INVALID_REFERENCE;
  381. JsValueRef * transferables = nullptr;
  382. HRESULT hr = S_OK;
  383. if (argumentCount < 2)
  384. {
  385. errorCode = JsErrorInvalidArgument;
  386. errorMessage = _u("Need an argument for WScript.Deserialize");
  387. }
  388. else
  389. {
  390. JsValueRef dataObject = arguments[1];
  391. uint32 dataLength = 0;
  392. BYTE *data = nullptr;
  393. IfJsrtErrorSetGo(ChakraRTInterface::JsGetArrayBufferStorage(dataObject, &data, &dataLength));
  394. SerializerBlob *blob = (SerializerBlob*)data;
  395. JsVarDeserializerHandle deserializerHandle = nullptr;
  396. IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializer(blob->data, blob->dataLength, ReadHostObject, GetSharedArrayBufferFromId, nullptr, &deserializerHandle));
  397. size_t arraySize = blob->transferableArrays.size();
  398. if (arraySize > 0)
  399. {
  400. transferables = new JsValueRef[arraySize];
  401. for (size_t i = 0; i < arraySize; ++i)
  402. {
  403. JsValueRef result = nullptr;
  404. BufferFreeFunctionState* bufferFreeState = new BufferFreeFunctionState();
  405. bufferFreeState->buffer = blob->transferableArrays[i].buffer;
  406. bufferFreeState->freeFn = blob->transferableArrays[i].freeFn;
  407. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer(blob->transferableArrays[i].buffer, blob->transferableArrays[i].length, BufferFreeFunction, bufferFreeState, &result));
  408. transferables[i] = result;
  409. }
  410. IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializerSetTransferableVars(deserializerHandle, transferables, arraySize));
  411. }
  412. IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializerReadValue(deserializerHandle, &returnValue));
  413. IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializerFree(deserializerHandle));
  414. delete blob;
  415. }
  416. Error:
  417. SetExceptionIf(errorCode, errorMessage);
  418. if (transferables)
  419. {
  420. delete[] transferables;
  421. }
  422. return returnValue;
  423. }
  424. JsValueRef __stdcall WScriptJsrt::GetModuleNamespace(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  425. {
  426. JsErrorCode errorCode = JsNoError;
  427. JsValueRef returnValue = JS_INVALID_REFERENCE;
  428. LPCWSTR errorMessage = _u("");
  429. char fullPath[_MAX_PATH];
  430. if (argumentCount < 2)
  431. {
  432. errorCode = JsErrorInvalidArgument;
  433. errorMessage = _u("Need an argument for WScript.GetModuleNamespace");
  434. }
  435. else
  436. {
  437. AutoString specifierStr(arguments[1]);
  438. errorCode = specifierStr.GetError();
  439. if (errorCode == JsNoError)
  440. {
  441. if (_fullpath(fullPath, specifierStr.GetString(), _MAX_PATH) == nullptr)
  442. {
  443. errorCode = JsErrorInvalidArgument;
  444. }
  445. else
  446. {
  447. auto moduleEntry = moduleRecordMap.find(fullPath);
  448. if (moduleEntry == moduleRecordMap.end())
  449. {
  450. errorCode = JsErrorInvalidArgument;
  451. errorMessage = _u("Need to supply a path for an already loaded module for WScript.GetModuleNamespace");
  452. }
  453. else
  454. {
  455. errorCode = ChakraRTInterface::JsGetModuleNamespace(moduleEntry->second, &returnValue);
  456. if (errorCode == JsErrorModuleNotEvaluated)
  457. {
  458. errorMessage = _u("GetModuleNamespace called with un-evaluated module");
  459. }
  460. }
  461. }
  462. }
  463. }
  464. SetExceptionIf(errorCode, errorMessage);
  465. return returnValue;
  466. }
  467. JsValueRef __stdcall WScriptJsrt::LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  468. {
  469. return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, false);
  470. }
  471. JsValueRef __stdcall WScriptJsrt::LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  472. {
  473. return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, true);
  474. }
  475. JsValueRef WScriptJsrt::LoadScriptHelper(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState, bool isSourceModule)
  476. {
  477. HRESULT hr = E_FAIL;
  478. JsErrorCode errorCode = JsNoError;
  479. LPCWSTR errorMessage = _u("");
  480. JsValueRef returnValue = JS_INVALID_REFERENCE;
  481. if (argumentCount < 2 || argumentCount > 4)
  482. {
  483. errorCode = JsErrorInvalidArgument;
  484. errorMessage = _u("Need more or fewer arguments for WScript.LoadScript");
  485. }
  486. else
  487. {
  488. AutoString fileContent;
  489. char *fileNameNarrow = nullptr;
  490. AutoString fileName;
  491. AutoString scriptInjectType;
  492. char fileNameBuffer[MAX_PATH];
  493. bool isFile = true;
  494. IfJsrtErrorSetGo(fileContent.Initialize(arguments[1]));
  495. // ExternalArrayBuffer Finalize will clean this up
  496. // but only if we actually register a finalizecallback for this
  497. fileContent.MakePersistent();
  498. if (argumentCount > 2)
  499. {
  500. IfJsrtErrorSetGo(scriptInjectType.Initialize(arguments[2]));
  501. if (argumentCount > 3)
  502. {
  503. IfJsrtErrorSetGo(fileName.Initialize(arguments[3]));
  504. fileNameNarrow = *fileName;
  505. }
  506. }
  507. if (!fileNameNarrow)
  508. {
  509. isFile = false;
  510. if (isSourceModule)
  511. {
  512. sprintf_s(fileNameBuffer, MAX_PATH, "moduleScript%i.js", (int)sourceContext);
  513. fileNameNarrow = fileNameBuffer;
  514. }
  515. }
  516. if (*fileContent)
  517. {
  518. // TODO: This is CESU-8. How to tell the engine?
  519. // TODO: How to handle this source (script) life time?
  520. returnValue = LoadScript(callee, fileNameNarrow, *fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree, isFile);
  521. }
  522. }
  523. Error:
  524. SetExceptionIf(errorCode, errorMessage);
  525. return returnValue;
  526. }
  527. JsErrorCode WScriptJsrt::InitializeModuleInfo(JsValueRef specifier, JsModuleRecord moduleRecord)
  528. {
  529. JsErrorCode errorCode = JsNoError;
  530. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_FetchImportedModuleCallback, (void*)WScriptJsrt::FetchImportedModule);
  531. if (errorCode == JsNoError)
  532. {
  533. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_FetchImportedModuleFromScriptCallback, (void*)WScriptJsrt::FetchImportedModuleFromScript);
  534. if (errorCode == JsNoError)
  535. {
  536. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_NotifyModuleReadyCallback, (void*)WScriptJsrt::NotifyModuleReadyCallback);
  537. if (errorCode == JsNoError)
  538. {
  539. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_InitializeImportMetaCallback, (void*)WScriptJsrt::InitializeImportMetaCallback);
  540. if (errorCode == JsNoError && moduleRecord != nullptr)
  541. {
  542. errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_HostDefined, specifier);
  543. }
  544. }
  545. }
  546. }
  547. IfJsrtErrorFailLogAndRetErrorCode(errorCode);
  548. return JsNoError;
  549. }
  550. void WScriptJsrt::GetDir(LPCSTR fullPathNarrow, std::string *fullDirNarrow)
  551. {
  552. char fileDrive[_MAX_DRIVE];
  553. char fileDir[_MAX_DIR];
  554. std::string result;
  555. if (_splitpath_s(fullPathNarrow, fileDrive, _countof(fileDrive), fileDir, _countof(fileDir), nullptr, 0, nullptr, 0) == 0)
  556. {
  557. result += fileDrive;
  558. result += fileDir;
  559. }
  560. *fullDirNarrow = result;
  561. }
  562. JsErrorCode WScriptJsrt::ModuleEntryPoint(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName)
  563. {
  564. return LoadModuleFromString(fileName, fileContent, fullName, true);
  565. }
  566. JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName, bool isFile)
  567. {
  568. DWORD_PTR dwSourceCookie = WScriptJsrt::GetNextSourceContext();
  569. JsModuleRecord requestModule = JS_INVALID_REFERENCE;
  570. LPCSTR moduleRecordKey = fullName ? fullName : fileName;
  571. auto moduleRecordEntry = moduleRecordMap.find(std::string(moduleRecordKey));
  572. JsErrorCode errorCode = JsNoError;
  573. // we need to create a new moduleRecord if the specifier (fileName) is not found;
  574. // otherwise we'll use the old one.
  575. if (moduleRecordEntry == moduleRecordMap.end())
  576. {
  577. JsValueRef specifier;
  578. errorCode = ChakraRTInterface::JsCreateString(
  579. fileName, strlen(fileName), &specifier);
  580. if (errorCode == JsNoError)
  581. {
  582. errorCode = ChakraRTInterface::JsInitializeModuleRecord(
  583. nullptr, specifier, &requestModule);
  584. }
  585. if (errorCode == JsNoError)
  586. {
  587. errorCode = InitializeModuleInfo(specifier, requestModule);
  588. }
  589. if (errorCode == JsNoError)
  590. {
  591. if (fullName)
  592. {
  593. GetDir(fullName, &moduleDirMap[requestModule]);
  594. }
  595. moduleRecordMap[std::string(moduleRecordKey)] = requestModule;
  596. moduleErrMap[requestModule] = RootModule;
  597. }
  598. }
  599. else
  600. {
  601. requestModule = moduleRecordEntry->second;
  602. }
  603. IfJsrtErrorFailLogAndRetErrorCode(errorCode);
  604. JsValueRef errorObject = JS_INVALID_REFERENCE;
  605. // ParseModuleSource is sync, while additional fetch & evaluation are async.
  606. unsigned int fileContentLength = (fileContent == nullptr) ? 0 : (unsigned int)strlen(fileContent);
  607. if (isFile && fullName)
  608. {
  609. JsValueRef moduleUrl;
  610. ChakraRTInterface::JsCreateString(fullName, strlen(fullName), &moduleUrl);
  611. errorCode = ChakraRTInterface::JsSetModuleHostInfo(requestModule, JsModuleHostInfo_Url, moduleUrl);
  612. IfJsrtErrorFail(errorCode, errorCode);
  613. }
  614. errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
  615. fileContentLength, JsParseModuleSourceFlags_DataIsUTF8, &errorObject);
  616. if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE && fileContent != nullptr && !HostConfigFlags::flags.IgnoreScriptErrorCode && moduleErrMap[requestModule] == RootModule)
  617. {
  618. ChakraRTInterface::JsSetException(errorObject);
  619. moduleErrMap[requestModule] = ErroredModule;
  620. return errorCode;
  621. }
  622. return JsNoError;
  623. }
  624. JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
  625. LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback, bool isFile)
  626. {
  627. HRESULT hr = E_FAIL;
  628. JsErrorCode errorCode = JsNoError;
  629. LPCWSTR errorMessage = _u("Internal error.");
  630. JsValueRef returnValue = JS_INVALID_REFERENCE;
  631. JsContextRef currentContext = JS_INVALID_REFERENCE;
  632. JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
  633. void *callbackArg = (finalizeCallback != nullptr ? (void*)fileContent : nullptr);
  634. char fullPath[_MAX_PATH];
  635. IfJsrtErrorSetGo(ChakraRTInterface::JsGetCurrentContext(&currentContext));
  636. IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime));
  637. if (fileName == nullptr)
  638. {
  639. fileName = "script.js";
  640. }
  641. if (_fullpath(fullPath, fileName, _MAX_PATH) == nullptr)
  642. {
  643. goto Error;
  644. }
  645. // this is called with LoadModuleCallback method as well where caller pass in a string that should be
  646. // treated as a module source text instead of opening a new file.
  647. if (isSourceModule || (strcmp(scriptInjectType, "module") == 0))
  648. {
  649. errorCode = LoadModuleFromString(fileName, fileContent, fullPath, isFile);
  650. }
  651. else if (strcmp(scriptInjectType, "self") == 0)
  652. {
  653. JsContextRef calleeContext;
  654. IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
  655. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(calleeContext));
  656. JsValueRef scriptSource;
  657. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContent,
  658. (unsigned int)strlen(fileContent), finalizeCallback, callbackArg, &scriptSource));
  659. JsValueRef fname;
  660. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(fullPath,
  661. strlen(fullPath), &fname));
  662. JsSourceContext sourceContext = GetNextSourceContext();
  663. RegisterScriptDir(sourceContext, fullPath);
  664. if (HostConfigFlags::flags.UseParserStateCacheIsEnabled)
  665. {
  666. JsValueRef parserState;
  667. IfJsrtErrorSetGo(ChakraRTInterface::JsSerializeParserState(scriptSource, &parserState, JsParseScriptAttributeNone));
  668. errorCode = ChakraRTInterface::JsRunScriptWithParserState(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, parserState, &returnValue);
  669. }
  670. else
  671. {
  672. errorCode = ChakraRTInterface::JsRun(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, &returnValue);
  673. }
  674. if(errorCode == JsNoError)
  675. {
  676. errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
  677. }
  678. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(currentContext));
  679. }
  680. else if (strcmp(scriptInjectType, "samethread") == 0)
  681. {
  682. JsValueRef newContext = JS_INVALID_REFERENCE;
  683. // Create a new context and set it as the current context
  684. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateContext(runtime, &newContext));
  685. #if ENABLE_TTD
  686. //We need this here since this context is created in record
  687. IfJsrtErrorSetGo(ChakraRTInterface::JsSetObjectBeforeCollectCallback(newContext, nullptr, WScriptJsrt::JsContextBeforeCollectCallback));
  688. #endif
  689. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(newContext));
  690. IfJsErrorFailLog(ChakraRTInterface::JsSetPromiseContinuationCallback(PromiseContinuationCallback, (void*)messageQueue));
  691. // Initialize the host objects
  692. Initialize();
  693. JsValueRef scriptSource;
  694. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContent,
  695. (unsigned int)strlen(fileContent), finalizeCallback, callbackArg, &scriptSource));
  696. JsValueRef fname;
  697. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(fullPath,
  698. strlen(fullPath), &fname));
  699. JsSourceContext sourceContext = GetNextSourceContext();
  700. RegisterScriptDir(sourceContext, fullPath);
  701. if (HostConfigFlags::flags.UseParserStateCacheIsEnabled)
  702. {
  703. JsValueRef parserState;
  704. IfJsrtErrorSetGo(ChakraRTInterface::JsSerializeParserState(scriptSource, &parserState, JsParseScriptAttributeNone));
  705. errorCode = ChakraRTInterface::JsRunScriptWithParserState(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, parserState, &returnValue);
  706. }
  707. else
  708. {
  709. errorCode = ChakraRTInterface::JsRun(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, &returnValue);
  710. }
  711. if (errorCode == JsNoError)
  712. {
  713. errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
  714. }
  715. // Set the context back to the old one
  716. ChakraRTInterface::JsSetCurrentContext(currentContext);
  717. }
  718. else if (strcmp(scriptInjectType, "crossthread") == 0)
  719. {
  720. auto& threadData = GetRuntimeThreadLocalData().threadData;
  721. if (threadData == nullptr)
  722. {
  723. threadData = new RuntimeThreadData();
  724. }
  725. RuntimeThreadData* child = new RuntimeThreadData();
  726. child->initialSource = fileContent;
  727. threadData->children.push_back(child);
  728. child->parent = threadData;
  729. // TODO: need to add a switch in case we don't need to wait for
  730. // child initial script completion
  731. ResetEvent(threadData->hevntInitialScriptCompleted);
  732. child->hThread = ::CreateThread(NULL, NULL, [](void* param) -> DWORD
  733. {
  734. return ((RuntimeThreadData*)param)->ThreadProc();
  735. }, (void*)child, NULL, NULL);
  736. WaitForSingleObject(threadData->hevntInitialScriptCompleted, INFINITE);
  737. }
  738. else
  739. {
  740. errorCode = JsErrorInvalidArgument;
  741. errorMessage = _u("Unsupported argument type inject type.");
  742. }
  743. Error:
  744. JsValueRef value = returnValue;
  745. if (errorCode != JsNoError)
  746. {
  747. SetExceptionIf(errorCode, errorMessage);
  748. ChakraRTInterface::JsDoubleToNumber(errorCode, &value);
  749. }
  750. _flushall();
  751. return value;
  752. }
  753. JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  754. {
  755. LPCWSTR errorMessage = _u("invalid call to WScript.SetTimeout");
  756. JsErrorCode errorCode = JsNoError;
  757. HRESULT hr = S_OK;
  758. JsValueRef function;
  759. JsValueRef timerId;
  760. unsigned int time;
  761. double tmp;
  762. CallbackMessage *msg = nullptr;
  763. if (argumentCount != 3)
  764. {
  765. errorCode = JsErrorInvalidArgument;
  766. goto Error;
  767. }
  768. function = arguments[1];
  769. IfJsrtErrorSetGo(ChakraRTInterface::JsNumberToDouble(arguments[2], &tmp));
  770. time = static_cast<int>(tmp);
  771. msg = new CallbackMessage(time, function);
  772. messageQueue->InsertSorted(msg);
  773. IfJsrtErrorSetGo(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(msg->GetId()), &timerId));
  774. return timerId;
  775. Error:
  776. SetExceptionIf(errorCode, errorMessage);
  777. return JS_INVALID_REFERENCE;
  778. }
  779. JsValueRef WScriptJsrt::ClearTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  780. {
  781. LPCWSTR errorMessage = _u("invalid call to WScript.ClearTimeout");
  782. JsErrorCode errorCode = JsNoError;
  783. HRESULT hr = S_OK;
  784. if (argumentCount != 2)
  785. {
  786. errorCode = JsErrorInvalidArgument;
  787. goto Error;
  788. }
  789. unsigned int timerId;
  790. double tmp;
  791. JsValueRef undef;
  792. if (ChakraRTInterface::JsNumberToDouble(arguments[1], &tmp) == JsNoError)
  793. {
  794. timerId = static_cast<int>(tmp);
  795. messageQueue->RemoveById(timerId);
  796. }
  797. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&undef));
  798. return undef;
  799. Error:
  800. SetExceptionIf(errorCode, errorMessage);
  801. return JS_INVALID_REFERENCE;
  802. }
  803. template <class DebugOperationFunc>
  804. void QueueDebugOperation(JsValueRef function, const DebugOperationFunc& operation)
  805. {
  806. WScriptJsrt::PushMessage(WScriptJsrt::CallbackMessage::Create(function, operation));
  807. }
  808. JsValueRef WScriptJsrt::AttachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  809. {
  810. LPCWSTR errorMessage = _u("WScript.Attach requires a function, like WScript.Attach(foo);");
  811. JsErrorCode errorCode = JsNoError;
  812. HRESULT hr = S_OK;
  813. JsValueType argumentType = JsUndefined;
  814. if (argumentCount != 2)
  815. {
  816. errorCode = JsErrorInvalidArgument;
  817. goto Error;
  818. }
  819. IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType));
  820. if (argumentType != JsFunction)
  821. {
  822. errorCode = JsErrorInvalidArgument;
  823. goto Error;
  824. }
  825. QueueDebugOperation(arguments[1], [](WScriptJsrt::CallbackMessage& msg)
  826. {
  827. JsContextRef currentContext = JS_INVALID_REFERENCE;
  828. ChakraRTInterface::JsGetCurrentContext(&currentContext);
  829. JsRuntimeHandle currentRuntime = JS_INVALID_RUNTIME_HANDLE;
  830. ChakraRTInterface::JsGetRuntime(currentContext, &currentRuntime);
  831. Debugger* debugger = Debugger::GetDebugger(currentRuntime);
  832. debugger->StartDebugging(currentRuntime);
  833. debugger->SourceRunDown();
  834. return msg.CallFunction("");
  835. });
  836. Error:
  837. SetExceptionIf(errorCode, errorMessage);
  838. return JS_INVALID_REFERENCE;
  839. }
  840. JsValueRef WScriptJsrt::DetachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  841. {
  842. LPCWSTR errorMessage = _u("WScript.Detach requires a function, like WScript.Detach(foo);");
  843. JsErrorCode errorCode = JsNoError;
  844. HRESULT hr = S_OK;
  845. JsValueType argumentType = JsUndefined;
  846. if (argumentCount != 2)
  847. {
  848. errorCode = JsErrorInvalidArgument;
  849. goto Error;
  850. }
  851. IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType));
  852. if (argumentType != JsFunction)
  853. {
  854. errorCode = JsErrorInvalidArgument;
  855. goto Error;
  856. }
  857. QueueDebugOperation(arguments[1], [](WScriptJsrt::CallbackMessage& msg)
  858. {
  859. JsContextRef currentContext = JS_INVALID_REFERENCE;
  860. ChakraRTInterface::JsGetCurrentContext(&currentContext);
  861. JsRuntimeHandle currentRuntime = JS_INVALID_RUNTIME_HANDLE;
  862. ChakraRTInterface::JsGetRuntime(currentContext, &currentRuntime);
  863. if (Debugger::debugger != nullptr)
  864. {
  865. Debugger* debugger = Debugger::GetDebugger(currentRuntime);
  866. debugger->StopDebugging(currentRuntime);
  867. }
  868. return msg.CallFunction("");
  869. });
  870. Error:
  871. SetExceptionIf(errorCode, errorMessage);
  872. return JS_INVALID_REFERENCE;
  873. }
  874. JsValueRef WScriptJsrt::DumpFunctionPositionCallback(JsValueRef callee, bool isConstructCall, JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
  875. {
  876. JsValueRef functionPosition = JS_INVALID_REFERENCE;
  877. if (argumentCount > 1)
  878. {
  879. if (ChakraRTInterface::JsDiagGetFunctionPosition(arguments[1], &functionPosition) != JsNoError)
  880. {
  881. // If we can't get the functionPosition pass undefined
  882. IfJsErrorFailLogAndRet(ChakraRTInterface::JsGetUndefinedValue(&functionPosition));
  883. }
  884. if (Debugger::debugger != nullptr)
  885. {
  886. Debugger::debugger->DumpFunctionPosition(functionPosition);
  887. }
  888. }
  889. return JS_INVALID_REFERENCE;
  890. }
  891. JsValueRef WScriptJsrt::RequestAsyncBreakCallback(JsValueRef callee, bool isConstructCall,
  892. JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
  893. {
  894. if (Debugger::debugger != nullptr && !Debugger::debugger->IsDetached())
  895. {
  896. IfJsErrorFailLogAndRet(ChakraRTInterface::JsDiagRequestAsyncBreak(Debugger::GetRuntime()));
  897. }
  898. else
  899. {
  900. Helpers::LogError(_u("RequestAsyncBreak can only be called when debugger is attached"));
  901. }
  902. return JS_INVALID_REFERENCE;
  903. }
  904. JsValueRef WScriptJsrt::EmptyCallback(JsValueRef callee, bool isConstructCall,
  905. JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
  906. {
  907. return JS_INVALID_REFERENCE;
  908. }
  909. bool WScriptJsrt::CreateNamedFunction(const char* nameString, JsNativeFunction callback,
  910. JsValueRef* functionVar)
  911. {
  912. JsValueRef nameVar;
  913. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  914. nameString, strlen(nameString), &nameVar), false);
  915. IfJsrtErrorFail(ChakraRTInterface::JsCreateNamedFunction(nameVar, callback,
  916. nullptr, functionVar), false);
  917. return true;
  918. }
  919. bool WScriptJsrt::InstallObjectsOnObject(JsValueRef object, const char* name,
  920. JsNativeFunction nativeFunction)
  921. {
  922. JsValueRef propertyValueRef;
  923. JsPropertyIdRef propertyId;
  924. IfJsrtErrorFail(CreatePropertyIdFromString(name, &propertyId), false);
  925. if (!CreateNamedFunction(name, nativeFunction, &propertyValueRef))
  926. {
  927. return false;
  928. }
  929. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(object, propertyId,
  930. propertyValueRef, true), false);
  931. return true;
  932. }
  933. bool WScriptJsrt::Initialize()
  934. {
  935. HRESULT hr = S_OK;
  936. char CH_BINARY_LOCATION[2048];
  937. #ifdef CHAKRA_STATIC_LIBRARY
  938. const char* LINK_TYPE = "static";
  939. #else
  940. const char* LINK_TYPE = "shared";
  941. #endif
  942. #ifdef HAS_ICU
  943. int icuVersion = PlatformAgnostic::ICUHelpers::GetICUMajorVersion();
  944. #else
  945. int icuVersion = -1;
  946. #endif
  947. JsValueRef wscript;
  948. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&wscript), false);
  949. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Echo", EchoCallback));
  950. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Quit", QuitCallback));
  951. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScriptFile", LoadScriptFileCallback));
  952. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScript", LoadScriptCallback));
  953. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadModule", LoadModuleCallback));
  954. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SetTimeout", SetTimeoutCallback));
  955. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ClearTimeout", ClearTimeoutCallback));
  956. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Attach", AttachCallback));
  957. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Detach", DetachCallback));
  958. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "DumpFunctionPosition", DumpFunctionPositionCallback));
  959. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "RequestAsyncBreak", RequestAsyncBreakCallback));
  960. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadBinaryFile", LoadBinaryFileCallback));
  961. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadTextFile", LoadTextFileCallback));
  962. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Flag", FlagCallback));
  963. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "RegisterModuleSource", RegisterModuleSourceCallback));
  964. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetModuleNamespace", GetModuleNamespace));
  965. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetProxyProperties", GetProxyPropertiesCallback));
  966. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SerializeObject", SerializeObject));
  967. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Deserialize", Deserialize));
  968. // ToDo Remove
  969. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Edit", EmptyCallback));
  970. // Platform
  971. JsValueRef platformObject;
  972. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&platformObject), false);
  973. JsPropertyIdRef platformProperty;
  974. IfJsrtErrorFail(CreatePropertyIdFromString("Platform", &platformProperty), false);
  975. // Set CPU arch
  976. JsPropertyIdRef archProperty;
  977. IfJsrtErrorFail(CreatePropertyIdFromString("ARCH", &archProperty), false);
  978. JsValueRef archValue;
  979. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  980. CPU_ARCH_TEXT, strlen(CPU_ARCH_TEXT), &archValue), false);
  981. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, archProperty,
  982. archValue, true), false);
  983. // Set Build Type
  984. JsPropertyIdRef buildProperty;
  985. IfJsrtErrorFail(CreatePropertyIdFromString("BUILD_TYPE", &buildProperty), false);
  986. JsValueRef buildValue;
  987. #ifdef _DEBUG
  988. #define BUILD_TYPE_STRING_CH "Debug" // (O0)
  989. #elif defined(ENABLE_DEBUG_CONFIG_OPTIONS)
  990. #define BUILD_TYPE_STRING_CH "Test" // (O3 with debug config options)
  991. #else
  992. #define BUILD_TYPE_STRING_CH "Release" // (O3)
  993. #endif
  994. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  995. BUILD_TYPE_STRING_CH, strlen(BUILD_TYPE_STRING_CH), &buildValue), false);
  996. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, buildProperty,
  997. buildValue, true), false);
  998. #undef BUILD_TYPE_STRING_CH
  999. // Set Link Type [static / shared]
  1000. JsPropertyIdRef linkProperty;
  1001. IfJsrtErrorFail(CreatePropertyIdFromString("LINK_TYPE", &linkProperty), false);
  1002. JsValueRef linkValue;
  1003. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  1004. LINK_TYPE, strlen(LINK_TYPE), &linkValue), false);
  1005. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, linkProperty,
  1006. linkValue, true), false);
  1007. // Set Binary Location
  1008. JsValueRef binaryPathValue;
  1009. PlatformAgnostic::SystemInfo::GetBinaryLocation(CH_BINARY_LOCATION, sizeof(CH_BINARY_LOCATION));
  1010. JsPropertyIdRef binaryPathProperty;
  1011. IfJsrtErrorFail(CreatePropertyIdFromString("BINARY_PATH", &binaryPathProperty), false);
  1012. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  1013. CH_BINARY_LOCATION,
  1014. strlen(CH_BINARY_LOCATION), &binaryPathValue), false);
  1015. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(
  1016. platformObject, binaryPathProperty, binaryPathValue, true), false);
  1017. // Set destination OS
  1018. JsPropertyIdRef osProperty;
  1019. IfJsrtErrorFail(CreatePropertyIdFromString("OS", &osProperty), false);
  1020. JsValueRef osValue;
  1021. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
  1022. DEST_PLATFORM_TEXT, strlen(DEST_PLATFORM_TEXT), &osValue), false);
  1023. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, osProperty,
  1024. osValue, true), false);
  1025. // set Internationalization library
  1026. JsPropertyIdRef intlLibraryProp;
  1027. IfJsrtErrorFail(CreatePropertyIdFromString("INTL_LIBRARY", &intlLibraryProp), false);
  1028. JsValueRef intlLibraryStr;
  1029. IfJsrtErrorFail(ChakraRTInterface::JsCreateString(INTL_LIBRARY_TEXT, strlen(INTL_LIBRARY_TEXT), &intlLibraryStr), false);
  1030. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, intlLibraryProp, intlLibraryStr, true), false);
  1031. JsPropertyIdRef icuVersionProp;
  1032. IfJsrtErrorFail(CreatePropertyIdFromString("ICU_VERSION", &icuVersionProp), false);
  1033. JsValueRef icuVersionNum;
  1034. IfJsrtErrorFail(ChakraRTInterface::JsIntToNumber(icuVersion, &icuVersionNum), false);
  1035. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, icuVersionProp, icuVersionNum, true), false);
  1036. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, platformProperty,
  1037. platformObject, true), false);
  1038. JsValueRef argsObject;
  1039. if (!CreateArgumentsObject(&argsObject))
  1040. {
  1041. return false;
  1042. }
  1043. JsPropertyIdRef argsName;
  1044. IfJsrtErrorFail(CreatePropertyIdFromString("Arguments", &argsName), false);
  1045. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, argsName, argsObject, true), false);
  1046. JsPropertyIdRef wscriptName;
  1047. IfJsrtErrorFail(CreatePropertyIdFromString("WScript", &wscriptName), false);
  1048. JsValueRef global;
  1049. IfJsrtErrorFail(ChakraRTInterface::JsGetGlobalObject(&global), false);
  1050. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, wscriptName, wscript, true), false);
  1051. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "print", EchoCallback));
  1052. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "read", LoadTextFileCallback));
  1053. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "readbuffer", LoadBinaryFileCallback));
  1054. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "readline", ReadLineStdinCallback));
  1055. JsValueRef console;
  1056. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&console), false);
  1057. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(console, "log", EchoCallback));
  1058. JsPropertyIdRef consoleName;
  1059. IfJsrtErrorFail(CreatePropertyIdFromString("console", &consoleName), false);
  1060. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, consoleName, console, true), false);
  1061. IfJsrtErrorFail(InitializeModuleCallbacks(), false);
  1062. // When the command-line argument `-Test262` is set,
  1063. // WScript will have the extra support API below and $262 will be
  1064. // added to global scope
  1065. if (HostConfigFlags::flags.Test262)
  1066. {
  1067. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Broadcast", BroadcastCallback));
  1068. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ReceiveBroadcast", ReceiveBroadcastCallback));
  1069. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Report", ReportCallback));
  1070. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetReport", GetReportCallback));
  1071. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Leaving", LeavingCallback));
  1072. IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Sleep", SleepCallback));
  1073. // $262
  1074. const char Test262[] =
  1075. #include "262.js"
  1076. ;
  1077. JsValueRef Test262ScriptRef;
  1078. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString(Test262, strlen(Test262), &Test262ScriptRef));
  1079. JsValueRef fname;
  1080. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString("262", strlen("262"), &fname));
  1081. IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsRun(Test262ScriptRef, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr));
  1082. }
  1083. Error:
  1084. return hr == S_OK;
  1085. }
  1086. JsErrorCode WScriptJsrt::InitializeModuleCallbacks()
  1087. {
  1088. return InitializeModuleInfo(nullptr, nullptr);
  1089. }
  1090. bool WScriptJsrt::Uninitialize()
  1091. {
  1092. // moduleRecordMap is a global std::map, its destructor may access overridden
  1093. // "operator delete" / global HeapAllocator::Instance. Clear it manually here
  1094. // to avoid worrying about global destructor order.
  1095. moduleRecordMap.clear();
  1096. moduleDirMap.clear();
  1097. moduleErrMap.clear();
  1098. scriptDirMap.clear();
  1099. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1100. if (threadData && !threadData->children.empty())
  1101. {
  1102. LONG count = (LONG)threadData->children.size();
  1103. std::vector<HANDLE> childrenHandles;
  1104. //Clang does not support "for each" yet
  1105. for(auto i = threadData->children.begin(); i!= threadData->children.end(); i++)
  1106. {
  1107. auto child = *i;
  1108. childrenHandles.push_back(child->hThread);
  1109. SetEvent(child->hevntShutdown);
  1110. }
  1111. DWORD waitRet = WaitForMultipleObjects(count, &childrenHandles[0], TRUE, INFINITE);
  1112. Assert(waitRet == WAIT_OBJECT_0);
  1113. for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
  1114. {
  1115. delete *i;
  1116. }
  1117. threadData->children.clear();
  1118. }
  1119. return true;
  1120. }
  1121. #if ENABLE_TTD
  1122. void CALLBACK WScriptJsrt::JsContextBeforeCollectCallback(JsRef contextRef, void *data)
  1123. {
  1124. ChakraRTInterface::JsTTDNotifyContextDestroy(contextRef);
  1125. }
  1126. #endif
  1127. FileNode * SourceMap::root = nullptr;
  1128. JsValueRef __stdcall WScriptJsrt::RegisterModuleSourceCallback(JsValueRef callee, bool isConstructCall,
  1129. JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1130. {
  1131. HRESULT hr = E_FAIL;
  1132. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1133. JsErrorCode errorCode = JsNoError;
  1134. if (argumentCount < 3)
  1135. {
  1136. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1137. }
  1138. else
  1139. {
  1140. AutoString fileName;
  1141. AutoString data;
  1142. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  1143. IfJsrtErrorSetGo(data.Initialize(arguments[2]));
  1144. SourceMap::Add(fileName, data);
  1145. }
  1146. Error:
  1147. return returnValue;
  1148. }
  1149. JsValueRef __stdcall WScriptJsrt::LoadTextFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1150. {
  1151. HRESULT hr = E_FAIL;
  1152. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1153. JsErrorCode errorCode = JsNoError;
  1154. const char* fileContent = nullptr;
  1155. if (argumentCount < 2)
  1156. {
  1157. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1158. }
  1159. else
  1160. {
  1161. AutoString fileName;
  1162. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  1163. if (errorCode == JsNoError)
  1164. {
  1165. UINT lengthBytes = 0;
  1166. hr = Helpers::LoadScriptFromFile(*fileName, fileContent, &lengthBytes);
  1167. if (FAILED(hr))
  1168. {
  1169. fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
  1170. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1171. return returnValue;
  1172. }
  1173. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(
  1174. fileContent, lengthBytes, &returnValue));
  1175. }
  1176. }
  1177. Error:
  1178. if (fileContent)
  1179. {
  1180. free((void*)fileContent);
  1181. }
  1182. return returnValue;
  1183. }
  1184. int JsFgets(char* buf, int size, FILE* file)
  1185. {
  1186. int n = size - 1;
  1187. if (n < 0)
  1188. return -1;
  1189. bool crflag = false;
  1190. int c, i = 0;
  1191. for (i = 0; i < n && (c = getc(file)) != EOF; i++) {
  1192. buf[i] = (char)c;
  1193. if (c == '\n') { // any \n ends a line
  1194. i++; // keep the \n; we know there is room for \0
  1195. break;
  1196. }
  1197. if (crflag) { // \r not followed by \n ends line at the \r
  1198. ungetc(c, file);
  1199. break; // and overwrite c in buf with \0
  1200. }
  1201. crflag = (c == '\r');
  1202. }
  1203. buf[i] = '\0';
  1204. return i;
  1205. }
  1206. JsValueRef __stdcall WScriptJsrt::ReadLineStdinCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1207. {
  1208. HRESULT hr = E_FAIL;
  1209. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1210. JsErrorCode errorCode = JsNoError;
  1211. const int BUFSIZE = 256;
  1212. FILE* from = stdin;
  1213. int buflength = 0;
  1214. int bufsize = BUFSIZE;
  1215. char* buf = static_cast<char*>(malloc(bufsize));
  1216. char* tmp;
  1217. int gotlength = 0;
  1218. if (!buf)
  1219. {
  1220. goto Error;
  1221. }
  1222. while ((gotlength = JsFgets(buf + buflength, bufsize - buflength, from)) > 0)
  1223. {
  1224. buflength += gotlength;
  1225. // are we done?
  1226. if (buf[buflength - 2] == '\r' && buf[buflength - 1] == '\n')
  1227. {
  1228. buf[buflength - 1] = '\0';
  1229. buf[buflength - 2] = '\0';
  1230. buflength -= 2;
  1231. break;
  1232. }
  1233. else if (buf[buflength - 1] == '\n')
  1234. {
  1235. buf[buflength - 1] = '\0';
  1236. buflength -= 1;
  1237. break;
  1238. }
  1239. else if (buflength < bufsize - 1)
  1240. {
  1241. break;
  1242. }
  1243. // Else, grow our buffer for another pass.
  1244. bufsize *= 2;
  1245. if (bufsize > buflength)
  1246. {
  1247. tmp = static_cast<char*>(realloc(buf, bufsize));
  1248. }
  1249. else
  1250. {
  1251. goto Error;
  1252. }
  1253. if (!tmp)
  1254. {
  1255. goto Error;
  1256. }
  1257. buf = tmp;
  1258. }
  1259. //Treat the empty string specially.
  1260. if (buflength == 0)
  1261. {
  1262. if (feof(from))
  1263. {
  1264. goto Error;
  1265. }
  1266. else
  1267. {
  1268. JsValueRef emptyStringObject;
  1269. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(buf, buflength, &emptyStringObject));
  1270. free(buf);
  1271. return emptyStringObject;
  1272. }
  1273. }
  1274. // Turn buf into a JSString. Note that buflength includes the trailing null character.
  1275. JsValueRef stringObject;
  1276. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(buf, buflength, &stringObject));
  1277. free(buf);
  1278. return stringObject;
  1279. Error:
  1280. if (buf)
  1281. {
  1282. free(buf);
  1283. }
  1284. return returnValue;
  1285. }
  1286. JsValueRef __stdcall WScriptJsrt::LoadBinaryFileCallback(JsValueRef callee,
  1287. bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1288. {
  1289. HRESULT hr = E_FAIL;
  1290. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1291. JsErrorCode errorCode = JsNoError;
  1292. bool isHeapAlloc = true;
  1293. if (argumentCount < 2)
  1294. {
  1295. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1296. }
  1297. else
  1298. {
  1299. const char *fileContent;
  1300. AutoString fileName;
  1301. IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
  1302. if (errorCode == JsNoError)
  1303. {
  1304. UINT lengthBytes = 0;
  1305. hr = Helpers::LoadBinaryFile(*fileName, fileContent, lengthBytes);
  1306. if (FAILED(hr))
  1307. {
  1308. fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
  1309. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetUndefinedValue(&returnValue), Error);
  1310. return returnValue;
  1311. }
  1312. JsValueRef arrayBuffer;
  1313. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsCreateArrayBuffer(lengthBytes, &arrayBuffer), ErrorStillFree);
  1314. BYTE* buffer;
  1315. unsigned int bufferLength;
  1316. IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetArrayBufferStorage(arrayBuffer, &buffer, &bufferLength), ErrorStillFree);
  1317. if (bufferLength < lengthBytes)
  1318. {
  1319. fwprintf(stderr, _u("Array buffer size is insufficient to store the binary file.\n"));
  1320. }
  1321. else
  1322. {
  1323. if (memcpy_s(buffer, bufferLength, (BYTE*)fileContent, lengthBytes) == 0)
  1324. {
  1325. returnValue = arrayBuffer;
  1326. }
  1327. }
  1328. ErrorStillFree:
  1329. if (isHeapAlloc)
  1330. {
  1331. HeapFree(GetProcessHeap(), 0, (void*)fileContent);
  1332. }
  1333. }
  1334. }
  1335. Error:
  1336. return returnValue;
  1337. }
  1338. JsValueRef __stdcall WScriptJsrt::FlagCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1339. {
  1340. HRESULT hr = E_FAIL;
  1341. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1342. JsErrorCode errorCode = JsNoError;
  1343. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1344. #if ENABLE_DEBUG_CONFIG_OPTIONS
  1345. if (argumentCount > 1)
  1346. {
  1347. AutoString cmd;
  1348. IfJsrtErrorSetGo(cmd.Initialize(arguments[1]));
  1349. char16* argv[] = { nullptr, cmd.GetWideString() };
  1350. ChakraRTInterface::SetConfigFlags(2, argv, nullptr);
  1351. }
  1352. #endif
  1353. Error:
  1354. return returnValue;
  1355. }
  1356. JsValueRef __stdcall WScriptJsrt::BroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1357. {
  1358. HRESULT hr = E_FAIL;
  1359. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1360. JsErrorCode errorCode = JsNoError;
  1361. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1362. if (argumentCount > 1)
  1363. {
  1364. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1365. if (threadData)
  1366. {
  1367. ChakraRTInterface::JsGetSharedArrayBufferContent(arguments[1], &threadData->sharedContent);
  1368. LONG count = (LONG)threadData->children.size();
  1369. threadData->hSemaphore = CreateSemaphore(NULL, 0, count, NULL);
  1370. if (threadData->hSemaphore)
  1371. {
  1372. //Clang does not support "for each" yet
  1373. for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
  1374. {
  1375. auto child = *i;
  1376. SetEvent(child->hevntReceivedBroadcast);
  1377. }
  1378. WaitForSingleObject(threadData->hSemaphore, INFINITE);
  1379. CloseHandle(threadData->hSemaphore);
  1380. threadData->hSemaphore = INVALID_HANDLE_VALUE;
  1381. }
  1382. else
  1383. {
  1384. fwprintf(stderr, _u("Couldn't create semaphore.\n"));
  1385. fflush(stderr);
  1386. }
  1387. ChakraRTInterface::JsReleaseSharedArrayBufferContentHandle(threadData->sharedContent);
  1388. }
  1389. }
  1390. Error:
  1391. return returnValue;
  1392. }
  1393. JsValueRef __stdcall WScriptJsrt::ReceiveBroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1394. {
  1395. HRESULT hr = E_FAIL;
  1396. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1397. JsErrorCode errorCode = JsNoError;
  1398. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1399. if (argumentCount > 1)
  1400. {
  1401. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1402. if (threadData)
  1403. {
  1404. if (threadData->receiveBroadcastCallbackFunc)
  1405. {
  1406. ChakraRTInterface::JsRelease(threadData->receiveBroadcastCallbackFunc, nullptr);
  1407. }
  1408. threadData->receiveBroadcastCallbackFunc = arguments[1];
  1409. ChakraRTInterface::JsAddRef(threadData->receiveBroadcastCallbackFunc, nullptr);
  1410. }
  1411. }
  1412. Error:
  1413. return returnValue;
  1414. }
  1415. JsValueRef __stdcall WScriptJsrt::ReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1416. {
  1417. HRESULT hr = E_FAIL;
  1418. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1419. JsErrorCode errorCode = JsNoError;
  1420. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1421. if (argumentCount > 1)
  1422. {
  1423. JsValueRef stringRef;
  1424. ChakraRTInterface::JsConvertValueToString(arguments[1], &stringRef);
  1425. AutoString autoStr(stringRef);
  1426. if (autoStr.GetError() == JsNoError)
  1427. {
  1428. std::string str(autoStr.GetString());
  1429. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1430. if (threadData && threadData->parent)
  1431. {
  1432. EnterCriticalSection(&threadData->parent->csReportQ);
  1433. threadData->parent->reportQ.push_back(str);
  1434. LeaveCriticalSection(&threadData->parent->csReportQ);
  1435. }
  1436. }
  1437. }
  1438. Error:
  1439. return returnValue;
  1440. }
  1441. JsValueRef __stdcall WScriptJsrt::GetReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1442. {
  1443. HRESULT hr = E_FAIL;
  1444. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1445. JsErrorCode errorCode = JsNoError;
  1446. IfJsrtErrorSetGo(ChakraRTInterface::JsGetNullValue(&returnValue));
  1447. if (argumentCount > 0)
  1448. {
  1449. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1450. if (threadData)
  1451. {
  1452. EnterCriticalSection(&threadData->csReportQ);
  1453. if (threadData->reportQ.size() > 0)
  1454. {
  1455. auto str = threadData->reportQ.front();
  1456. threadData->reportQ.pop_front();
  1457. ChakraRTInterface::JsCreateString(str.c_str(), str.size(), &returnValue);
  1458. }
  1459. LeaveCriticalSection(&threadData->csReportQ);
  1460. }
  1461. }
  1462. Error:
  1463. return returnValue;
  1464. }
  1465. JsValueRef __stdcall WScriptJsrt::LeavingCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1466. {
  1467. HRESULT hr = E_FAIL;
  1468. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1469. JsErrorCode errorCode = JsNoError;
  1470. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1471. if (argumentCount > 0)
  1472. {
  1473. auto& threadData = GetRuntimeThreadLocalData().threadData;
  1474. if (threadData)
  1475. {
  1476. threadData->leaving = true;
  1477. }
  1478. }
  1479. Error:
  1480. return returnValue;
  1481. }
  1482. JsValueRef __stdcall WScriptJsrt::SleepCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1483. {
  1484. HRESULT hr = E_FAIL;
  1485. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1486. JsErrorCode errorCode = JsNoError;
  1487. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
  1488. if (argumentCount > 1)
  1489. {
  1490. double timeout = 0.0;
  1491. ChakraRTInterface::JsNumberToDouble(arguments[1], &timeout);
  1492. Sleep((DWORD)timeout);
  1493. }
  1494. Error:
  1495. return returnValue;
  1496. }
  1497. JsValueRef __stdcall WScriptJsrt::GetProxyPropertiesCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  1498. {
  1499. HRESULT hr = E_FAIL;
  1500. JsValueRef returnValue = JS_INVALID_REFERENCE;
  1501. JsValueRef undefined = JS_INVALID_REFERENCE;
  1502. JsErrorCode errorCode = JsNoError;
  1503. IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&undefined));
  1504. returnValue = undefined;
  1505. if (argumentCount > 1)
  1506. {
  1507. bool isProxy = false;
  1508. JsValueRef target;
  1509. JsValueRef handler;
  1510. IfJsrtErrorSetGo(ChakraRTInterface::JsGetProxyProperties(arguments[1], &isProxy, &target, &handler));
  1511. if (isProxy)
  1512. {
  1513. JsPropertyIdRef targetProperty;
  1514. JsPropertyIdRef handlerProperty;
  1515. JsPropertyIdRef revokedProperty;
  1516. IfJsrtErrorSetGo(CreatePropertyIdFromString("target", &targetProperty));
  1517. IfJsrtErrorSetGo(CreatePropertyIdFromString("handler", &handlerProperty));
  1518. IfJsrtErrorSetGo(CreatePropertyIdFromString("revoked", &revokedProperty));
  1519. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateObject(&returnValue));
  1520. JsValueRef revoked = JS_INVALID_REFERENCE;
  1521. if (target == JS_INVALID_REFERENCE)
  1522. {
  1523. IfJsrtErrorSetGo(ChakraRTInterface::JsGetTrueValue(&revoked));
  1524. target = undefined;
  1525. handler = undefined;
  1526. }
  1527. else
  1528. {
  1529. IfJsrtErrorSetGo(ChakraRTInterface::JsGetFalseValue(&revoked));
  1530. }
  1531. IfJsrtErrorSetGo(ChakraRTInterface::JsSetProperty(returnValue, handlerProperty, handler, true));
  1532. IfJsrtErrorSetGo(ChakraRTInterface::JsSetProperty(returnValue, targetProperty, target, true));
  1533. IfJsrtErrorSetGo(ChakraRTInterface::JsSetProperty(returnValue, revokedProperty, revoked, true));
  1534. }
  1535. }
  1536. Error:
  1537. return returnValue;
  1538. }
  1539. bool WScriptJsrt::PrintException(LPCSTR fileName, JsErrorCode jsErrorCode)
  1540. {
  1541. LPCWSTR errorTypeString = ConvertErrorCodeToMessage(jsErrorCode);
  1542. JsValueRef exception;
  1543. ChakraRTInterface::JsGetAndClearException(&exception);
  1544. if (HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
  1545. {
  1546. return false;
  1547. }
  1548. if (exception != nullptr)
  1549. {
  1550. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile || jsErrorCode == JsErrorCode::JsErrorScriptException)
  1551. {
  1552. AutoString errorMessage;
  1553. IfJsrtErrorFail(errorMessage.Initialize(exception), false);
  1554. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile)
  1555. {
  1556. JsPropertyIdRef linePropertyId = JS_INVALID_REFERENCE;
  1557. JsValueRef lineProperty = JS_INVALID_REFERENCE;
  1558. JsPropertyIdRef columnPropertyId = JS_INVALID_REFERENCE;
  1559. JsValueRef columnProperty = JS_INVALID_REFERENCE;
  1560. int line;
  1561. int column;
  1562. IfJsrtErrorFail(CreatePropertyIdFromString("line", &linePropertyId), false);
  1563. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, linePropertyId, &lineProperty), false);
  1564. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(lineProperty, &line), false);
  1565. IfJsrtErrorFail(CreatePropertyIdFromString("column", &columnPropertyId), false);
  1566. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, columnPropertyId, &columnProperty), false);
  1567. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(columnProperty, &column), false);
  1568. CHAR shortFileName[_MAX_PATH];
  1569. CHAR ext[_MAX_EXT];
  1570. _splitpath_s(fileName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  1571. fwprintf(stderr, _u("%ls\n\tat code (%S%S:%d:%d)\n"),
  1572. errorMessage.GetWideString(), shortFileName, ext, (int)line + 1,
  1573. (int)column + 1);
  1574. }
  1575. else
  1576. {
  1577. JsValueType propertyType = JsUndefined;
  1578. JsPropertyIdRef stackPropertyId = JS_INVALID_REFERENCE;
  1579. JsValueRef stackProperty = JS_INVALID_REFERENCE;
  1580. AutoString errorStack;
  1581. JsErrorCode errorCode = CreatePropertyIdFromString("stack", &stackPropertyId);
  1582. if (errorCode == JsErrorCode::JsNoError)
  1583. {
  1584. errorCode = ChakraRTInterface::JsGetProperty(exception, stackPropertyId, &stackProperty);
  1585. if (errorCode == JsErrorCode::JsNoError)
  1586. {
  1587. errorCode = ChakraRTInterface::JsGetValueType(stackProperty, &propertyType);
  1588. }
  1589. }
  1590. if (errorCode != JsErrorCode::JsNoError || propertyType == JsUndefined)
  1591. {
  1592. const char *fName = fileName != nullptr ? fileName : "(unknown)";
  1593. CHAR shortFileName[_MAX_PATH];
  1594. CHAR ext[_MAX_EXT];
  1595. _splitpath_s(fName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  1596. // do not mix char/wchar. print them separately
  1597. fprintf(stderr, "thrown at %s%s:\n^\n", shortFileName, ext);
  1598. fwprintf(stderr, _u("%ls\n"), errorMessage.GetWideString());
  1599. }
  1600. else
  1601. {
  1602. IfJsrtErrorFail(errorStack.Initialize(stackProperty), false);
  1603. fwprintf(stderr, _u("%ls\n"), errorStack.GetWideString());
  1604. }
  1605. }
  1606. }
  1607. else
  1608. {
  1609. fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
  1610. }
  1611. return true;
  1612. }
  1613. else
  1614. {
  1615. fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
  1616. }
  1617. return false;
  1618. }
  1619. void WScriptJsrt::AddMessageQueue(MessageQueue *_messageQueue)
  1620. {
  1621. Assert(messageQueue == nullptr);
  1622. messageQueue = _messageQueue;
  1623. }
  1624. WScriptJsrt::CallbackMessage::CallbackMessage(unsigned int time, JsValueRef function) : MessageBase(time), m_function(function)
  1625. {
  1626. JsErrorCode error = ChakraRTInterface::JsAddRef(m_function, nullptr);
  1627. if (error != JsNoError)
  1628. {
  1629. // Simply report a fatal error and exit because continuing from this point would result in inconsistent state
  1630. // and FailFast telemetry would not be useful.
  1631. wprintf(_u("FATAL ERROR: ChakraRTInterface::JsAddRef failed in WScriptJsrt::CallbackMessage::`ctor`. error=0x%x\n"), error);
  1632. exit(1);
  1633. }
  1634. }
  1635. WScriptJsrt::CallbackMessage::~CallbackMessage()
  1636. {
  1637. bool hasException = false;
  1638. ChakraRTInterface::JsHasException(&hasException);
  1639. if (hasException)
  1640. {
  1641. WScriptJsrt::PrintException("", JsErrorScriptException);
  1642. }
  1643. JsErrorCode errorCode = ChakraRTInterface::JsRelease(m_function, nullptr);
  1644. Assert(errorCode == JsNoError);
  1645. m_function = JS_INVALID_REFERENCE;
  1646. }
  1647. HRESULT WScriptJsrt::CallbackMessage::Call(LPCSTR fileName)
  1648. {
  1649. return CallFunction(fileName);
  1650. }
  1651. HRESULT WScriptJsrt::CallbackMessage::CallFunction(LPCSTR fileName)
  1652. {
  1653. HRESULT hr = S_OK;
  1654. JsValueRef global;
  1655. JsValueRef result;
  1656. JsValueRef stringValue;
  1657. JsValueType type;
  1658. JsErrorCode errorCode = JsNoError;
  1659. IfJsrtErrorHR(ChakraRTInterface::JsGetGlobalObject(&global));
  1660. IfJsrtErrorHR(ChakraRTInterface::JsGetValueType(m_function, &type));
  1661. if (type == JsString)
  1662. {
  1663. IfJsrtErrorHR(ChakraRTInterface::JsConvertValueToString(m_function, &stringValue));
  1664. JsValueRef fname;
  1665. ChakraRTInterface::JsCreateString("", strlen(""), &fname);
  1666. // Run the code
  1667. errorCode = ChakraRTInterface::JsRun(stringValue, JS_SOURCE_CONTEXT_NONE,
  1668. fname, JsParseScriptAttributeArrayBufferIsUtf16Encoded,
  1669. nullptr /*no result needed*/);
  1670. }
  1671. else
  1672. {
  1673. errorCode = ChakraRTInterface::JsCallFunction(m_function, &global, 1, &result);
  1674. }
  1675. if (errorCode != JsNoError)
  1676. {
  1677. hr = E_FAIL;
  1678. PrintException(fileName, errorCode);
  1679. }
  1680. Error:
  1681. return hr;
  1682. }
  1683. WScriptJsrt::ModuleMessage::ModuleMessage(JsModuleRecord module, JsValueRef specifier, std::string* fullPathPtr)
  1684. : MessageBase(0), moduleRecord(module), specifier(specifier)
  1685. {
  1686. fullPath = nullptr;
  1687. ChakraRTInterface::JsAddRef(module, nullptr);
  1688. if (specifier != nullptr)
  1689. {
  1690. fullPath = new std::string (*fullPathPtr);
  1691. // nullptr specifier means a Promise to execute; non-nullptr means a "fetch" operation.
  1692. ChakraRTInterface::JsAddRef(specifier, nullptr);
  1693. }
  1694. }
  1695. WScriptJsrt::ModuleMessage::~ModuleMessage()
  1696. {
  1697. ChakraRTInterface::JsRelease(moduleRecord, nullptr);
  1698. if (specifier != nullptr)
  1699. {
  1700. delete fullPath;
  1701. ChakraRTInterface::JsRelease(specifier, nullptr);
  1702. }
  1703. }
  1704. HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
  1705. {
  1706. JsErrorCode errorCode = JsNoError;
  1707. JsValueRef result = JS_INVALID_REFERENCE;
  1708. HRESULT hr;
  1709. if (specifier == nullptr)
  1710. {
  1711. if (moduleErrMap[moduleRecord] != ErroredModule)
  1712. {
  1713. errorCode = ChakraRTInterface::JsModuleEvaluation(moduleRecord, &result);
  1714. if (errorCode != JsNoError)
  1715. {
  1716. if (moduleErrMap[moduleRecord] == RootModule)
  1717. {
  1718. PrintException(fileName, errorCode);
  1719. }
  1720. else
  1721. {
  1722. bool hasException = false;
  1723. ChakraRTInterface::JsHasException(&hasException);
  1724. if (hasException)
  1725. {
  1726. JsValueRef exception;
  1727. ChakraRTInterface::JsGetAndClearException(&exception);
  1728. exception; //unusued
  1729. }
  1730. }
  1731. }
  1732. }
  1733. }
  1734. else
  1735. {
  1736. LPCSTR fileContent = nullptr;
  1737. AutoString specifierStr(specifier);
  1738. errorCode = specifierStr.GetError();
  1739. if (errorCode == JsNoError)
  1740. {
  1741. hr = Helpers::LoadScriptFromFile(*specifierStr, fileContent, nullptr, fullPath, true);
  1742. if (FAILED(hr))
  1743. {
  1744. if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
  1745. {
  1746. auto actualModuleRecord = moduleRecordMap.find(*fullPath);
  1747. if (actualModuleRecord == moduleRecordMap.end() || moduleErrMap[actualModuleRecord->second] == RootModule)
  1748. {
  1749. fprintf(stderr, "Couldn't load file '%s'\n", specifierStr.GetString());
  1750. }
  1751. }
  1752. LoadScript(nullptr, fullPath == nullptr ? *specifierStr : fullPath->c_str(), nullptr, "module", true, WScriptJsrt::FinalizeFree, false);
  1753. goto Error;
  1754. }
  1755. LoadScript(nullptr, fullPath == nullptr ? *specifierStr : fullPath->c_str(), fileContent, "module", true, WScriptJsrt::FinalizeFree, true);
  1756. }
  1757. }
  1758. Error:
  1759. return errorCode;
  1760. }
  1761. JsErrorCode WScriptJsrt::FetchImportedModuleHelper(JsModuleRecord referencingModule,
  1762. JsValueRef specifier, __out JsModuleRecord* dependentModuleRecord, LPCSTR refdir)
  1763. {
  1764. JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
  1765. AutoString specifierStr;
  1766. *dependentModuleRecord = nullptr;
  1767. if (specifierStr.Initialize(specifier) != JsNoError)
  1768. {
  1769. return specifierStr.GetError();
  1770. }
  1771. char fullPath[_MAX_PATH];
  1772. std::string specifierFullPath = refdir ? refdir : "";
  1773. specifierFullPath += *specifierStr;
  1774. if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
  1775. {
  1776. return JsErrorInvalidArgument;
  1777. }
  1778. auto moduleEntry = moduleRecordMap.find(std::string(fullPath));
  1779. if (moduleEntry != moduleRecordMap.end())
  1780. {
  1781. *dependentModuleRecord = moduleEntry->second;
  1782. return JsNoError;
  1783. }
  1784. JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(referencingModule, specifier, &moduleRecord);
  1785. if (errorCode == JsNoError)
  1786. {
  1787. GetDir(fullPath, &moduleDirMap[moduleRecord]);
  1788. InitializeModuleInfo(specifier, moduleRecord);
  1789. std::string pathKey = std::string(fullPath);
  1790. moduleRecordMap[pathKey] = moduleRecord;
  1791. moduleErrMap[moduleRecord] = ImportedModule;
  1792. ModuleMessage* moduleMessage = WScriptJsrt::ModuleMessage::Create(referencingModule, specifier, &pathKey);
  1793. if (moduleMessage == nullptr)
  1794. {
  1795. return JsErrorOutOfMemory;
  1796. }
  1797. WScriptJsrt::PushMessage(moduleMessage);
  1798. *dependentModuleRecord = moduleRecord;
  1799. }
  1800. return errorCode;
  1801. }
  1802. // Callback from chakracore to fetch dependent module. In the test harness,
  1803. // we are not doing any translation, just treat the specifier as fileName.
  1804. // While this call will come back directly from ParseModuleSource, the additional
  1805. // task are treated as Promise that will be executed later.
  1806. JsErrorCode WScriptJsrt::FetchImportedModule(_In_ JsModuleRecord referencingModule,
  1807. _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
  1808. {
  1809. auto moduleDirEntry = moduleDirMap.find(referencingModule);
  1810. if (moduleDirEntry != moduleDirMap.end())
  1811. {
  1812. std::string dir = moduleDirEntry->second;
  1813. return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord, dir.c_str());
  1814. }
  1815. return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord);
  1816. }
  1817. // Callback from chakracore to fetch module dynamically during runtime. In the test harness,
  1818. // we are not doing any translation, just treat the specifier as fileName.
  1819. // While this call will come back directly from runtime script or module code, the additional
  1820. // task can be scheduled asynchronously that executed later.
  1821. JsErrorCode WScriptJsrt::FetchImportedModuleFromScript(_In_ JsSourceContext dwReferencingSourceContext,
  1822. _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
  1823. {
  1824. return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord);
  1825. }
  1826. // Callback from chakraCore when the module resolution is finished, either successfuly or unsuccessfully.
  1827. JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
  1828. {
  1829. if (exceptionVar != nullptr)
  1830. {
  1831. ChakraRTInterface::JsSetException(exceptionVar);
  1832. JsValueRef specifier = JS_INVALID_REFERENCE;
  1833. ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
  1834. AutoString fileName;
  1835. if (specifier != JS_INVALID_REFERENCE)
  1836. {
  1837. fileName.Initialize(specifier);
  1838. }
  1839. if (HostConfigFlags::flags.TraceHostCallbackIsEnabled)
  1840. {
  1841. wprintf(_u("NotifyModuleReadyCallback(exception) %S\n"), fileName.GetString());
  1842. }
  1843. // No need to print - just consume the exception
  1844. JsValueRef exception;
  1845. ChakraRTInterface::JsGetAndClearException(&exception);
  1846. exception; // unused
  1847. }
  1848. if (exceptionVar != nullptr || moduleErrMap[referencingModule] != ErroredModule)
  1849. {
  1850. WScriptJsrt::ModuleMessage* moduleMessage =
  1851. WScriptJsrt::ModuleMessage::Create(referencingModule, nullptr);
  1852. if (moduleMessage == nullptr)
  1853. {
  1854. return JsErrorOutOfMemory;
  1855. }
  1856. WScriptJsrt::PushMessage(moduleMessage);
  1857. }
  1858. return JsNoError;
  1859. }
  1860. JsErrorCode __stdcall WScriptJsrt::InitializeImportMetaCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef importMetaVar)
  1861. {
  1862. if (importMetaVar != nullptr)
  1863. {
  1864. JsValueRef specifier = JS_INVALID_REFERENCE;
  1865. ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
  1866. JsPropertyIdRef urlPropId;
  1867. if (JsNoError == CreatePropertyIdFromString("url", &urlPropId))
  1868. {
  1869. ChakraRTInterface::JsSetProperty(importMetaVar, urlPropId, specifier, false);
  1870. }
  1871. }
  1872. return JsNoError;
  1873. }
  1874. void WScriptJsrt::PromiseContinuationCallback(JsValueRef task, void *callbackState)
  1875. {
  1876. Assert(task != JS_INVALID_REFERENCE);
  1877. Assert(callbackState != JS_INVALID_REFERENCE);
  1878. MessageQueue * messageQueue = (MessageQueue *)callbackState;
  1879. WScriptJsrt::CallbackMessage *msg = new WScriptJsrt::CallbackMessage(0, task);
  1880. messageQueue->InsertSorted(msg);
  1881. }
  1882. void WScriptJsrt::PromiseRejectionTrackerCallback(JsValueRef promise, JsValueRef reason, bool handled, void *callbackState)
  1883. {
  1884. Assert(promise != JS_INVALID_REFERENCE);
  1885. Assert(reason != JS_INVALID_REFERENCE);
  1886. if (!handled)
  1887. {
  1888. wprintf(_u("Uncaught promise rejection\n"));
  1889. }
  1890. else
  1891. {
  1892. wprintf(_u("Promise rejection handled\n"));
  1893. }
  1894. JsPropertyIdRef stackPropertyID;
  1895. JsErrorCode error = ChakraRTInterface::JsCreatePropertyId("stack", strlen("stack"), &stackPropertyID);
  1896. if (error == JsNoError)
  1897. {
  1898. JsValueRef stack;
  1899. error = ChakraRTInterface::JsGetProperty(reason, stackPropertyID, &stack);
  1900. if (error == JsNoError)
  1901. {
  1902. JsValueRef stackStrValue;
  1903. error = ChakraRTInterface::JsConvertValueToString(stack, &stackStrValue);
  1904. if (error == JsNoError)
  1905. {
  1906. AutoString str(stackStrValue);
  1907. wprintf(_u("%ls\n"), str.GetWideString());
  1908. }
  1909. }
  1910. }
  1911. if (error != JsNoError)
  1912. {
  1913. // weren't able to print stack, so just convert reason to a string
  1914. JsValueRef strValue;
  1915. error = ChakraRTInterface::JsConvertValueToString(reason, &strValue);
  1916. if (error == JsNoError)
  1917. {
  1918. AutoString str(strValue);
  1919. wprintf(_u("%ls\n"), str.GetWideString());
  1920. }
  1921. }
  1922. fflush(stdout);
  1923. }