Re: [w3c/ServiceWorker] Size limits with synchronous WebAssembly functions (#1499)

The summary is that @moshevds wants to write their service worker entirely in Wasm, without any JS at all. Right now that's not possible, because:

1. [esm-integration](https://github.com/WebAssembly/esm-integration) requires top-level `await` which has been banned in service workers.

2. wasm-bindgen can't generate code which uses top-level `await` to load the `.wasm` file... because top-level `await` has been banned.

3. wasm-bindgen can't generate code which loads the `.wasm` file synchronously... because sync XHR has been banned.

4. wasm-bindgen *could* convert the `.wasm` file into base64 and embed it inside the `.js` file and use the synchronous `WebAssembly` APIs to load it... except that won't work if there is a 4 KB size limit.

So right now it's not really possible to create a service worker which is pure Wasm.

Instead you have to create a `.js` file which loads and caches the `.wasm` file, and defines the event listeners, like this:

```js
async function load(url) {
    const cache = await caches.open("offline");

    try {
        const response = await fetch(url);

        if (response.ok) {
            await cache.put(url, response);
            return response;

        } else {
            throw new Error("Invalid status code: " + response.status);
        }

    } catch (e) {
        const response = await cache.match(url);

        if (response) {
            return response;

        } else {
            throw e;
        }
    }
}

async function loadWasm(url) {
    const response = await load(url);
    const bytes = await response.arrayBuffer();
    await wasm_bindgen(bytes);
}

function events(...names) {
    importScripts("./path/to/wasm.js");
    const wasm = loadWasm("./path/to/wasm_bg.wasm");

    self.addEventListener("install", (event) => {
        event.waitUntil(wasm);
    });

    names.forEach((name) => {
        const f = wasm_bindgen[name];

        self.addEventListener(name, (event) => {
            event.waitUntil(wasm.then(() => f(event)));
        });
    });
}

events("fetch", "push", "message");
```

From wasm-bindgen's perspective, the ideal solution is for the browser to have built-in support for `.wasm` (such as with [esm-integration](https://github.com/WebAssembly/esm-integration)).

Removing the 4 KB limit isn't a great solution, since it still requires base64-encoding the `.wasm` file and embedding it into the `.js` file, and it also doesn't handle caching/offline use.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/ServiceWorker/issues/1499#issuecomment-578730536

Received on Monday, 27 January 2020 12:45:54 UTC