diff --git a/engine/src/flutter/lib/web_ui/skwasm/library_skwasm_support.js b/engine/src/flutter/lib/web_ui/skwasm/library_skwasm_support.js index 702724e71d..ac98d599ca 100644 --- a/engine/src/flutter/lib/web_ui/skwasm/library_skwasm_support.js +++ b/engine/src/flutter/lib/web_ui/skwasm/library_skwasm_support.js @@ -8,51 +8,72 @@ mergeInto(LibraryManager.library, { $skwasm_support_setup__postset: 'skwasm_support_setup();', $skwasm_support_setup: function() { - // This value represents the difference between the time origin of the main - // thread and whichever web worker this code is running on. This is so that - // when we report frame timings, that they are in the same time domain - // regardless of whether they are captured on the main thread or the web - // worker. - let timeOriginDelta = 0; - skwasm_registerMessageListener = function(threadId, listener) { - const eventListener = function({data}) { - const skwasmMessage = data.skwasmMessage; - if (!skwasmMessage) { - return; - } - if (skwasmMessage == 'syncTimeOrigin') { - timeOriginDelta = performance.timeOrigin - data.timeOrigin; - return; - } - listener(data); + if (Module["skwasmSingleThreaded"]) { + _skwasm_isSingleThreaded = function() { + return true; }; - if (!threadId) { - addEventListener("message", eventListener); - } else { - _wasmWorkers[threadId].addEventListener("message", eventListener); - _wasmWorkers[threadId].postMessage({ - skwasmMessage: 'syncTimeOrigin', - timeOrigin: performance.timeOrigin, - }); + + let messageListener; + // In single threaded mode, we simply invoke the message listener as a + // microtask, as it's much cheaper than doing a full postMessage + skwasm_registerMessageListener = function(threadId, listener) { + messageListener = listener; } - }; - skwasm_getCurrentTimestamp = function() { - return performance.now() + timeOriginDelta; - }; - skwasm_postMessage = function(message, transfers, threadId) { - if (threadId) { - _wasmWorkers[threadId].postMessage(message, transfers); - } else { - postMessage(message, transfers); - } - }; + skwasm_getCurrentTimestamp = function() { + return performance.now(); + }; + skwasm_postMessage = function(message, transfers, threadId) { + // If we're in single-threaded mode, we shouldn't use postMessage, as + // it ends up being quite expensive. Instead, just queue a microtask. + queueMicrotask(() => messageListener(message)); + }; + } else { + _skwasm_isSingleThreaded = function() { + return false; + }; + + // This value represents the difference between the time origin of the main + // thread and whichever web worker this code is running on. This is so that + // when we report frame timings, that they are in the same time domain + // regardless of whether they are captured on the main thread or the web + // worker. + let timeOriginDelta = 0; + skwasm_registerMessageListener = function(threadId, listener) { + const eventListener = function({data}) { + const skwasmMessage = data.skwasmMessage; + if (!skwasmMessage) { + return; + } + if (skwasmMessage == 'syncTimeOrigin') { + timeOriginDelta = performance.timeOrigin - data.timeOrigin; + return; + } + listener(data); + }; + if (!threadId) { + addEventListener("message", eventListener); + } else { + _wasmWorkers[threadId].addEventListener("message", eventListener); + _wasmWorkers[threadId].postMessage({ + skwasmMessage: 'syncTimeOrigin', + timeOrigin: performance.timeOrigin, + }); + } + }; + skwasm_getCurrentTimestamp = function() { + return performance.now() + timeOriginDelta; + }; + skwasm_postMessage = function(message, transfers, threadId) { + if (threadId) { + _wasmWorkers[threadId].postMessage(message, { transfer: transfers } ); + } else { + postMessage(message, { transfer: transfers }); + } + }; + } const handleToCanvasMap = new Map(); const associatedObjectsMap = new Map(); - - _skwasm_isSingleThreaded = function() { - return Module["skwasmSingleThreaded"]; - }; _skwasm_setAssociatedObjectOnThread = function(threadId, pointer, object) { skwasm_postMessage({ skwasmMessage: 'setAssociatedObject',