summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorStephan Bergmann <stephan.bergmann@allotropia.de>2024-08-14 16:54:49 +0200
committerStephan Bergmann <stephan.bergmann@allotropia.de>2024-08-14 21:57:00 +0200
commitcccc983eb3f0532dbf7e3edf4477ce63ec3d2795 (patch)
treecba9fe3b1bd9277fba60173199ffb43cdaf5a365 /desktop
parentd193bf5cec65ab55d5a76b3a4f68eb52e5a747f3 (diff)
Emscripten: Run external code on LO's main thread
...and not the browser's main thread. Those are different threads now since 6e6451ce96f47e0ef5e8ecf1750f394ff3fb48e4 "Emscripten: Move the Qt event loop off the JS main thread". Running `Module.uno_init.then` on the browser's main thread would never trigger, as that promise is only resolved on LO's main thread. When external code was included in soffice.js via EMSCRIPTEN_EXTRA_SOFFICE_POST_JS, that didn't make a difference: Emscripten effectively replicates that code to all the worker threads, so whatever worker thread resolved the Module.uno_init promise (i.e., the LO main thread) had the external code available and ran it. But when external code was included directly in some HTML file (which "manually" provides a canvas and loads soffice.js, not relying on the qt_soffice.html convenience functionality), it was available in the browser's main thread but not in LO's main thread. For that use case, introduce a new Module.uno_scripts array that can be set up in the HTML file to contain an array of URLs (represented as strings) of scripts to load into LO's main thread. (Alternatively, running external code on the browser's main thread rather than on LO's main thread could be more ideal in the sense that the external code would then have access to the browser's document object. But, for one, it would be less ideal in the sense that we would then potentially again execute LO code (which we call into from the external code via UNO) on the browser's main thread, which would bring back the issues that 6e6451ce96f47e0ef5e8ecf1750f394ff3fb48e4 "Emscripten: Move the Qt event loop off the JS main thread" solved. And, for another, when I experimentally tried it out, it caused massive Qt threading issues, so I quickly gave up again.) Change-Id: If01a7859751706f168e93ccac75758ae5ce17cd2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171870 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Diffstat (limited to 'desktop')
-rw-r--r--desktop/source/app/appinit.cxx51
1 files changed, 49 insertions, 2 deletions
diff --git a/desktop/source/app/appinit.cxx b/desktop/source/app/appinit.cxx
index f2b7edba1c8e..6f8bffa1146a 100644
--- a/desktop/source/app/appinit.cxx
+++ b/desktop/source/app/appinit.cxx
@@ -19,6 +19,10 @@
#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <string>
+#include <vector>
#include <app.hxx>
#include <dp_shared.hxx>
@@ -46,6 +50,8 @@
#if defined EMSCRIPTEN
#include <emscripten.h>
+#include <emscripten/threading.h>
+#include <emscripten/val.h>
#include <bindings_uno.hxx>
#endif
@@ -53,6 +59,48 @@ using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::ucb;
+#if defined EMSCRIPTEN
+
+namespace {
+
+extern "C" void getUnoScriptUrls(std::vector<std::u16string> * urls) {
+ assert(urls != nullptr);
+ auto const val = emscripten::val::module_property("uno_scripts");
+ if (!val.isUndefined()) {
+ auto const len = val["length"].as<std::uint32_t>();
+ for (std::uint32_t i = 0; i != len; ++i) {
+ urls->push_back(val[i].as<std::u16string>());
+ }
+ }
+}
+
+EM_JS(void, runUnoScriptUrl, (char16_t const * url), {
+ fetch(UTF16ToString(url)).then(res => {
+ if (!res.ok) {
+ throw Error(
+ "Loading <" + res.url + "> failed with " + res.status + " " + res.statusText);
+ }
+ return res.blob();
+ }).then(blob => blob.text()).then(text => eval(text));
+});
+
+void initUno() {
+ init_unoembind_uno();
+ EM_ASM(Module.uno_init$resolve(););
+ std::vector<std::u16string> urls;
+ emscripten_sync_run_in_main_runtime_thread(EM_FUNC_SIG_VI, getUnoScriptUrls, &urls);
+ for (auto const & url: urls) {
+ if (url.find('\0') != std::u16string::npos) {
+ throw std::invalid_argument("Module.uno_scripts element contains embedded NUL");
+ }
+ runUnoScriptUrl(url.c_str());
+ }
+}
+
+}
+
+#endif
+
namespace desktop
{
@@ -86,8 +134,7 @@ void Desktop::InitApplicationServiceManager()
#endif
comphelper::setProcessServiceFactory(sm);
#if defined EMSCRIPTEN
- init_unoembind_uno();
- EM_ASM(Module.uno_init$resolve(););
+ initUno();
#endif
}