WScriptJsrt.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "stdafx.h"
  6. MessageQueue* WScriptJsrt::messageQueue = nullptr;
  7. DWORD_PTR WScriptJsrt::sourceContext = 0;
  8. DWORD_PTR WScriptJsrt::GetNextSourceContext()
  9. {
  10. return sourceContext++;
  11. }
  12. bool WScriptJsrt::CreateArgumentsObject(JsValueRef *argsObject)
  13. {
  14. LPWSTR *argv = HostConfigFlags::argsVal;
  15. JsValueRef retArr;
  16. Assert(argsObject);
  17. *argsObject = nullptr;
  18. IfJsrtErrorFail(ChakraRTInterface::JsCreateArray(HostConfigFlags::argsCount, &retArr), false);
  19. for (int i = 0; i < HostConfigFlags::argsCount; i++)
  20. {
  21. JsValueRef value;
  22. JsValueRef index;
  23. IfJsrtErrorFail(ChakraRTInterface::JsPointerToString(argv[i], wcslen(argv[i]), &value), false);
  24. IfJsrtErrorFail(ChakraRTInterface::JsDoubleToNumber(i, &index), false);
  25. IfJsrtErrorFail(ChakraRTInterface::JsSetIndexedProperty(retArr, index, value), false);
  26. }
  27. *argsObject = retArr;
  28. return true;
  29. }
  30. JsValueRef __stdcall WScriptJsrt::EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  31. {
  32. for (unsigned int i = 1; i < argumentCount; i++)
  33. {
  34. JsValueRef strValue;
  35. JsErrorCode error = ChakraRTInterface::JsConvertValueToString(arguments[i], &strValue);
  36. if (error == JsNoError)
  37. {
  38. LPCWSTR str = nullptr;
  39. size_t length;
  40. error = ChakraRTInterface::JsStringToPointer(strValue, &str, &length);
  41. if (error == JsNoError)
  42. {
  43. if (i > 1)
  44. {
  45. wprintf(L" ");
  46. }
  47. wprintf(L"%ls", str);
  48. }
  49. }
  50. if (error == JsErrorScriptException)
  51. {
  52. return nullptr;
  53. }
  54. }
  55. wprintf(L"\n");
  56. JsValueRef undefinedValue;
  57. if (ChakraRTInterface::JsGetUndefinedValue(&undefinedValue) == JsNoError)
  58. {
  59. return undefinedValue;
  60. }
  61. else
  62. {
  63. return nullptr;
  64. }
  65. }
  66. JsValueRef __stdcall WScriptJsrt::QuitCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  67. {
  68. int exitCode = 0;
  69. if (argumentCount > 1)
  70. {
  71. double exitCodeDouble;
  72. IfJsrtErrorFail(ChakraRTInterface::JsNumberToDouble(arguments[1], &exitCodeDouble), JS_INVALID_REFERENCE);
  73. exitCode = (int)exitCodeDouble;
  74. }
  75. ExitProcess(exitCode);
  76. }
  77. JsValueRef __stdcall WScriptJsrt::LoadModuleFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  78. {
  79. return LoadScriptFileHelper(callee, arguments, argumentCount, true);
  80. }
  81. JsValueRef __stdcall WScriptJsrt::LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  82. {
  83. return LoadScriptFileHelper(callee, arguments, argumentCount, false);
  84. }
  85. JsValueRef WScriptJsrt::LoadScriptFileHelper(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, bool isSourceModule)
  86. {
  87. HRESULT hr = E_FAIL;
  88. JsValueRef returnValue = JS_INVALID_REFERENCE;
  89. JsErrorCode errorCode = JsNoError;
  90. LPCWSTR errorMessage = L"";
  91. if (argumentCount < 2 || argumentCount > 4)
  92. {
  93. errorCode = JsErrorInvalidArgument;
  94. errorMessage = L"Need more or fewer arguments for WScript.LoadScript";
  95. }
  96. else
  97. {
  98. const wchar_t *fileContent;
  99. const wchar_t *fileName;
  100. const wchar_t *scriptInjectType = L"self";
  101. size_t fileNameLength;
  102. size_t scriptInjectTypeLength;
  103. IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[1], &fileName, &fileNameLength));
  104. if (argumentCount > 2)
  105. {
  106. IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[2], &scriptInjectType, &scriptInjectTypeLength));
  107. }
  108. if (errorCode == JsNoError)
  109. {
  110. hr = Helpers::LoadScriptFromFile(fileName, fileContent);
  111. if (FAILED(hr))
  112. {
  113. fwprintf(stderr, L"Couldn't load file.\n");
  114. }
  115. else
  116. {
  117. returnValue = LoadScript(callee, fileName, fileNameLength, fileContent, scriptInjectType, isSourceModule);
  118. }
  119. }
  120. }
  121. Error:
  122. if (errorCode != JsNoError)
  123. {
  124. JsValueRef errorObject;
  125. JsValueRef errorMessageString;
  126. if (wcscmp(errorMessage, L"") == 0) {
  127. errorMessage = ConvertErrorCodeToMessage(errorCode);
  128. }
  129. ChakraRTInterface::JsPointerToString(errorMessage, wcslen(errorMessage), &errorMessageString);
  130. ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  131. ChakraRTInterface::JsSetException(errorObject);
  132. }
  133. return returnValue;
  134. }
  135. JsValueRef __stdcall WScriptJsrt::LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  136. {
  137. return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, false);
  138. }
  139. JsValueRef __stdcall WScriptJsrt::LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  140. {
  141. return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, true);
  142. }
  143. JsValueRef WScriptJsrt::LoadScriptHelper(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState, bool isSourceModule)
  144. {
  145. HRESULT hr = E_FAIL;
  146. JsErrorCode errorCode = JsNoError;
  147. LPCWSTR errorMessage = L"";
  148. JsValueRef returnValue = JS_INVALID_REFERENCE;
  149. if (argumentCount < 2 || argumentCount > 4)
  150. {
  151. errorCode = JsErrorInvalidArgument;
  152. errorMessage = L"Need more or fewer arguments for WScript.LoadScript";
  153. }
  154. else
  155. {
  156. const wchar_t *fileContent;
  157. const wchar_t *fileName;
  158. const wchar_t *scriptInjectType = L"self";
  159. size_t fileContentLength;
  160. size_t fileNameLength;
  161. size_t scriptInjectTypeLength;
  162. IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[1], &fileContent, &fileContentLength));
  163. if (argumentCount > 2)
  164. {
  165. IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[2], &scriptInjectType, &scriptInjectTypeLength));
  166. }
  167. fileName = L"script.js";
  168. fileNameLength = wcslen(fileName);
  169. if (argumentCount > 3)
  170. {
  171. IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[3], &fileName, &fileNameLength));
  172. }
  173. returnValue = LoadScript(callee, fileName, fileNameLength, fileContent, scriptInjectType, isSourceModule);
  174. }
  175. Error:
  176. if (errorCode != JsNoError)
  177. {
  178. JsValueRef errorObject;
  179. JsValueRef errorMessageString;
  180. if (wcscmp(errorMessage, L"") == 0) {
  181. errorMessage = ConvertErrorCodeToMessage(errorCode);
  182. }
  183. ChakraRTInterface::JsPointerToString(errorMessage, wcslen(errorMessage), &errorMessageString);
  184. ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  185. ChakraRTInterface::JsSetException(errorObject);
  186. }
  187. return returnValue;
  188. }
  189. JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCWSTR fileName, size_t fileNameLength, LPCWSTR fileContent, LPCWSTR scriptInjectType, bool isSourceModule)
  190. {
  191. HRESULT hr = E_FAIL;
  192. JsErrorCode errorCode = JsNoError;
  193. LPCWSTR errorMessage = L"Internal error.";
  194. size_t errorMessageLength = wcslen(errorMessage);
  195. JsValueRef returnValue = JS_INVALID_REFERENCE;
  196. JsErrorCode innerErrorCode = JsNoError;
  197. JsContextRef currentContext = JS_INVALID_REFERENCE;
  198. JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
  199. IfJsrtErrorSetGo(ChakraRTInterface::JsGetCurrentContext(&currentContext));
  200. IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime));
  201. wchar_t fullPath[_MAX_PATH];
  202. if (_wfullpath(fullPath, fileName, _MAX_PATH) == nullptr)
  203. {
  204. IfFailGo(E_FAIL);
  205. }
  206. // canonicalize that path name to lower case for the profile storage
  207. size_t len = wcslen(fullPath);
  208. for (size_t i = 0; i < len; i++)
  209. {
  210. fullPath[i] = towlower(fullPath[i]);
  211. }
  212. if (wcscmp(scriptInjectType, L"self") == 0)
  213. {
  214. JsContextRef calleeContext;
  215. IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
  216. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(calleeContext));
  217. if (isSourceModule)
  218. {
  219. errorCode = ChakraRTInterface::JsRunModule(fileContent, GetNextSourceContext(), fullPath, &returnValue);
  220. }
  221. else
  222. {
  223. errorCode = ChakraRTInterface::JsRunScript(fileContent, GetNextSourceContext(), fullPath, &returnValue);
  224. }
  225. if (errorCode == JsNoError)
  226. {
  227. errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
  228. }
  229. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(currentContext));
  230. }
  231. else if (wcscmp(scriptInjectType, L"samethread") == 0)
  232. {
  233. JsValueRef newContext = JS_INVALID_REFERENCE;
  234. // Create a new context and set it as the current context
  235. IfJsrtErrorSetGo(ChakraRTInterface::JsCreateContext(runtime, &newContext));
  236. IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(newContext));
  237. // Initialize the host objects
  238. Initialize();
  239. if (isSourceModule)
  240. {
  241. errorCode = ChakraRTInterface::JsRunModule(fileContent, GetNextSourceContext(), fullPath, &returnValue);
  242. }
  243. else
  244. {
  245. errorCode = ChakraRTInterface::JsRunScript(fileContent, GetNextSourceContext(), fullPath, &returnValue);
  246. }
  247. if (errorCode == JsNoError)
  248. {
  249. errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
  250. }
  251. // Set the context back to the old one
  252. ChakraRTInterface::JsSetCurrentContext(currentContext);
  253. }
  254. else
  255. {
  256. errorCode = JsErrorInvalidArgument;
  257. errorMessage = L"Unsupported argument type inject type.";
  258. }
  259. Error:
  260. JsValueRef value = returnValue;
  261. if (errorCode != JsNoError)
  262. {
  263. if (innerErrorCode != JsNoError)
  264. {
  265. // Failed to retrieve the inner error message, so set a custom error string
  266. errorMessage = ConvertErrorCodeToMessage(errorCode);
  267. }
  268. JsValueRef error = JS_INVALID_REFERENCE;
  269. JsValueRef messageProperty = JS_INVALID_REFERENCE;
  270. errorMessageLength = wcslen(errorMessage);
  271. innerErrorCode = ChakraRTInterface::JsPointerToString(errorMessage, errorMessageLength, &messageProperty);
  272. if (innerErrorCode == JsNoError)
  273. {
  274. innerErrorCode = ChakraRTInterface::JsCreateError(messageProperty, &error);
  275. if (innerErrorCode == JsNoError)
  276. {
  277. innerErrorCode = ChakraRTInterface::JsSetException(error);
  278. }
  279. }
  280. ChakraRTInterface::JsDoubleToNumber(errorCode, &value);
  281. }
  282. _flushall();
  283. return value;
  284. }
  285. JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  286. {
  287. LPWSTR errorMessage = L"invalid call to WScript.SetTimeout";
  288. if (argumentCount != 3)
  289. {
  290. goto Error;
  291. }
  292. JsValueRef function = arguments[1];
  293. JsValueRef timerId;
  294. unsigned int time;
  295. double tmp;
  296. CallbackMessage *msg = nullptr;
  297. IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[2], &tmp));
  298. time = static_cast<int>(tmp);
  299. msg = new CallbackMessage(time, function);
  300. messageQueue->Push(msg);
  301. IfJsrtError(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(msg->GetId()), &timerId));
  302. return timerId;
  303. Error:
  304. JsValueRef errorObject;
  305. JsValueRef errorMessageString;
  306. JsErrorCode errorCode = ChakraRTInterface::JsPointerToString(errorMessage, wcslen(errorMessage), &errorMessageString);
  307. if (errorCode != JsNoError)
  308. {
  309. errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  310. if (errorCode != JsNoError)
  311. {
  312. ChakraRTInterface::JsSetException(errorObject);
  313. }
  314. }
  315. return JS_INVALID_REFERENCE;
  316. }
  317. JsValueRef WScriptJsrt::ClearTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
  318. {
  319. LPWSTR errorMessage = L"invalid call to WScript.ClearTimeout";
  320. if (argumentCount != 2)
  321. {
  322. goto Error;
  323. }
  324. unsigned int timerId;
  325. double tmp;
  326. JsValueRef undef;
  327. JsValueRef global;
  328. IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[1], &tmp));
  329. timerId = static_cast<int>(tmp);
  330. messageQueue->RemoveById(timerId);
  331. IfJsrtError(ChakraRTInterface::JsGetGlobalObject(&global));
  332. IfJsrtError(ChakraRTInterface::JsGetUndefinedValue(&undef));
  333. return undef;
  334. Error:
  335. JsValueRef errorObject;
  336. JsValueRef errorMessageString;
  337. JsErrorCode errorCode = ChakraRTInterface::JsPointerToString(errorMessage, wcslen(errorMessage), &errorMessageString);
  338. if (errorCode != JsNoError)
  339. {
  340. errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
  341. if (errorCode != JsNoError)
  342. {
  343. ChakraRTInterface::JsSetException(errorObject);
  344. }
  345. }
  346. return JS_INVALID_REFERENCE;
  347. }
  348. bool WScriptJsrt::CreateNamedFunction(const wchar_t* nameString, JsNativeFunction callback, JsValueRef* functionVar)
  349. {
  350. JsValueRef nameVar;
  351. IfJsrtErrorFail(ChakraRTInterface::JsPointerToString(nameString, wcslen(nameString), &nameVar), false);
  352. IfJsrtErrorFail(ChakraRTInterface::JsCreateNamedFunction(nameVar, callback, nullptr, functionVar), false);
  353. return true;
  354. }
  355. bool WScriptJsrt::Initialize()
  356. {
  357. JsValueRef wscript;
  358. IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&wscript), false);
  359. JsValueRef echo;
  360. JsPropertyIdRef echoPropertyId;
  361. const wchar_t* echoString = L"Echo";
  362. CreateNamedFunction(echoString, EchoCallback, &echo);
  363. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(echoString, &echoPropertyId), false);
  364. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, echoPropertyId, echo, true), false);
  365. JsValueRef argsObject;
  366. if (!CreateArgumentsObject(&argsObject))
  367. {
  368. return false;
  369. }
  370. JsPropertyIdRef argsName;
  371. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(L"Arguments", &argsName), false);
  372. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, argsName, argsObject, true), false);
  373. JsValueRef quit;
  374. const wchar_t* quitString = L"Quit";
  375. JsPropertyIdRef quitPropertyId;
  376. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(quitString, &quitPropertyId), false);
  377. CreateNamedFunction(quitString, QuitCallback, &quit);
  378. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, quitPropertyId, quit, true), false);
  379. JsValueRef loadScriptFile;
  380. const wchar_t* loadScriptFileString = L"LoadScriptFile";
  381. JsPropertyIdRef loadScriptFilePropertyId;
  382. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(loadScriptFileString, &loadScriptFilePropertyId), false);
  383. CreateNamedFunction(loadScriptFileString, LoadScriptFileCallback, &loadScriptFile);
  384. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, loadScriptFilePropertyId, loadScriptFile, true), false);
  385. JsValueRef loadModuleFile;
  386. const wchar_t* loadModuleFileString = L"LoadModuleFile";
  387. JsPropertyIdRef loadModuleFilePropertyId;
  388. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(loadModuleFileString, &loadModuleFilePropertyId), false);
  389. CreateNamedFunction(loadModuleFileString, LoadModuleFileCallback, &loadModuleFile);
  390. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, loadModuleFilePropertyId, loadModuleFile, true), false);
  391. JsValueRef loadScript;
  392. JsPropertyIdRef loadScriptName;
  393. const wchar_t* loadScriptString = L"LoadScript";
  394. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(loadScriptString, &loadScriptName), false);
  395. CreateNamedFunction(loadScriptString, LoadScriptCallback, &loadScript);
  396. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, loadScriptName, loadScript, true), false);
  397. JsValueRef loadModule;
  398. JsPropertyIdRef loadModuleName;
  399. const wchar_t* loadModuleString = L"LoadModule";
  400. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(loadModuleString, &loadModuleName), false);
  401. CreateNamedFunction(loadModuleString, LoadModuleCallback, &loadModule);
  402. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, loadModuleName, loadModule, true), false);
  403. JsValueRef setTimeout;
  404. JsPropertyIdRef setTimeoutName;
  405. const wchar_t* setTimeoutString = L"SetTimeout";
  406. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(setTimeoutString, &setTimeoutName), false);
  407. CreateNamedFunction(setTimeoutString, SetTimeoutCallback, &setTimeout);
  408. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, setTimeoutName, setTimeout, true), false);
  409. JsValueRef clearTimeout;
  410. JsPropertyIdRef clearTimeoutName;
  411. const wchar_t* clearTimeoutString = L"ClearTimeout";
  412. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(clearTimeoutString, &clearTimeoutName), false);
  413. CreateNamedFunction(clearTimeoutString, ClearTimeoutCallback, &clearTimeout);
  414. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, clearTimeoutName, clearTimeout, true), false);
  415. JsPropertyIdRef wscriptName;
  416. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(L"WScript", &wscriptName), false);
  417. JsValueRef global;
  418. IfJsrtErrorFail(ChakraRTInterface::JsGetGlobalObject(&global), false);
  419. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, wscriptName, wscript, true), false);
  420. JsPropertyIdRef printName;
  421. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(L"print", &printName), false);
  422. IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, printName, echo, true), false);
  423. return true;
  424. }
  425. bool WScriptJsrt::PrintException(LPCWSTR fileName, JsErrorCode jsErrorCode)
  426. {
  427. LPCWSTR errorTypeString = ConvertErrorCodeToMessage(jsErrorCode);
  428. JsValueRef exception;
  429. ChakraRTInterface::JsGetAndClearException(&exception);
  430. if (exception != nullptr)
  431. {
  432. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile || jsErrorCode == JsErrorCode::JsErrorScriptException)
  433. {
  434. LPCWSTR errorMessage = nullptr;
  435. size_t errorMessageLength = 0;
  436. JsValueRef errorString = JS_INVALID_REFERENCE;
  437. IfJsrtErrorFail(ChakraRTInterface::JsConvertValueToString(exception, &errorString), false);
  438. IfJsrtErrorFail(ChakraRTInterface::JsStringToPointer(errorString, &errorMessage, &errorMessageLength), false);
  439. if (jsErrorCode == JsErrorCode::JsErrorScriptCompile)
  440. {
  441. JsPropertyIdRef linePropertyId = JS_INVALID_REFERENCE;
  442. JsValueRef lineProperty = JS_INVALID_REFERENCE;
  443. JsPropertyIdRef columnPropertyId = JS_INVALID_REFERENCE;
  444. JsValueRef columnProperty = JS_INVALID_REFERENCE;
  445. int line;
  446. int column;
  447. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(L"line", &linePropertyId), false);
  448. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, linePropertyId, &lineProperty), false);
  449. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(lineProperty, &line), false);
  450. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(L"column", &columnPropertyId), false);
  451. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, columnPropertyId, &columnProperty), false);
  452. IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(columnProperty, &column), false);
  453. WCHAR shortFileName[_MAX_PATH];
  454. WCHAR ext[_MAX_EXT];
  455. _wsplitpath_s(fileName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
  456. fwprintf(stderr, L"%ls\n\tat code (%ls%ls:%d:%d)\n", errorMessage, shortFileName, ext, (int)line + 1, (int)column + 1);
  457. }
  458. else
  459. {
  460. JsValueType propertyType = JsUndefined;
  461. JsPropertyIdRef stackPropertyId = JS_INVALID_REFERENCE;
  462. JsValueRef stackProperty = JS_INVALID_REFERENCE;
  463. LPCWSTR errorStack = nullptr;
  464. size_t errorStackLength = 0;
  465. IfJsrtErrorFail(ChakraRTInterface::JsGetPropertyIdFromName(L"stack", &stackPropertyId), false);
  466. IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, stackPropertyId, &stackProperty), false);
  467. IfJsrtErrorFail(ChakraRTInterface::JsGetValueType(stackProperty, &propertyType), false);
  468. if (propertyType == JsUndefined)
  469. {
  470. fwprintf(stderr, L"%ls\n", errorMessage);
  471. }
  472. else
  473. {
  474. IfJsrtErrorFail(ChakraRTInterface::JsStringToPointer(stackProperty, &errorStack, &errorStackLength), false);
  475. fwprintf(stderr, L"%ls\n", errorStack);
  476. }
  477. }
  478. }
  479. else
  480. {
  481. fwprintf(stderr, L"Error : %ls\n", errorTypeString);
  482. }
  483. return true;
  484. }
  485. else
  486. {
  487. fwprintf(stderr, L"Error : %ls\n", errorTypeString);
  488. }
  489. return false;
  490. }
  491. void WScriptJsrt::AddMessageQueue(MessageQueue *_messageQueue)
  492. {
  493. Assert(messageQueue == nullptr);
  494. messageQueue = _messageQueue;
  495. }
  496. WScriptJsrt::CallbackMessage::CallbackMessage(unsigned int time, JsValueRef function) : MessageBase(time), m_function(function)
  497. {
  498. ChakraRTInterface::JsAddRef(m_function, nullptr);
  499. }
  500. WScriptJsrt::CallbackMessage::~CallbackMessage()
  501. {
  502. ChakraRTInterface::JsRelease(m_function, nullptr);
  503. m_function = JS_INVALID_REFERENCE;
  504. }
  505. HRESULT WScriptJsrt::CallbackMessage::Call(LPCWSTR fileName)
  506. {
  507. HRESULT hr = S_OK;
  508. JsValueRef global;
  509. JsValueRef result;
  510. JsValueRef stringValue;
  511. JsValueType type;
  512. JsErrorCode errorCode = JsNoError;
  513. IfJsrtErrorHR(ChakraRTInterface::JsGetGlobalObject(&global));
  514. IfJsrtErrorHR(ChakraRTInterface::JsGetValueType(m_function, &type));
  515. if (type == JsString)
  516. {
  517. LPCWSTR script = nullptr;
  518. size_t length = 0;
  519. IfJsrtErrorHR(ChakraRTInterface::JsConvertValueToString(m_function, &stringValue));
  520. IfJsrtErrorHR(ChakraRTInterface::JsStringToPointer(stringValue, &script, &length));
  521. // Run the code
  522. errorCode = ChakraRTInterface::JsRunScript(script, JS_SOURCE_CONTEXT_NONE, L"" /*sourceUrl*/, nullptr /*no result needed*/);
  523. }
  524. else
  525. {
  526. errorCode = ChakraRTInterface::JsCallFunction(m_function, &global, 1, &result);
  527. }
  528. if (errorCode != JsNoError)
  529. {
  530. hr = E_FAIL;
  531. PrintException(fileName, errorCode);
  532. }
  533. Error:
  534. return hr;
  535. }