Emscripten: Establish a channel between browser and LO main threads

...to be used by external code, to mitigate the issue mentioned in the commit
message of cccc983eb3 "Emscripten: Run external
code on 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."

On the browser main thread, external JS code can now await a Module.uno_main
Promise that provides one port of a MessageChannel.  And on the LO main thread,
external JS code has access to the other port of that MessageChannel as
Module.uno_mainPort.  (And the external code is completely free in what
onmessage handlers to set up and what form of postMessage calls to use on those
two MessagePorts.)

Change-Id: Iab6bc7676c744eacb70ddd9f3f80f64e9efd1cf1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171907
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Tested-by: Jenkins
This commit is contained in:
Stephan Bergmann
2024-08-15 15:18:29 +02:00
parent f684f284de
commit e952204b40
2 changed files with 36 additions and 1 deletions

View File

@@ -84,9 +84,36 @@ EM_JS(void, runUnoScriptUrl, (char16_t const * url), {
}).then(blob => blob.text()).then(text => eval(text));
});
EM_JS(void, setupMainChannel, (), {
const orig = self.onmessage;
self.onmessage = function(e) {
if (e.data.cmd === "LOWA-channel") {
self.onmessage = orig;
Module.uno_mainPort = e.ports[0];
} else if (orig) {
orig(e);
}
};
});
extern "C" void resolveUnoMain() {
EM_ASM(
let sofficeMain;
for (const i in PThread.pthreads) {
const worker = PThread.pthreads[i];
if (worker.workerID === 1) {
sofficeMain = worker;
break;
}
}
const channel = new MessageChannel();
sofficeMain.postMessage({cmd:"LOWA-channel"}, [channel.port2]);
Module.uno_main$resolve(channel.port1);
);
}
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) {
@@ -95,6 +122,9 @@ void initUno() {
}
runUnoScriptUrl(url.c_str());
}
setupMainChannel();
EM_ASM(Module.uno_init$resolve(););
emscripten_async_run_in_main_runtime_thread(EM_FUNC_SIG_V, resolveUnoMain);
}
}

View File

@@ -19,6 +19,11 @@ Module.uno_init = new Promise(function (resolve, reject) {
Module.uno_init$reject = reject;
});
Module.uno_main = new Promise(function (resolve, reject) {
Module.uno_main$resolve = resolve;
Module.uno_main$reject = reject;
});
Module.catchUnoException = function(exception) {
// Rethrow non-C++ exceptions (non-UNO C++ exceptions are mapped to css.uno.RuntimeException in
// Module.getUnoExceptionFromCxaException):