Early this year, I faced a wall when trying to implement basic offline map routing (gregvolny/CSPro-Demos#7) efficiently in CSPro's QuickJS worker thread engine....
Response from GPT-5.2-Codex (used last January)
The QuickJS context is created with JS_NewContext, and only print, console, and the CS Action Invoker are added. There are no calls to js_std, js_os, JS_AddIntrinsicOS, or any Worker registration.
See Executor.cpp:1-75.
There is no Worker API or os.Worker exposure in zJavaScript. The “worker” functions in Executor.cpp are internal helpers for wrapping module functions (e.g., ExecuteFunctionWorker), not thread workers.
See Executor.cpp:695-755.
QuickJSAccess only handles context/runtime setup, module loading, and error handling. No Worker hooks.
See QuickJSAccess.h and QuickJSAccess.cpp:1-200.
Conclusion: CSPro’s current zJavaScript integration does not provide complete QuickJS support for Workers (os.Worker), so Worker-based multithreading is not available without additional native integration.
I used a workaround running some codes in the Webview's QSF worker thread and partly solve the issue. However, This "background webview" is only available for items having QSF, not for other form components such as level, etc.
Thanks to powerful LLMs, I implemented low level technical report to understand how QuickJS and Webview (V8 JS Engine) can communicate and I'm sharing them with you.
As I mentioned to @Oryxamus, implementing event loop (or other appropriate technologies) in CSPro logic or QuickJS NG can facilitate expanding
CS.getWindowForEventListener().addEventListener("message", event => {
// ...
});
where a "Window" environment simply don't exist such as in CSPro logic and QuickJS.
CSPro 8.1 — QuickJS ↔ WebView JavaScript Communication Report
Date: Jan 2026 (Updated: April 2026)
Scope: Analysis of how JavaScript executed in QuickJS-NG and JavaScript running in WebView2 (Chromium) communicate within CSPro 8.1's architecture
Source: cspro-dev 8.1 codebase
Executive Summary
CSPro 8.1 embeds two distinct JavaScript engines: QuickJS-NG (a lightweight C-based engine for CSPro Logic scripting) and WebView2/WebView (the Chromium-based rendering engine for HTML dialogs, views, Question text and can also be used to run JS ). These two engines do not communicate directly with each other. Instead, both route through a shared C++ ActionInvoker::Runtime instance — the central dispatch hub that processes all Action Invoker requests regardless of origin.
WebView/WebView2 has two JavaScript APIs: the new CSProActionInvoker class (full Action Invoker wrapper with all 16 namespaces, loaded from action-invoker.js) and the legacy CSPro class (deprecated since 8.0, injected via AddScriptToExecuteOnDocumentCreated(), will be removed). The legacy CSPro.runLogic() method still exists but wraps Logic.eval — new projects should use CSProActionInvoker.
There is no dedicated "JS" or "JavaScript" namespace in the Action Invoker. The 16 namespaces are: Application, Clipboard, Data, Dictionary, File, Hash, Localhost, Logic, Message, Network, Path, Settings, Sqlite, Sync, System, and UI — plus 3 global actions (execute, registerAccessToken, throwException). The Logic namespace serves as the primary cross-engine bridge, enabling both engines to (evaluate CSPro Logic expressions in the future), invoke functions, and read/write symbol values through the shared interpreter state.
Table of Contents
- Architecture Overview
- The Two JavaScript Engines
- Action Invoker Namespaces — No "JS" Namespace
- QuickJS → C++ Communication Path
- WebView2 → C++ Communication Path
- C++ → WebView2 Communication Path
- The Logic Namespace as a Cross-Engine Bridge
- Shared ActionInvoker::Runtime — The Hub
- Synchronous vs. Asynchronous Patterns
- Security: Access Token Model
- Sequence Diagrams
- Key Source Files
- Practical Implications
- Conclusion
The full report can be read here:
CSPro_QuickJS_WebView_JS_Communication_Report.md
PS: I also implemented a report about direct communication pathways between these two JS engines in the CSPro ecosystem. I will share it very soon.
Early this year, I faced a wall when trying to implement basic offline map routing (gregvolny/CSPro-Demos#7) efficiently in CSPro's QuickJS worker thread engine....
Response from GPT-5.2-Codex (used last January)
I used a workaround running some codes in the Webview's QSF worker thread and partly solve the issue. However, This "background webview" is only available for items having QSF, not for other form components such as level, etc.
Thanks to powerful LLMs, I implemented low level technical report to understand how QuickJS and Webview (V8 JS Engine) can communicate and I'm sharing them with you.
As I mentioned to @Oryxamus, implementing event loop (or other appropriate technologies) in CSPro logic or QuickJS NG can facilitate expanding
where a "Window" environment simply don't exist such as in CSPro logic and QuickJS.
CSPro 8.1 — QuickJS ↔ WebView JavaScript Communication Report
Date: Jan 2026 (Updated: April 2026)
Scope: Analysis of how JavaScript executed in QuickJS-NG and JavaScript running in WebView2 (Chromium) communicate within CSPro 8.1's architecture
Source:
cspro-dev 8.1codebaseExecutive Summary
CSPro 8.1 embeds two distinct JavaScript engines: QuickJS-NG (a lightweight C-based engine for CSPro Logic scripting) and WebView2/WebView (the Chromium-based rendering engine for HTML dialogs, views, Question text and can also be used to run JS ). These two engines do not communicate directly with each other. Instead, both route through a shared C++
ActionInvoker::Runtimeinstance — the central dispatch hub that processes all Action Invoker requests regardless of origin.WebView/WebView2 has two JavaScript APIs: the new
CSProActionInvokerclass (full Action Invoker wrapper with all 16 namespaces, loaded fromaction-invoker.js) and the legacyCSProclass (deprecated since 8.0, injected viaAddScriptToExecuteOnDocumentCreated(), will be removed). The legacyCSPro.runLogic()method still exists but wrapsLogic.eval— new projects should useCSProActionInvoker.There is no dedicated "JS" or "JavaScript" namespace in the Action Invoker. The 16 namespaces are: Application, Clipboard, Data, Dictionary, File, Hash, Localhost, Logic, Message, Network, Path, Settings, Sqlite, Sync, System, and UI — plus 3 global actions (
execute,registerAccessToken,throwException). The Logic namespace serves as the primary cross-engine bridge, enabling both engines to (evaluate CSPro Logic expressions in the future), invoke functions, and read/write symbol values through the shared interpreter state.Table of Contents
The full report can be read here:
CSPro_QuickJS_WebView_JS_Communication_Report.md
PS: I also implemented a report about direct communication pathways between these two JS engines in the CSPro ecosystem. I will share it very soon.