Skip to content

Commit

Permalink
Add WScript.GetFileName() and WScript.GetDirectory() to solve annoyan…
Browse files Browse the repository at this point in the history
…ce when trying to execute a file that needs to refer to another file with a relative path.

Will be able to do
```
WScript.LoadScriptFile(WScript.GetDirectory() + "../TestHarness.js");
```
  • Loading branch information
Cellule committed Aug 6, 2016
1 parent 42ed37b commit 2ec7811
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 2 deletions.
1 change: 1 addition & 0 deletions bin/ch/ChakraRtInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ bool ChakraRTInterface::LoadChakraDll(ArgInfo* argInfo, HINSTANCE *outLibrary)
m_jsApiHooks.pfJsrtCreateRuntime = (JsAPIHooks::JsrtCreateRuntimePtr)GetChakraCoreSymbol(library, "JsCreateRuntime");
m_jsApiHooks.pfJsrtCreateContext = (JsAPIHooks::JsrtCreateContextPtr)GetChakraCoreSymbol(library, "JsCreateContext");
m_jsApiHooks.pfJsrtSetRuntimeMemoryLimit = (JsAPIHooks::JsrtSetRuntimeMemoryLimitPtr)GetChakraCoreSymbol(library, "JsSetRuntimeMemoryLimit");
m_jsApiHooks.pfJsrtGetContextUrl = (JsAPIHooks::JsrtGetContextUrlPtr)GetChakraCoreSymbol(library, "JsGetContextUrl");
m_jsApiHooks.pfJsrtSetCurrentContext = (JsAPIHooks::JsrtSetCurrentContextPtr)GetChakraCoreSymbol(library, "JsSetCurrentContext");
m_jsApiHooks.pfJsrtGetCurrentContext = (JsAPIHooks::JsrtGetCurrentContextPtr)GetChakraCoreSymbol(library, "JsGetCurrentContext");
m_jsApiHooks.pfJsrtDisposeRuntime = (JsAPIHooks::JsrtDisposeRuntimePtr)GetChakraCoreSymbol(library, "JsDisposeRuntime");
Expand Down
3 changes: 3 additions & 0 deletions bin/ch/ChakraRtInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ struct JsAPIHooks
typedef JsErrorCode (WINAPI *JsrtCreateRuntimePtr)(JsRuntimeAttributes attributes, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime);
typedef JsErrorCode (WINAPI *JsrtCreateContextPtr)(JsRuntimeHandle runtime, JsContextRef *newContext);
typedef JsErrorCode (WINAPI *JsrtSetRuntimeMemoryLimitPtr)(JsRuntimeHandle runtime, size_t memoryLimit);
typedef JsErrorCode (WINAPI *JsrtGetContextUrlPtr)(JsContextRef context, char** url);
typedef JsErrorCode (WINAPI *JsrtSetCurrentContextPtr)(JsContextRef context);
typedef JsErrorCode (WINAPI *JsrtGetCurrentContextPtr)(JsContextRef* context);
typedef JsErrorCode (WINAPI *JsrtDisposeRuntimePtr)(JsRuntimeHandle runtime);
Expand Down Expand Up @@ -100,6 +101,7 @@ struct JsAPIHooks
JsrtCreateRuntimePtr pfJsrtCreateRuntime;
JsrtCreateContextPtr pfJsrtCreateContext;
JsrtSetRuntimeMemoryLimitPtr pfJsrtSetRuntimeMemoryLimit;
JsrtGetContextUrlPtr pfJsrtGetContextUrl;
JsrtSetCurrentContextPtr pfJsrtSetCurrentContext;
JsrtGetCurrentContextPtr pfJsrtGetCurrentContext;
JsrtDisposeRuntimePtr pfJsrtDisposeRuntime;
Expand Down Expand Up @@ -270,6 +272,7 @@ class ChakraRTInterface
static JsErrorCode WINAPI JsCreateRuntime(JsRuntimeAttributes attributes, JsThreadServiceCallback threadService, JsRuntimeHandle *runtime) { return HOOK_JS_API(CreateRuntime(attributes, threadService, runtime)); }
static JsErrorCode WINAPI JsCreateContext(JsRuntimeHandle runtime, JsContextRef *newContext) { return HOOK_JS_API(CreateContext(runtime, newContext)); }
static JsErrorCode WINAPI JsSetRuntimeMemoryLimit(JsRuntimeHandle runtime, size_t memory) { return HOOK_JS_API(SetRuntimeMemoryLimit(runtime, memory)); }
static JsErrorCode WINAPI JsGetContextUrl(JsContextRef context, char** url) { return HOOK_JS_API(GetContextUrl(context, url)); }
static JsErrorCode WINAPI JsSetCurrentContext(JsContextRef context) { return HOOK_JS_API(SetCurrentContext(context)); }
static JsErrorCode WINAPI JsGetCurrentContext(JsContextRef* context) { return HOOK_JS_API(GetCurrentContext(context)); }
static JsErrorCode WINAPI JsDisposeRuntime(JsRuntimeHandle runtime) { return HOOK_JS_API(DisposeRuntime(runtime)); }
Expand Down
76 changes: 74 additions & 2 deletions bin/ch/WScriptJsrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,76 @@ JsValueRef __stdcall WScriptJsrt::QuitCallback(JsValueRef callee, bool isConstru
ExitProcess(exitCode);
}

