| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "stdafx.h"
- #include "PlatformAgnostic/ChakraICU.h"
- #include <vector>
- #if defined(_X86_) || defined(_M_IX86)
- #define CPU_ARCH_TEXT "x86"
- #elif defined(_AMD64_) || defined(_IA64_) || defined(_M_AMD64) || defined(_M_IA64)
- #define CPU_ARCH_TEXT "x86_64"
- #elif defined(_ARM_) || defined(_M_ARM)
- #define CPU_ARCH_TEXT "ARM"
- #elif defined(_ARM64_) || defined(_M_ARM64)
- #define CPU_ARCH_TEXT "ARM64"
- #endif
- // do not change the order below
- // otherwise, i.e. android system can be marked as posix? etc..
- #ifdef _WIN32
- #define DEST_PLATFORM_TEXT "win32"
- #else // ! _WIN32
- #if defined(__APPLE__)
- #ifdef __IOS__
- #define DEST_PLATFORM_TEXT "ios"
- #else // ! iOS
- #define DEST_PLATFORM_TEXT "darwin"
- #endif // iOS ?
- #elif defined(__ANDROID__)
- #define DEST_PLATFORM_TEXT "android"
- #elif defined(__linux__)
- #define DEST_PLATFORM_TEXT "posix"
- #elif defined(__FreeBSD__) || defined(__unix__)
- #define DEST_PLATFORM_TEXT "bsd"
- #endif // FreeBSD or unix ?
- #endif // _WIN32 ?
- #pragma prefast(disable:26444, "This warning unfortunately raises false positives when auto is used for declaring the type of an iterator in a loop.")
- #ifdef HAS_ICU
- #define INTL_LIBRARY_TEXT "icu"
- #elif defined(_WIN32)
- #define INTL_LIBRARY_TEXT "winglob"
- #else
- #define INTL_LIBRARY_TEXT ""
- #endif
- struct ArrayBufferTransferInfo {
- byte* buffer;
- uint length;
- ArrayBufferFreeFn freeFn;
- };
- struct SerializerBlob
- {
- void *data;
- size_t dataLength;
- std::vector<ArrayBufferTransferInfo> transferableArrays;
- };
- MessageQueue* WScriptJsrt::messageQueue = nullptr;
- std::map<std::string, JsModuleRecord> WScriptJsrt::moduleRecordMap;
- std::map<JsModuleRecord, std::string> WScriptJsrt::moduleDirMap;
- std::map<JsModuleRecord, ModuleState> WScriptJsrt::moduleErrMap;
- std::map<DWORD_PTR, std::string> WScriptJsrt::scriptDirMap;
- DWORD_PTR WScriptJsrt::sourceContext = 0;
- #define ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString) \
- JsErrorCode errorCode = JsNoError; \
- do \
- { \
- const char *outOfMemoryString = \
- "Failed to convert wide string. Out of memory?";\
- \
- char *errorMessageNarrow; \
- if (FAILED(WideStringToNarrowDynamic(errorMessage, &errorMessageNarrow))) \
- { \
- errorCode = ChakraRTInterface::JsCreateString(outOfMemoryString, \
- strlen(outOfMemoryString), &errorMessageString); \
- } \
- else \
- { \
- errorCode = ChakraRTInterface::JsCreateString(errorMessageNarrow, \
- strlen(errorMessageNarrow), &errorMessageString); \
- free(errorMessageNarrow); \
- } \
- } \
- while(0)
- DWORD_PTR WScriptJsrt::GetNextSourceContext()
- {
- return sourceContext++;
- }
- void WScriptJsrt::RegisterScriptDir(DWORD_PTR sourceContext, LPCSTR fullDirNarrow)
- {
- GetDir(fullDirNarrow, &scriptDirMap[sourceContext]);
- }
- bool WScriptJsrt::CreateArgumentsObject(JsValueRef *argsObject)
- {
- LPWSTR *argv = HostConfigFlags::argsVal;
- JsValueRef retArr;
- Assert(argsObject);
- *argsObject = nullptr;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateArray(HostConfigFlags::argsCount, &retArr), false);
- for (int i = 0; i < HostConfigFlags::argsCount; i++)
- {
- JsValueRef value;
- JsValueRef index;
- char *argNarrow;
- if (FAILED(WideStringToNarrowDynamic(argv[i], &argNarrow)))
- {
- return false;
- }
- JsErrorCode errCode = ChakraRTInterface::JsCreateString(
- argNarrow,
- strlen(argNarrow), &value);
- free(argNarrow);
- IfJsrtErrorFail(errCode, false);
- IfJsrtErrorFail(ChakraRTInterface::JsDoubleToNumber(i, &index), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetIndexedProperty(retArr, index, value), false);
- }
- *argsObject = retArr;
- return true;
- }
- JsValueRef __stdcall WScriptJsrt::EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- for (unsigned int i = 1; i < argumentCount; i++)
- {
- JsValueRef strValue;
- JsErrorCode error = ChakraRTInterface::JsConvertValueToString(arguments[i], &strValue);
- if (error == JsNoError)
- {
- AutoString str(strValue);
- if (str.GetError() == JsNoError)
- {
- if (i > 1)
- {
- wprintf(_u(" "));
- }
- charcount_t len;
- LPWSTR ws = str.GetWideString(&len);
- LPWSTR wsNoNull = new WCHAR[((size_t)len) + 1];
- charcount_t newIndex = 0;
- for (charcount_t j = 0; j < len; j++)
- {
- if (ws[j] != _u('\0'))
- {
- wsNoNull[newIndex++] = ws[j];
- }
- }
- wsNoNull[newIndex] = _u('\0');
- wprintf(_u("%s"), wsNoNull);
- delete[] wsNoNull;
- }
- }
- if (error == JsErrorScriptException)
- {
- return nullptr;
- }
- }
- wprintf(_u("\n"));
- fflush(stdout);
- JsValueRef undefinedValue;
- if (ChakraRTInterface::JsGetUndefinedValue(&undefinedValue) == JsNoError)
- {
- return undefinedValue;
- }
- else
- {
- return nullptr;
- }
- }
- JsValueRef __stdcall WScriptJsrt::QuitCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- int exitCode = 0;
- if (argumentCount > 1)
- {
- double exitCodeDouble;
- IfJsrtErrorFail(ChakraRTInterface::JsNumberToDouble(arguments[1], &exitCodeDouble), JS_INVALID_REFERENCE);
- exitCode = (int)exitCodeDouble;
- }
- ExitProcess(exitCode);
- }
- JsValueRef __stdcall WScriptJsrt::LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- return LoadScriptFileHelper(callee, arguments, argumentCount, false);
- }
- // needed because of calling convention differences between _stdcall and _cdecl
- void CHAKRA_CALLBACK WScriptJsrt::FinalizeFree(void* addr)
- {
- free(addr);
- }
- JsValueRef WScriptJsrt::LoadScriptFileHelper(JsValueRef callee, JsValueRef *arguments, unsigned short argumentCount, bool isSourceModule)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- LPCWSTR errorMessage = _u("");
- if (argumentCount < 2 || argumentCount > 4)
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Need more or fewer arguments for WScript.LoadScript");
- }
- else
- {
- LPCSTR fileContent;
- AutoString fileName(arguments[1]);
- IfJsrtErrorSetGo(fileName.GetError());
- AutoString scriptInjectType;
- if (argumentCount > 2)
- {
- IfJsrtErrorSetGo(scriptInjectType.Initialize(arguments[2]));
- }
- if (errorCode == JsNoError)
- {
- hr = Helpers::LoadScriptFromFile(*fileName, fileContent);
- if (FAILED(hr))
- {
- fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- return returnValue;
- }
- returnValue = LoadScript(callee, *fileName, fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree, true);
- }
- }
- Error:
- SetExceptionIf(errorCode, errorMessage);
- return returnValue;
- }
- void WScriptJsrt::SetExceptionIf(JsErrorCode errorCode, LPCWSTR errorMessage)
- {
- if (errorCode != JsNoError)
- {
- // If the exception is already is set - no need to create a new exception.
- bool hasException = false;
- if (!(ChakraRTInterface::JsHasException(&hasException) == JsNoError && hasException))
- {
- JsValueRef errorObject;
- JsValueRef errorMessageString;
- if (wcscmp(errorMessage, _u("")) == 0)
- {
- errorMessage = ConvertErrorCodeToMessage(errorCode);
- }
- ERROR_MESSAGE_TO_STRING(errCode, errorMessage, errorMessageString);
- ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
- ChakraRTInterface::JsSetException(errorObject);
- }
- }
- }
- byte * CHAKRA_CALLBACK ReallocateBufferMemory(void * state, byte *oldBuffer, size_t newSize, size_t *allocatedSize)
- {
- void* data = realloc((void*)oldBuffer, newSize);
- if (allocatedSize)
- {
- *allocatedSize = newSize;
- }
- return (byte*)data;
- }
- bool CHAKRA_CALLBACK WriteHostObject(void * state, JsValueRef data)
- {
- // Not implemented
- return true;
- }
- JsValueRef __stdcall WScriptJsrt::SerializeObject(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- JsErrorCode errorCode = JsNoError;
- LPCWSTR errorMessage = _u("");
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- HRESULT hr = S_OK;
- JsValueRef *transferVarsArray = nullptr;
- int transferVarsCount = 0;
- if (argumentCount < 2)
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Need an argument for WScript.Serialize");
- }
- else
- {
- JsValueRef rootObject = arguments[1];
- JsValueRef transferArray = nullptr;
- if (argumentCount > 2)
- {
- JsValueType argumentType = JsUndefined;
- transferArray = arguments[2];
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(transferArray, &argumentType));
- if (argumentType != JsUndefined)
- {
- if (argumentType != JsArray)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- JsPropertyIdRef lengthPropId;
- JsValueRef arrayLengthObj = JS_INVALID_REFERENCE;
- int arrayLength = 0;
- IfJsrtErrorSetGo(CreatePropertyIdFromString("length", &lengthPropId));
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetProperty(transferArray, lengthPropId, &arrayLengthObj));
- IfJsrtErrorSetGo(ChakraRTInterface::JsNumberToInt(arrayLengthObj, &arrayLength));
- if (arrayLength > 0)
- {
- transferVarsArray = new JsValueRef[arrayLength];
- if (transferVarsArray == nullptr)
- {
- errorCode = JsErrorOutOfMemory;
- goto Error;
- }
- for (int i = 0; i < arrayLength; i++)
- {
- JsValueRef index;
- JsValueRef value = JS_INVALID_REFERENCE;
- JsValueType jsType = JsUndefined;
- IfJsrtErrorSetGo(ChakraRTInterface::JsIntToNumber(i, &index));
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetIndexedProperty(transferArray, index, &value));
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(value, &jsType));
- if (jsType == JsArrayBuffer)
- {
- *(transferVarsArray + transferVarsCount) = value;
- transferVarsCount++;
- }
- }
- }
- }
- }
- JsVarSerializerHandle serializerHandle = nullptr;
- // This memory will be claimed at WScriptJsrt::Deserialize.
- SerializerBlob *blob = new SerializerBlob();
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializer(ReallocateBufferMemory, WriteHostObject, nullptr, &serializerHandle));
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerSetTransferableVars(serializerHandle, transferVarsArray, transferVarsCount));
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerWriteValue(serializerHandle, rootObject));
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerReleaseData(serializerHandle, (byte**)&blob->data, &blob->dataLength));
- for (int i = 0; i < transferVarsCount; i++)
- {
- JsValueRef arrayBuffer = transferVarsArray[i];
- ArrayBufferTransferInfo bufferInfo;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetArrayBufferStorage(arrayBuffer, &bufferInfo.buffer, &bufferInfo.length));
- IfJsrtErrorSetGo(ChakraRTInterface::JsExternalizeArrayBuffer(arrayBuffer));
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetArrayBufferFreeFunction(arrayBuffer, &bufferInfo.freeFn));
- blob->transferableArrays.push_back(bufferInfo);
- IfJsrtErrorSetGo(ChakraRTInterface::JsDetachArrayBuffer(arrayBuffer));
- }
- errorCode = ChakraRTInterface::JsCreateExternalArrayBuffer((void*)blob, sizeof(SerializerBlob), nullptr, nullptr, &returnValue);
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarSerializerFree(serializerHandle));
- }
- Error:
- SetExceptionIf(errorCode, errorMessage);
- if (transferVarsArray)
- {
- delete[] transferVarsArray;
- }
- return returnValue;
- }
- JsValueRef CHAKRA_CALLBACK ReadHostObject(void * state)
- {
- Assert(false); // TBD
- return nullptr;
- }
- JsValueRef CHAKRA_CALLBACK GetSharedArrayBufferFromId(void * state, uint32_t id)
- {
- Assert(false); // TBD
- return nullptr;
- }
- JsValueRef CHAKRA_CALLBACK GetWasmModuleFromId(void * state, uint32_t transfer_id)
- {
- Assert(false); // TBD
- return nullptr;
- }
- struct BufferFreeFunctionState {
- ArrayBufferFreeFn freeFn;
- void* buffer;
- };
- void CHAKRA_CALLBACK BufferFreeFunction(void * state)
- {
- BufferFreeFunctionState* bufferState = (BufferFreeFunctionState*)state;
- if (!bufferState)
- {
- return;
- }
- if (bufferState->freeFn)
- {
- bufferState->freeFn(bufferState->buffer);
- }
- delete bufferState;
- }
- JsValueRef __stdcall WScriptJsrt::Deserialize(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- JsErrorCode errorCode = JsNoError;
- LPCWSTR errorMessage = _u("");
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsValueRef * transferables = nullptr;
- HRESULT hr = S_OK;
- if (argumentCount < 2)
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Need an argument for WScript.Deserialize");
- }
- else
- {
- JsValueRef dataObject = arguments[1];
- uint32 dataLength = 0;
- BYTE *data = nullptr;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetArrayBufferStorage(dataObject, &data, &dataLength));
- SerializerBlob *blob = (SerializerBlob*)data;
- JsVarDeserializerHandle deserializerHandle = nullptr;
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializer(blob->data, blob->dataLength, ReadHostObject, GetSharedArrayBufferFromId, nullptr, &deserializerHandle));
- size_t arraySize = blob->transferableArrays.size();
- if (arraySize > 0)
- {
- transferables = new JsValueRef[arraySize];
- for (size_t i = 0; i < arraySize; ++i)
- {
- JsValueRef result = nullptr;
- BufferFreeFunctionState* bufferFreeState = new BufferFreeFunctionState();
- bufferFreeState->buffer = blob->transferableArrays[i].buffer;
- bufferFreeState->freeFn = blob->transferableArrays[i].freeFn;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer(blob->transferableArrays[i].buffer, blob->transferableArrays[i].length, BufferFreeFunction, bufferFreeState, &result));
- transferables[i] = result;
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializerSetTransferableVars(deserializerHandle, transferables, arraySize));
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializerReadValue(deserializerHandle, &returnValue));
- IfJsrtErrorSetGo(ChakraRTInterface::JsVarDeserializerFree(deserializerHandle));
- delete blob;
- }
- Error:
- SetExceptionIf(errorCode, errorMessage);
- if (transferables)
- {
- delete[] transferables;
- }
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::GetModuleNamespace(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- JsErrorCode errorCode = JsNoError;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- LPCWSTR errorMessage = _u("");
- char fullPath[_MAX_PATH];
- if (argumentCount < 2)
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Need an argument for WScript.GetModuleNamespace");
- }
- else
- {
- AutoString specifierStr(arguments[1]);
- errorCode = specifierStr.GetError();
- if (errorCode == JsNoError)
- {
- if (_fullpath(fullPath, specifierStr.GetString(), _MAX_PATH) == nullptr)
- {
- errorCode = JsErrorInvalidArgument;
- }
- else
- {
- auto moduleEntry = moduleRecordMap.find(fullPath);
- if (moduleEntry == moduleRecordMap.end())
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Need to supply a path for an already loaded module for WScript.GetModuleNamespace");
- }
- else
- {
- errorCode = ChakraRTInterface::JsGetModuleNamespace(moduleEntry->second, &returnValue);
- if (errorCode == JsErrorModuleNotEvaluated)
- {
- errorMessage = _u("GetModuleNamespace called with un-evaluated module");
- }
- }
- }
- }
- }
- SetExceptionIf(errorCode, errorMessage);
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, false);
- }
- JsValueRef __stdcall WScriptJsrt::LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- return LoadScriptHelper(callee, isConstructCall, arguments, argumentCount, callbackState, true);
- }
- JsValueRef WScriptJsrt::LoadScriptHelper(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState, bool isSourceModule)
- {
- HRESULT hr = E_FAIL;
- JsErrorCode errorCode = JsNoError;
- LPCWSTR errorMessage = _u("");
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- if (argumentCount < 2 || argumentCount > 4)
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Need more or fewer arguments for WScript.LoadScript");
- }
- else
- {
- AutoString fileContent;
- char *fileNameNarrow = nullptr;
- AutoString fileName;
- AutoString scriptInjectType;
- char fileNameBuffer[MAX_PATH];
- bool isFile = true;
- IfJsrtErrorSetGo(fileContent.Initialize(arguments[1]));
- // ExternalArrayBuffer Finalize will clean this up
- // but only if we actually register a finalizecallback for this
- fileContent.MakePersistent();
- if (argumentCount > 2)
- {
- IfJsrtErrorSetGo(scriptInjectType.Initialize(arguments[2]));
- if (argumentCount > 3)
- {
- IfJsrtErrorSetGo(fileName.Initialize(arguments[3]));
- fileNameNarrow = *fileName;
- }
- }
- if (!fileNameNarrow)
- {
- isFile = false;
- if (isSourceModule)
- {
- sprintf_s(fileNameBuffer, MAX_PATH, "moduleScript%i.js", (int)sourceContext);
- fileNameNarrow = fileNameBuffer;
- }
- }
- if (*fileContent)
- {
- // TODO: This is CESU-8. How to tell the engine?
- // TODO: How to handle this source (script) life time?
- returnValue = LoadScript(callee, fileNameNarrow, *fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule, WScriptJsrt::FinalizeFree, isFile);
- }
- }
- Error:
- SetExceptionIf(errorCode, errorMessage);
- return returnValue;
- }
- JsErrorCode WScriptJsrt::InitializeModuleInfo(JsValueRef specifier, JsModuleRecord moduleRecord)
- {
- JsErrorCode errorCode = JsNoError;
- errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_FetchImportedModuleCallback, (void*)WScriptJsrt::FetchImportedModule);
- if (errorCode == JsNoError)
- {
- errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_FetchImportedModuleFromScriptCallback, (void*)WScriptJsrt::FetchImportedModuleFromScript);
- if (errorCode == JsNoError)
- {
- errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_NotifyModuleReadyCallback, (void*)WScriptJsrt::NotifyModuleReadyCallback);
- if (errorCode == JsNoError)
- {
- errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_InitializeImportMetaCallback, (void*)WScriptJsrt::InitializeImportMetaCallback);
- if (errorCode == JsNoError && moduleRecord != nullptr)
- {
- errorCode = ChakraRTInterface::JsSetModuleHostInfo(moduleRecord, JsModuleHostInfo_HostDefined, specifier);
- }
- }
- }
- }
- IfJsrtErrorFailLogAndRetErrorCode(errorCode);
- return JsNoError;
- }
- void WScriptJsrt::GetDir(LPCSTR fullPathNarrow, std::string *fullDirNarrow)
- {
- char fileDrive[_MAX_DRIVE];
- char fileDir[_MAX_DIR];
- std::string result;
- if (_splitpath_s(fullPathNarrow, fileDrive, _countof(fileDrive), fileDir, _countof(fileDir), nullptr, 0, nullptr, 0) == 0)
- {
- result += fileDrive;
- result += fileDir;
- }
- *fullDirNarrow = result;
- }
- JsErrorCode WScriptJsrt::ModuleEntryPoint(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName)
- {
- return LoadModuleFromString(fileName, fileContent, fullName, true);
- }
- JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileContent, LPCSTR fullName, bool isFile)
- {
- DWORD_PTR dwSourceCookie = WScriptJsrt::GetNextSourceContext();
- JsModuleRecord requestModule = JS_INVALID_REFERENCE;
- LPCSTR moduleRecordKey = fullName ? fullName : fileName;
- auto moduleRecordEntry = moduleRecordMap.find(std::string(moduleRecordKey));
- JsErrorCode errorCode = JsNoError;
- // we need to create a new moduleRecord if the specifier (fileName) is not found;
- // otherwise we'll use the old one.
- if (moduleRecordEntry == moduleRecordMap.end())
- {
- JsValueRef specifier;
- errorCode = ChakraRTInterface::JsCreateString(
- fileName, strlen(fileName), &specifier);
- if (errorCode == JsNoError)
- {
- errorCode = ChakraRTInterface::JsInitializeModuleRecord(
- nullptr, specifier, &requestModule);
- }
- if (errorCode == JsNoError)
- {
- errorCode = InitializeModuleInfo(specifier, requestModule);
- }
- if (errorCode == JsNoError)
- {
- if (fullName)
- {
- GetDir(fullName, &moduleDirMap[requestModule]);
- }
- moduleRecordMap[std::string(moduleRecordKey)] = requestModule;
- moduleErrMap[requestModule] = RootModule;
- }
- }
- else
- {
- requestModule = moduleRecordEntry->second;
- }
- IfJsrtErrorFailLogAndRetErrorCode(errorCode);
- JsValueRef errorObject = JS_INVALID_REFERENCE;
- // ParseModuleSource is sync, while additional fetch & evaluation are async.
- unsigned int fileContentLength = (fileContent == nullptr) ? 0 : (unsigned int)strlen(fileContent);
-
- if (isFile && fullName)
- {
- JsValueRef moduleUrl;
- ChakraRTInterface::JsCreateString(fullName, strlen(fullName), &moduleUrl);
- errorCode = ChakraRTInterface::JsSetModuleHostInfo(requestModule, JsModuleHostInfo_Url, moduleUrl);
- IfJsrtErrorFail(errorCode, errorCode);
- }
-
- errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
- fileContentLength, JsParseModuleSourceFlags_DataIsUTF8, &errorObject);
- if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE && fileContent != nullptr && !HostConfigFlags::flags.IgnoreScriptErrorCode && moduleErrMap[requestModule] == RootModule)
- {
- ChakraRTInterface::JsSetException(errorObject);
- moduleErrMap[requestModule] = ErroredModule;
- return errorCode;
- }
- return JsNoError;
- }
- JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName,
- LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule, JsFinalizeCallback finalizeCallback, bool isFile)
- {
- HRESULT hr = E_FAIL;
- JsErrorCode errorCode = JsNoError;
- LPCWSTR errorMessage = _u("Internal error.");
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsContextRef currentContext = JS_INVALID_REFERENCE;
- JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
- void *callbackArg = (finalizeCallback != nullptr ? (void*)fileContent : nullptr);
- char fullPath[_MAX_PATH];
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetCurrentContext(¤tContext));
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime));
- if (fileName == nullptr)
- {
- fileName = "script.js";
- }
- if (_fullpath(fullPath, fileName, _MAX_PATH) == nullptr)
- {
- goto Error;
- }
- // this is called with LoadModuleCallback method as well where caller pass in a string that should be
- // treated as a module source text instead of opening a new file.
- if (isSourceModule || (strcmp(scriptInjectType, "module") == 0))
- {
- errorCode = LoadModuleFromString(fileName, fileContent, fullPath, isFile);
- }
- else if (strcmp(scriptInjectType, "self") == 0)
- {
- JsContextRef calleeContext;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(calleeContext));
- JsValueRef scriptSource;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContent,
- (unsigned int)strlen(fileContent), finalizeCallback, callbackArg, &scriptSource));
- JsValueRef fname;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(fullPath,
- strlen(fullPath), &fname));
- JsSourceContext sourceContext = GetNextSourceContext();
- RegisterScriptDir(sourceContext, fullPath);
- if (HostConfigFlags::flags.UseParserStateCacheIsEnabled)
- {
- JsValueRef parserState;
- IfJsrtErrorSetGo(ChakraRTInterface::JsSerializeParserState(scriptSource, &parserState, JsParseScriptAttributeNone));
- errorCode = ChakraRTInterface::JsRunScriptWithParserState(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, parserState, &returnValue);
- }
- else
- {
- errorCode = ChakraRTInterface::JsRun(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, &returnValue);
- }
- if(errorCode == JsNoError)
- {
- errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(currentContext));
- }
- else if (strcmp(scriptInjectType, "samethread") == 0)
- {
- JsValueRef newContext = JS_INVALID_REFERENCE;
- // Create a new context and set it as the current context
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateContext(runtime, &newContext));
- #if ENABLE_TTD
- //We need this here since this context is created in record
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetObjectBeforeCollectCallback(newContext, nullptr, WScriptJsrt::JsContextBeforeCollectCallback));
- #endif
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(newContext));
- IfJsErrorFailLog(ChakraRTInterface::JsSetPromiseContinuationCallback(PromiseContinuationCallback, (void*)messageQueue));
- // Initialize the host objects
- Initialize();
- JsValueRef scriptSource;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateExternalArrayBuffer((void*)fileContent,
- (unsigned int)strlen(fileContent), finalizeCallback, callbackArg, &scriptSource));
- JsValueRef fname;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(fullPath,
- strlen(fullPath), &fname));
- JsSourceContext sourceContext = GetNextSourceContext();
- RegisterScriptDir(sourceContext, fullPath);
- if (HostConfigFlags::flags.UseParserStateCacheIsEnabled)
- {
- JsValueRef parserState;
- IfJsrtErrorSetGo(ChakraRTInterface::JsSerializeParserState(scriptSource, &parserState, JsParseScriptAttributeNone));
- errorCode = ChakraRTInterface::JsRunScriptWithParserState(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, parserState, &returnValue);
- }
- else
- {
- errorCode = ChakraRTInterface::JsRun(scriptSource, sourceContext, fname, JsParseScriptAttributeNone, &returnValue);
- }
- if (errorCode == JsNoError)
- {
- errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
- }
- // Set the context back to the old one
- ChakraRTInterface::JsSetCurrentContext(currentContext);
- }
- else if (strcmp(scriptInjectType, "crossthread") == 0)
- {
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData == nullptr)
- {
- threadData = new RuntimeThreadData();
- }
- RuntimeThreadData* child = new RuntimeThreadData();
- child->initialSource = fileContent;
- threadData->children.push_back(child);
- child->parent = threadData;
- // TODO: need to add a switch in case we don't need to wait for
- // child initial script completion
- ResetEvent(threadData->hevntInitialScriptCompleted);
- child->hThread = ::CreateThread(NULL, NULL, [](void* param) -> DWORD
- {
- return ((RuntimeThreadData*)param)->ThreadProc();
- }, (void*)child, NULL, NULL);
- WaitForSingleObject(threadData->hevntInitialScriptCompleted, INFINITE);
- }
- else
- {
- errorCode = JsErrorInvalidArgument;
- errorMessage = _u("Unsupported argument type inject type.");
- }
- Error:
- JsValueRef value = returnValue;
- if (errorCode != JsNoError)
- {
- SetExceptionIf(errorCode, errorMessage);
- ChakraRTInterface::JsDoubleToNumber(errorCode, &value);
- }
- _flushall();
- return value;
- }
- JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- LPCWSTR errorMessage = _u("invalid call to WScript.SetTimeout");
- JsErrorCode errorCode = JsNoError;
- HRESULT hr = S_OK;
- JsValueRef function;
- JsValueRef timerId;
- unsigned int time;
- double tmp;
- CallbackMessage *msg = nullptr;
- if (argumentCount != 3)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- function = arguments[1];
- IfJsrtErrorSetGo(ChakraRTInterface::JsNumberToDouble(arguments[2], &tmp));
- time = static_cast<int>(tmp);
- msg = new CallbackMessage(time, function);
- messageQueue->InsertSorted(msg);
- IfJsrtErrorSetGo(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(msg->GetId()), &timerId));
- return timerId;
- Error:
- SetExceptionIf(errorCode, errorMessage);
- return JS_INVALID_REFERENCE;
- }
- JsValueRef WScriptJsrt::ClearTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- LPCWSTR errorMessage = _u("invalid call to WScript.ClearTimeout");
- JsErrorCode errorCode = JsNoError;
- HRESULT hr = S_OK;
- if (argumentCount != 2)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- unsigned int timerId;
- double tmp;
- JsValueRef undef;
- if (ChakraRTInterface::JsNumberToDouble(arguments[1], &tmp) == JsNoError)
- {
- timerId = static_cast<int>(tmp);
- messageQueue->RemoveById(timerId);
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&undef));
- return undef;
- Error:
- SetExceptionIf(errorCode, errorMessage);
- return JS_INVALID_REFERENCE;
- }
- template <class DebugOperationFunc>
- void QueueDebugOperation(JsValueRef function, const DebugOperationFunc& operation)
- {
- WScriptJsrt::PushMessage(WScriptJsrt::CallbackMessage::Create(function, operation));
- }
- JsValueRef WScriptJsrt::AttachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- LPCWSTR errorMessage = _u("WScript.Attach requires a function, like WScript.Attach(foo);");
- JsErrorCode errorCode = JsNoError;
- HRESULT hr = S_OK;
- JsValueType argumentType = JsUndefined;
- if (argumentCount != 2)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType));
- if (argumentType != JsFunction)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- QueueDebugOperation(arguments[1], [](WScriptJsrt::CallbackMessage& msg)
- {
- JsContextRef currentContext = JS_INVALID_REFERENCE;
- ChakraRTInterface::JsGetCurrentContext(¤tContext);
- JsRuntimeHandle currentRuntime = JS_INVALID_RUNTIME_HANDLE;
- ChakraRTInterface::JsGetRuntime(currentContext, ¤tRuntime);
- Debugger* debugger = Debugger::GetDebugger(currentRuntime);
- debugger->StartDebugging(currentRuntime);
- debugger->SourceRunDown();
- return msg.CallFunction("");
- });
- Error:
- SetExceptionIf(errorCode, errorMessage);
- return JS_INVALID_REFERENCE;
- }
- JsValueRef WScriptJsrt::DetachCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- LPCWSTR errorMessage = _u("WScript.Detach requires a function, like WScript.Detach(foo);");
- JsErrorCode errorCode = JsNoError;
- HRESULT hr = S_OK;
- JsValueType argumentType = JsUndefined;
- if (argumentCount != 2)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType));
- if (argumentType != JsFunction)
- {
- errorCode = JsErrorInvalidArgument;
- goto Error;
- }
- QueueDebugOperation(arguments[1], [](WScriptJsrt::CallbackMessage& msg)
- {
- JsContextRef currentContext = JS_INVALID_REFERENCE;
- ChakraRTInterface::JsGetCurrentContext(¤tContext);
- JsRuntimeHandle currentRuntime = JS_INVALID_RUNTIME_HANDLE;
- ChakraRTInterface::JsGetRuntime(currentContext, ¤tRuntime);
- if (Debugger::debugger != nullptr)
- {
- Debugger* debugger = Debugger::GetDebugger(currentRuntime);
- debugger->StopDebugging(currentRuntime);
- }
- return msg.CallFunction("");
- });
- Error:
- SetExceptionIf(errorCode, errorMessage);
- return JS_INVALID_REFERENCE;
- }
- JsValueRef WScriptJsrt::DumpFunctionPositionCallback(JsValueRef callee, bool isConstructCall, JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
- {
- JsValueRef functionPosition = JS_INVALID_REFERENCE;
- if (argumentCount > 1)
- {
- if (ChakraRTInterface::JsDiagGetFunctionPosition(arguments[1], &functionPosition) != JsNoError)
- {
- // If we can't get the functionPosition pass undefined
- IfJsErrorFailLogAndRet(ChakraRTInterface::JsGetUndefinedValue(&functionPosition));
- }
- if (Debugger::debugger != nullptr)
- {
- Debugger::debugger->DumpFunctionPosition(functionPosition);
- }
- }
- return JS_INVALID_REFERENCE;
- }
- JsValueRef WScriptJsrt::RequestAsyncBreakCallback(JsValueRef callee, bool isConstructCall,
- JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
- {
- if (Debugger::debugger != nullptr && !Debugger::debugger->IsDetached())
- {
- IfJsErrorFailLogAndRet(ChakraRTInterface::JsDiagRequestAsyncBreak(Debugger::GetRuntime()));
- }
- else
- {
- Helpers::LogError(_u("RequestAsyncBreak can only be called when debugger is attached"));
- }
- return JS_INVALID_REFERENCE;
- }
- JsValueRef WScriptJsrt::EmptyCallback(JsValueRef callee, bool isConstructCall,
- JsValueRef * arguments, unsigned short argumentCount, void * callbackState)
- {
- return JS_INVALID_REFERENCE;
- }
- bool WScriptJsrt::CreateNamedFunction(const char* nameString, JsNativeFunction callback,
- JsValueRef* functionVar)
- {
- JsValueRef nameVar;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
- nameString, strlen(nameString), &nameVar), false);
- IfJsrtErrorFail(ChakraRTInterface::JsCreateNamedFunction(nameVar, callback,
- nullptr, functionVar), false);
- return true;
- }
- bool WScriptJsrt::InstallObjectsOnObject(JsValueRef object, const char* name,
- JsNativeFunction nativeFunction)
- {
- JsValueRef propertyValueRef;
- JsPropertyIdRef propertyId;
- IfJsrtErrorFail(CreatePropertyIdFromString(name, &propertyId), false);
- if (!CreateNamedFunction(name, nativeFunction, &propertyValueRef))
- {
- return false;
- }
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(object, propertyId,
- propertyValueRef, true), false);
- return true;
- }
- bool WScriptJsrt::Initialize()
- {
- HRESULT hr = S_OK;
- char CH_BINARY_LOCATION[2048];
- #ifdef CHAKRA_STATIC_LIBRARY
- const char* LINK_TYPE = "static";
- #else
- const char* LINK_TYPE = "shared";
- #endif
- #ifdef HAS_ICU
- int icuVersion = PlatformAgnostic::ICUHelpers::GetICUMajorVersion();
- #else
- int icuVersion = -1;
- #endif
- JsValueRef wscript;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&wscript), false);
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Echo", EchoCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Quit", QuitCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScriptFile", LoadScriptFileCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScript", LoadScriptCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadModule", LoadModuleCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SetTimeout", SetTimeoutCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ClearTimeout", ClearTimeoutCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Attach", AttachCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Detach", DetachCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "DumpFunctionPosition", DumpFunctionPositionCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "RequestAsyncBreak", RequestAsyncBreakCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadBinaryFile", LoadBinaryFileCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadTextFile", LoadTextFileCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Flag", FlagCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "RegisterModuleSource", RegisterModuleSourceCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetModuleNamespace", GetModuleNamespace));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetProxyProperties", GetProxyPropertiesCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "SerializeObject", SerializeObject));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Deserialize", Deserialize));
- // ToDo Remove
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Edit", EmptyCallback));
- // Platform
- JsValueRef platformObject;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&platformObject), false);
- JsPropertyIdRef platformProperty;
- IfJsrtErrorFail(CreatePropertyIdFromString("Platform", &platformProperty), false);
- // Set CPU arch
- JsPropertyIdRef archProperty;
- IfJsrtErrorFail(CreatePropertyIdFromString("ARCH", &archProperty), false);
- JsValueRef archValue;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
- CPU_ARCH_TEXT, strlen(CPU_ARCH_TEXT), &archValue), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, archProperty,
- archValue, true), false);
- // Set Build Type
- JsPropertyIdRef buildProperty;
- IfJsrtErrorFail(CreatePropertyIdFromString("BUILD_TYPE", &buildProperty), false);
- JsValueRef buildValue;
- #ifdef _DEBUG
- #define BUILD_TYPE_STRING_CH "Debug" // (O0)
- #elif defined(ENABLE_DEBUG_CONFIG_OPTIONS)
- #define BUILD_TYPE_STRING_CH "Test" // (O3 with debug config options)
- #else
- #define BUILD_TYPE_STRING_CH "Release" // (O3)
- #endif
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
- BUILD_TYPE_STRING_CH, strlen(BUILD_TYPE_STRING_CH), &buildValue), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, buildProperty,
- buildValue, true), false);
- #undef BUILD_TYPE_STRING_CH
- // Set Link Type [static / shared]
- JsPropertyIdRef linkProperty;
- IfJsrtErrorFail(CreatePropertyIdFromString("LINK_TYPE", &linkProperty), false);
- JsValueRef linkValue;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
- LINK_TYPE, strlen(LINK_TYPE), &linkValue), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, linkProperty,
- linkValue, true), false);
- // Set Binary Location
- JsValueRef binaryPathValue;
- PlatformAgnostic::SystemInfo::GetBinaryLocation(CH_BINARY_LOCATION, sizeof(CH_BINARY_LOCATION));
- JsPropertyIdRef binaryPathProperty;
- IfJsrtErrorFail(CreatePropertyIdFromString("BINARY_PATH", &binaryPathProperty), false);
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
- CH_BINARY_LOCATION,
- strlen(CH_BINARY_LOCATION), &binaryPathValue), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(
- platformObject, binaryPathProperty, binaryPathValue, true), false);
- // Set destination OS
- JsPropertyIdRef osProperty;
- IfJsrtErrorFail(CreatePropertyIdFromString("OS", &osProperty), false);
- JsValueRef osValue;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(
- DEST_PLATFORM_TEXT, strlen(DEST_PLATFORM_TEXT), &osValue), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, osProperty,
- osValue, true), false);
- // set Internationalization library
- JsPropertyIdRef intlLibraryProp;
- IfJsrtErrorFail(CreatePropertyIdFromString("INTL_LIBRARY", &intlLibraryProp), false);
- JsValueRef intlLibraryStr;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateString(INTL_LIBRARY_TEXT, strlen(INTL_LIBRARY_TEXT), &intlLibraryStr), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, intlLibraryProp, intlLibraryStr, true), false);
- JsPropertyIdRef icuVersionProp;
- IfJsrtErrorFail(CreatePropertyIdFromString("ICU_VERSION", &icuVersionProp), false);
- JsValueRef icuVersionNum;
- IfJsrtErrorFail(ChakraRTInterface::JsIntToNumber(icuVersion, &icuVersionNum), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(platformObject, icuVersionProp, icuVersionNum, true), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, platformProperty,
- platformObject, true), false);
- JsValueRef argsObject;
- if (!CreateArgumentsObject(&argsObject))
- {
- return false;
- }
- JsPropertyIdRef argsName;
- IfJsrtErrorFail(CreatePropertyIdFromString("Arguments", &argsName), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(wscript, argsName, argsObject, true), false);
- JsPropertyIdRef wscriptName;
- IfJsrtErrorFail(CreatePropertyIdFromString("WScript", &wscriptName), false);
- JsValueRef global;
- IfJsrtErrorFail(ChakraRTInterface::JsGetGlobalObject(&global), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, wscriptName, wscript, true), false);
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "print", EchoCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "read", LoadTextFileCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "readbuffer", LoadBinaryFileCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(global, "readline", ReadLineStdinCallback));
- JsValueRef console;
- IfJsrtErrorFail(ChakraRTInterface::JsCreateObject(&console), false);
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(console, "log", EchoCallback));
- JsPropertyIdRef consoleName;
- IfJsrtErrorFail(CreatePropertyIdFromString("console", &consoleName), false);
- IfJsrtErrorFail(ChakraRTInterface::JsSetProperty(global, consoleName, console, true), false);
- IfJsrtErrorFail(InitializeModuleCallbacks(), false);
- // When the command-line argument `-Test262` is set,
- // WScript will have the extra support API below and $262 will be
- // added to global scope
- if (HostConfigFlags::flags.Test262)
- {
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Broadcast", BroadcastCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "ReceiveBroadcast", ReceiveBroadcastCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Report", ReportCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetReport", GetReportCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Leaving", LeavingCallback));
- IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Sleep", SleepCallback));
- // $262
- const char Test262[] =
- #include "262.js"
- ;
- JsValueRef Test262ScriptRef;
- IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString(Test262, strlen(Test262), &Test262ScriptRef));
- JsValueRef fname;
- IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsCreateString("262", strlen("262"), &fname));
- IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsRun(Test262ScriptRef, WScriptJsrt::GetNextSourceContext(), fname, JsParseScriptAttributeNone, nullptr));
- }
- Error:
- return hr == S_OK;
- }
- JsErrorCode WScriptJsrt::InitializeModuleCallbacks()
- {
- return InitializeModuleInfo(nullptr, nullptr);
- }
- bool WScriptJsrt::Uninitialize()
- {
- // moduleRecordMap is a global std::map, its destructor may access overridden
- // "operator delete" / global HeapAllocator::Instance. Clear it manually here
- // to avoid worrying about global destructor order.
- moduleRecordMap.clear();
- moduleDirMap.clear();
- moduleErrMap.clear();
- scriptDirMap.clear();
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData && !threadData->children.empty())
- {
- LONG count = (LONG)threadData->children.size();
- std::vector<HANDLE> childrenHandles;
- //Clang does not support "for each" yet
- for(auto i = threadData->children.begin(); i!= threadData->children.end(); i++)
- {
- auto child = *i;
- childrenHandles.push_back(child->hThread);
- SetEvent(child->hevntShutdown);
- }
- DWORD waitRet = WaitForMultipleObjects(count, &childrenHandles[0], TRUE, INFINITE);
- Assert(waitRet == WAIT_OBJECT_0);
- for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
- {
- delete *i;
- }
- threadData->children.clear();
- }
- return true;
- }
- #if ENABLE_TTD
- void CALLBACK WScriptJsrt::JsContextBeforeCollectCallback(JsRef contextRef, void *data)
- {
- ChakraRTInterface::JsTTDNotifyContextDestroy(contextRef);
- }
- #endif
- FileNode * SourceMap::root = nullptr;
- JsValueRef __stdcall WScriptJsrt::RegisterModuleSourceCallback(JsValueRef callee, bool isConstructCall,
- JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- if (argumentCount < 3)
- {
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- }
- else
- {
- AutoString fileName;
- AutoString data;
- IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
- IfJsrtErrorSetGo(data.Initialize(arguments[2]));
- SourceMap::Add(fileName, data);
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::LoadTextFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- const char* fileContent = nullptr;
- if (argumentCount < 2)
- {
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- }
- else
- {
- AutoString fileName;
- IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
- if (errorCode == JsNoError)
- {
- UINT lengthBytes = 0;
- hr = Helpers::LoadScriptFromFile(*fileName, fileContent, &lengthBytes);
- if (FAILED(hr))
- {
- fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- return returnValue;
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(
- fileContent, lengthBytes, &returnValue));
- }
- }
- Error:
- if (fileContent)
- {
- free((void*)fileContent);
- }
- return returnValue;
- }
- int JsFgets(char* buf, int size, FILE* file)
- {
- int n = size - 1;
- if (n < 0)
- return -1;
- bool crflag = false;
- int c, i = 0;
- for (i = 0; i < n && (c = getc(file)) != EOF; i++) {
- buf[i] = (char)c;
- if (c == '\n') { // any \n ends a line
- i++; // keep the \n; we know there is room for \0
- break;
- }
- if (crflag) { // \r not followed by \n ends line at the \r
- ungetc(c, file);
- break; // and overwrite c in buf with \0
- }
- crflag = (c == '\r');
- }
- buf[i] = '\0';
- return i;
- }
- JsValueRef __stdcall WScriptJsrt::ReadLineStdinCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- const int BUFSIZE = 256;
- FILE* from = stdin;
- int buflength = 0;
- int bufsize = BUFSIZE;
- char* buf = static_cast<char*>(malloc(bufsize));
- char* tmp;
- int gotlength = 0;
- if (!buf)
- {
- goto Error;
- }
- while ((gotlength = JsFgets(buf + buflength, bufsize - buflength, from)) > 0)
- {
- buflength += gotlength;
- // are we done?
- if (buf[buflength - 2] == '\r' && buf[buflength - 1] == '\n')
- {
- buf[buflength - 1] = '\0';
- buf[buflength - 2] = '\0';
- buflength -= 2;
- break;
- }
- else if (buf[buflength - 1] == '\n')
- {
- buf[buflength - 1] = '\0';
- buflength -= 1;
- break;
- }
- else if (buflength < bufsize - 1)
- {
- break;
- }
- // Else, grow our buffer for another pass.
- bufsize *= 2;
- if (bufsize > buflength)
- {
- tmp = static_cast<char*>(realloc(buf, bufsize));
- }
- else
- {
- goto Error;
- }
- if (!tmp)
- {
- goto Error;
- }
- buf = tmp;
- }
- //Treat the empty string specially.
- if (buflength == 0)
- {
- if (feof(from))
- {
- goto Error;
- }
- else
- {
- JsValueRef emptyStringObject;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(buf, buflength, &emptyStringObject));
- free(buf);
- return emptyStringObject;
- }
- }
-
- // Turn buf into a JSString. Note that buflength includes the trailing null character.
- JsValueRef stringObject;
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateString(buf, buflength, &stringObject));
- free(buf);
- return stringObject;
- Error:
- if (buf)
- {
- free(buf);
- }
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::LoadBinaryFileCallback(JsValueRef callee,
- bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- bool isHeapAlloc = true;
- if (argumentCount < 2)
- {
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- }
- else
- {
- const char *fileContent;
- AutoString fileName;
- IfJsrtErrorSetGo(fileName.Initialize(arguments[1]));
- if (errorCode == JsNoError)
- {
- UINT lengthBytes = 0;
- hr = Helpers::LoadBinaryFile(*fileName, fileContent, lengthBytes);
- if (FAILED(hr))
- {
- fprintf(stderr, "Couldn't load file '%s'\n", fileName.GetString());
- IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetUndefinedValue(&returnValue), Error);
- return returnValue;
- }
- JsValueRef arrayBuffer;
- IfJsrtErrorSetGoLabel(ChakraRTInterface::JsCreateArrayBuffer(lengthBytes, &arrayBuffer), ErrorStillFree);
- BYTE* buffer;
- unsigned int bufferLength;
- IfJsrtErrorSetGoLabel(ChakraRTInterface::JsGetArrayBufferStorage(arrayBuffer, &buffer, &bufferLength), ErrorStillFree);
- if (bufferLength < lengthBytes)
- {
- fwprintf(stderr, _u("Array buffer size is insufficient to store the binary file.\n"));
- }
- else
- {
- if (memcpy_s(buffer, bufferLength, (BYTE*)fileContent, lengthBytes) == 0)
- {
- returnValue = arrayBuffer;
- }
- }
- ErrorStillFree:
- if (isHeapAlloc)
- {
- HeapFree(GetProcessHeap(), 0, (void*)fileContent);
- }
- }
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::FlagCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- #if ENABLE_DEBUG_CONFIG_OPTIONS
- if (argumentCount > 1)
- {
- AutoString cmd;
- IfJsrtErrorSetGo(cmd.Initialize(arguments[1]));
- char16* argv[] = { nullptr, cmd.GetWideString() };
- ChakraRTInterface::SetConfigFlags(2, argv, nullptr);
- }
- #endif
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::BroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- if (argumentCount > 1)
- {
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData)
- {
- ChakraRTInterface::JsGetSharedArrayBufferContent(arguments[1], &threadData->sharedContent);
- LONG count = (LONG)threadData->children.size();
- threadData->hSemaphore = CreateSemaphore(NULL, 0, count, NULL);
- if (threadData->hSemaphore)
- {
- //Clang does not support "for each" yet
- for (auto i = threadData->children.begin(); i != threadData->children.end(); i++)
- {
- auto child = *i;
- SetEvent(child->hevntReceivedBroadcast);
- }
- WaitForSingleObject(threadData->hSemaphore, INFINITE);
- CloseHandle(threadData->hSemaphore);
- threadData->hSemaphore = INVALID_HANDLE_VALUE;
- }
- else
- {
- fwprintf(stderr, _u("Couldn't create semaphore.\n"));
- fflush(stderr);
- }
- ChakraRTInterface::JsReleaseSharedArrayBufferContentHandle(threadData->sharedContent);
- }
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::ReceiveBroadcastCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- if (argumentCount > 1)
- {
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData)
- {
- if (threadData->receiveBroadcastCallbackFunc)
- {
- ChakraRTInterface::JsRelease(threadData->receiveBroadcastCallbackFunc, nullptr);
- }
- threadData->receiveBroadcastCallbackFunc = arguments[1];
- ChakraRTInterface::JsAddRef(threadData->receiveBroadcastCallbackFunc, nullptr);
- }
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::ReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- if (argumentCount > 1)
- {
- JsValueRef stringRef;
- ChakraRTInterface::JsConvertValueToString(arguments[1], &stringRef);
- AutoString autoStr(stringRef);
- if (autoStr.GetError() == JsNoError)
- {
- std::string str(autoStr.GetString());
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData && threadData->parent)
- {
- EnterCriticalSection(&threadData->parent->csReportQ);
- threadData->parent->reportQ.push_back(str);
- LeaveCriticalSection(&threadData->parent->csReportQ);
- }
- }
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::GetReportCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetNullValue(&returnValue));
- if (argumentCount > 0)
- {
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData)
- {
- EnterCriticalSection(&threadData->csReportQ);
- if (threadData->reportQ.size() > 0)
- {
- auto str = threadData->reportQ.front();
- threadData->reportQ.pop_front();
- ChakraRTInterface::JsCreateString(str.c_str(), str.size(), &returnValue);
- }
- LeaveCriticalSection(&threadData->csReportQ);
- }
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::LeavingCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- if (argumentCount > 0)
- {
- auto& threadData = GetRuntimeThreadLocalData().threadData;
- if (threadData)
- {
- threadData->leaving = true;
- }
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::SleepCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&returnValue));
- if (argumentCount > 1)
- {
- double timeout = 0.0;
- ChakraRTInterface::JsNumberToDouble(arguments[1], &timeout);
- Sleep((DWORD)timeout);
- }
- Error:
- return returnValue;
- }
- JsValueRef __stdcall WScriptJsrt::GetProxyPropertiesCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
- {
- HRESULT hr = E_FAIL;
- JsValueRef returnValue = JS_INVALID_REFERENCE;
- JsValueRef undefined = JS_INVALID_REFERENCE;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetUndefinedValue(&undefined));
- returnValue = undefined;
- if (argumentCount > 1)
- {
- bool isProxy = false;
- JsValueRef target;
- JsValueRef handler;
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetProxyProperties(arguments[1], &isProxy, &target, &handler));
- if (isProxy)
- {
- JsPropertyIdRef targetProperty;
- JsPropertyIdRef handlerProperty;
- JsPropertyIdRef revokedProperty;
-
- IfJsrtErrorSetGo(CreatePropertyIdFromString("target", &targetProperty));
- IfJsrtErrorSetGo(CreatePropertyIdFromString("handler", &handlerProperty));
- IfJsrtErrorSetGo(CreatePropertyIdFromString("revoked", &revokedProperty));
- IfJsrtErrorSetGo(ChakraRTInterface::JsCreateObject(&returnValue));
- JsValueRef revoked = JS_INVALID_REFERENCE;
- if (target == JS_INVALID_REFERENCE)
- {
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetTrueValue(&revoked));
- target = undefined;
- handler = undefined;
- }
- else
- {
- IfJsrtErrorSetGo(ChakraRTInterface::JsGetFalseValue(&revoked));
- }
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetProperty(returnValue, handlerProperty, handler, true));
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetProperty(returnValue, targetProperty, target, true));
- IfJsrtErrorSetGo(ChakraRTInterface::JsSetProperty(returnValue, revokedProperty, revoked, true));
- }
- }
- Error:
- return returnValue;
- }
- bool WScriptJsrt::PrintException(LPCSTR fileName, JsErrorCode jsErrorCode)
- {
- LPCWSTR errorTypeString = ConvertErrorCodeToMessage(jsErrorCode);
- JsValueRef exception;
- ChakraRTInterface::JsGetAndClearException(&exception);
- if (HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
- {
- return false;
- }
- if (exception != nullptr)
- {
- if (jsErrorCode == JsErrorCode::JsErrorScriptCompile || jsErrorCode == JsErrorCode::JsErrorScriptException)
- {
- AutoString errorMessage;
- IfJsrtErrorFail(errorMessage.Initialize(exception), false);
- if (jsErrorCode == JsErrorCode::JsErrorScriptCompile)
- {
- JsPropertyIdRef linePropertyId = JS_INVALID_REFERENCE;
- JsValueRef lineProperty = JS_INVALID_REFERENCE;
- JsPropertyIdRef columnPropertyId = JS_INVALID_REFERENCE;
- JsValueRef columnProperty = JS_INVALID_REFERENCE;
- int line;
- int column;
-
- IfJsrtErrorFail(CreatePropertyIdFromString("line", &linePropertyId), false);
- IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, linePropertyId, &lineProperty), false);
- IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(lineProperty, &line), false);
- IfJsrtErrorFail(CreatePropertyIdFromString("column", &columnPropertyId), false);
- IfJsrtErrorFail(ChakraRTInterface::JsGetProperty(exception, columnPropertyId, &columnProperty), false);
- IfJsrtErrorFail(ChakraRTInterface::JsNumberToInt(columnProperty, &column), false);
- CHAR shortFileName[_MAX_PATH];
- CHAR ext[_MAX_EXT];
- _splitpath_s(fileName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
- fwprintf(stderr, _u("%ls\n\tat code (%S%S:%d:%d)\n"),
- errorMessage.GetWideString(), shortFileName, ext, (int)line + 1,
- (int)column + 1);
- }
- else
- {
- JsValueType propertyType = JsUndefined;
- JsPropertyIdRef stackPropertyId = JS_INVALID_REFERENCE;
- JsValueRef stackProperty = JS_INVALID_REFERENCE;
- AutoString errorStack;
- JsErrorCode errorCode = CreatePropertyIdFromString("stack", &stackPropertyId);
- if (errorCode == JsErrorCode::JsNoError)
- {
- errorCode = ChakraRTInterface::JsGetProperty(exception, stackPropertyId, &stackProperty);
- if (errorCode == JsErrorCode::JsNoError)
- {
- errorCode = ChakraRTInterface::JsGetValueType(stackProperty, &propertyType);
- }
- }
- if (errorCode != JsErrorCode::JsNoError || propertyType == JsUndefined)
- {
- const char *fName = fileName != nullptr ? fileName : "(unknown)";
- CHAR shortFileName[_MAX_PATH];
- CHAR ext[_MAX_EXT];
- _splitpath_s(fName, nullptr, 0, nullptr, 0, shortFileName, _countof(shortFileName), ext, _countof(ext));
- // do not mix char/wchar. print them separately
- fprintf(stderr, "thrown at %s%s:\n^\n", shortFileName, ext);
- fwprintf(stderr, _u("%ls\n"), errorMessage.GetWideString());
- }
- else
- {
- IfJsrtErrorFail(errorStack.Initialize(stackProperty), false);
- fwprintf(stderr, _u("%ls\n"), errorStack.GetWideString());
- }
- }
- }
- else
- {
- fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
- }
- return true;
- }
- else
- {
- fwprintf(stderr, _u("Error : %ls\n"), errorTypeString);
- }
- return false;
- }
- void WScriptJsrt::AddMessageQueue(MessageQueue *_messageQueue)
- {
- Assert(messageQueue == nullptr);
- messageQueue = _messageQueue;
- }
- WScriptJsrt::CallbackMessage::CallbackMessage(unsigned int time, JsValueRef function) : MessageBase(time), m_function(function)
- {
- JsErrorCode error = ChakraRTInterface::JsAddRef(m_function, nullptr);
- if (error != JsNoError)
- {
- // Simply report a fatal error and exit because continuing from this point would result in inconsistent state
- // and FailFast telemetry would not be useful.
- wprintf(_u("FATAL ERROR: ChakraRTInterface::JsAddRef failed in WScriptJsrt::CallbackMessage::`ctor`. error=0x%x\n"), error);
- exit(1);
- }
- }
- WScriptJsrt::CallbackMessage::~CallbackMessage()
- {
- bool hasException = false;
- ChakraRTInterface::JsHasException(&hasException);
- if (hasException)
- {
- WScriptJsrt::PrintException("", JsErrorScriptException);
- }
- JsErrorCode errorCode = ChakraRTInterface::JsRelease(m_function, nullptr);
- Assert(errorCode == JsNoError);
- m_function = JS_INVALID_REFERENCE;
- }
- HRESULT WScriptJsrt::CallbackMessage::Call(LPCSTR fileName)
- {
- return CallFunction(fileName);
- }
- HRESULT WScriptJsrt::CallbackMessage::CallFunction(LPCSTR fileName)
- {
- HRESULT hr = S_OK;
- JsValueRef global;
- JsValueRef result;
- JsValueRef stringValue;
- JsValueType type;
- JsErrorCode errorCode = JsNoError;
- IfJsrtErrorHR(ChakraRTInterface::JsGetGlobalObject(&global));
- IfJsrtErrorHR(ChakraRTInterface::JsGetValueType(m_function, &type));
- if (type == JsString)
- {
- IfJsrtErrorHR(ChakraRTInterface::JsConvertValueToString(m_function, &stringValue));
- JsValueRef fname;
- ChakraRTInterface::JsCreateString("", strlen(""), &fname);
- // Run the code
- errorCode = ChakraRTInterface::JsRun(stringValue, JS_SOURCE_CONTEXT_NONE,
- fname, JsParseScriptAttributeArrayBufferIsUtf16Encoded,
- nullptr /*no result needed*/);
- }
- else
- {
- errorCode = ChakraRTInterface::JsCallFunction(m_function, &global, 1, &result);
- }
- if (errorCode != JsNoError)
- {
- hr = E_FAIL;
- PrintException(fileName, errorCode);
- }
- Error:
- return hr;
- }
- WScriptJsrt::ModuleMessage::ModuleMessage(JsModuleRecord module, JsValueRef specifier, std::string* fullPathPtr)
- : MessageBase(0), moduleRecord(module), specifier(specifier)
- {
- fullPath = nullptr;
- ChakraRTInterface::JsAddRef(module, nullptr);
- if (specifier != nullptr)
- {
- fullPath = new std::string (*fullPathPtr);
- // nullptr specifier means a Promise to execute; non-nullptr means a "fetch" operation.
- ChakraRTInterface::JsAddRef(specifier, nullptr);
- }
- }
- WScriptJsrt::ModuleMessage::~ModuleMessage()
- {
- ChakraRTInterface::JsRelease(moduleRecord, nullptr);
- if (specifier != nullptr)
- {
- delete fullPath;
- ChakraRTInterface::JsRelease(specifier, nullptr);
- }
- }
- HRESULT WScriptJsrt::ModuleMessage::Call(LPCSTR fileName)
- {
- JsErrorCode errorCode = JsNoError;
- JsValueRef result = JS_INVALID_REFERENCE;
- HRESULT hr;
- if (specifier == nullptr)
- {
- if (moduleErrMap[moduleRecord] != ErroredModule)
- {
- errorCode = ChakraRTInterface::JsModuleEvaluation(moduleRecord, &result);
- if (errorCode != JsNoError)
- {
- if (moduleErrMap[moduleRecord] == RootModule)
- {
- PrintException(fileName, errorCode);
- }
- else
- {
- bool hasException = false;
- ChakraRTInterface::JsHasException(&hasException);
- if (hasException)
- {
- JsValueRef exception;
- ChakraRTInterface::JsGetAndClearException(&exception);
- exception; //unusued
- }
- }
- }
- }
- }
- else
- {
- LPCSTR fileContent = nullptr;
- AutoString specifierStr(specifier);
- errorCode = specifierStr.GetError();
- if (errorCode == JsNoError)
- {
- hr = Helpers::LoadScriptFromFile(*specifierStr, fileContent, nullptr, fullPath, true);
- if (FAILED(hr))
- {
- if (!HostConfigFlags::flags.MuteHostErrorMsgIsEnabled)
- {
- auto actualModuleRecord = moduleRecordMap.find(*fullPath);
- if (actualModuleRecord == moduleRecordMap.end() || moduleErrMap[actualModuleRecord->second] == RootModule)
- {
- fprintf(stderr, "Couldn't load file '%s'\n", specifierStr.GetString());
- }
- }
- LoadScript(nullptr, fullPath == nullptr ? *specifierStr : fullPath->c_str(), nullptr, "module", true, WScriptJsrt::FinalizeFree, false);
- goto Error;
- }
- LoadScript(nullptr, fullPath == nullptr ? *specifierStr : fullPath->c_str(), fileContent, "module", true, WScriptJsrt::FinalizeFree, true);
- }
- }
- Error:
- return errorCode;
- }
- JsErrorCode WScriptJsrt::FetchImportedModuleHelper(JsModuleRecord referencingModule,
- JsValueRef specifier, __out JsModuleRecord* dependentModuleRecord, LPCSTR refdir)
- {
- JsModuleRecord moduleRecord = JS_INVALID_REFERENCE;
- AutoString specifierStr;
- *dependentModuleRecord = nullptr;
- if (specifierStr.Initialize(specifier) != JsNoError)
- {
- return specifierStr.GetError();
- }
- char fullPath[_MAX_PATH];
- std::string specifierFullPath = refdir ? refdir : "";
- specifierFullPath += *specifierStr;
- if (_fullpath(fullPath, specifierFullPath.c_str(), _MAX_PATH) == nullptr)
- {
- return JsErrorInvalidArgument;
- }
- auto moduleEntry = moduleRecordMap.find(std::string(fullPath));
- if (moduleEntry != moduleRecordMap.end())
- {
- *dependentModuleRecord = moduleEntry->second;
- return JsNoError;
- }
- JsErrorCode errorCode = ChakraRTInterface::JsInitializeModuleRecord(referencingModule, specifier, &moduleRecord);
- if (errorCode == JsNoError)
- {
- GetDir(fullPath, &moduleDirMap[moduleRecord]);
- InitializeModuleInfo(specifier, moduleRecord);
- std::string pathKey = std::string(fullPath);
- moduleRecordMap[pathKey] = moduleRecord;
- moduleErrMap[moduleRecord] = ImportedModule;
- ModuleMessage* moduleMessage = WScriptJsrt::ModuleMessage::Create(referencingModule, specifier, &pathKey);
- if (moduleMessage == nullptr)
- {
- return JsErrorOutOfMemory;
- }
- WScriptJsrt::PushMessage(moduleMessage);
- *dependentModuleRecord = moduleRecord;
- }
- return errorCode;
- }
- // Callback from chakracore to fetch dependent module. In the test harness,
- // we are not doing any translation, just treat the specifier as fileName.
- // While this call will come back directly from ParseModuleSource, the additional
- // task are treated as Promise that will be executed later.
- JsErrorCode WScriptJsrt::FetchImportedModule(_In_ JsModuleRecord referencingModule,
- _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
- {
- auto moduleDirEntry = moduleDirMap.find(referencingModule);
- if (moduleDirEntry != moduleDirMap.end())
- {
- std::string dir = moduleDirEntry->second;
- return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord, dir.c_str());
- }
- return FetchImportedModuleHelper(referencingModule, specifier, dependentModuleRecord);
- }
- // Callback from chakracore to fetch module dynamically during runtime. In the test harness,
- // we are not doing any translation, just treat the specifier as fileName.
- // While this call will come back directly from runtime script or module code, the additional
- // task can be scheduled asynchronously that executed later.
- JsErrorCode WScriptJsrt::FetchImportedModuleFromScript(_In_ JsSourceContext dwReferencingSourceContext,
- _In_ JsValueRef specifier, _Outptr_result_maybenull_ JsModuleRecord* dependentModuleRecord)
- {
- return FetchImportedModuleHelper(nullptr, specifier, dependentModuleRecord);
- }
- // Callback from chakraCore when the module resolution is finished, either successfuly or unsuccessfully.
- JsErrorCode WScriptJsrt::NotifyModuleReadyCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef exceptionVar)
- {
- if (exceptionVar != nullptr)
- {
- ChakraRTInterface::JsSetException(exceptionVar);
- JsValueRef specifier = JS_INVALID_REFERENCE;
- ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
- AutoString fileName;
- if (specifier != JS_INVALID_REFERENCE)
- {
- fileName.Initialize(specifier);
- }
- if (HostConfigFlags::flags.TraceHostCallbackIsEnabled)
- {
- wprintf(_u("NotifyModuleReadyCallback(exception) %S\n"), fileName.GetString());
- }
- // No need to print - just consume the exception
- JsValueRef exception;
- ChakraRTInterface::JsGetAndClearException(&exception);
- exception; // unused
- }
-
- if (exceptionVar != nullptr || moduleErrMap[referencingModule] != ErroredModule)
- {
- WScriptJsrt::ModuleMessage* moduleMessage =
- WScriptJsrt::ModuleMessage::Create(referencingModule, nullptr);
- if (moduleMessage == nullptr)
- {
- return JsErrorOutOfMemory;
- }
- WScriptJsrt::PushMessage(moduleMessage);
- }
- return JsNoError;
- }
- JsErrorCode __stdcall WScriptJsrt::InitializeImportMetaCallback(_In_opt_ JsModuleRecord referencingModule, _In_opt_ JsValueRef importMetaVar)
- {
- if (importMetaVar != nullptr)
- {
- JsValueRef specifier = JS_INVALID_REFERENCE;
- ChakraRTInterface::JsGetModuleHostInfo(referencingModule, JsModuleHostInfo_HostDefined, &specifier);
- JsPropertyIdRef urlPropId;
- if (JsNoError == CreatePropertyIdFromString("url", &urlPropId))
- {
- ChakraRTInterface::JsSetProperty(importMetaVar, urlPropId, specifier, false);
- }
- }
- return JsNoError;
- }
- void WScriptJsrt::PromiseContinuationCallback(JsValueRef task, void *callbackState)
- {
- Assert(task != JS_INVALID_REFERENCE);
- Assert(callbackState != JS_INVALID_REFERENCE);
- MessageQueue * messageQueue = (MessageQueue *)callbackState;
- WScriptJsrt::CallbackMessage *msg = new WScriptJsrt::CallbackMessage(0, task);
- messageQueue->InsertSorted(msg);
- }
- void WScriptJsrt::PromiseRejectionTrackerCallback(JsValueRef promise, JsValueRef reason, bool handled, void *callbackState)
- {
- Assert(promise != JS_INVALID_REFERENCE);
- Assert(reason != JS_INVALID_REFERENCE);
- if (!handled)
- {
- wprintf(_u("Uncaught promise rejection\n"));
- }
- else
- {
- wprintf(_u("Promise rejection handled\n"));
- }
- JsPropertyIdRef stackPropertyID;
- JsErrorCode error = ChakraRTInterface::JsCreatePropertyId("stack", strlen("stack"), &stackPropertyID);
- if (error == JsNoError)
- {
- JsValueRef stack;
- error = ChakraRTInterface::JsGetProperty(reason, stackPropertyID, &stack);
- if (error == JsNoError)
- {
- JsValueRef stackStrValue;
- error = ChakraRTInterface::JsConvertValueToString(stack, &stackStrValue);
- if (error == JsNoError)
- {
- AutoString str(stackStrValue);
- wprintf(_u("%ls\n"), str.GetWideString());
- }
- }
- }
-
- if (error != JsNoError)
- {
- // weren't able to print stack, so just convert reason to a string
- JsValueRef strValue;
- error = ChakraRTInterface::JsConvertValueToString(reason, &strValue);
- if (error == JsNoError)
- {
- AutoString str(strValue);
- wprintf(_u("%ls\n"), str.GetWideString());
- }
- }
- fflush(stdout);
- }
|