//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "StdAfx.h"
MessageQueue* WScriptJsrt::messageQueue = nullptr;
DWORD_PTR WScriptJsrt::sourceContext = 0;
DWORD_PTR WScriptJsrt::GetNextSourceContext()
{
return 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;
IfJsrtErrorFail(ChakraRTInterface::JsPointerToString(argv[i], wcslen(argv[i]), &value), 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)
{
LPCWSTR str = nullptr;
size_t length;
error = ChakraRTInterface::JsStringToPointer(strValue, &str, &length);
if (error == JsNoError)
{
if (i > 1)
{
wprintf(L" ");
}
wprintf(L"%ls", str);
}
}
if (error == JsErrorScriptException)
{
return nullptr;
}
}
wprintf(L"\n");
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)
{
HRESULT hr = E_FAIL;
JsValueRef returnValue = JS_INVALID_REFERENCE;
JsErrorCode errorCode = JsNoError;
LPCWSTR errorMessage = L"";
if (argumentCount < 2 || argumentCount > 4)
{
errorCode = JsErrorInvalidArgument;
errorMessage = L"Need more or fewer arguments for WScript.LoadScript";
}
else
{
const wchar_t *fileContent;
const wchar_t *fileName;
const wchar_t *scriptInjectType = L"self";
size_t fileNameLength;
size_t scriptInjectTypeLength;
IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[1], &fileName, &fileNameLength));
if (argumentCount > 2)
{
IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[2], &scriptInjectType, &scriptInjectTypeLength));
}
if (errorCode == JsNoError)
{
hr = Helpers::LoadScriptFromFile(fileName, fileContent);
if (FAILED(hr))
{
fwprintf(stderr, L"Couldn't load file.\n");
}
else
{
returnValue = LoadScript(callee, fileName, fileNameLength, fileContent, scriptInjectType);
}
}
}
Error:
if (errorCode != JsNoError)
{
JsValueRef errorObject;
JsValueRef errorMessageString;
if (wcscmp(errorMessage, L"") == 0) {
errorMessage = ConvertErrorCodeToMessage(errorCode);
}
ChakraRTInterface::JsPointerToString(errorMessage, wcslen(errorMessage), &errorMessageString);
ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
ChakraRTInterface::JsSetException(errorObject);
}
return returnValue;
}
JsValueRef __stdcall WScriptJsrt::LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
HRESULT hr = E_FAIL;
JsErrorCode errorCode = JsNoError;
LPCWSTR errorMessage = L"";
JsValueRef returnValue = JS_INVALID_REFERENCE;
if (argumentCount < 2 || argumentCount > 4)
{
errorCode = JsErrorInvalidArgument;
errorMessage = L"Need more or fewer arguments for WScript.LoadScript";
}
else
{
const wchar_t *fileContent;
const wchar_t *fileName;
const wchar_t *scriptInjectType = L"self";
size_t fileContentLength;
size_t fileNameLength;
size_t scriptInjectTypeLength;
IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[1], &fileContent, &fileContentLength));
if (argumentCount > 2)
{
IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[2], &scriptInjectType, &scriptInjectTypeLength));
}
fileName = L"script.js";
fileNameLength = wcslen(fileName);
if (argumentCount > 3)
{
IfJsrtErrorSetGo(ChakraRTInterface::JsStringToPointer(arguments[3], &fileName, &fileNameLength));
}
returnValue = LoadScript(callee, fileName, fileNameLength, fileContent, scriptInjectType);
}
Error:
if (errorCode != JsNoError)
{
JsValueRef errorObject;
JsValueRef errorMessageString;
if (wcscmp(errorMessage, L"") == 0) {
errorMessage = ConvertErrorCodeToMessage(errorCode);
}
ChakraRTInterface::JsPointerToString(errorMessage, wcslen(errorMessage), &errorMessageString);
ChakraRTInterface::JsCreateError(errorMessageString, &errorObject);
ChakraRTInterface::JsSetException(errorObject);
}
return returnValue;
}
JsValueRef WScriptJsrt::LoadScript(JsValueRef callee, LPCWSTR fileName, size_t fileNameLength, LPCWSTR fileContent, LPCWSTR scriptInjectType)
{
HRESULT hr = E_FAIL;
JsErrorCode errorCode = JsNoError;
LPCWSTR errorMessage = L"Internal error.";
size_t errorMessageLength = wcslen(errorMessage);
JsValueRef returnValue = JS_INVALID_REFERENCE;
JsErrorCode innerErrorCode = JsNoError;
JsContextRef currentContext = JS_INVALID_REFERENCE;
JsRuntimeHandle runtime = JS_INVALID_RUNTIME_HANDLE;
IfJsrtErrorSetGo(ChakraRTInterface::JsGetCurrentContext(¤tContext));
IfJsrtErrorSetGo(ChakraRTInterface::JsGetRuntime(currentContext, &runtime));
wchar_t fullPath[_MAX_PATH];
if (_wfullpath(fullPath, fileName, _MAX_PATH) == nullptr)
{
IfFailGo(E_FAIL);
}
// canonicalize that path name to lower case for the profile storage
size_t len = wcslen(fullPath);
for (size_t i = 0; i < len; i++)
{
fullPath[i] = towlower(fullPath[i]);
}
if (wcscmp(scriptInjectType, L"self") == 0)
{
JsContextRef calleeContext;
IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(calleeContext));
errorCode = ChakraRTInterface::JsRunScript(fileContent, GetNextSourceContext(), fullPath, &returnValue);
if (errorCode == JsNoError)
{
errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
}
IfJsrtErrorSetGo(ChakraRTInterface::JsSetCurrentContext(currentContext));
}
else if (wcscmp(scriptInjectType, L"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::JsRunScript(fileContent, GetNextSourceContext(), fullPath, &returnValue);
if (errorCode == JsNoError)
{
errorCode = ChakraRTInterface::JsGetGlobalObject(&returnValue);
}
// Set the context back to the old one
ChakraRTInterface::JsSetCurrentContext(currentContext);
}
else
{
errorCode = JsErrorInvalidArgument;
errorMessage = L"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;
errorMessageLength = wcslen(errorMessage);
innerErrorCode = ChakraRTInterface::JsPointerToString(errorMessage, errorMessageLength, &messageProperty);
if (innerErrorCode == JsNoError)
{
innerErrorCode = ChakraRTInterface::JsCreateError(messageProperty, &error);
if (innerErrorCode == JsNoError)
{
innerErrorCode = ChakraRTInterface::JsSetException(error);
}
}
ChakraRTInterface::JsDoubleToNumber(errorCode, &value);
}
_flushall();
return value;
}
JsValueRef WScriptJsrt::SetTimeoutCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
LPWSTR errorMessage = L"invalid call to WScript.SetTimeout";
if (argumentCount != 3)
{
goto Error;
}
JsValueRef function = arguments[1];
JsValueRef timerId;
unsigned int time;
double tmp;
CallbackMessage *msg = nullptr;
IfJsrtError(ChakraRTInterface::JsNumberToDouble(arguments[2], &tmp));
time = static_cast