-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathsw.js
More file actions
94 lines (71 loc) · 2.34 KB
/
sw.js
File metadata and controls
94 lines (71 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
class WasmHTTP {
#listeners = new Map();
setHandler(path, handler) {
const listener = this.#listeners.get(path);
if (!listener) {
throw new Error(`no listener for path "${path}"`);
}
listener.setHandler(handler);
}
handle(e) {
const { pathname } = new URL(e.request.url);
for (const [path, listener] of this.#listeners) {
if (pathname.startsWith(path)) {
listener.handle(e);
return;
}
}
}
addListener({ wasm, base = '', cacheName, passthrough, args = [], env = {} }) {
const path = new URL(trimStart(base, '/'), registration.scope).pathname;
if (this.#listeners.has(path)) {
throw new Error(`a listener is already registered for path "${path}"`);
}
this.#listeners.set(path, new WasmHTTPListener({ wasm, path, cacheName, passthrough, args, env }));
}
}
class WasmHTTPListener {
#handlerPromise;
#resolveHandler;
#passthrough;
constructor({ wasm, path, cacheName, passthrough, args, env }) {
this.#handlerPromise = new Promise((resolve) => {
this.#resolveHandler = resolve;
});
this.#passthrough = passthrough;
this.#run({ wasm, path, cacheName, passthrough, args, env });
}
async #run({ wasm, path, cacheName, args, env }) {
try {
const go = new Go();
go.argv = [wasm, ...args];
go.env = { ...env, WASM_HTTP_PATH: path };
const cache = cacheName ? await caches.open(cacheName) : caches;
const source = (await cache.match(wasm)) ?? (await fetch(wasm));
const { instance } = await WebAssembly.instantiateStreaming(source, go.importObject);
await go.run(instance);
} catch (err) {
console.error(`error while running ${wasm} for path "${path}"`, err);
}
}
setHandler(handler) {
this.#resolveHandler(handler);
}
handle(e) {
if (this.#passthrough?.(e.request)) return;
// FIXME return 500 if run has thrown
e.respondWith(this.#handlerPromise.then((handler) => handler(e.request)));
}
}
self.wasmhttp = new WasmHTTP();
addEventListener('fetch', (e) => {
self.wasmhttp.handle(e);
});
function registerWasmHTTPListener(wasm, { base, cacheName, passthrough, args, env } = {}) {
self.wasmhttp.addListener({ wasm, base, cacheName, passthrough, args, env });
}
function trimStart(s, c) {
let r = s;
while (r.startsWith(c)) r = r.slice(c.length);
return r;
}