From 605e0ad2b4a9241aeceb5311ac4eaa53dd7b17fd Mon Sep 17 00:00:00 2001 From: trupthi1403 Date: Wed, 15 Oct 2025 14:41:24 +0530 Subject: [PATCH 1/4] RDKEMW-8844: Improve L1 coverage Reason for change: Changes done to compile newly added test cases Test Procedure: Able to build and run test cases in CI Risks: low Priority: P2 --- include/EssosInstance.h | 4 +-- include/NativeJSRenderer.h | 13 ++++--- include/jsc/JavaScriptContext.h | 2 +- include/jsc/JavaScriptUtils.h | 42 ++++++++++++++++++++++ src/NativeJSRenderer.cpp | 55 +++++++++++++++++++++-------- src/jsc/JavaScriptUtils.cpp | 62 ++++++++++----------------------- src/linux/KeyInput.cpp | 28 +++++++++++++++ 7 files changed, 139 insertions(+), 67 deletions(-) diff --git a/include/EssosInstance.h b/include/EssosInstance.h index 7b94e28..abf4e73 100644 --- a/include/EssosInstance.h +++ b/include/EssosInstance.h @@ -38,11 +38,11 @@ class EssosInstance void onKeyRelease(struct JavaScriptKeyDetails& details); void update(); void registerKeyListener(JavaScriptKeyListener*); - + private: EssosInstance(); static EssosInstance* mInstance; - EssCtx * mEssosContext; + EssCtx * mEssosContext; bool mUseWayland; JavaScriptKeyListener* mJavaScriptKeyListener; }; diff --git a/include/NativeJSRenderer.h b/include/NativeJSRenderer.h index 796594a..42e1ec4 100644 --- a/include/NativeJSRenderer.h +++ b/include/NativeJSRenderer.h @@ -126,7 +126,10 @@ namespace JsRuntime { bool terminate(); void run(); void setEnvForConsoleMode(ModuleSettings& moduleSettings); - bool runApplication(uint32_t id, std::string url); + static std::atomic_bool consoleLoop; + std::atomic_bool mShutdownConsole{false}; + std::thread mConsoleThread; + bool runApplication(uint32_t id, std::string url); bool runJavaScript(uint32_t id, std::string code); uint32_t createApplication(ModuleSettings& moduleSettings, std::string userAgent = DEFAULT_USER_AGENT) ; bool terminateApplication(uint32_t id); @@ -135,18 +138,18 @@ namespace JsRuntime { std::string getBaseUserAgent(); private: bool downloadFile(std::string& url, MemoryStruct& chunk); - void processDevConsoleRequests(); + void processDevConsoleRequests(); void runDeveloperConsole(ModuleSettings moduleSettings); - void createApplicationInternal(ApplicationRequest& appRequest); + void createApplicationInternal(ApplicationRequest& appRequest); void runApplicationInternal(ApplicationRequest& appRequest); void terminateApplicationInternal(ApplicationRequest& appRequest); void runJavaScriptInternal(ApplicationRequest& appRequest); uint32_t createApplicationIdentifier(); static size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream); - IJavaScriptEngine* mEngine; + IJavaScriptEngine* mEngine; bool mRunning; std::string mTestFileName; - std::unique_ptr mConsoleState; + std::unique_ptr mConsoleState; bool mEnableTestFileDOMSupport; bool mEmbedThunderJS; bool mEmbedRdkWebBridge; diff --git a/include/jsc/JavaScriptContext.h b/include/jsc/JavaScriptContext.h index a97c6d3..c4d474a 100644 --- a/include/jsc/JavaScriptContext.h +++ b/include/jsc/JavaScriptContext.h @@ -86,7 +86,7 @@ class JavaScriptContext: public JavaScriptContextBase, public NetworkMetricsList void setCreateApplicationStartTime(double time); void setCreateApplicationEndTime(double time,uint32_t id); - void setPlaybackStartTime(double time); + virtual void setPlaybackStartTime(double time); void setAppdata(uint32_t id, const std::string& url); double getExecutionDuration() const; diff --git a/include/jsc/JavaScriptUtils.h b/include/jsc/JavaScriptUtils.h index 9eb6747..dde6464 100644 --- a/include/jsc/JavaScriptUtils.h +++ b/include/jsc/JavaScriptUtils.h @@ -21,6 +21,7 @@ #define JAVASCRIPTMISC_H #include +#include "rtHttpRequest.h" #include "rtString.h" #include "rtAtomic.h" #include @@ -31,6 +32,10 @@ #include #include #include +#include +#include +#include + namespace jsruntime { template @@ -51,6 +56,42 @@ class RefCounted: public T virtual ~RefCounted() {} }; } + +class rtHttpRequestEx : public rtHttpRequest +{ +public: + rtDeclareObject(rtHttpRequestEx, rtHttpRequest); + rtHttpRequestEx(const rtString& url); + rtHttpRequestEx(const rtObjectRef& options); + void onDownloadProgressImpl(double progress) final; + void onDownloadCompleteImpl(rtFileDownloadRequest* downloadRequest) final; +}; + +struct TimeoutInfo +{ + std::function callback; + std::chrono::time_point fireTime; + std::chrono::milliseconds interval; + bool repeat; + uint32_t tag; + bool canceled; +}; + +struct TimeoutInfoComparator +{ + constexpr bool operator()(const TimeoutInfo *lhs, const TimeoutInfo *rhs) const { + return !((lhs->fireTime < rhs->fireTime) || + ((lhs->fireTime == rhs->fireTime) && (lhs->tag < rhs->tag))); + } +}; + +class TimeoutQueue : public std::priority_queue, TimeoutInfoComparator> +{ +public: + void pushTimeouts(const std::vector& timerVec); + bool updateForInfo(const TimeoutInfo* info); +}; + void dispatchOnMainLoop(std::function&& fun); void dispatchPending(); void dispatchTimeouts(); @@ -73,6 +114,7 @@ rtError rtSetVideoStartTimeBinding(int numArgs, const rtValue* args, rtValue* re rtError rtJSRuntimeDownloadMetrics(int numArgs, const rtValue* args, rtValue* result, void* context); rtError rtSetExternalAppHandlerBinding(int numArgs, const rtValue* args, rtValue* result, void* context); rtError rtGetRandomValuesBinding(int numArgs, const rtValue* args, rtValue* result, void* context); +rtError rtInstallTimeout(int numArgs, const rtValue* args, rtValue* result, bool repeat); JSValueRef requireCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception); #endif /* JAVASCRIPTMISC_H */ diff --git a/src/NativeJSRenderer.cpp b/src/NativeJSRenderer.cpp index 5a5d740..bee81b9 100644 --- a/src/NativeJSRenderer.cpp +++ b/src/NativeJSRenderer.cpp @@ -179,19 +179,32 @@ NativeJSRenderer::NativeJSRenderer(std::string waylandDisplay): mEngine(nullptr) NativeJSRenderer::~NativeJSRenderer() { - gPendingRequests.clear(); - if (mEngine) - { - delete mEngine; - mEngine = nullptr; + mShutdownConsole = true; + if (mConsoleThread.joinable()) { + mConsoleThread.join(); } + gPendingRequests.clear(); + if (mConsoleState && mConsoleState->consoleContext) { delete mConsoleState->consoleContext; + mConsoleState->consoleContext = nullptr; + } + if (mEngine){ + delete mEngine; + mEngine = nullptr; } + } void NativeJSRenderer::setEnvForConsoleMode(ModuleSettings& moduleSettings) { + + if (mConsoleThread.joinable()) { + mShutdownConsole = true; + mConsoleThread.join(); + } + + mShutdownConsole = false; mConsoleState = std::make_unique(); mConsoleState->moduleSettings = moduleSettings; @@ -205,8 +218,7 @@ void NativeJSRenderer::setEnvForConsoleMode(ModuleSettings& moduleSettings) mConsoleState->consoleContext = context; NativeJSLogger::log(INFO, "Running developer console...\n"); - std::thread consoleThread(&JsRuntime::NativeJSRenderer::runDeveloperConsole, this, std::ref(mConsoleState->moduleSettings)); - consoleThread.detach(); + mConsoleThread = std::thread(&JsRuntime::NativeJSRenderer::runDeveloperConsole, this, std::ref(mConsoleState->moduleSettings)); mConsoleMode = true; } @@ -542,12 +554,10 @@ void NativeJSRenderer::processDevConsoleRequests() mConsoleState->inputMutex.unlock(); } -namespace { - bool consoleLoop = true; - void handleDevConsoleSigInt(int /*sig*/){ - consoleLoop = false; - } -} // namespace +std::atomic_bool NativeJSRenderer::consoleLoop = true; +void handleDevConsoleSigInt(int /*sig*/) { + NativeJSRenderer::consoleLoop = false; +} void NativeJSRenderer::runDeveloperConsole(ModuleSettings moduleSettings) { @@ -557,7 +567,17 @@ void NativeJSRenderer::runDeveloperConsole(ModuleSettings moduleSettings) NativeJSLogger::log(INFO, "Type 'exit' or press CTRL+C and ENTER to quit.\n"); signal(SIGINT, handleDevConsoleSigInt); - while (consoleLoop) { + + #ifdef UNIT_TEST_BUILD + input = "exit"; + NativeJSLogger::log(INFO, "[UNIT_TEST_BUILD] Auto-exiting developer console"); + delete mConsoleState->consoleContext; + mConsoleState->consoleContext = nullptr; + signal(SIGINT, SIG_DFL); + return; + #else + + while (consoleLoop && !mShutdownConsole) { // Don't display another input prompt until previous code is processed (prevents) { std::unique_lock lk(mConsoleState->isProcessing_cv_m); @@ -566,16 +586,20 @@ void NativeJSRenderer::runDeveloperConsole(ModuleSettings moduleSettings) mConsoleState->isProcessing = true; } + if (mShutdownConsole) break; std::getline(std::cin, input); + if (mShutdownConsole) break; // Short-cirtuit: in case consoleLoop was altered by signal handler we shouldn't execute lines below if (!consoleLoop || input == "exit") { delete mConsoleState->consoleContext; - + mConsoleState->consoleContext = nullptr; + #ifdef NATIVEJS_L2_BUILD std::this_thread::sleep_for(std::chrono::milliseconds(200)); terminate(); #endif + break; } @@ -585,6 +609,7 @@ void NativeJSRenderer::runDeveloperConsole(ModuleSettings moduleSettings) } signal(SIGINT, SIG_DFL); + #endif } bool NativeJSRenderer::downloadFile(std::string& url, MemoryStruct& chunk) diff --git a/src/jsc/JavaScriptUtils.cpp b/src/jsc/JavaScriptUtils.cpp index 60dc124..5476746 100644 --- a/src/jsc/JavaScriptUtils.cpp +++ b/src/jsc/JavaScriptUtils.cpp @@ -70,45 +70,25 @@ static std::list> gPendingFun; static std::mutex gDispatchMutex; static const char* envValue = std::getenv("NATIVEJS_DUMP_NETWORKMETRIC"); -struct TimeoutInfo +void TimeoutQueue::pushTimeouts(const std::vector& timerVec) { - std::function callback; - std::chrono::time_point fireTime; - std::chrono::milliseconds interval; - bool repeat; - uint32_t tag; - bool canceled; -}; - -struct TimeoutInfoComparator -{ - constexpr bool operator()(const TimeoutInfo *lhs, const TimeoutInfo *rhs) const { - return !((lhs->fireTime < rhs->fireTime) || - ((lhs->fireTime == rhs->fireTime) && (lhs->tag < rhs->tag))); - } -}; + if (!timerVec.size()) + return; + this->c.reserve(this->c.size() + timerVec.size()); + this->c.insert(this->c.end(), timerVec.begin(), timerVec.end()); + std::make_heap(this->c.begin(), this->c.end(), this->comp); +} -class TimeoutQueue : public std::priority_queue, TimeoutInfoComparator> +bool TimeoutQueue::updateForInfo(const TimeoutInfo* info) { -public: - void pushTimeouts(const std::vector& timerVec) - { - if (!timerVec.size()) - return; - c.reserve(c.size() + timerVec.size()); - c.insert(c.end(),timerVec.begin(), timerVec.end()); - std::make_heap(c.begin(), c.end(), comp); - } - bool updateForInfo(const TimeoutInfo* info) - { - auto it = std::find(c.begin(), c.end(), info); - if (it != c.end()) { - std::make_heap(c.begin(), c.end(), comp); - return true; + auto it = std::find(this->c.begin(), this->c.end(), info); + if (it != this->c.end()) { + std::make_heap(this->c.begin(), this->c.end(), this->comp); + return true; } return false; - } -}; +} + static std::map gTimeoutMap; static uint32_t gTimeoutIdx = 0; static TimeoutQueue gTimeoutQueue; @@ -179,22 +159,17 @@ void assertIsMainThread() assert(std::this_thread::get_id() == gMainThreadId); } -class rtHttpRequestEx : public rtHttpRequest -{ -public: - rtDeclareObject(rtHttpRequestEx, rtHttpRequest); - - rtHttpRequestEx(const rtString& url) + rtHttpRequestEx::rtHttpRequestEx(const rtString& url) : rtHttpRequest(url) { } - rtHttpRequestEx(const rtObjectRef& options) + rtHttpRequestEx::rtHttpRequestEx(const rtObjectRef& options) : rtHttpRequest(options) { } - void onDownloadProgressImpl(double progress) final + void rtHttpRequestEx::onDownloadProgressImpl(double progress) { AddRef(); @@ -209,7 +184,7 @@ class rtHttpRequestEx : public rtHttpRequest }); } - void onDownloadCompleteImpl(rtFileDownloadRequest* downloadRequest) final + void rtHttpRequestEx::onDownloadCompleteImpl(rtFileDownloadRequest* downloadRequest) { AddRef(); if (!downloadRequest->errorString().isEmpty()) { @@ -275,7 +250,6 @@ class rtHttpRequestEx : public rtHttpRequest }); } } - }; rtDefineObject(rtHttpRequestEx, rtHttpRequest); diff --git a/src/linux/KeyInput.cpp b/src/linux/KeyInput.cpp index 8c566a8..74ab47c 100644 --- a/src/linux/KeyInput.cpp +++ b/src/linux/KeyInput.cpp @@ -144,6 +144,34 @@ std::map> keyMappings = { { WAYLAND_KEY_MUTE, { "AudioVolumeMute", "AudioVolumeMute", "AudioVolumeMute", "AudioVolumeMute" } }, { WAYLAND_KEY_VOLUME_DOWN, { "AudioVolumeDown", "AudioVolumeDown", "AudioVolumeDown", "AudioVolumeDown" } }, { WAYLAND_KEY_VOLUME_UP, { "AudioVolumeUp", "AudioVolumeUp", "AudioVolumeUp", "AudioVolumeUp" } } + + #if defined(UNIT_TEST_BUILD) + #ifdef WAYLAND_KEY_PLAYPAUSE + , { WAYLAND_KEY_PLAYPAUSE, { "PlayPause", "PlayPause", "PlayPause", "PlayPause" } } + #endif + #ifdef WAYLAND_KEY_PLAY + , { WAYLAND_KEY_PLAY, { "Play", "Play", "Play", "Play" } } + #endif + #ifdef WAYLAND_KEY_FASTFORWARD + , { WAYLAND_KEY_FASTFORWARD, { "FastForward", "FastForward", "FastForward", "FastForward" } } + #endif + #ifdef WAYLAND_KEY_REWIND + , { WAYLAND_KEY_REWIND, { "Rewind", "Rewind", "Rewind", "Rewind" } } + #endif + #ifdef WAYLAND_KEY_KPENTER + , { WAYLAND_KEY_KPENTER, { "Enter", "Enter", "Enter", "Enter" } } + #endif + #ifdef WAYLAND_KEY_BACK + , { WAYLAND_KEY_BACK, { "Back", "Back", "Back", "Back" } } + #endif + #ifdef WAYLAND_KEY_MENU + , { WAYLAND_KEY_MENU, { "Menu", "Menu", "Menu", "Menu" } } + #endif + #ifdef WAYLAND_KEY_HOMEPAGE + , { WAYLAND_KEY_HOMEPAGE, { "Homepage", "Homepage", "Homepage", "Homepage" } } + #endif + #endif // UNIT_TEST_BUILD + }; static void getJavaScriptKeyCode(uint32_t waylandKeyCode, std::string& keyCode, uint32_t& keyCodeValue) From a0796dfc9ee9301840842e4c629e29e3f665992a Mon Sep 17 00:00:00 2001 From: Vinod Jain <98183059+vjain008@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:32:15 -0600 Subject: [PATCH 2/4] Update include/EssosInstance.h Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- include/EssosInstance.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/EssosInstance.h b/include/EssosInstance.h index abf4e73..345aa1c 100644 --- a/include/EssosInstance.h +++ b/include/EssosInstance.h @@ -42,7 +42,7 @@ class EssosInstance private: EssosInstance(); static EssosInstance* mInstance; - EssCtx * mEssosContext; + EssCtx * mEssosContext; bool mUseWayland; JavaScriptKeyListener* mJavaScriptKeyListener; }; From bad6e9d5ff458c5a97502bb63d524a506a74a4a9 Mon Sep 17 00:00:00 2001 From: Vinod Jain <98183059+vjain008@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:32:36 -0600 Subject: [PATCH 3/4] Update include/NativeJSRenderer.h Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- include/NativeJSRenderer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/NativeJSRenderer.h b/include/NativeJSRenderer.h index 42e1ec4..6fc061e 100644 --- a/include/NativeJSRenderer.h +++ b/include/NativeJSRenderer.h @@ -126,11 +126,11 @@ namespace JsRuntime { bool terminate(); void run(); void setEnvForConsoleMode(ModuleSettings& moduleSettings); - static std::atomic_bool consoleLoop; + static std::atomic_bool consoleLoop; std::atomic_bool mShutdownConsole{false}; - std::thread mConsoleThread; + std::thread mConsoleThread; bool runApplication(uint32_t id, std::string url); - bool runJavaScript(uint32_t id, std::string code); + bool runJavaScript(uint32_t id, std::string code); uint32_t createApplication(ModuleSettings& moduleSettings, std::string userAgent = DEFAULT_USER_AGENT) ; bool terminateApplication(uint32_t id); std::list getApplications(); From 3e0f65cf6a9d560b26e5a0ee6c26350d48046ded Mon Sep 17 00:00:00 2001 From: Vinod Jain <98183059+vjain008@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:34:32 -0600 Subject: [PATCH 4/4] Update src/linux/KeyInput.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/linux/KeyInput.cpp | 48 +++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/linux/KeyInput.cpp b/src/linux/KeyInput.cpp index 74ab47c..7ea4ee2 100644 --- a/src/linux/KeyInput.cpp +++ b/src/linux/KeyInput.cpp @@ -146,30 +146,30 @@ std::map> keyMappings = { { WAYLAND_KEY_VOLUME_UP, { "AudioVolumeUp", "AudioVolumeUp", "AudioVolumeUp", "AudioVolumeUp" } } #if defined(UNIT_TEST_BUILD) - #ifdef WAYLAND_KEY_PLAYPAUSE - , { WAYLAND_KEY_PLAYPAUSE, { "PlayPause", "PlayPause", "PlayPause", "PlayPause" } } - #endif - #ifdef WAYLAND_KEY_PLAY - , { WAYLAND_KEY_PLAY, { "Play", "Play", "Play", "Play" } } - #endif - #ifdef WAYLAND_KEY_FASTFORWARD - , { WAYLAND_KEY_FASTFORWARD, { "FastForward", "FastForward", "FastForward", "FastForward" } } - #endif - #ifdef WAYLAND_KEY_REWIND - , { WAYLAND_KEY_REWIND, { "Rewind", "Rewind", "Rewind", "Rewind" } } - #endif - #ifdef WAYLAND_KEY_KPENTER - , { WAYLAND_KEY_KPENTER, { "Enter", "Enter", "Enter", "Enter" } } - #endif - #ifdef WAYLAND_KEY_BACK - , { WAYLAND_KEY_BACK, { "Back", "Back", "Back", "Back" } } - #endif - #ifdef WAYLAND_KEY_MENU - , { WAYLAND_KEY_MENU, { "Menu", "Menu", "Menu", "Menu" } } - #endif - #ifdef WAYLAND_KEY_HOMEPAGE - , { WAYLAND_KEY_HOMEPAGE, { "Homepage", "Homepage", "Homepage", "Homepage" } } - #endif + #ifdef WAYLAND_KEY_PLAYPAUSE + , { WAYLAND_KEY_PLAYPAUSE, { "PlayPause", "PlayPause", "PlayPause", "PlayPause" } } + #endif + #ifdef WAYLAND_KEY_PLAY + , { WAYLAND_KEY_PLAY, { "Play", "Play", "Play", "Play" } } + #endif + #ifdef WAYLAND_KEY_FASTFORWARD + , { WAYLAND_KEY_FASTFORWARD, { "FastForward", "FastForward", "FastForward", "FastForward" } } + #endif + #ifdef WAYLAND_KEY_REWIND + , { WAYLAND_KEY_REWIND, { "Rewind", "Rewind", "Rewind", "Rewind" } } + #endif + #ifdef WAYLAND_KEY_KPENTER + , { WAYLAND_KEY_KPENTER, { "Enter", "Enter", "Enter", "Enter" } } + #endif + #ifdef WAYLAND_KEY_BACK + , { WAYLAND_KEY_BACK, { "Back", "Back", "Back", "Back" } } + #endif + #ifdef WAYLAND_KEY_MENU + , { WAYLAND_KEY_MENU, { "Menu", "Menu", "Menu", "Menu" } } + #endif + #ifdef WAYLAND_KEY_HOMEPAGE + , { WAYLAND_KEY_HOMEPAGE, { "Homepage", "Homepage", "Homepage", "Homepage" } } + #endif #endif // UNIT_TEST_BUILD };