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; AutoString scriptInjectType; size_t fileNameLength; size_t scriptInjectTypeLength; IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointerUtf8Copy(arguments[1], &fileName, &fileNameLength)); if (argumentCount > 2) { IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointerUtf8Copy(arguments[2], &scriptInjectType, &scriptInjectTypeLength)); } if (errorCode == JsNoError) { hr = Helpers::LoadScriptFromFile(*fileName, fileContent); if (FAILED(hr)) { fwprintf(stderr, _u("Couldn't load file.\n")); } else { returnValue = LoadScript(callee, *fileName, fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule); } } } Error: if (errorCode != JsNoError) { 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); } return returnValue; }
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; AutoString fileName; AutoString scriptInjectType; size_t fileContentLength; size_t scriptInjectTypeLength; IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointerUtf8Copy(arguments[1], &fileContent, &fileContentLength)); if (argumentCount > 2) { IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointerUtf8Copy(arguments[2], &scriptInjectType, &scriptInjectTypeLength)); if (argumentCount > 3) { size_t unused; IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointerUtf8Copy(arguments[3], &fileName, &unused)); } } if (*fileContent) { // TODO: This is CESU-8. How to tell the engine? // TODO: How to handle this source (script) life time? returnValue = LoadScript(callee, *fileName, *fileContent, *scriptInjectType ? *scriptInjectType : "self", isSourceModule); } } Error: if (errorCode != JsNoError) { 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); } return returnValue; }
JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState) { LPCWSTR errorMessage = _u("invalid call to WScript.SetTimeout"); JsValueRef function; JsValueRef timerId; unsigned int time; double tmp; CallbackMessage *msg = nullptr; if (argumentCount != 3) { goto Error; } function = arguments[1]; IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[2], &tmp)); time = static_cast<int>(tmp); msg = new CallbackMessage(time, function); messageQueue->InsertSorted(msg); #if ENABLE_TTD ChakraRTInterface::JsTTDNotifyHostCallbackCreatedOrCanceled(true /*isCreate*/, false /*isCancel*/, false /*isRepeating*/, function, msg->GetId()); #endif IfJsrtError(ChakraRTInterface::JsDoubleToNumber(static_cast<double>(msg->GetId()), &timerId)); return timerId; Error: JsValueRef errorObject; JsValueRef errorMessageString; ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString); if (errorCode != JsNoError) { errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject); if (errorCode != JsNoError) { ChakraRTInterface::JsSetException(errorObject); } } 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"); if (argumentCount != 2) { goto Error; } unsigned int timerId; double tmp; JsValueRef undef; JsValueRef global; IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[1], &tmp)); timerId = static_cast<int>(tmp); messageQueue->RemoveById(timerId); #if ENABLE_TTD ChakraRTInterface::JsTTDNotifyHostCallbackCreatedOrCanceled(false /*isCreate*/, true /*isCancel*/, false /*isRepeating*/, nullptr, timerId); #endif IfJsrtError(ChakraRTInterface::JsGetGlobalObject(&global)); IfJsrtError(ChakraRTInterface::JsGetUndefinedValue(&undef)); return undef; Error: JsValueRef errorObject; JsValueRef errorMessageString; ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString); if (errorCode != JsNoError) { errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject); if (errorCode != JsNoError) { ChakraRTInterface::JsSetException(errorObject); } } 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);"); JsValueType argumentType = JsUndefined; if (argumentCount != 2) { goto Error; } IfJsrtError(ChakraRTInterface::JsGetValueType(arguments[1], &argumentType)); if (argumentType != JsFunction) { 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: JsValueRef errorObject; JsValueRef errorMessageString; ERROR_MESSAGE_TO_STRING(errorCode, errorMessage, errorMessageString); if (errorCode != JsNoError) { errorCode = ChakraRTInterface::JsCreateError(errorMessageString, &errorObject); if (errorCode != JsNoError) { ChakraRTInterface::JsSetException(errorObject); } } return JS_INVALID_REFERENCE; }
JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCSTR fileName, LPCSTR fileContent, LPCSTR scriptInjectType, bool isSourceModule) { HRESULT hr = E_FAIL; JsErrorCode errorCode = JsNoError; LPCWSTR errorMessage = _u("Internal error."); JsValueRef returnValue = JS_INVALID_REFERENCE; JsErrorCode innerErrorCode = JsNoError; JsContextRef currentContext = JS_INVALID_REFERENCE; JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE; char fullPathNarrow[_MAX_PATH]; size_t len = 0; IfJsrtErrorSetGo(ChakraRTInterface::JsGetCurrentContext(¤tContext)); IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime)); if (fileName) { if (_fullpath(fullPathNarrow, fileName, _MAX_PATH) == nullptr) { IfFailGo(E_FAIL); } // canonicalize that path name to lower case for the profile storage // REVIEW: This doesn't work for UTF8... len = strlen(fullPathNarrow); for (size_t i = 0; i < len; i++) { fullPathNarrow[i] = (char)tolower(fullPathNarrow[i]); } } else { // No fileName provided (WScript.LoadScript()), use dummy "script.js" strcpy_s(fullPathNarrow, "script.js"); } // 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); } else if (strcmp(scriptInjectType, "self") == 0) { JsContextRef calleeContext; IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext)); IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(calleeContext)); errorCode = ChakraRTInterface::JsRunScriptUtf8(fileContent, GetNextSourceContext(), fullPathNarrow, &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)); IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(newContext)); // Initialize the host objects Initialize(); errorCode = ChakraRTInterface::JsRunScriptUtf8(fileContent, GetNextSourceContext(), fullPathNarrow, &returnValue); if (errorCode == JsNoError) { errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue); } // Set the context back to the old one ChakraRTInterface::JsSetCurrentContext(currentContext); } else { errorCode = JsErrorInvalidArgument; errorMessage = _u("Unsupported argument type inject type."); } Error: JsValueRef value = returnValue; if (errorCode != JsNoError) { if (innerErrorCode != JsNoError) { // Failed to retrieve the inner error message, so set a custom error string errorMessage = ConvertErrorCodeToMessage(errorCode); } JsValueRef error = JS_INVALID_REFERENCE; JsValueRef messageProperty = JS_INVALID_REFERENCE; ERROR_MESSAGE_TO_STRING(errCode, errorMessage, messageProperty); if (errCode == JsNoError) { errCode = ChakraRTInterface::JsCreateError(messageProperty, &error); if (errCode == JsNoError) { errCode = ChakraRTInterface::JsSetException(error); } } ChakraRTInterface::JsDoubleToNumber(errorCode, &value); } _flushall(); return value; }