JsValueRef __stdcall WScriptJsrt::GetDirectoryCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
HRESULT hr = E_FAIL;
JsErrorCode errorCode = JsNoError;
LPCWSTR errorMessage = _u("Internal error.");
JsValueRef returnValue = JS_INVALID_REFERENCE;
JsContextRef calleeContext = JS_INVALID_REFERENCE;
AutoString url;

IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextUrl(calleeContext, &url));
char drive[8], dir[256], filename[256], ext[256];
IfJsrtErrorSetGo(_splitpath_s(*url, drive, 8, dir, 256, filename, 256, ext, 256) ? JsErrorInvalidArgument : JsNoError);
char fullDir[256];
_makepath_s(fullDir, 256, drive, dir, nullptr, nullptr);
size_t len = strlen(fullDir);
IfJsrtErrorSetGo(ChakraRTInterface::JsPointerToStringUtf8(fullDir, len, &returnValue));

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 __stdcall WScriptJsrt::GetFileNameCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
HRESULT hr = E_FAIL;
JsErrorCode errorCode = JsNoError;
LPCWSTR errorMessage = _u("Internal error.");
JsValueRef returnValue = JS_INVALID_REFERENCE;
JsContextRef calleeContext = JS_INVALID_REFERENCE;
AutoString url;

IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextOfObject(callee, &calleeContext));
IfJsrtErrorSetGo(ChakraRTInterface::JsGetContextUrl(calleeContext, &url));
size_t len = strlen(*url);
IfJsrtErrorSetGo(ChakraRTInterface::JsPointerToStringUtf8(*url, len, &returnValue));

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 __stdcall WScriptJsrt::LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState)
{
return LoadScriptFileHelper(callee, arguments, argumentCount, false);
Expand Down Expand Up @@ -322,7 +392,7 @@ JsErrorCode WScriptJsrt::LoadModuleFromString(LPCSTR fileName, LPCSTR fileConten
JsValueRef errorObject = JS_INVALID_REFERENCE;

// ParseModuleSource is sync, while additional fetch & evaluation are async.
errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
errorCode = ChakraRTInterface::JsParseModuleSource(requestModule, dwSourceCookie, (LPBYTE)fileContent,
(unsigned int)strlen(fileContent), JsParseModuleSourceFlags_DataIsUTF8, &errorObject);
if ((errorCode != JsNoError) && errorObject != JS_INVALID_REFERENCE)
{
Expand Down Expand Up @@ -711,6 +781,8 @@ bool WScriptJsrt::Initialize()

IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Echo", EchoCallback));
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "Quit", QuitCallback));
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetFileName", GetFileNameCallback));
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "GetDirectory", GetDirectoryCallback));
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScriptFile", LoadScriptFileCallback));
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadScript", LoadScriptCallback));
IfFalseGo(WScriptJsrt::InstallObjectsOnObject(wscript, "LoadModule", LoadModuleCallback));
Expand Down Expand Up @@ -1017,7 +1089,7 @@ JsErrorCode WScriptJsrt::FetchImportedModule(_In_ JsModuleRecord referencingModu
return errorCode;
}

