diff --git a/bin/ch/ChakraRtInterface.cpp b/bin/ch/ChakraRtInterface.cpp index 2d8feacef01..d806527c696 100644 --- a/bin/ch/ChakraRtInterface.cpp +++ b/bin/ch/ChakraRtInterface.cpp @@ -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"); diff --git a/bin/ch/ChakraRtInterface.h b/bin/ch/ChakraRtInterface.h index 30ce885c89d..50101744199 100644 --- a/bin/ch/ChakraRtInterface.h +++ b/bin/ch/ChakraRtInterface.h @@ -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); @@ -100,6 +101,7 @@ struct JsAPIHooks JsrtCreateRuntimePtr pfJsrtCreateRuntime; JsrtCreateContextPtr pfJsrtCreateContext; JsrtSetRuntimeMemoryLimitPtr pfJsrtSetRuntimeMemoryLimit; + JsrtGetContextUrlPtr pfJsrtGetContextUrl; JsrtSetCurrentContextPtr pfJsrtSetCurrentContext; JsrtGetCurrentContextPtr pfJsrtGetCurrentContext; JsrtDisposeRuntimePtr pfJsrtDisposeRuntime; @@ -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)); } diff --git a/bin/ch/WScriptJsrt.cpp b/bin/ch/WScriptJsrt.cpp index c0355545dc1..343a2b56706 100644 --- a/bin/ch/WScriptJsrt.cpp +++ b/bin/ch/WScriptJsrt.cpp @@ -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); @@ -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) { @@ -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)); @@ -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) diff --git a/bin/ch/WScriptJsrt.h b/bin/ch/WScriptJsrt.h index 4044fb50bc5..2f815fc9382 100644 --- a/bin/ch/WScriptJsrt.h +++ b/bin/ch/WScriptJsrt.h @@ -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); diff --git a/lib/Jsrt/ChakraCommon.h b/lib/Jsrt/ChakraCommon.h index a598b54614f..f32107507f0 100644 --- a/lib/Jsrt/ChakraCommon.h +++ b/lib/Jsrt/ChakraCommon.h @@ -930,6 +930,19 @@ typedef UINT32 DWORD; _In_ JsRuntimeHandle runtime, _Out_ JsContextRef *newContext); + /// + /// Gets the source url of the context + /// + /// The context the url belongs to. + /// The url of the context + /// + /// The code JsNoError if the operation succeeded, a failure code otherwise. + /// + CHAKRA_API + JsGetContextUrl( + _In_ JsContextRef context, + _Out_ char** url); + /// /// Gets the current script context on the thread. /// diff --git a/lib/Jsrt/Jsrt.cpp b/lib/Jsrt/Jsrt.cpp index 39b8009d491..4d3fd84afd2 100644 --- a/lib/Jsrt/Jsrt.cpp +++ b/lib/Jsrt/Jsrt.cpp @@ -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); diff --git a/lib/Jsrt/JsrtCommonExports.inc b/lib/Jsrt/JsrtCommonExports.inc index 9bc6d7530aa..b7447e3f915 100644 --- a/lib/Jsrt/JsrtCommonExports.inc +++ b/lib/Jsrt/JsrtCommonExports.inc @@ -5,6 +5,7 @@ JsAddRef JsRelease JsCreateContext + JsGetContextUrl JsGetCurrentContext JsSetCurrentContext JsGetContextOfObject diff --git a/lib/Runtime/Base/ScriptContext.cpp b/lib/Runtime/Base/ScriptContext.cpp index b2e41e5b7c6..f0c5c2dc771 100644 --- a/lib/Runtime/Base/ScriptContext.cpp +++ b/lib/Runtime/Base/ScriptContext.cpp @@ -33,6 +33,7 @@ #ifdef ENABLE_BASIC_TELEMETRY #include "ScriptContextTelemetry.h" #endif +#include "Codex/Utf8Helper.h" namespace Js { @@ -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 diff --git a/lib/Runtime/Base/ScriptContext.h b/lib/Runtime/Base/ScriptContext.h index 7b453fc7b1e..34c7acf1293 100644 --- a/lib/Runtime/Base/ScriptContext.h +++ b/lib/Runtime/Base/ScriptContext.h @@ -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