wasmworker/webworker/
js.rs

1use js_sys::JsString;
2use wasm_bindgen::prelude::wasm_bindgen;
3
4/// The initialization code for the worker,
5/// which will be loaded as a blob.
6///
7/// `{{wasm}}` will be replaced later by an actual path.
8pub(crate) const WORKER_JS: &str = r#"
9console.debug('Initializing worker');
10
11(async () => {
12    let mod;
13    try {
14        mod = await import('{{wasm}}');
15    } catch (e) {
16        console.error('Unable to import module {{wasm}}', e);
17        self.postMessage({ success: false, message: e.toString() });
18        return;
19    }
20
21    await mod.default();
22    self.postMessage({ success: true });
23    console.debug('Worker started');
24
25    self.addEventListener('message', async event => {
26        console.debug('Received worker event');
27        const { id, func_name, arg } = event.data;
28
29        const webworker_func_name = `__webworker_${func_name}`;
30        const fn = mod[webworker_func_name];
31        if (!fn) {
32            console.error(`Function '${func_name}' is not exported.`);
33            self.postMessage({ id: id, response: null });
34            return;
35        }
36
37        const worker_result = await fn(arg);
38
39        // Send response back to be handled by callback in main thread.
40        console.debug('Send worker result');
41        self.postMessage({ id: id, response: worker_result });
42    });
43})();
44"#;
45
46/// This function normally returns the path of our wasm-bindgen glue file.
47/// It only works in module environments, though.
48pub(crate) fn main_js() -> JsString {
49    #[wasm_bindgen]
50    extern "C" {
51        #[wasm_bindgen(thread_local, js_namespace = ["import", "meta"], js_name = url)]
52        static URL: JsString;
53    }
54
55    URL.with(Clone::clone)
56}