wasm-host-sw.mjs raw
1 // sw-build: 20260520-v0.6.36
2 import * as sw from '../$runtime/sw.mjs';
3 import * as idb from '../$runtime/idb.mjs';
4
5 let mem;
6 let xp;
7 const enc = new TextEncoder();
8 const dec = new TextDecoder();
9
10 function readStr(ptr, len) {
11 if (len <= 0) return '';
12 return dec.decode(new Uint8Array(mem.buffer, ptr, len));
13 }
14
15 function writeStr(s) {
16 const bytes = enc.encode('' + s);
17 const ptr = xp.__alloc(bytes.length);
18 new Uint8Array(mem.buffer, ptr, bytes.length).set(bytes);
19 return [ptr, bytes.length];
20 }
21
22 function writeStrOut(s, rPtrAddr, rLenAddr) {
23 const [ptr, len] = writeStr(s);
24 const dv = new DataView(mem.buffer);
25 dv.setInt32(rPtrAddr, ptr, true);
26 dv.setInt32(rLenAddr, len, true);
27 }
28
29 function cb0(id) { xp.__cb0(id); }
30 function cbs(id, s) { const [ptr, len] = writeStr(s); xp.__cbs(id, ptr, len); }
31 function cbb(id, v) { xp.__cbb(id, v ? 1 : 0); }
32 function cbi(id, v) { xp.__cbi(id, v); }
33 function cbii(id, a, b) { xp.__cbii(id, a, b); }
34
35 function readNullSep(ptr, len) {
36 if (len <= 0) return [];
37 return readStr(ptr, len).split('\0');
38 }
39
40 const bridge = {
41 // --- sw lifecycle ---
42 sw_on_install(cbID) { sw.OnInstall(function(id) { cbi(cbID, id); }); },
43 sw_on_activate(cbID) { sw.OnActivate(function(id) { cbi(cbID, id); }); },
44 sw_on_fetch(cbID) { sw.OnFetch(function(id) { cbi(cbID, id); }); },
45 sw_on_message(cbID) { sw.OnMessage(function(id) { cbi(cbID, id); }); },
46
47 // --- event methods ---
48 sw_wait_until(event, cbID) {
49 sw.WaitUntil(event, function(done) { cb0(cbID); done(); });
50 },
51 sw_respond_with_cache_first(event) { sw.RespondWithCacheFirst(event); },
52 sw_respond_with_network_first(event) { sw.RespondWithNetworkFirst(event); },
53 sw_get_request_url(event, rPtrAddr, rLenAddr) {
54 writeStrOut(sw.GetRequestURL(event), rPtrAddr, rLenAddr);
55 },
56 sw_get_request_path(event, rPtrAddr, rLenAddr) {
57 writeStrOut(sw.GetRequestPath(event), rPtrAddr, rLenAddr);
58 },
59 sw_get_message_data(event, rPtrAddr, rLenAddr) {
60 writeStrOut(sw.GetMessageData(event), rPtrAddr, rLenAddr);
61 },
62 sw_get_message_client_id(event, rPtrAddr, rLenAddr) {
63 writeStrOut(sw.GetMessageClientID(event), rPtrAddr, rLenAddr);
64 },
65
66 // --- sw globals ---
67 sw_skip_waiting() { sw.SkipWaiting(); },
68 sw_claim_clients(cbID) { sw.ClaimClients(function() { cb0(cbID); }); },
69 sw_match_clients(cbID) { sw.MatchClients(function(c) { cbi(cbID, c); }); },
70 sw_post_message(client, ptr, len, cap) { sw.PostMessage(client, readStr(ptr, len)); },
71 sw_post_message_json(client, ptr, len, cap) { sw.PostMessageJSON(client, readStr(ptr, len)); },
72 sw_get_client_by_id(ptr, len, cap, cbID) {
73 sw.GetClientByID(readStr(ptr, len), function(c, found) { cbii(cbID, c, found ? 1 : 0); });
74 },
75 sw_origin(rPtrAddr, rLenAddr) { writeStrOut(sw.Origin(), rPtrAddr, rLenAddr); },
76 sw_log(ptr, len, cap) { sw.Log(readStr(ptr, len)); },
77
78 // --- cache ---
79 sw_cache_open(ptr, len, cap, cbID) {
80 sw.CacheOpen(readStr(ptr, len), function(c) { cbi(cbID, c); });
81 },
82 sw_cache_from_manifests(cache, filesPtr, filesLen, filesCap, count, cbID) {
83 sw.CacheFromManifests(cache, readNullSep(filesPtr, filesLen), function() { cb0(cbID); });
84 },
85 sw_cache_delete(ptr, len, cap, cbID) {
86 sw.CacheDelete(readStr(ptr, len), function() { cb0(cbID); });
87 },
88
89 // --- fetch ---
90 sw_fetch(ptr, len, cap, cbID) {
91 sw.Fetch(readStr(ptr, len), function(resp, ok) { cbii(cbID, resp, ok ? 1 : 0); });
92 },
93
94 // --- sse ---
95 sw_sse_connect(ptr, len, cap, cbID) {
96 return sw.SSEConnect(readStr(ptr, len), function(data) { cbs(cbID, data); });
97 },
98
99 // --- timers ---
100 sw_set_timeout(ms, cbID) { return sw.SetTimeout(ms, function() { cb0(cbID); }); },
101 sw_clear_timeout(t) { sw.ClearTimeout(t); },
102 sw_now_seconds() { return sw.NowSeconds(); },
103
104 // --- idb ---
105 idb_set_enc_key(ptr, len, cap) { idb.SetEncKey(readStr(ptr, len)); },
106 idb_open(cbID) { idb.Open(function() { cb0(cbID); }); },
107 idb_save_event(ptr, len, cap, cbID) {
108 idb.SaveEvent(readStr(ptr, len), function(ok) { cbb(cbID, ok); });
109 },
110 idb_query_events(ptr, len, cap, cbID) {
111 idb.QueryEvents(readStr(ptr, len), function(json) { cbs(cbID, json); });
112 },
113 idb_save_dm(ptr, len, cap, cbID) {
114 idb.SaveDM(readStr(ptr, len), function(status) { cbs(cbID, status); });
115 },
116 idb_query_dms(peerPtr, peerLen, peerCap, limit, until, cbID) {
117 idb.QueryDMs(readStr(peerPtr, peerLen), limit, Number(until), function(json) { cbs(cbID, json); });
118 },
119 idb_get_conversation_list(cbID) {
120 idb.GetConversationList(function(json) { cbs(cbID, json); });
121 },
122 idb_clear_dms_by_peer(ptr, len, cap, cbID) {
123 idb.ClearDMsByPeer(readStr(ptr, len), function() { cb0(cbID); });
124 },
125
126 // --- time ---
127 timezone_offset_minutes() {
128 return new Date().getTimezoneOffset();
129 },
130
131 // --- subtle ---
132 subtle_random_bytes(ptr, len, cap) {
133 crypto.getRandomValues(new Uint8Array(mem.buffer, ptr, len));
134 },
135 };
136
137 const wasi = {
138 fd_write(fd, iovs, iovs_len, nwritten_ptr) {
139 const dv = new DataView(mem.buffer);
140 let total = 0;
141 for (let i = 0; i < iovs_len; i++) {
142 const ptr = dv.getUint32(iovs + i * 8, true);
143 const len = dv.getUint32(iovs + i * 8 + 4, true);
144 const s = dec.decode(new Uint8Array(mem.buffer, ptr, len));
145 if (fd === 1) console.log(s);
146 else if (fd === 2) console.error(s);
147 total += len;
148 }
149 dv.setUint32(nwritten_ptr, total, true);
150 return 0;
151 },
152 clock_time_get(clock_id, precision, time_ptr) {
153 const dv = new DataView(mem.buffer);
154 const ms = (clock_id === 1) ? performance.now() : Date.now();
155 const ns = BigInt(Math.trunc(ms * 1e6));
156 dv.setBigUint64(time_ptr >>> 0, ns, true);
157 return 0;
158 },
159 };
160
161
162
163 async function boot() {
164 const { instance } = await WebAssembly.instantiateStreaming(
165 fetch('/$sw/sw.wasm'),
166 { bridge, wasi_snapshot_preview1: wasi }
167 );
168 mem = instance.exports.memory;
169 xp = instance.exports;
170 instance.exports._start();
171 }
172
173 boot().catch(e => console.error('SW WASM boot failed:', e));
174