Improve worker.js reliability (#1820)

While it doesn't happen right now in this particular example, `lastPtr` can be potentially overridden several times before the module is fully initialised.

Rather than having a boolean and a storage for one last argument, `await` a promise returned from `wasm_bindgen` itself in the new `onmessage` handler before executing actual command.

This way all the potential tasks will queue up naturally, wait for the initialisation, and then execute in a correct order.
This commit is contained in:
Ingvar Stepanyan 2019-10-17 23:29:37 +01:00 committed by Alex Crichton
parent a31b81307c
commit 46cbd19e60

View File

@ -1,36 +1,25 @@
// synchronously, using the browser, import out shim JS scripts // synchronously, using the browser, import out shim JS scripts
importScripts('raytrace_parallel.js'); importScripts('raytrace_parallel.js');
let booted = false;
let lastPtr = null;
// Wait for the main thread to send us the shared module/memory. Once we've got // Wait for the main thread to send us the shared module/memory. Once we've got
// it, initialize it all with the `wasm_bindgen` global we imported via // it, initialize it all with the `wasm_bindgen` global we imported via
// `importScripts`. // `importScripts`.
// //
// After our first message all subsequent messages are an entry point to run, // After our first message all subsequent messages are an entry point to run,
// so we just do that. // so we just do that.
self.onmessage = function(args) { self.onmessage = event => {
self.onmessage = event => run(event.data); let initialised = wasm_bindgen(...event.data).catch(err => {
const [module, memory] = args.data; // Propagate to main `onerror`:
wasm_bindgen(module, memory) setTimeout(() => {
.then(() => { throw err;
booted = true; });
if (lastPtr) // Rethrow to keep promise rejected and prevent execution of further commands:
run(lastPtr); throw err;
}) });
.catch(e => setTimeout(() => { throw e; })); // propagate to main `onerror`
};
function run(ptr) { self.onmessage = async event => {
if (!booted) { // This will queue further commands up until the module is fully initialised:
lastPtr = ptr; await initialised;
return; wasm_bindgen.child_entry_point(event.data);
} };
lastPtr = null; };
try {
wasm_bindgen.child_entry_point(ptr);
} catch (e) {
throw new Error(e.message + "\n\n" + e.stack);
}
}