// Callback from chakraCore when the module resolution is finished, either successfuly or unsuccessfully.
// 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)
Expand Down
2 changes: 2 additions & 0 deletions bin/ch/WScriptJsrt.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class WScriptJsrt
static bool CreateNamedFunction(const char*, JsNativeFunction callback, JsValueRef* functionVar);
static JsValueRef __stdcall EchoCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef __stdcall QuitCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef __stdcall GetDirectoryCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef __stdcall GetFileNameCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef __stdcall LoadScriptFileCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef __stdcall LoadScriptCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
static JsValueRef __stdcall LoadModuleCallback(JsValueRef callee, bool isConstructCall, JsValueRef *arguments, unsigned short argumentCount, void *callbackState);
Expand Down
13 changes: 13 additions & 0 deletions lib/Jsrt/ChakraCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,19 @@ typedef UINT32 DWORD;
_In_ JsRuntimeHandle runtime,
_Out_ JsContextRef *newContext);

/// <summary>
/// Gets the source url of the context
/// </summary>
/// <param name="context">The context the url belongs to.</param>
/// <param name="url">The url of the context</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsGetContextUrl(
_In_ JsContextRef context,
_Out_ char** url);

/// <summary>
/// Gets the current script context on the thread.
/// </summary>
Expand Down
18 changes: 18 additions & 0 deletions lib/Jsrt/Jsrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,24 @@ CHAKRA_API JsCreateContext(_In_ JsRuntimeHandle runtimeHandle, _Out_ JsContextRe
return CreateContextCore(runtimeHandle, false /*createUnderTimeTravel*/, newContext);
}


CHAKRA_API JsGetContextUrl(_In_ JsContextRef context, _Out_ char **url)
{
PARAM_NOT_NULL(context);
PARAM_NOT_NULL(url);

BEGIN_JSRT_NO_EXCEPTION
{
*url = ((JsrtContext*)context)->GetScriptContext()->GetCurrentUrl();
if (!*url)
{
RETURN_NO_EXCEPTION(JsErrorInvalidContext);
}
}
END_JSRT_NO_EXCEPTION
}


CHAKRA_API JsGetCurrentContext(_Out_ JsContextRef *currentContext)
{
PARAM_NOT_NULL(currentContext);
Expand Down
1 change: 1 addition & 0 deletions lib/Jsrt/JsrtCommonExports.inc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
JsAddRef
JsRelease
JsCreateContext
JsGetContextUrl
JsGetCurrentContext
JsSetCurrentContext
JsGetContextOfObject
Expand Down
22 changes: 22 additions & 0 deletions lib/Runtime/Base/ScriptContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#ifdef ENABLE_BASIC_TELEMETRY
#include "ScriptContextTelemetry.h"
#endif
#include "Codex/Utf8Helper.h"

namespace Js
{
Expand Down Expand Up @@ -491,6 +492,27 @@ namespace Js
PERF_COUNTER_DEC(Basic, ScriptContext);
}

char* ScriptContext::GetCurrentUrl()
{
Js::JavascriptStackWalker walker(this);
char* url = nullptr;;
walker.WalkUntil((ushort)10, [&](Js::JavascriptFunction* func, ushort frameIndex) -> bool
{
FunctionBody* body = func->GetFunctionBody();
if (body)
{
SourceContextInfo* info = body->GetSourceContextInfo();
if (info)
{
utf8::WideStringToNarrowDynamic(info->url, &url);
return true;
}
}
return false;
});
return url;
}

void ScriptContext::SetUrl(BSTR bstrUrl)
{
// Assumption: this method is never called multiple times
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Base/ScriptContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,7 @@ namespace Js
#ifdef ENABLE_DOM_FAST_PATH
DOMFastPathIRHelperMap* EnsureDOMFastPathIRHelperMap();
#endif
char* GetCurrentUrl();
char16 const * GetUrl() const { return url; }
void SetUrl(BSTR bstr);
#ifdef RUNTIME_DATA_COLLECTION
Expand Down

0 comments on commit 2ec7811

Please sign in to comment.