ziex 0.1.0-dev.1367 → 0.1.0-dev.1381

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/aws-lambda/index.js +20 -29
  2. package/build.zig.zon +10 -3
  3. package/cloudflare/index.js +1635 -1854
  4. package/index.js +155 -216
  5. package/{pkg/ziex/src/react → jsx}/dom.d.ts +5 -9
  6. package/{pkg/ziex/src/react → jsx}/index.d.ts +1 -1
  7. package/{react → jsx}/index.js +19 -25
  8. package/{pkg/ziex/src/react → jsx}/types.d.ts +14 -9
  9. package/package.json +6 -14
  10. package/vercel/index.js +0 -15
  11. package/wasm/index.js +253 -261
  12. package/wasm/init.dev.js +242 -189
  13. package/wasm/init.js +3 -3
  14. package/pkg/ziex/src/zx.d.ts +0 -1
  15. package/vendor/jsz/js/src/index.d.ts +0 -1
  16. package/vendor/jsz/js/src/zigjs.d.ts +0 -107
  17. /package/{pkg/ziex/src/app.d.ts → app.d.ts} +0 -0
  18. /package/{pkg/ziex/src/aws-lambda → aws-lambda}/index.d.ts +0 -0
  19. /package/{pkg/ziex/src/browser → browser}/kv.d.ts +0 -0
  20. /package/{pkg/ziex/src/cloudflare → cloudflare}/app.d.ts +0 -0
  21. /package/{pkg/ziex/src/cloudflare → cloudflare}/db.d.ts +0 -0
  22. /package/{pkg/ziex/src/cloudflare → cloudflare}/do.d.ts +0 -0
  23. /package/{pkg/ziex/src/cloudflare → cloudflare}/index.d.ts +0 -0
  24. /package/{pkg/ziex/src/cloudflare → cloudflare}/kv.d.ts +0 -0
  25. /package/{pkg/ziex/src/cloudflare → cloudflare}/worker.d.ts +0 -0
  26. /package/{pkg/ziex/src/db.d.ts → db.d.ts} +0 -0
  27. /package/{pkg/ziex/src/fetch.d.ts → fetch.d.ts} +0 -0
  28. /package/{pkg/ziex/src/index.d.ts → index.d.ts} +0 -0
  29. /package/{pkg/ziex/src/kv.d.ts → kv.d.ts} +0 -0
  30. /package/{pkg/ziex/src/runtime.d.ts → runtime.d.ts} +0 -0
  31. /package/{pkg/ziex/src/vercel → vercel}/index.d.ts +0 -0
  32. /package/{pkg/ziex/src/wasi.d.ts → wasi.d.ts} +0 -0
  33. /package/{pkg/ziex/src/wasm → wasm}/core.d.ts +0 -0
  34. /package/{pkg/ziex/src/wasm → wasm}/dom.d.ts +0 -0
  35. /package/{pkg/ziex/src/wasm → wasm}/index.d.ts +0 -0
  36. /package/{pkg/ziex/src/wasm → wasm}/init.d.ts +0 -0
  37. /package/{pkg/ziex/src/wasm → wasm}/types.d.ts +0 -0
  38. /package/{pkg/ziex/src/wasm → wasm}/wasi.d.ts +0 -0
@@ -1,468 +1,142 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __returnValue = (v) => v;
3
- function __exportSetter(name, newValue) {
4
- this[name] = __returnValue.bind(null, newValue);
5
- }
6
2
  var __export = (target, all) => {
7
3
  for (var name in all)
8
- __defProp(target, name, {
9
- get: all[name],
10
- enumerable: true,
11
- configurable: true,
12
- set: __exportSetter.bind(all, name)
13
- });
4
+ __defProp(target, name, { get: all[name], enumerable: true });
14
5
  };
15
6
 
16
- // ../../vendor/jsz/js/src/zigjs.ts
17
- var NAN_PREFIX = 2146959360;
18
- var predefined = {
19
- nan: 0,
20
- null: 1,
21
- true: 2,
22
- false: 3,
23
- undefined: 4,
24
- globalThis: 5,
25
- runtime: 6
26
- };
27
- var PREDEFINED_ID_MAX = 6;
28
- var encoder = new TextEncoder;
29
- var decoder = new TextDecoder("utf-8");
7
+ // src/runtime.ts
8
+ var runtime_exports = {};
9
+ __export(runtime_exports, {
10
+ attachWebSocket: () => attachWebSocket,
11
+ buildWsImports: () => buildWsImports,
12
+ run: () => run
13
+ });
30
14
 
31
- class ZigJS {
32
- memory;
33
- values = [NaN, null, true, false, undefined, globalThis, this];
34
- idPool = [];
35
- importObject() {
36
- return {
37
- "zig-js": {
38
- valueGet: this.valueGet.bind(this),
39
- valueSet: this.valueSet.bind(this),
40
- valueDeinit: this.valueDeinit.bind(this),
41
- valueObjectCreate: this.valueObjectCreate.bind(this),
42
- valueStringCreate: this.valueStringCreate.bind(this),
43
- valueStringLen: this.valueStringLen.bind(this),
44
- valueStringCopy: this.valueStringCopy.bind(this),
45
- valueNew: this.valueNew.bind(this),
46
- funcApply: this.funcApply.bind(this)
47
- }
48
- };
49
- }
50
- valueGet(out, id, ptr, len) {
51
- const val = this.loadValue(id);
52
- const str = this.loadString(ptr, len);
53
- const result = Reflect.get(val, str);
54
- this.storeValue(out, result);
55
- }
56
- valueSet(id, ptr, len, refAddr) {
57
- const obj = this.loadValue(id);
58
- const str = this.loadString(ptr, len);
59
- const val = this.loadRef(refAddr);
60
- Reflect.set(obj, str, val);
61
- }
62
- valueDeinit(id) {
63
- if (id > PREDEFINED_ID_MAX) {
64
- this.values[id] = null;
65
- this.idPool.push(id);
66
- }
67
- }
68
- valueObjectCreate(out) {
69
- this.storeValue(out, new Object);
70
- }
71
- valueStringCreate(out, ptr, len) {
72
- const str = this.loadString(ptr, len);
73
- this.storeValue(out, str);
74
- }
75
- valueStringLen(id) {
76
- const val = this.loadValue(id);
77
- const buf = encoder.encode(val);
78
- return buf.byteLength;
79
- }
80
- valueStringCopy(id, ptr, max) {
81
- if (this.memory == null)
82
- return;
83
- const val = this.loadValue(id);
84
- const bytes = encoder.encode(val);
85
- if (bytes.byteLength > max)
86
- return;
87
- if (bytes.length === 0)
88
- return;
89
- new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
90
- }
91
- valueNew(out, id, argsAddr, argsLen) {
92
- const fn = this.loadValue(id);
93
- const args = [];
94
- for (let i = 0;i < argsLen; i++) {
95
- args.push(this.loadRef(argsAddr + i * 8));
96
- }
97
- const result = Reflect.construct(fn, args);
98
- this.storeValue(out, result);
15
+ // src/wasm/wasi.ts
16
+ var decoder = new TextDecoder();
17
+ var encoder = new TextEncoder();
18
+ var ZxWasiBridge = class {
19
+ #alloc;
20
+ #fetchCompleteHandler;
21
+ #memory;
22
+ #cb;
23
+ #intervals = /* @__PURE__ */ new Map();
24
+ // Cached memory view - invalidated when the WASM buffer grows.
25
+ #memView = null;
26
+ #memBuf = null;
27
+ constructor(exports) {
28
+ this.#memory = exports.memory;
29
+ this.#alloc = exports.__zx_alloc;
30
+ this.#fetchCompleteHandler = exports.__zx_fetch_complete;
31
+ this.#cb = exports.__zx_cb;
99
32
  }
100
- funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
101
- const fn = this.loadValue(id);
102
- const thisVal = this.loadRef(thisRefAddr);
103
- const args = [];
104
- for (let i = 0;i < argsLen; i++) {
105
- args.push(this.loadRef(argsAddr + i * 8));
33
+ #view() {
34
+ const buf = this.#memory.buffer;
35
+ if (buf !== this.#memBuf) {
36
+ this.#memBuf = buf;
37
+ this.#memView = new Uint8Array(buf);
106
38
  }
107
- const result = Reflect.apply(fn, thisVal, args);
108
- this.storeValue(out, result);
109
- }
110
- loadValue(id) {
111
- return this.values[id];
112
- }
113
- deleteValue(id) {
114
- const val = this.values[id];
115
- this.valueDeinit(id);
116
- return val;
39
+ return this.#memView;
117
40
  }
118
- loadRef(refAddr) {
119
- if (this.memory == null)
120
- return;
121
- const view = new DataView(this.memory.buffer);
122
- const floatVal = view.getFloat64(refAddr, true);
123
- if (!isNaN(floatVal))
124
- return floatVal;
125
- const id = this.loadRefId(refAddr);
126
- return this.values[id];
41
+ #readString(ptr, len) {
42
+ return decoder.decode(this.#view().subarray(ptr, ptr + len));
127
43
  }
128
- loadRefId(refAddr) {
129
- if (this.memory == null)
130
- return 0;
131
- return new DataView(this.memory.buffer).getUint32(refAddr, true);
44
+ #writeBytes(ptr, data) {
45
+ this.#view().set(data, ptr);
132
46
  }
133
- storeValue(out, val) {
134
- if (this.memory == null)
135
- return;
136
- const view = new DataView(this.memory.buffer);
137
- if (typeof val === "number") {
138
- if (isNaN(val)) {
139
- view.setUint32(out, predefined.nan, true);
140
- view.setUint32(out + 4, NAN_PREFIX, true);
141
- } else {
142
- view.setFloat64(out, val, true);
143
- }
144
- return;
145
- }
146
- if (val === null) {
147
- view.setUint32(out, predefined.null, true);
148
- view.setUint32(out + 4, NAN_PREFIX, true);
149
- return;
150
- }
151
- if (val === undefined) {
152
- view.setUint32(out, predefined.undefined, true);
153
- view.setUint32(out + 4, NAN_PREFIX, true);
154
- return;
155
- }
156
- if (typeof val === "boolean") {
157
- view.setUint32(out, val ? predefined.true : predefined.false, true);
158
- view.setUint32(out + 4, NAN_PREFIX, true);
159
- return;
160
- }
161
- if (typeof val === "bigint") {
162
- view.setFloat64(out, Number(val), true);
163
- return;
164
- }
165
- let id = this.idPool.pop();
166
- if (id === undefined) {
167
- id = this.values.length;
168
- }
169
- this.values[id] = val;
170
- let typeId = 0;
171
- switch (typeof val) {
172
- case "object":
173
- typeId = 1;
47
+ log(level, ptr, len) {
48
+ const msg = decoder.decode(this.#view().subarray(ptr, ptr + len));
49
+ switch (level) {
50
+ case 0:
51
+ console.error(msg);
174
52
  break;
175
- case "string":
176
- typeId = 2;
53
+ case 1:
54
+ console.warn(msg);
177
55
  break;
178
- case "symbol":
179
- typeId = 3;
56
+ case 3:
57
+ console.debug(msg);
180
58
  break;
181
- case "function":
182
- typeId = 4;
59
+ default:
60
+ console.log(msg);
183
61
  break;
184
62
  }
185
- view.setUint32(out, Number(id), true);
186
- view.setUint32(out + 4, NAN_PREFIX | typeId, true);
187
- }
188
- loadString(ptr, len) {
189
- if (this.memory == null)
190
- return "";
191
- const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
192
- const data = arr.slice();
193
- return decoder.decode(data);
194
- }
195
- }
196
- // src/fetch.ts
197
- function createFetchImports(getMemory) {
198
- const encoder2 = new TextEncoder;
199
- const decoder2 = new TextDecoder;
200
- function readStr(ptr, len) {
201
- return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
202
- }
203
- function writeBytes(buf_ptr, buf_max, data) {
204
- if (data.length > buf_max)
205
- return -2;
206
- new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
207
- return data.length;
208
63
  }
209
- function readBytes(ptr, len) {
210
- return new Uint8Array(getMemory().buffer, ptr, len);
211
- }
212
- function parseHeaders(headersJson) {
64
+ fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
65
+ const url = this.#readString(urlPtr, urlLen);
66
+ const method = methodLen > 0 ? this.#readString(methodPtr, methodLen) : "GET";
67
+ const headersJson = headersLen > 0 ? this.#readString(headersPtr, headersLen) : "{}";
68
+ const body = bodyLen > 0 ? this.#view().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
213
69
  let headers = {};
214
70
  try {
215
71
  headers = JSON.parse(headersJson);
216
72
  } catch {
217
- for (const line of headersJson.split(`
218
- `)) {
219
- const colonIdx = line.indexOf(":");
220
- if (colonIdx > 0) {
221
- headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
222
- }
73
+ for (const line of headersJson.split("\n")) {
74
+ const i = line.indexOf(":");
75
+ if (i > 0) headers[line.slice(0, i)] = line.slice(i + 1);
223
76
  }
224
77
  }
225
- return headers;
78
+ const controller = new AbortController();
79
+ const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
80
+ fetch(url, {
81
+ method,
82
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
83
+ body: method !== "GET" && method !== "HEAD" ? body : void 0,
84
+ signal: controller.signal
85
+ }).then(async (res) => {
86
+ if (timeout) clearTimeout(timeout);
87
+ const bytes = new Uint8Array(await res.arrayBuffer());
88
+ this.#notifyFetchComplete(fetchId, res.status, bytes, false);
89
+ }).catch((err) => {
90
+ if (timeout) clearTimeout(timeout);
91
+ const msg = err.name === "AbortError" ? "Request timeout" : err.message ?? "Fetch failed";
92
+ this.#notifyFetchComplete(fetchId, 0, msg, true);
93
+ });
226
94
  }
227
- async function doFetch(url_ptr, url_len, method_ptr, method_len, headers_ptr, headers_len, body_ptr, body_len, timeout_ms, status_out, buf_ptr, buf_max) {
228
- const url = readStr(url_ptr, url_len);
229
- const method = method_len > 0 ? readStr(method_ptr, method_len) : "GET";
230
- const headersJson = headers_len > 0 ? readStr(headers_ptr, headers_len) : "{}";
231
- const body = body_len > 0 ? readBytes(body_ptr, body_len) : undefined;
232
- const headers = parseHeaders(headersJson);
233
- const controller = new AbortController;
234
- const timeout = timeout_ms > 0 ? setTimeout(() => controller.abort(), timeout_ms) : null;
235
- try {
236
- const response = await fetch(url, {
237
- method,
238
- headers: Object.keys(headers).length > 0 ? headers : undefined,
239
- body: method !== "GET" && method !== "HEAD" ? body : undefined,
240
- signal: controller.signal
241
- });
242
- if (timeout)
243
- clearTimeout(timeout);
244
- new DataView(getMemory().buffer).setUint16(status_out, response.status, true);
245
- const bytes = new Uint8Array(await response.arrayBuffer());
246
- return writeBytes(buf_ptr, buf_max, bytes);
247
- } catch (err) {
248
- if (timeout)
249
- clearTimeout(timeout);
250
- const msg = err instanceof Error ? err.message : String(err);
251
- console.error(`wasm fetch failed: ${url} (${msg})`);
252
- return -1;
95
+ #notifyFetchComplete(fetchId, status, body, isError) {
96
+ const encoded = typeof body === "string" ? encoder.encode(body) : body;
97
+ const ptr = this.#alloc(encoded.length);
98
+ this.#writeBytes(ptr, encoded);
99
+ this.#fetchCompleteHandler(fetchId, status, ptr, encoded.length, isError ? 1 : 0);
100
+ }
101
+ setTimeout(callbackId, delayMs) {
102
+ setTimeout(() => this.#cb?.(3, callbackId, 0n), delayMs);
103
+ }
104
+ setInterval(callbackId, intervalMs) {
105
+ const handle = setInterval(() => this.#cb?.(4, callbackId, 0n), intervalMs);
106
+ this.#intervals.set(callbackId, handle);
107
+ }
108
+ clearInterval(callbackId) {
109
+ const handle = this.#intervals.get(callbackId);
110
+ if (handle !== void 0) {
111
+ clearInterval(handle);
112
+ this.#intervals.delete(callbackId);
253
113
  }
254
114
  }
255
- const Suspending = WebAssembly.Suspending;
256
- if (typeof Suspending !== "function") {
115
+ /**
116
+ * Create the WASI import object for WASM instantiation.
117
+ *
118
+ * Returns only the `__zx` namespace (log, fetch, timers).
119
+ * Does NOT include jsz.importObject() - the server binary does not use jsz.
120
+ */
121
+ static createImportObject(bridgeRef) {
257
122
  return {
258
- fetch: (_url_ptr, _url_len, _method_ptr, _method_len, _headers_ptr, _headers_len, _body_ptr, _body_len, _timeout_ms, _status_out, _buf_ptr, _buf_max) => -1
259
- };
260
- }
261
- return {
262
- fetch: new Suspending(doFetch)
263
- };
264
- }
265
-
266
- // src/wasm/core.ts
267
- var CallbackType = {
268
- Event: 0,
269
- FetchSuccess: 1,
270
- FetchError: 2,
271
- Timeout: 3,
272
- Interval: 4,
273
- WebSocketOpen: 5,
274
- WebSocketMessage: 6,
275
- WebSocketError: 7,
276
- WebSocketClose: 8
277
- };
278
- var jsz = new ZigJS;
279
- var tempRefBuffer = new ArrayBuffer(8);
280
- var tempRefView = new DataView(tempRefBuffer);
281
- function storeValueGetRef(val) {
282
- const originalMemory = jsz.memory;
283
- jsz.memory = { buffer: tempRefBuffer };
284
- jsz.storeValue(0, val);
285
- jsz.memory = originalMemory;
286
- return tempRefView.getBigUint64(0, true);
287
- }
288
- var textDecoder = new TextDecoder;
289
- var textEncoder = new TextEncoder;
290
- var memoryView = null;
291
- var memoryBuffer = null;
292
- function getMemoryView() {
293
- const buf = jsz.memory.buffer;
294
- if (buf !== memoryBuffer) {
295
- memoryBuffer = buf;
296
- memoryView = new Uint8Array(buf);
297
- }
298
- return memoryView;
299
- }
300
- var stringCache = new Map;
301
- function stringCacheKey(ptr, len) {
302
- return ptr * 65536 + len;
303
- }
304
- function readString(ptr, len) {
305
- const key = stringCacheKey(ptr, len);
306
- const cached = stringCache.get(key);
307
- if (cached !== undefined)
308
- return cached;
309
- const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
310
- stringCache.set(key, str);
311
- return str;
312
- }
313
- function writeBytes(ptr, data) {
314
- getMemoryView().set(data, ptr);
315
- }
316
- function wrapPromisingExport(fn) {
317
- if (!fn)
318
- return;
319
- const promising = WebAssembly.promising;
320
- if (typeof promising !== "function")
321
- return fn;
322
- return promising(fn);
323
- }
324
- function invokeWasmExport(fn, ...args) {
325
- if (!fn)
326
- return;
327
- const result = fn(...args);
328
- if (result && typeof result.then === "function") {
329
- result.then(undefined, (error) => {
330
- console.error(error);
331
- });
332
- }
333
- }
334
-
335
- class ZxBridgeCore {
336
- #intervals = new Map;
337
- _alloc;
338
- #handler;
339
- #fetchCompleteHandler;
340
- constructor(exports) {
341
- this._alloc = exports.__zx_alloc;
342
- this.#handler = wrapPromisingExport(exports.__zx_cb);
343
- const fetchCompleteHandler = wrapPromisingExport(exports.__zx_fetch_complete);
344
- if (!fetchCompleteHandler) {
345
- throw new Error("__zx_fetch_complete not exported from WASM");
346
- }
347
- this.#fetchCompleteHandler = fetchCompleteHandler;
348
- if (exports.memory)
349
- jsz.memory = exports.memory;
350
- }
351
- #invoke(type, id, data) {
352
- const handler = this.#handler;
353
- if (!handler) {
354
- console.warn("__zx_cb not exported from WASM");
355
- return;
356
- }
357
- const dataRef = storeValueGetRef(data);
358
- invokeWasmExport(handler, type, id, dataRef);
359
- }
360
- fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
361
- const url = readString(urlPtr, urlLen);
362
- const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
363
- const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
364
- const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : undefined;
365
- let headers = {};
366
- try {
367
- headers = JSON.parse(headersJson);
368
- } catch {
369
- for (const line of headersJson.split(`
370
- `)) {
371
- const colonIdx = line.indexOf(":");
372
- if (colonIdx > 0) {
373
- headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
374
- }
375
- }
376
- }
377
- const controller = new AbortController;
378
- const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
379
- const fetchOptions = {
380
- method,
381
- headers: Object.keys(headers).length > 0 ? headers : undefined,
382
- body: method !== "GET" && method !== "HEAD" ? body : undefined,
383
- signal: controller.signal
384
- };
385
- fetch(url, fetchOptions).then(async (response) => {
386
- if (timeout)
387
- clearTimeout(timeout);
388
- const bytes = new Uint8Array(await response.arrayBuffer());
389
- this._notifyFetchComplete(fetchId, response.status, bytes, false);
390
- }).catch((error) => {
391
- if (timeout)
392
- clearTimeout(timeout);
393
- const isAbort = error.name === "AbortError";
394
- const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
395
- this._notifyFetchComplete(fetchId, 0, errorMsg, true);
396
- });
397
- }
398
- _notifyFetchComplete(fetchId, statusCode, body, isError) {
399
- const handler = this.#fetchCompleteHandler;
400
- const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
401
- const ptr = this._alloc(encoded.length);
402
- writeBytes(ptr, encoded);
403
- invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
404
- }
405
- setTimeout(callbackId, delayMs) {
406
- setTimeout(() => {
407
- this.#invoke(CallbackType.Timeout, callbackId, null);
408
- }, delayMs);
409
- }
410
- setInterval(callbackId, intervalMs) {
411
- const handle = setInterval(() => {
412
- this.#invoke(CallbackType.Interval, callbackId, null);
413
- }, intervalMs);
414
- this.#intervals.set(callbackId, handle);
415
- }
416
- clearInterval(callbackId) {
417
- const handle = this.#intervals.get(callbackId);
418
- if (handle !== undefined) {
419
- clearInterval(handle);
420
- this.#intervals.delete(callbackId);
421
- }
422
- }
423
- dispose() {
424
- for (const handle of this.#intervals.values()) {
425
- clearInterval(handle);
426
- }
427
- this.#intervals.clear();
428
- }
429
- _writeStringToWasm(str) {
430
- return this._writeBytesToWasm(textEncoder.encode(str));
431
- }
432
- _writeBytesToWasm(data) {
433
- const ptr = this._alloc(data.length);
434
- writeBytes(ptr, data);
435
- return { ptr, len: data.length };
436
- }
437
- static log(level, ptr, len) {
438
- const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
439
- switch (level) {
440
- case 0:
441
- console.error(msg);
442
- break;
443
- case 1:
444
- console.warn(msg);
445
- break;
446
- case 3:
447
- console.debug(msg);
448
- break;
449
- default:
450
- console.log(msg);
451
- break;
452
- }
453
- }
454
- static createImportObject(bridgeRef) {
455
- return {
456
- ...jsz.importObject(),
457
- __zx_net: createFetchImports(() => {
458
- if (!jsz.memory)
459
- throw new Error("WASM memory is not ready");
460
- return jsz.memory;
461
- }),
462
123
  __zx: {
463
- _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
124
+ _log: (level, ptr, len) => {
125
+ bridgeRef.current?.log(level, ptr, len);
126
+ },
464
127
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
465
- bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
128
+ bridgeRef.current?.fetchAsync(
129
+ urlPtr,
130
+ urlLen,
131
+ methodPtr,
132
+ methodLen,
133
+ headersPtr,
134
+ headersLen,
135
+ bodyPtr,
136
+ bodyLen,
137
+ timeoutMs,
138
+ fetchId
139
+ );
466
140
  },
467
141
  _setTimeout: (callbackId, delayMs) => {
468
142
  bridgeRef.current?.setTimeout(callbackId, delayMs);
@@ -476,25 +150,24 @@ class ZxBridgeCore {
476
150
  }
477
151
  };
478
152
  }
479
- }
153
+ };
154
+
480
155
  // src/kv.ts
481
- var exports_kv = {};
482
- __export(exports_kv, {
483
- createMemoryKV: () => createMemoryKV,
484
- createKVImports: () => createKVImports
156
+ var kv_exports = {};
157
+ __export(kv_exports, {
158
+ createKVImports: () => createKVImports,
159
+ createMemoryKV: () => createMemoryKV
485
160
  });
486
161
  function putOptions(ttlSeconds) {
487
- if (ttlSeconds < 60)
488
- return;
162
+ if (ttlSeconds < 60) return void 0;
489
163
  return { expirationTtl: ttlSeconds };
490
164
  }
491
165
  function createMemoryKV() {
492
- const store = new Map;
166
+ const store = /* @__PURE__ */ new Map();
493
167
  function read(key) {
494
168
  const entry = store.get(key);
495
- if (!entry)
496
- return null;
497
- if (entry.expiresAt !== undefined && Date.now() >= entry.expiresAt) {
169
+ if (!entry) return null;
170
+ if (entry.expiresAt !== void 0 && Date.now() >= entry.expiresAt) {
498
171
  store.delete(key);
499
172
  return null;
500
173
  }
@@ -502,10 +175,10 @@ function createMemoryKV() {
502
175
  }
503
176
  function write(key, value, options) {
504
177
  let expiresAt;
505
- if (options?.expiration !== undefined) {
506
- expiresAt = options.expiration * 1000;
507
- } else if (options?.expirationTtl !== undefined) {
508
- expiresAt = Date.now() + options.expirationTtl * 1000;
178
+ if (options?.expiration !== void 0) {
179
+ expiresAt = options.expiration * 1e3;
180
+ } else if (options?.expirationTtl !== void 0) {
181
+ expiresAt = Date.now() + options.expirationTtl * 1e3;
509
182
  }
510
183
  store.set(key, { value, expiresAt });
511
184
  }
@@ -521,8 +194,7 @@ function createMemoryKV() {
521
194
  },
522
195
  async list(options) {
523
196
  const keys = [...store.keys()].filter((k) => {
524
- if (options?.prefix && !k.startsWith(options.prefix))
525
- return false;
197
+ if (options?.prefix && !k.startsWith(options.prefix)) return false;
526
198
  return read(k) !== null;
527
199
  }).map((name) => ({ name }));
528
200
  return { keys };
@@ -534,14 +206,13 @@ function isSyncKVNamespace(binding) {
534
206
  return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
535
207
  }
536
208
  function createKVImports(bindings, getMemory) {
537
- const encoder2 = new TextEncoder;
538
- const decoder2 = new TextDecoder;
209
+ const encoder3 = new TextEncoder();
210
+ const decoder3 = new TextDecoder();
539
211
  function readStr(ptr, len) {
540
- return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
212
+ return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
541
213
  }
542
214
  function writeBytes2(buf_ptr, buf_max, data) {
543
- if (data.length > buf_max)
544
- return -2;
215
+ if (data.length > buf_max) return -2;
545
216
  new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
546
217
  return data.length;
547
218
  }
@@ -550,1158 +221,314 @@ function createKVImports(bindings, getMemory) {
550
221
  }
551
222
  const Suspending = WebAssembly.Suspending;
552
223
  if (typeof Suspending !== "function") {
553
- let syncBinding = function(ns) {
224
+ let syncBinding2 = function(ns) {
554
225
  const candidate = binding(ns);
555
226
  return candidate && isSyncKVNamespace(candidate) ? candidate : null;
556
227
  };
228
+ var syncBinding = syncBinding2;
557
229
  return {
558
230
  kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
559
- const b = syncBinding(readStr(ns_ptr, ns_len));
560
- if (!b)
561
- return -1;
231
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
232
+ if (!b) return -1;
562
233
  const value = b.getSync(readStr(key_ptr, key_len));
563
- if (value === null)
564
- return -1;
565
- return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
234
+ if (value === null) return -1;
235
+ return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
566
236
  },
567
237
  kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
568
- const b = syncBinding(readStr(ns_ptr, ns_len));
569
- if (!b)
570
- return 0;
238
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
239
+ if (!b) return 0;
571
240
  b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
572
241
  return 0;
573
242
  },
574
243
  kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
575
- const b = syncBinding(readStr(ns_ptr, ns_len));
576
- if (!b)
577
- return 0;
244
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
245
+ if (!b) return 0;
578
246
  b.deleteSync(readStr(key_ptr, key_len));
579
247
  return 0;
580
248
  },
581
249
  kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
582
- const b = syncBinding(readStr(ns_ptr, ns_len));
583
- if (!b)
584
- return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
250
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
251
+ if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
585
252
  const prefix = readStr(pfx_ptr, pfx_len);
586
- const result = b.listSync(prefix.length > 0 ? { prefix } : undefined);
587
- return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
253
+ const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
254
+ return writeBytes2(buf_ptr, buf_max, encoder3.encode(JSON.stringify(result.keys.map((k) => k.name))));
588
255
  }
589
256
  };
590
257
  }
591
258
  return {
592
259
  kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
593
260
  const b = binding(readStr(ns_ptr, ns_len));
594
- if (!b)
595
- return -1;
261
+ if (!b) return -1;
596
262
  const value = await b.get(readStr(key_ptr, key_len));
597
- if (value === null)
598
- return -1;
599
- return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
263
+ if (value === null) return -1;
264
+ return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
600
265
  }),
601
266
  kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
602
267
  const b = binding(readStr(ns_ptr, ns_len));
603
- if (!b)
604
- return -1;
268
+ if (!b) return -1;
605
269
  await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
606
270
  return 0;
607
271
  }),
608
272
  kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
609
273
  const b = binding(readStr(ns_ptr, ns_len));
610
- if (!b)
611
- return -1;
274
+ if (!b) return -1;
612
275
  await b.delete(readStr(key_ptr, key_len));
613
276
  return 0;
614
277
  }),
615
278
  kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
616
279
  const b = binding(readStr(ns_ptr, ns_len));
617
- if (!b)
618
- return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
280
+ if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
619
281
  const prefix = readStr(prefix_ptr, prefix_len);
620
- const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
621
- return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
282
+ const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
283
+ return writeBytes2(buf_ptr, buf_max, encoder3.encode(JSON.stringify(result.keys.map((k) => k.name))));
622
284
  })
623
285
  };
624
286
  }
625
287
 
626
- // src/browser/kv.ts
627
- function getIndexedDb() {
628
- if (typeof indexedDB === "undefined") {
629
- throw new Error("IndexedDB is not available in this environment");
288
+ // src/fetch.ts
289
+ function createFetchImports(getMemory) {
290
+ const encoder3 = new TextEncoder();
291
+ const decoder3 = new TextDecoder();
292
+ function readStr(ptr, len) {
293
+ return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
630
294
  }
631
- return indexedDB;
632
- }
633
- function requestToPromise(request) {
634
- return new Promise((resolve, reject) => {
635
- request.onsuccess = () => resolve(request.result);
636
- request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
637
- });
638
- }
639
- function transactionToPromise(transaction) {
640
- return new Promise((resolve, reject) => {
641
- transaction.oncomplete = () => resolve();
642
- transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
643
- transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
644
- });
645
- }
646
- function createIndexedDbKV(options = {}) {
647
- const databaseName = options.databaseName ?? "ziex-kv";
648
- const storeName = options.storeName ?? "kv";
649
- const namespace = options.namespace ?? "default";
650
- const dbPromise = new Promise((resolve, reject) => {
651
- const request = getIndexedDb().open(databaseName, 1);
652
- request.onupgradeneeded = () => {
653
- const db = request.result;
654
- if (!db.objectStoreNames.contains(storeName)) {
655
- db.createObjectStore(storeName);
295
+ function writeBytes2(buf_ptr, buf_max, data) {
296
+ if (data.length > buf_max) return -2;
297
+ new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
298
+ return data.length;
299
+ }
300
+ function readBytes(ptr, len) {
301
+ return new Uint8Array(getMemory().buffer, ptr, len);
302
+ }
303
+ function parseHeaders(headersJson) {
304
+ let headers = {};
305
+ try {
306
+ headers = JSON.parse(headersJson);
307
+ } catch {
308
+ for (const line of headersJson.split("\n")) {
309
+ const colonIdx = line.indexOf(":");
310
+ if (colonIdx > 0) {
311
+ headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
312
+ }
656
313
  }
657
- };
658
- request.onsuccess = () => resolve(request.result);
659
- request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
660
- });
661
- const scopedKey = (key) => `${namespace}:${key}`;
662
- return {
663
- async get(key) {
664
- const db = await dbPromise;
665
- const tx = db.transaction(storeName, "readonly");
666
- const store = tx.objectStore(storeName);
667
- const value = await requestToPromise(store.get(scopedKey(key)));
668
- await transactionToPromise(tx);
669
- console.debug(`KV GET - Key: ${key}, Value: ${value}`);
670
- return typeof value === "string" ? value : null;
671
- },
672
- async put(key, value) {
673
- const db = await dbPromise;
674
- const tx = db.transaction(storeName, "readwrite");
675
- tx.objectStore(storeName).put(value, scopedKey(key));
676
- await transactionToPromise(tx);
677
- console.debug(`KV PUT - Key: ${key}, Value: ${value}`);
678
- },
679
- async delete(key) {
680
- const db = await dbPromise;
681
- const tx = db.transaction(storeName, "readwrite");
682
- tx.objectStore(storeName).delete(scopedKey(key));
683
- await transactionToPromise(tx);
684
- },
685
- async list(options2) {
686
- const db = await dbPromise;
687
- const tx = db.transaction(storeName, "readonly");
688
- const store = tx.objectStore(storeName);
689
- const keys = await requestToPromise(store.getAllKeys());
690
- await transactionToPromise(tx);
691
- const prefix = scopedKey(options2?.prefix ?? "");
692
- return {
693
- keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
694
- };
695
314
  }
696
- };
697
- }
698
- function getLocalStorage() {
699
- if (typeof localStorage === "undefined") {
700
- throw new Error("localStorage is not available in this environment");
315
+ return headers;
701
316
  }
702
- return localStorage;
703
- }
704
- function createLocalStorageKV(options = {}) {
705
- const storage = getLocalStorage();
706
- const namespace = options.namespace ?? "default";
707
- const storagePrefix = options.storagePrefix ?? "ziex-kv";
708
- const scopedKey = (key) => `${storagePrefix}:${namespace}:${key}`;
709
- const namespacePrefix = scopedKey("");
710
- return {
711
- getSync(key) {
712
- return storage.getItem(scopedKey(key));
713
- },
714
- async get(key) {
715
- return this.getSync(key);
716
- },
717
- putSync(key, value) {
718
- storage.setItem(scopedKey(key), value);
719
- },
720
- async put(key, value) {
721
- this.putSync(key, value);
722
- },
723
- deleteSync(key) {
724
- storage.removeItem(scopedKey(key));
725
- },
726
- async delete(key) {
727
- this.deleteSync(key);
728
- },
729
- listSync(options2) {
730
- const prefix = namespacePrefix + (options2?.prefix ?? "");
731
- const keys = [];
732
- for (let i = 0;i < storage.length; i += 1) {
733
- const key = storage.key(i);
734
- if (!key || !key.startsWith(prefix))
735
- continue;
736
- keys.push({ name: key.slice(namespacePrefix.length) });
737
- }
738
- return { keys };
739
- },
740
- async list(options2) {
741
- return this.listSync(options2);
317
+ async function doFetch(url_ptr, url_len, method_ptr, method_len, headers_ptr, headers_len, body_ptr, body_len, timeout_ms, status_out, buf_ptr, buf_max) {
318
+ const url = readStr(url_ptr, url_len);
319
+ const method = method_len > 0 ? readStr(method_ptr, method_len) : "GET";
320
+ const headersJson = headers_len > 0 ? readStr(headers_ptr, headers_len) : "{}";
321
+ const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
322
+ const headers = parseHeaders(headersJson);
323
+ const controller = new AbortController();
324
+ const timeout = timeout_ms > 0 ? setTimeout(() => controller.abort(), timeout_ms) : null;
325
+ try {
326
+ const response = await fetch(url, {
327
+ method,
328
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
329
+ body: method !== "GET" && method !== "HEAD" ? body : void 0,
330
+ signal: controller.signal
331
+ });
332
+ if (timeout) clearTimeout(timeout);
333
+ new DataView(getMemory().buffer).setUint16(status_out, response.status, true);
334
+ const bytes = new Uint8Array(await response.arrayBuffer());
335
+ return writeBytes2(buf_ptr, buf_max, bytes);
336
+ } catch (err) {
337
+ if (timeout) clearTimeout(timeout);
338
+ const msg = err instanceof Error ? err.message : String(err);
339
+ console.error(`wasm fetch failed: ${url} (${msg})`);
340
+ return -1;
742
341
  }
743
- };
744
- }
745
- function hasJSPI() {
746
- return typeof WebAssembly.Suspending === "function" && typeof WebAssembly.promising === "function";
747
- }
748
- function createBrowserKVBindings(options = {}) {
749
- const namespace = options.namespace ?? "default";
342
+ }
343
+ const Suspending = WebAssembly.Suspending;
344
+ if (typeof Suspending !== "function") {
345
+ return {
346
+ fetch: (_url_ptr, _url_len, _method_ptr, _method_len, _headers_ptr, _headers_len, _body_ptr, _body_len, _timeout_ms, _status_out, _buf_ptr, _buf_max) => -1
347
+ };
348
+ }
750
349
  return {
751
- [namespace]: hasJSPI() ? createIndexedDbKV(options) : createLocalStorageKV(options)
350
+ fetch: new Suspending(doFetch)
752
351
  };
753
352
  }
754
353
 
755
- // src/wasm/index.ts
756
- class ZxBridge extends ZxBridgeCore {
757
- #websockets = new Map;
758
- #wsOnOpenHandler;
759
- #wsOnMessageHandler;
760
- #wsOnErrorHandler;
761
- #wsOnCloseHandler;
762
- #eventbridge;
763
- #eventbridgeAsync;
764
- constructor(exports) {
765
- super(exports);
766
- this.#wsOnOpenHandler = wrapPromisingExport(exports.__zx_ws_onopen);
767
- this.#wsOnMessageHandler = wrapPromisingExport(exports.__zx_ws_onmessage);
768
- this.#wsOnErrorHandler = wrapPromisingExport(exports.__zx_ws_onerror);
769
- this.#wsOnCloseHandler = wrapPromisingExport(exports.__zx_ws_onclose);
770
- this.#eventbridge = exports.__zx_eventbridge;
771
- this.#eventbridgeAsync = wrapPromisingExport(exports.__zx_eventbridge_async ?? exports.__zx_eventbridge);
354
+ // src/db.ts
355
+ function decodeBlob(base64) {
356
+ const binary = atob(base64);
357
+ const bytes = new Uint8Array(binary.length);
358
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
359
+ return bytes;
360
+ }
361
+ function toD1Value(value) {
362
+ switch (value.kind) {
363
+ case "null":
364
+ return null;
365
+ case "integer":
366
+ return value.integer;
367
+ case "float":
368
+ return value.float;
369
+ case "text":
370
+ return value.text;
371
+ case "blob":
372
+ return decodeBlob(value.blob);
373
+ case "boolean":
374
+ return value.boolean;
772
375
  }
773
- eventMaySuspend(velementId, eventTypeId) {
774
- return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
376
+ }
377
+ function toPositionalBindings(json) {
378
+ switch (json.kind) {
379
+ case "none":
380
+ return [];
381
+ case "positional":
382
+ return json.values.map(toD1Value);
383
+ case "named":
384
+ throw new Error("Cloudflare D1 adapter does not support named bindings yet");
775
385
  }
776
- setEventHandlerMode(velementId, eventTypeId, maySuspend) {
777
- const bit = 1 << eventTypeId;
778
- const current = eventHandlerModes.get(velementId) ?? 0;
779
- const next = maySuspend ? current | bit : current & ~bit;
780
- if (next === 0)
781
- eventHandlerModes.delete(velementId);
782
- else
783
- eventHandlerModes.set(velementId, next);
386
+ }
387
+ function toWireValue(value) {
388
+ if (value === null || value === void 0) return { kind: "null" };
389
+ if (typeof value === "string") return { kind: "text", text: value };
390
+ if (typeof value === "boolean") return { kind: "boolean", boolean: value };
391
+ if (typeof value === "number") {
392
+ return Number.isInteger(value) ? { kind: "integer", integer: value } : { kind: "float", float: value };
784
393
  }
785
- clearEventHandlerModes(velementId) {
786
- eventHandlerModes.delete(velementId);
394
+ if (value instanceof ArrayBuffer) {
395
+ const bytes = new Uint8Array(value);
396
+ let binary = "";
397
+ for (const byte of bytes) binary += String.fromCharCode(byte);
398
+ return { kind: "blob", blob: btoa(binary) };
787
399
  }
788
- submitFormActionAsync(form, actionId, statesJson, fetchId) {
789
- const formData = new FormData(form);
790
- formData.append("__$states", statesJson);
791
- fetch(window.location.href, {
792
- method: "POST",
793
- headers: { "x-action": String(actionId >>> 0) },
794
- body: formData
795
- }).then(async (response) => {
796
- const text = await response.text();
797
- this._notifyFetchComplete(fetchId, response.status, text, false);
798
- }).catch((error) => {
799
- const msg = error instanceof Error ? error.message : "Fetch failed";
800
- this._notifyFetchComplete(fetchId, 0, msg, true);
801
- });
400
+ if (ArrayBuffer.isView(value)) {
401
+ const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
402
+ let binary = "";
403
+ for (const byte of bytes) binary += String.fromCharCode(byte);
404
+ return { kind: "blob", blob: btoa(binary) };
802
405
  }
803
- wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
804
- const url = readString(urlPtr, urlLen);
805
- const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
806
- const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : undefined;
807
- try {
808
- const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
809
- ws.binaryType = "arraybuffer";
810
- ws.onopen = () => {
811
- const handler = this.#wsOnOpenHandler;
812
- if (!handler)
813
- return;
814
- const protocol = ws.protocol || "";
815
- const { ptr, len } = this._writeStringToWasm(protocol);
816
- invokeWasmExport(handler, wsId, ptr, len);
817
- };
818
- ws.onmessage = (event) => {
819
- const handler = this.#wsOnMessageHandler;
820
- if (!handler)
821
- return;
822
- const isBinary = event.data instanceof ArrayBuffer;
823
- const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
824
- const { ptr, len } = this._writeBytesToWasm(data);
825
- invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
826
- };
827
- ws.onerror = (_event) => {
828
- const handler = this.#wsOnErrorHandler;
829
- if (!handler)
830
- return;
831
- const { ptr, len } = this._writeStringToWasm("WebSocket error");
832
- invokeWasmExport(handler, wsId, ptr, len);
833
- };
834
- ws.onclose = (event) => {
835
- const handler = this.#wsOnCloseHandler;
836
- if (!handler)
837
- return;
838
- const reason = event.reason || "";
839
- const { ptr, len } = this._writeStringToWasm(reason);
840
- invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
841
- this.#websockets.delete(wsId);
842
- };
843
- this.#websockets.set(wsId, ws);
844
- } catch (error) {
845
- const handler = this.#wsOnErrorHandler;
846
- if (handler) {
847
- const msg = error instanceof Error ? error.message : "WebSocket connection failed";
848
- const { ptr, len } = this._writeStringToWasm(msg);
849
- invokeWasmExport(handler, wsId, ptr, len);
850
- }
851
- }
406
+ return { kind: "text", text: String(value) };
407
+ }
408
+ function objectToWireRow(record) {
409
+ return {
410
+ fields: Object.entries(record).map(([name, value]) => ({
411
+ name,
412
+ value: toWireValue(value)
413
+ }))
414
+ };
415
+ }
416
+ function valuesToWireRows(rows) {
417
+ return rows.map((row) => row.map((value) => toWireValue(value)));
418
+ }
419
+ function createD1Imports(bindings, getMemory) {
420
+ const encoder3 = new TextEncoder();
421
+ const decoder3 = new TextDecoder();
422
+ function readStr(ptr, len) {
423
+ return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
852
424
  }
853
- wsSend(wsId, dataPtr, dataLen, isBinary) {
854
- const ws = this.#websockets.get(wsId);
855
- if (!ws || ws.readyState !== WebSocket.OPEN)
856
- return;
857
- const memory = getMemoryView();
858
- if (isBinary) {
859
- ws.send(memory.slice(dataPtr, dataPtr + dataLen));
860
- } else {
861
- ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
862
- }
425
+ function writeJson(buf_ptr, buf_max, value) {
426
+ const data = encoder3.encode(JSON.stringify(value));
427
+ if (data.length > buf_max) return -2;
428
+ new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
429
+ return data.length;
863
430
  }
864
- wsClose(wsId, code, reasonPtr, reasonLen) {
865
- const ws = this.#websockets.get(wsId);
866
- if (!ws)
867
- return;
868
- const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
869
- try {
870
- if (reason)
871
- ws.close(code, reason);
872
- else
873
- ws.close(code);
874
- } catch {
875
- ws.close();
876
- }
431
+ function binding(ns) {
432
+ return bindings[ns] ?? bindings["default"] ?? null;
877
433
  }
878
- dispose() {
879
- super.dispose();
880
- eventHandlerModes.clear();
881
- for (const ws of this.#websockets.values()) {
882
- try {
883
- ws.close();
884
- } catch {}
885
- }
886
- this.#websockets.clear();
434
+ async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
435
+ const database = binding(readStr(ns_ptr, ns_len));
436
+ if (!database) return null;
437
+ const sql = readStr(sql_ptr, sql_len);
438
+ const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
439
+ return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
887
440
  }
888
- eventbridge(velementId, eventTypeId, event) {
889
- const eventRef = storeValueGetRef(event);
890
- if (this.eventMaySuspend(velementId, eventTypeId)) {
891
- invokeWasmExport(this.#eventbridgeAsync, velementId, eventTypeId, eventRef);
892
- return;
893
- }
894
- invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
895
- }
896
- static createImportObject(bridgeRef) {
897
- return {
898
- ...jsz.importObject(),
899
- __zx_net: createFetchImports(() => {
900
- if (!jsz.memory)
901
- throw new Error("WASM memory is not ready");
902
- return jsz.memory;
903
- }),
904
- __zx: {
905
- _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
906
- _setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
907
- bridgeRef.current?.setEventHandlerMode(vnodeId, eventTypeId, maySuspend !== 0);
908
- },
909
- _clearEventHandlerModes: (vnodeId) => {
910
- bridgeRef.current?.clearEventHandlerModes(vnodeId);
911
- },
912
- _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
913
- bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
914
- },
915
- _setTimeout: (callbackId, delayMs) => {
916
- bridgeRef.current?.setTimeout(callbackId, delayMs);
917
- },
918
- _setInterval: (callbackId, intervalMs) => {
919
- bridgeRef.current?.setInterval(callbackId, intervalMs);
920
- },
921
- _clearInterval: (callbackId) => {
922
- bridgeRef.current?.clearInterval(callbackId);
923
- },
924
- _wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
925
- bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
926
- },
927
- _wsSend: (wsId, dataPtr, dataLen, isBinary) => {
928
- bridgeRef.current?.wsSend(wsId, dataPtr, dataLen, isBinary);
929
- },
930
- _wsClose: (wsId, code, reasonPtr, reasonLen) => {
931
- bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
932
- },
933
- _ce: (id, vnodeId) => {
934
- const tagName = TAG_NAMES[id];
935
- const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
936
- el.__zx_ref = Number(vnodeId);
937
- domNodes.set(vnodeId, el);
938
- return storeValueGetRef(el);
939
- },
940
- _ct: (ptr, len, vnodeId) => {
941
- const text = readString(ptr, len);
942
- const node = document.createTextNode(text);
943
- node.__zx_ref = Number(vnodeId);
944
- domNodes.set(vnodeId, node);
945
- return storeValueGetRef(node);
946
- },
947
- _sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
948
- domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
949
- },
950
- _sp: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
951
- const el = domNodes.get(vnodeId);
952
- if (el) {
953
- const name = readString(namePtr, nameLen);
954
- const val = readString(valPtr, valLen);
955
- if (name === "checked" || name === "selected" || name === "muted") {
956
- el[name] = val !== "false";
957
- } else {
958
- el[name] = val;
959
- }
960
- }
961
- },
962
- _ra: (vnodeId, namePtr, nameLen) => {
963
- domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
964
- },
965
- _snv: (vnodeId, ptr, len) => {
966
- const node = domNodes.get(vnodeId);
967
- if (node)
968
- node.nodeValue = readString(ptr, len);
969
- },
970
- _srh: (vnodeId, ptr, len) => {
971
- const el = domNodes.get(vnodeId);
972
- if (el)
973
- el.innerHTML = readString(ptr, len);
974
- },
975
- _ac: (parentId, childId) => {
976
- const parent = domNodes.get(parentId);
977
- const child = domNodes.get(childId);
978
- if (parent && child)
979
- parent.appendChild(child);
980
- },
981
- _ib: (parentId, childId, refId) => {
982
- const parent = domNodes.get(parentId);
983
- const child = domNodes.get(childId);
984
- const ref = domNodes.get(refId) ?? null;
985
- if (parent && child)
986
- parent.insertBefore(child, ref);
987
- },
988
- _rc: (parentId, childId) => {
989
- const parent = domNodes.get(parentId);
990
- const child = domNodes.get(childId);
991
- if (parent && child) {
992
- parent.removeChild(child);
993
- cleanupDomNodes(child);
994
- }
995
- },
996
- _rpc: (parentId, newId, oldId) => {
997
- const parent = domNodes.get(parentId);
998
- const newChild = domNodes.get(newId);
999
- const oldChild = domNodes.get(oldId);
1000
- if (parent && newChild && oldChild) {
1001
- parent.replaceChild(newChild, oldChild);
1002
- cleanupDomNodes(oldChild);
1003
- }
1004
- },
1005
- _getLocationHref: (bufPtr, bufLen) => {
1006
- const bytes = textEncoder.encode(window.location.href);
1007
- const len = Math.min(bytes.length, bufLen);
1008
- writeBytes(bufPtr, bytes.subarray(0, len));
1009
- return len;
1010
- },
1011
- _getFormData: (vnodeId, bufPtr, bufLen) => {
1012
- const form = domNodes.get(vnodeId);
1013
- if (!form || !(form instanceof HTMLFormElement))
1014
- return 0;
1015
- const formData = new FormData(form);
1016
- const urlEncoded = new URLSearchParams(formData).toString();
1017
- const bytes = textEncoder.encode(urlEncoded);
1018
- const len = Math.min(bytes.length, bufLen);
1019
- writeBytes(bufPtr, bytes.subarray(0, len));
1020
- return len;
1021
- },
1022
- _submitFormAction: (vnodeId, actionId) => {
1023
- const form = domNodes.get(vnodeId);
1024
- if (!form || !(form instanceof HTMLFormElement))
1025
- return;
1026
- const formData = new FormData(form);
1027
- fetch(window.location.href, {
1028
- method: "POST",
1029
- headers: { "x-action": String(actionId >>> 0) },
1030
- body: formData
1031
- }).catch(() => {});
1032
- },
1033
- _submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
1034
- const form = domNodes.get(vnodeId);
1035
- if (!form || !(form instanceof HTMLFormElement))
1036
- return;
1037
- const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
1038
- bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
1039
- }
1040
- }
1041
- };
1042
- }
1043
- }
1044
- var domNodes = new Map;
1045
- function cleanupDomNodes(node) {
1046
- const ref = node.__zx_ref;
1047
- if (ref !== undefined)
1048
- domNodes.delete(BigInt(ref));
1049
- const children = node.childNodes;
1050
- for (let i = 0;i < children.length; i++)
1051
- cleanupDomNodes(children[i]);
1052
- }
1053
- var SVG_TAG_START_INDEX = 140;
1054
- var TAG_NAMES = [
1055
- "aside",
1056
- "fragment",
1057
- "iframe",
1058
- "slot",
1059
- "img",
1060
- "html",
1061
- "base",
1062
- "head",
1063
- "link",
1064
- "meta",
1065
- "script",
1066
- "style",
1067
- "title",
1068
- "address",
1069
- "article",
1070
- "body",
1071
- "h1",
1072
- "h6",
1073
- "footer",
1074
- "header",
1075
- "h2",
1076
- "h3",
1077
- "h4",
1078
- "h5",
1079
- "hgroup",
1080
- "nav",
1081
- "section",
1082
- "dd",
1083
- "dl",
1084
- "dt",
1085
- "div",
1086
- "figcaption",
1087
- "figure",
1088
- "hr",
1089
- "li",
1090
- "ol",
1091
- "ul",
1092
- "menu",
1093
- "main",
1094
- "p",
1095
- "picture",
1096
- "pre",
1097
- "a",
1098
- "abbr",
1099
- "b",
1100
- "bdi",
1101
- "bdo",
1102
- "br",
1103
- "cite",
1104
- "code",
1105
- "data",
1106
- "time",
1107
- "dfn",
1108
- "em",
1109
- "i",
1110
- "kbd",
1111
- "mark",
1112
- "q",
1113
- "blockquote",
1114
- "rp",
1115
- "ruby",
1116
- "rt",
1117
- "rtc",
1118
- "rb",
1119
- "s",
1120
- "del",
1121
- "ins",
1122
- "samp",
1123
- "small",
1124
- "span",
1125
- "strong",
1126
- "sub",
1127
- "sup",
1128
- "u",
1129
- "var",
1130
- "wbr",
1131
- "area",
1132
- "map",
1133
- "audio",
1134
- "source",
1135
- "track",
1136
- "video",
1137
- "embed",
1138
- "object",
1139
- "param",
1140
- "canvas",
1141
- "noscript",
1142
- "caption",
1143
- "table",
1144
- "col",
1145
- "colgroup",
1146
- "tbody",
1147
- "tr",
1148
- "thead",
1149
- "tfoot",
1150
- "td",
1151
- "th",
1152
- "button",
1153
- "datalist",
1154
- "option",
1155
- "fieldset",
1156
- "label",
1157
- "form",
1158
- "input",
1159
- "keygen",
1160
- "legend",
1161
- "meter",
1162
- "optgroup",
1163
- "select",
1164
- "output",
1165
- "progress",
1166
- "textarea",
1167
- "details",
1168
- "dialog",
1169
- "menuitem",
1170
- "summary",
1171
- "content",
1172
- "element",
1173
- "shadow",
1174
- "template",
1175
- "acronym",
1176
- "applet",
1177
- "basefont",
1178
- "font",
1179
- "big",
1180
- "blink",
1181
- "center",
1182
- "command",
1183
- "dir",
1184
- "frame",
1185
- "frameset",
1186
- "isindex",
1187
- "listing",
1188
- "marquee",
1189
- "noembed",
1190
- "plaintext",
1191
- "spacer",
1192
- "strike",
1193
- "tt",
1194
- "xmp",
1195
- "animate",
1196
- "animateMotion",
1197
- "animateTransform",
1198
- "circle",
1199
- "clipPath",
1200
- "defs",
1201
- "desc",
1202
- "ellipse",
1203
- "feBlend",
1204
- "feColorMatrix",
1205
- "feComponentTransfer",
1206
- "feComposite",
1207
- "feConvolveMatrix",
1208
- "feDiffuseLighting",
1209
- "feDisplacementMap",
1210
- "feDistantLight",
1211
- "feDropShadow",
1212
- "feFlood",
1213
- "feFuncA",
1214
- "feFuncB",
1215
- "feFuncG",
1216
- "feFuncR",
1217
- "feGaussianBlur",
1218
- "feImage",
1219
- "feMerge",
1220
- "feMergeNode",
1221
- "feMorphology",
1222
- "feOffset",
1223
- "fePointLight",
1224
- "feSpecularLighting",
1225
- "feSpotLight",
1226
- "feTile",
1227
- "feTurbulence",
1228
- "filter",
1229
- "foreignObject",
1230
- "g",
1231
- "image",
1232
- "line",
1233
- "linearGradient",
1234
- "marker",
1235
- "mask",
1236
- "metadata",
1237
- "mpath",
1238
- "path",
1239
- "pattern",
1240
- "polygon",
1241
- "polyline",
1242
- "radialGradient",
1243
- "rect",
1244
- "set",
1245
- "stop",
1246
- "svg",
1247
- "switch",
1248
- "symbol",
1249
- "text",
1250
- "textPath",
1251
- "tspan",
1252
- "use",
1253
- "view"
1254
- ];
1255
- var DELEGATED_EVENTS = [
1256
- { domType: "click", eventTypeId: 0 },
1257
- { domType: "dblclick", eventTypeId: 1 },
1258
- { domType: "input", eventTypeId: 2 },
1259
- { domType: "change", eventTypeId: 3 },
1260
- { domType: "submit", eventTypeId: 4 },
1261
- { domType: "focusin", eventTypeId: 5 },
1262
- { domType: "focusout", eventTypeId: 6 },
1263
- { domType: "keydown", eventTypeId: 7 },
1264
- { domType: "keyup", eventTypeId: 8 },
1265
- { domType: "keypress", eventTypeId: 9 },
1266
- { domType: "mouseenter", eventTypeId: 10 },
1267
- { domType: "mouseleave", eventTypeId: 11 },
1268
- { domType: "mousedown", eventTypeId: 12 },
1269
- { domType: "mouseup", eventTypeId: 13 },
1270
- { domType: "mousemove", eventTypeId: 14 },
1271
- { domType: "touchstart", eventTypeId: 15 },
1272
- { domType: "touchend", eventTypeId: 16 },
1273
- { domType: "touchmove", eventTypeId: 17 },
1274
- { domType: "scroll", eventTypeId: 18 }
1275
- ];
1276
- var eventHandlerModes = new Map;
1277
- function initEventDelegation(bridge, rootSelector = "body") {
1278
- const root = document.querySelector(rootSelector);
1279
- if (!root)
1280
- return () => {};
1281
- const removers = [];
1282
- for (const delegatedEvent of DELEGATED_EVENTS) {
1283
- const listener = (event) => {
1284
- let target = event.target;
1285
- while (target && target !== document.body) {
1286
- const zxRef = target.__zx_ref;
1287
- if (zxRef !== undefined) {
1288
- bridge.eventbridge(BigInt(zxRef), delegatedEvent.eventTypeId, event);
1289
- if (event.cancelBubble)
1290
- break;
1291
- }
1292
- target = target.parentElement;
1293
- }
1294
- };
1295
- const options = { passive: delegatedEvent.domType.startsWith("touch") || delegatedEvent.domType === "scroll" };
1296
- root.addEventListener(delegatedEvent.domType, listener, options);
1297
- removers.push(() => root.removeEventListener(delegatedEvent.domType, listener, options));
1298
- }
1299
- return () => {
1300
- for (const remove of removers)
1301
- remove();
1302
- };
1303
- }
1304
- var DEFAULT_URL = "/assets/_/main.wasm";
1305
- var activeRuntime = null;
1306
- function buildDevtoolsLocation() {
1307
- return {
1308
- href: window.location.href,
1309
- origin: window.location.origin,
1310
- host: window.location.host,
1311
- pathname: window.location.pathname
1312
- };
1313
- }
1314
- function normalizeOptions(options = {}) {
1315
- return {
1316
- url: options.url,
1317
- eventDelegationRoot: options.eventDelegationRoot,
1318
- importObject: options.importObject,
1319
- kv: options.kv
1320
- };
1321
- }
1322
- function registerDevReinit(options) {
1323
- if (typeof window === "undefined")
1324
- return;
1325
- const reinit = () => init(options);
1326
- window.__zx_dev_reinit = reinit;
1327
- window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
1328
- location: buildDevtoolsLocation(),
1329
- reinit
1330
- };
1331
- }
1332
- async function init(options = {}) {
1333
- const normalizedOptions = normalizeOptions(options);
1334
- if (activeRuntime) {
1335
- activeRuntime.dispose();
1336
- activeRuntime = null;
1337
- }
1338
- const url = options.url ?? document.getElementById("__$wasmlink")?.href ?? DEFAULT_URL;
1339
- const bridgeRef = { current: null };
1340
- let wasmMemory = null;
1341
- const kvBindings = options.kv ?? createBrowserKVBindings();
1342
- const kvImportObject = {
1343
- __zx_kv: createKVImports(kvBindings, () => {
1344
- if (wasmMemory)
1345
- return wasmMemory;
1346
- if (jsz.memory)
1347
- return jsz.memory;
1348
- throw new Error("WASM memory is not ready");
1349
- })
1350
- };
1351
- const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), kvImportObject, options.importObject);
1352
- const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
1353
- const { instance } = source;
1354
- wasmMemory = instance.exports.memory;
1355
- jsz.memory = wasmMemory;
1356
- const bridge = new ZxBridge(instance.exports);
1357
- bridgeRef.current = bridge;
1358
- domNodes.clear();
1359
- const disposeDelegation = initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
1360
- const main = wrapPromisingExport(instance.exports.mainClient);
1361
- invokeWasmExport(main);
1362
- activeRuntime = {
1363
- options: normalizedOptions,
1364
- dispose: () => {
1365
- disposeDelegation();
1366
- bridge.dispose();
1367
- domNodes.clear();
1368
- }
1369
- };
1370
- if (true)
1371
- registerDevReinit(normalizedOptions);
1372
- return { source, bridge };
1373
- }
1374
-
1375
- // src/runtime.ts
1376
- var exports_runtime = {};
1377
- __export(exports_runtime, {
1378
- run: () => run,
1379
- buildWsImports: () => buildWsImports,
1380
- attachWebSocket: () => attachWebSocket
1381
- });
1382
-
1383
- // src/wasm/wasi.ts
1384
- var decoder2 = new TextDecoder;
1385
- var encoder2 = new TextEncoder;
1386
-
1387
- class ZxWasiBridge {
1388
- #alloc;
1389
- #fetchCompleteHandler;
1390
- #memory;
1391
- #cb;
1392
- #intervals = new Map;
1393
- #memView = null;
1394
- #memBuf = null;
1395
- constructor(exports) {
1396
- this.#memory = exports.memory;
1397
- this.#alloc = exports.__zx_alloc;
1398
- this.#fetchCompleteHandler = exports.__zx_fetch_complete;
1399
- this.#cb = exports.__zx_cb;
1400
- }
1401
- #view() {
1402
- const buf = this.#memory.buffer;
1403
- if (buf !== this.#memBuf) {
1404
- this.#memBuf = buf;
1405
- this.#memView = new Uint8Array(buf);
1406
- }
1407
- return this.#memView;
1408
- }
1409
- #readString(ptr, len) {
1410
- return decoder2.decode(this.#view().subarray(ptr, ptr + len));
1411
- }
1412
- #writeBytes(ptr, data) {
1413
- this.#view().set(data, ptr);
1414
- }
1415
- log(level, ptr, len) {
1416
- const msg = decoder2.decode(this.#view().subarray(ptr, ptr + len));
1417
- switch (level) {
1418
- case 0:
1419
- console.error(msg);
1420
- break;
1421
- case 1:
1422
- console.warn(msg);
1423
- break;
1424
- case 3:
1425
- console.debug(msg);
1426
- break;
1427
- default:
1428
- console.log(msg);
1429
- break;
1430
- }
1431
- }
1432
- fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
1433
- const url = this.#readString(urlPtr, urlLen);
1434
- const method = methodLen > 0 ? this.#readString(methodPtr, methodLen) : "GET";
1435
- const headersJson = headersLen > 0 ? this.#readString(headersPtr, headersLen) : "{}";
1436
- const body = bodyLen > 0 ? this.#view().subarray(bodyPtr, bodyPtr + bodyLen) : undefined;
1437
- let headers = {};
1438
- try {
1439
- headers = JSON.parse(headersJson);
1440
- } catch {
1441
- for (const line of headersJson.split(`
1442
- `)) {
1443
- const i = line.indexOf(":");
1444
- if (i > 0)
1445
- headers[line.slice(0, i)] = line.slice(i + 1);
1446
- }
1447
- }
1448
- const controller = new AbortController;
1449
- const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
1450
- fetch(url, {
1451
- method,
1452
- headers: Object.keys(headers).length > 0 ? headers : undefined,
1453
- body: method !== "GET" && method !== "HEAD" ? body : undefined,
1454
- signal: controller.signal
1455
- }).then(async (res) => {
1456
- if (timeout)
1457
- clearTimeout(timeout);
1458
- const bytes = new Uint8Array(await res.arrayBuffer());
1459
- this.#notifyFetchComplete(fetchId, res.status, bytes, false);
1460
- }).catch((err) => {
1461
- if (timeout)
1462
- clearTimeout(timeout);
1463
- const msg = err.name === "AbortError" ? "Request timeout" : err.message ?? "Fetch failed";
1464
- this.#notifyFetchComplete(fetchId, 0, msg, true);
1465
- });
1466
- }
1467
- #notifyFetchComplete(fetchId, status, body, isError) {
1468
- const encoded = typeof body === "string" ? encoder2.encode(body) : body;
1469
- const ptr = this.#alloc(encoded.length);
1470
- this.#writeBytes(ptr, encoded);
1471
- this.#fetchCompleteHandler(fetchId, status, ptr, encoded.length, isError ? 1 : 0);
1472
- }
1473
- setTimeout(callbackId, delayMs) {
1474
- setTimeout(() => this.#cb?.(3, callbackId, 0n), delayMs);
1475
- }
1476
- setInterval(callbackId, intervalMs) {
1477
- const handle = setInterval(() => this.#cb?.(4, callbackId, 0n), intervalMs);
1478
- this.#intervals.set(callbackId, handle);
1479
- }
1480
- clearInterval(callbackId) {
1481
- const handle = this.#intervals.get(callbackId);
1482
- if (handle !== undefined) {
1483
- clearInterval(handle);
1484
- this.#intervals.delete(callbackId);
1485
- }
1486
- }
1487
- static createImportObject(bridgeRef) {
1488
- return {
1489
- __zx: {
1490
- _log: (level, ptr, len) => {
1491
- bridgeRef.current?.log(level, ptr, len);
1492
- },
1493
- _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
1494
- bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
1495
- },
1496
- _setTimeout: (callbackId, delayMs) => {
1497
- bridgeRef.current?.setTimeout(callbackId, delayMs);
1498
- },
1499
- _setInterval: (callbackId, intervalMs) => {
1500
- bridgeRef.current?.setInterval(callbackId, intervalMs);
1501
- },
1502
- _clearInterval: (callbackId) => {
1503
- bridgeRef.current?.clearInterval(callbackId);
1504
- }
1505
- }
1506
- };
1507
- }
1508
- }
1509
-
1510
- // src/db.ts
1511
- function decodeBlob(base64) {
1512
- const binary = atob(base64);
1513
- const bytes = new Uint8Array(binary.length);
1514
- for (let i = 0;i < binary.length; i++)
1515
- bytes[i] = binary.charCodeAt(i);
1516
- return bytes;
1517
- }
1518
- function toD1Value(value) {
1519
- switch (value.kind) {
1520
- case "null":
1521
- return null;
1522
- case "integer":
1523
- return value.integer;
1524
- case "float":
1525
- return value.float;
1526
- case "text":
1527
- return value.text;
1528
- case "blob":
1529
- return decodeBlob(value.blob);
1530
- case "boolean":
1531
- return value.boolean;
1532
- }
1533
- }
1534
- function toPositionalBindings(json) {
1535
- switch (json.kind) {
1536
- case "none":
1537
- return [];
1538
- case "positional":
1539
- return json.values.map(toD1Value);
1540
- case "named":
1541
- throw new Error("Cloudflare D1 adapter does not support named bindings yet");
1542
- }
1543
- }
1544
- function toWireValue(value) {
1545
- if (value === null || value === undefined)
1546
- return { kind: "null" };
1547
- if (typeof value === "string")
1548
- return { kind: "text", text: value };
1549
- if (typeof value === "boolean")
1550
- return { kind: "boolean", boolean: value };
1551
- if (typeof value === "number") {
1552
- return Number.isInteger(value) ? { kind: "integer", integer: value } : { kind: "float", float: value };
1553
- }
1554
- if (value instanceof ArrayBuffer) {
1555
- const bytes = new Uint8Array(value);
1556
- let binary = "";
1557
- for (const byte of bytes)
1558
- binary += String.fromCharCode(byte);
1559
- return { kind: "blob", blob: btoa(binary) };
1560
- }
1561
- if (ArrayBuffer.isView(value)) {
1562
- const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
1563
- let binary = "";
1564
- for (const byte of bytes)
1565
- binary += String.fromCharCode(byte);
1566
- return { kind: "blob", blob: btoa(binary) };
1567
- }
1568
- return { kind: "text", text: String(value) };
1569
- }
1570
- function objectToWireRow(record) {
1571
- return {
1572
- fields: Object.entries(record).map(([name, value]) => ({
1573
- name,
1574
- value: toWireValue(value)
1575
- }))
1576
- };
1577
- }
1578
- function valuesToWireRows(rows) {
1579
- return rows.map((row) => row.map((value) => toWireValue(value)));
1580
- }
1581
- function createD1Imports(bindings, getMemory) {
1582
- const encoder3 = new TextEncoder;
1583
- const decoder3 = new TextDecoder;
1584
- function readStr(ptr, len) {
1585
- return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
1586
- }
1587
- function writeJson(buf_ptr, buf_max, value) {
1588
- const data = encoder3.encode(JSON.stringify(value));
1589
- if (data.length > buf_max)
1590
- return -2;
1591
- new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
1592
- return data.length;
1593
- }
1594
- function binding(ns) {
1595
- return bindings[ns] ?? bindings["default"] ?? null;
1596
- }
1597
- async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
1598
- const database = binding(readStr(ns_ptr, ns_len));
1599
- if (!database)
1600
- return null;
1601
- const sql = readStr(sql_ptr, sql_len);
1602
- const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
1603
- return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
1604
- }
1605
- const Suspending = WebAssembly.Suspending;
1606
- if (typeof Suspending !== "function") {
1607
- return {
1608
- db_open: (_ns, _ns_len) => -1,
1609
- db_run: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
1610
- db_get: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
1611
- db_all: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
1612
- db_values: (_a, _b, _c, _d, _e, _f, _g, _h) => -1
1613
- };
1614
- }
1615
- return {
1616
- db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
1617
- db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
1618
- const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
1619
- if (!stmt)
1620
- return -1;
1621
- const result = await stmt.run();
1622
- return writeJson(buf_ptr, buf_max, {
1623
- last_insert_rowid: result.meta?.last_row_id ?? 0,
1624
- changes: result.meta?.changes ?? 0
1625
- });
1626
- }),
1627
- db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
1628
- const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
1629
- if (!stmt)
1630
- return -1;
1631
- const row = await stmt.first();
1632
- if (!row)
1633
- return 0;
1634
- return writeJson(buf_ptr, buf_max, [objectToWireRow(row)]);
1635
- }),
1636
- db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
1637
- const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
1638
- if (!stmt)
1639
- return -1;
1640
- const result = await stmt.all();
1641
- return writeJson(buf_ptr, buf_max, (result.results ?? []).map(objectToWireRow));
1642
- }),
1643
- db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
1644
- const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
1645
- if (!stmt)
1646
- return -1;
1647
- const rows = await stmt.raw();
1648
- return writeJson(buf_ptr, buf_max, valuesToWireRows(rows));
1649
- })
1650
- };
1651
- }
1652
-
1653
- // src/wasi.ts
1654
- class ProcExit extends Error {
1655
- code;
1656
- constructor(code) {
1657
- super(`proc_exit(${code})`);
1658
- this.code = code;
1659
- }
1660
- }
1661
- function createWasiImports({
1662
- request,
1663
- stdinData,
1664
- onStdout
1665
- }) {
1666
- const encoder3 = new TextEncoder;
1667
- const url = new URL(request.url);
1668
- const argStrings = [
1669
- "wasm",
1670
- "--pathname",
1671
- url.pathname,
1672
- "--method",
1673
- request.method,
1674
- "--search",
1675
- url.search,
1676
- "--url",
1677
- url.href
1678
- ];
1679
- request.headers.forEach((value, name) => {
1680
- if (value)
1681
- argStrings.push("--header", `${name}:${value}`);
1682
- });
1683
- const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\x00"));
1684
- const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
1685
- let wasmMemory = null;
1686
- const setMemory = (m2) => {
1687
- wasmMemory = m2;
1688
- };
1689
- const stdoutChunks = [];
1690
- let stderrMeta = "";
1691
- let stderrPartial = "";
1692
- const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
1693
- function processStderrChunk(chunk) {
1694
- const text = stderrDecoder.decode(chunk, { stream: true });
1695
- const lines = (stderrPartial + text).split(`
1696
- `);
1697
- stderrPartial = lines.pop() ?? "";
1698
- for (const line of lines) {
1699
- if (line.startsWith("__ZIEX_META__:")) {
1700
- stderrMeta += line + `
1701
- `;
1702
- } else if (line.length > 0) {
1703
- console.error("[ziex]", line);
1704
- }
441
+ const Suspending = WebAssembly.Suspending;
442
+ if (typeof Suspending !== "function") {
443
+ return {
444
+ db_open: (_ns, _ns_len) => -1,
445
+ db_run: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
446
+ db_get: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
447
+ db_all: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
448
+ db_values: (_a, _b, _c, _d, _e, _f, _g, _h) => -1
449
+ };
450
+ }
451
+ return {
452
+ db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
453
+ db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
454
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
455
+ if (!stmt) return -1;
456
+ const result = await stmt.run();
457
+ return writeJson(buf_ptr, buf_max, {
458
+ last_insert_rowid: result.meta?.last_row_id ?? 0,
459
+ changes: result.meta?.changes ?? 0
460
+ });
461
+ }),
462
+ db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
463
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
464
+ if (!stmt) return -1;
465
+ const row = await stmt.first();
466
+ if (!row) return 0;
467
+ return writeJson(buf_ptr, buf_max, [objectToWireRow(row)]);
468
+ }),
469
+ db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
470
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
471
+ if (!stmt) return -1;
472
+ const result = await stmt.all();
473
+ return writeJson(buf_ptr, buf_max, (result.results ?? []).map(objectToWireRow));
474
+ }),
475
+ db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
476
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
477
+ if (!stmt) return -1;
478
+ const rows = await stmt.raw();
479
+ return writeJson(buf_ptr, buf_max, valuesToWireRows(rows));
480
+ })
481
+ };
482
+ }
483
+
484
+ // src/wasi.ts
485
+ var ProcExit = class extends Error {
486
+ constructor(code) {
487
+ super(`proc_exit(${code})`);
488
+ this.code = code;
489
+ }
490
+ };
491
+ function createWasiImports({
492
+ request,
493
+ stdinData,
494
+ onStdout
495
+ }) {
496
+ const encoder3 = new TextEncoder();
497
+ const url = new URL(request.url);
498
+ const argStrings = [
499
+ "wasm",
500
+ "--pathname",
501
+ url.pathname,
502
+ "--method",
503
+ request.method,
504
+ "--search",
505
+ url.search,
506
+ "--url",
507
+ url.href
508
+ ];
509
+ request.headers.forEach((value, name) => {
510
+ if (value) argStrings.push("--header", `${name}:${value}`);
511
+ });
512
+ const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\0"));
513
+ const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
514
+ let wasmMemory = null;
515
+ const setMemory = (m2) => {
516
+ wasmMemory = m2;
517
+ };
518
+ const stdoutChunks = [];
519
+ let stderrMeta = "";
520
+ let stderrPartial = "";
521
+ const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
522
+ function processStderrChunk(chunk) {
523
+ const text = stderrDecoder.decode(chunk, { stream: true });
524
+ const lines = (stderrPartial + text).split("\n");
525
+ stderrPartial = lines.pop() ?? "";
526
+ for (const line of lines) {
527
+ if (line.startsWith("__ZIEX_META__:")) {
528
+ stderrMeta += line + "\n";
529
+ } else if (line.length > 0) {
530
+ console.error("[ziex]", line);
531
+ }
1705
532
  }
1706
533
  }
1707
534
  let stdinOffset = 0;
@@ -1741,17 +568,14 @@ function createWasiImports({
1741
568
  const dv = v();
1742
569
  const mem = m();
1743
570
  let written = 0;
1744
- for (let i = 0;i < iovs_len; i++) {
571
+ for (let i = 0; i < iovs_len; i++) {
1745
572
  const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
1746
573
  const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
1747
574
  const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
1748
575
  if (fd === 1) {
1749
- if (onStdout)
1750
- onStdout(chunk);
1751
- else
1752
- stdoutChunks.push(chunk);
1753
- } else if (fd === 2)
1754
- processStderrChunk(chunk);
576
+ if (onStdout) onStdout(chunk);
577
+ else stdoutChunks.push(chunk);
578
+ } else if (fd === 2) processStderrChunk(chunk);
1755
579
  written += buf_len;
1756
580
  }
1757
581
  dv.setUint32(nwritten_ptr, written, true);
@@ -1762,7 +586,7 @@ function createWasiImports({
1762
586
  const mem = m();
1763
587
  const stdin = stdinData ?? new Uint8Array(0);
1764
588
  let totalRead = 0;
1765
- for (let i = 0;i < iovs_len; i++) {
589
+ for (let i = 0; i < iovs_len; i++) {
1766
590
  const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
1767
591
  const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
1768
592
  if (fd === 0 && stdinOffset < stdin.length) {
@@ -1919,341 +743,1298 @@ function createWasiImports({
1919
743
  v().setUint32(bufused_ptr, 0, true);
1920
744
  return 76;
1921
745
  },
746
+ // Stub for poll_oneoff - no blocking I/O in edge runtimes.
1922
747
  poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
1923
748
  v().setUint32(nevents_ptr, 0, true);
1924
749
  return 0;
1925
750
  }
1926
- };
1927
- function collectOutput() {
1928
- const remaining = stderrDecoder.decode(undefined, { stream: false });
1929
- const tail = stderrPartial + remaining;
1930
- if (tail.length > 0) {
1931
- if (tail.startsWith("__ZIEX_META__:"))
1932
- stderrMeta += tail;
1933
- else
1934
- console.error("[ziex]", tail);
1935
- stderrPartial = "";
751
+ };
752
+ function collectOutput() {
753
+ const remaining = stderrDecoder.decode(void 0, { stream: false });
754
+ const tail = stderrPartial + remaining;
755
+ if (tail.length > 0) {
756
+ if (tail.startsWith("__ZIEX_META__:")) stderrMeta += tail;
757
+ else console.error("[ziex]", tail);
758
+ stderrPartial = "";
759
+ }
760
+ return {
761
+ stdout: mergeUint8Arrays(stdoutChunks),
762
+ stderrText: stderrMeta
763
+ };
764
+ }
765
+ return { wasiImport, setMemory, collectOutput };
766
+ }
767
+ function mergeUint8Arrays(arrays) {
768
+ const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
769
+ const result = new Uint8Array(totalLen);
770
+ let offset = 0;
771
+ for (const arr of arrays) {
772
+ result.set(arr, offset);
773
+ offset += arr.length;
774
+ }
775
+ return result;
776
+ }
777
+
778
+ // src/runtime.ts
779
+ function buildWsImports(Suspending, mem, decoder3, ws) {
780
+ const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
781
+ return {
782
+ ws_upgrade: () => {
783
+ ws.upgraded = true;
784
+ },
785
+ ws_write: (ptr, len) => {
786
+ const data = new Uint8Array(mem().buffer, ptr, len).slice();
787
+ if (!ws.server) {
788
+ ws.pendingWrites.push(data);
789
+ } else {
790
+ ws.server.send(data);
791
+ }
792
+ },
793
+ ws_close: (code, reason_ptr, reason_len) => {
794
+ ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
795
+ },
796
+ ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
797
+ if (ws._resolveFirstSuspend) {
798
+ const fn = ws._resolveFirstSuspend;
799
+ ws._resolveFirstSuspend = void 0;
800
+ fn();
801
+ }
802
+ const deliver = (bytes) => {
803
+ if (bytes === null) return -1;
804
+ const n = Math.min(bytes.length, buf_max);
805
+ new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
806
+ return n;
807
+ };
808
+ if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
809
+ return new Promise((resolve) => {
810
+ ws.recvResolve = (bytes) => resolve(deliver(bytes));
811
+ });
812
+ }) : (_buf_ptr, _buf_max) => -1,
813
+ // Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
814
+ ws_subscribe: (ptr, len) => {
815
+ ws.subscribe?.(readStr(ptr, len));
816
+ },
817
+ ws_unsubscribe: (ptr, len) => {
818
+ ws.unsubscribe?.(readStr(ptr, len));
819
+ },
820
+ ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
821
+ const topic = readStr(topic_ptr, topic_len);
822
+ const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
823
+ return ws.publish?.(topic, data) ?? 0;
824
+ },
825
+ ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
826
+ };
827
+ }
828
+ function attachWebSocket(ws) {
829
+ const WebSocketPairCtor = globalThis.WebSocketPair;
830
+ const pair = new WebSocketPairCtor();
831
+ const client = pair[0];
832
+ const server = pair[1];
833
+ ws.server = server;
834
+ server.accept();
835
+ for (const data of ws.pendingWrites) server.send(data);
836
+ ws.pendingWrites = [];
837
+ server.addEventListener("message", (event) => {
838
+ const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
839
+ if (ws.recvResolve) {
840
+ const res = ws.recvResolve;
841
+ ws.recvResolve = null;
842
+ res(data);
843
+ } else {
844
+ ws.messageQueue.push(data);
845
+ }
846
+ });
847
+ server.addEventListener("close", () => {
848
+ if (ws.recvResolve) {
849
+ const res = ws.recvResolve;
850
+ ws.recvResolve = null;
851
+ res(null);
852
+ }
853
+ });
854
+ return { client };
855
+ }
856
+ function buildSysImports(jspi, Suspending) {
857
+ return {
858
+ sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
859
+ }
860
+ };
861
+ }
862
+ function executeWasm(instance, jspi, Suspending, wsState) {
863
+ if (!jspi) {
864
+ try {
865
+ instance.exports._start();
866
+ } catch (e) {
867
+ if (!(e instanceof ProcExit)) throw e;
868
+ }
869
+ return Promise.resolve();
870
+ }
871
+ const start = WebAssembly.promising(instance.exports._start);
872
+ return start().catch((e) => {
873
+ if (e instanceof Error && e.message.startsWith("proc_exit")) return;
874
+ throw e;
875
+ }).finally(() => {
876
+ if (wsState.recvResolve) {
877
+ const res = wsState.recvResolve;
878
+ wsState.recvResolve = null;
879
+ res(null);
880
+ }
881
+ });
882
+ }
883
+ function parseZiexMeta(stderrText) {
884
+ const meta = { status: 200, headers: new Headers(), streaming: false };
885
+ const metaPrefix = "__ZIEX_META__:";
886
+ const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
887
+ if (metaLine) {
888
+ try {
889
+ const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
890
+ if (parsed.status) meta.status = parsed.status;
891
+ if (parsed.streaming === true) meta.streaming = true;
892
+ if (Array.isArray(parsed.headers)) {
893
+ for (const [name, value] of parsed.headers) {
894
+ meta.headers.append(name, value);
895
+ }
896
+ }
897
+ } catch {
898
+ }
899
+ }
900
+ return meta;
901
+ }
902
+ async function run({
903
+ request,
904
+ env,
905
+ ctx,
906
+ module,
907
+ kv: kvBindings,
908
+ db: dbBindings,
909
+ imports,
910
+ wasi,
911
+ websocket: doNamespace
912
+ }) {
913
+ if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
914
+ const id = doNamespace.idFromName(new URL(request.url).pathname);
915
+ return doNamespace.get(id).fetch(request);
916
+ }
917
+ const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
918
+ const stdoutChunks = [];
919
+ let streamWriter = null;
920
+ const { wasiImport, setMemory, collectOutput } = createWasiImports({
921
+ request,
922
+ stdinData,
923
+ onStdout: (chunk) => {
924
+ if (streamWriter) void streamWriter.write(chunk);
925
+ else stdoutChunks.push(chunk);
926
+ }
927
+ });
928
+ let wasmMemory = null;
929
+ const mem = () => wasmMemory;
930
+ const bridgeRef = { current: null };
931
+ const Suspending = WebAssembly.Suspending;
932
+ const jspi = typeof Suspending === "function";
933
+ const wsState = {
934
+ upgraded: false,
935
+ server: null,
936
+ pendingWrites: [],
937
+ messageQueue: [],
938
+ recvResolve: null
939
+ };
940
+ const instance = new WebAssembly.Instance(module, {
941
+ wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
942
+ __zx_sys: buildSysImports(jspi, Suspending),
943
+ __zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder(), wsState),
944
+ __zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
945
+ __zx_db: createD1Imports(dbBindings ?? {}, mem),
946
+ __zx_net: createFetchImports(mem),
947
+ ...imports ? imports(mem) : {},
948
+ ...ZxWasiBridge.createImportObject(bridgeRef)
949
+ });
950
+ wasmMemory = instance.exports.memory;
951
+ setMemory(wasmMemory);
952
+ bridgeRef.current = new ZxWasiBridge(instance.exports);
953
+ const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
954
+ if (wsState.upgraded) {
955
+ const server = attachWebSocket(wsState);
956
+ ctx?.waitUntil(wasmPromise);
957
+ return new Response(null, { status: 101, webSocket: server.client });
958
+ }
959
+ const { stderrText: earlyStderrText } = collectOutput();
960
+ const earlyMeta = parseZiexMeta(earlyStderrText);
961
+ if (earlyMeta.streaming) {
962
+ const { readable, writable } = new TransformStream();
963
+ streamWriter = writable.getWriter();
964
+ for (const chunk of stdoutChunks) void streamWriter.write(chunk);
965
+ stdoutChunks.length = 0;
966
+ void wasmPromise.finally(() => streamWriter?.close());
967
+ return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
968
+ }
969
+ await wasmPromise;
970
+ const { stderrText } = collectOutput();
971
+ const meta = parseZiexMeta(stderrText);
972
+ const body = mergeUint8Arrays(stdoutChunks);
973
+ meta.headers.delete("transfer-encoding");
974
+ const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
975
+ if (nullBody) {
976
+ meta.headers.delete("content-length");
977
+ return new Response(null, { status: meta.status, headers: meta.headers });
978
+ }
979
+ if (!meta.headers.has("content-length")) meta.headers.set("content-length", String(body.byteLength));
980
+ return new Response(body.buffer, { status: meta.status, headers: meta.headers });
981
+ }
982
+
983
+ // src/app.ts
984
+ async function resolveModule(input) {
985
+ if (typeof input === "string") {
986
+ if (input.startsWith("http://") || input.startsWith("https://")) {
987
+ return WebAssembly.compileStreaming(fetch(input));
988
+ }
989
+ const url = input.startsWith("/") ? `file://${input}` : input;
990
+ return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
991
+ }
992
+ if (input instanceof URL) {
993
+ return WebAssembly.compileStreaming(fetch(input));
994
+ }
995
+ if (input instanceof Response) {
996
+ return WebAssembly.compileStreaming(input);
997
+ }
998
+ if (input instanceof ArrayBuffer) {
999
+ return WebAssembly.compile(input);
1000
+ }
1001
+ if (ArrayBuffer.isView(input)) {
1002
+ return WebAssembly.compile(input.buffer);
1003
+ }
1004
+ return input;
1005
+ }
1006
+ var Ziex = class {
1007
+ constructor(options) {
1008
+ this.resolved = null;
1009
+ /**
1010
+ * Fetch handler called by the runtime on every request.
1011
+ *
1012
+ * Arrow function so `this` is always the class instance, even when the
1013
+ * runtime extracts `fetch` from the exported object (e.g. Bun).
1014
+ */
1015
+ this.fetch = async (request, env, ctx) => {
1016
+ const module = await this.getModule();
1017
+ const { wasi, imports, websocket } = this.options;
1018
+ return run({
1019
+ request,
1020
+ env,
1021
+ ctx,
1022
+ module,
1023
+ wasi,
1024
+ imports,
1025
+ kv: this.resolveKV(env),
1026
+ db: this.resolveDB(env),
1027
+ websocket: websocket !== void 0 ? env[websocket] : void 0
1028
+ });
1029
+ };
1030
+ this.options = options;
1031
+ }
1032
+ async getModule() {
1033
+ if (!this.resolved) this.resolved = await resolveModule(this.options.module);
1034
+ return this.resolved;
1035
+ }
1036
+ resolveKV(env) {
1037
+ const { kv } = this.options;
1038
+ if (kv === void 0) return void 0;
1039
+ if (typeof kv === "object" && kv !== null) {
1040
+ const result = {};
1041
+ for (const [name, key] of Object.entries(kv)) {
1042
+ result[name] = env[key];
1043
+ }
1044
+ return result;
1045
+ }
1046
+ return { default: env[kv] };
1047
+ }
1048
+ resolveDB(env) {
1049
+ const { db } = this.options;
1050
+ if (db === void 0) return void 0;
1051
+ if (typeof db === "object" && db !== null) {
1052
+ const result = {};
1053
+ for (const [name, key] of Object.entries(db)) {
1054
+ result[name] = env[key];
1055
+ }
1056
+ return result;
1936
1057
  }
1058
+ return { default: env[db] };
1059
+ }
1060
+ };
1061
+
1062
+ // ../../vendor/jsz/js/src/zigjs.ts
1063
+ var NAN_PREFIX = 2146959360;
1064
+ var predefined = {
1065
+ "nan": 0,
1066
+ "null": 1,
1067
+ "true": 2,
1068
+ "false": 3,
1069
+ "undefined": 4,
1070
+ "globalThis": 5,
1071
+ "runtime": 6
1072
+ };
1073
+ var PREDEFINED_ID_MAX = 6;
1074
+ var encoder2 = new TextEncoder();
1075
+ var decoder2 = new TextDecoder("utf-8");
1076
+ var ZigJS = class {
1077
+ constructor() {
1078
+ /**
1079
+ * The values, indexed by ID (number). Duplicate values can be in this
1080
+ * if they are loaded multiple times. That just acts as duplicate references.
1081
+ * */
1082
+ this.values = [NaN, null, true, false, void 0, globalThis, this];
1083
+ /**
1084
+ * When a value is removed from the values array, its ID is put
1085
+ * in the pool so that we can use it next. This avoids fragmentation in
1086
+ * our array keys.
1087
+ * */
1088
+ this.idPool = [];
1089
+ }
1090
+ /**
1091
+ * Returns the import object that should be merged with your import
1092
+ * object when instantiating your wasm instance. This injects the required
1093
+ * functions into the wasm environment.
1094
+ * */
1095
+ importObject() {
1937
1096
  return {
1938
- stdout: mergeUint8Arrays(stdoutChunks),
1939
- stderrText: stderrMeta
1097
+ "zig-js": {
1098
+ valueGet: this.valueGet.bind(this),
1099
+ valueSet: this.valueSet.bind(this),
1100
+ valueDeinit: this.valueDeinit.bind(this),
1101
+ valueObjectCreate: this.valueObjectCreate.bind(this),
1102
+ valueStringCreate: this.valueStringCreate.bind(this),
1103
+ valueStringLen: this.valueStringLen.bind(this),
1104
+ valueStringCopy: this.valueStringCopy.bind(this),
1105
+ valueNew: this.valueNew.bind(this),
1106
+ funcApply: this.funcApply.bind(this)
1107
+ }
1940
1108
  };
1941
1109
  }
1942
- return { wasiImport, setMemory, collectOutput };
1943
- }
1944
- function mergeUint8Arrays(arrays) {
1945
- const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
1946
- const result = new Uint8Array(totalLen);
1947
- let offset = 0;
1948
- for (const arr of arrays) {
1949
- result.set(arr, offset);
1950
- offset += arr.length;
1110
+ /**
1111
+ * Get a value from the JS environment.
1112
+ * */
1113
+ valueGet(out, id, ptr, len) {
1114
+ const val = this.loadValue(id);
1115
+ const str = this.loadString(ptr, len);
1116
+ const result = Reflect.get(val, str);
1117
+ this.storeValue(out, result);
1951
1118
  }
1952
- return result;
1953
- }
1954
-
1955
- // src/runtime.ts
1956
- function buildWsImports(Suspending, mem, decoder3, ws) {
1957
- const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
1958
- return {
1959
- ws_upgrade: () => {
1960
- ws.upgraded = true;
1961
- },
1962
- ws_write: (ptr, len) => {
1963
- const data = new Uint8Array(mem().buffer, ptr, len).slice();
1964
- if (!ws.server) {
1965
- ws.pendingWrites.push(data);
1119
+ /**
1120
+ * Set a value on an object.
1121
+ * */
1122
+ valueSet(id, ptr, len, refAddr) {
1123
+ const obj = this.loadValue(id);
1124
+ const str = this.loadString(ptr, len);
1125
+ const val = this.loadRef(refAddr);
1126
+ Reflect.set(obj, str, val);
1127
+ }
1128
+ /**
1129
+ * Dereference a value, allowing the JS environment to potentially GC it.
1130
+ * */
1131
+ valueDeinit(id) {
1132
+ if (id > PREDEFINED_ID_MAX) {
1133
+ this.values[id] = null;
1134
+ this.idPool.push(id);
1135
+ }
1136
+ }
1137
+ /**
1138
+ * Create an empty object.
1139
+ * */
1140
+ valueObjectCreate(out) {
1141
+ this.storeValue(out, new Object());
1142
+ }
1143
+ /**
1144
+ * Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
1145
+ * */
1146
+ valueStringCreate(out, ptr, len) {
1147
+ const str = this.loadString(ptr, len);
1148
+ this.storeValue(out, str);
1149
+ }
1150
+ /**
1151
+ * Returns the length of the string given by id.
1152
+ * */
1153
+ valueStringLen(id) {
1154
+ const val = this.loadValue(id);
1155
+ const buf = encoder2.encode(val);
1156
+ return buf.byteLength;
1157
+ }
1158
+ /**
1159
+ * Copy the string at id "id" into the shared memory at ptr.
1160
+ * */
1161
+ valueStringCopy(id, ptr, max) {
1162
+ if (this.memory == null) return;
1163
+ const val = this.loadValue(id);
1164
+ const bytes = encoder2.encode(val);
1165
+ if (bytes.byteLength > max) return;
1166
+ if (bytes.length === 0) return;
1167
+ new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
1168
+ }
1169
+ /**
1170
+ * Call a constructor given by id.
1171
+ * */
1172
+ valueNew(out, id, argsAddr, argsLen) {
1173
+ const fn = this.loadValue(id);
1174
+ const args = [];
1175
+ for (let i = 0; i < argsLen; i++) {
1176
+ args.push(this.loadRef(argsAddr + i * 8));
1177
+ }
1178
+ const result = Reflect.construct(fn, args);
1179
+ this.storeValue(out, result);
1180
+ }
1181
+ /**
1182
+ * Call a function given by id.
1183
+ * */
1184
+ funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
1185
+ const fn = this.loadValue(id);
1186
+ const thisVal = this.loadRef(thisRefAddr);
1187
+ const args = [];
1188
+ for (let i = 0; i < argsLen; i++) {
1189
+ args.push(this.loadRef(argsAddr + i * 8));
1190
+ }
1191
+ const result = Reflect.apply(fn, thisVal, args);
1192
+ this.storeValue(out, result);
1193
+ }
1194
+ /**
1195
+ * This can be used to load a value given by an ID. A WASM function
1196
+ * might return a value as an ID. This can be used to retrieve it.
1197
+ * */
1198
+ loadValue(id) {
1199
+ return this.values[id];
1200
+ }
1201
+ /**
1202
+ * This removes the value from the values list and returns it. This
1203
+ * will not remove predefined values but can still be used to retrieve
1204
+ * them.
1205
+ * */
1206
+ deleteValue(id) {
1207
+ const val = this.values[id];
1208
+ this.valueDeinit(id);
1209
+ return val;
1210
+ }
1211
+ loadRef(refAddr) {
1212
+ if (this.memory == null) return;
1213
+ const view = new DataView(this.memory.buffer);
1214
+ const floatVal = view.getFloat64(refAddr, true);
1215
+ if (!isNaN(floatVal)) return floatVal;
1216
+ const id = this.loadRefId(refAddr);
1217
+ return this.values[id];
1218
+ }
1219
+ loadRefId(refAddr) {
1220
+ if (this.memory == null) return 0;
1221
+ return new DataView(this.memory.buffer).getUint32(refAddr, true);
1222
+ }
1223
+ storeValue(out, val) {
1224
+ if (this.memory == null) return;
1225
+ const view = new DataView(this.memory.buffer);
1226
+ if (typeof val === "number") {
1227
+ if (isNaN(val)) {
1228
+ view.setUint32(out, predefined.nan, true);
1229
+ view.setUint32(out + 4, NAN_PREFIX, true);
1966
1230
  } else {
1967
- ws.server.send(data);
1968
- }
1969
- },
1970
- ws_close: (code, reason_ptr, reason_len) => {
1971
- ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
1972
- },
1973
- ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
1974
- if (ws._resolveFirstSuspend) {
1975
- const fn = ws._resolveFirstSuspend;
1976
- ws._resolveFirstSuspend = undefined;
1977
- fn();
1231
+ view.setFloat64(out, val, true);
1978
1232
  }
1979
- const deliver = (bytes) => {
1980
- if (bytes === null)
1981
- return -1;
1982
- const n = Math.min(bytes.length, buf_max);
1983
- new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
1984
- return n;
1985
- };
1986
- if (ws.messageQueue.length > 0)
1987
- return deliver(ws.messageQueue.shift());
1988
- return new Promise((resolve) => {
1989
- ws.recvResolve = (bytes) => resolve(deliver(bytes));
1990
- });
1991
- }) : (_buf_ptr, _buf_max) => -1,
1992
- ws_subscribe: (ptr, len) => {
1993
- ws.subscribe?.(readStr(ptr, len));
1994
- },
1995
- ws_unsubscribe: (ptr, len) => {
1996
- ws.unsubscribe?.(readStr(ptr, len));
1997
- },
1998
- ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
1999
- const topic = readStr(topic_ptr, topic_len);
2000
- const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
2001
- return ws.publish?.(topic, data) ?? 0;
2002
- },
2003
- ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
2004
- };
2005
- }
2006
- function attachWebSocket(ws) {
2007
- const WebSocketPairCtor = globalThis.WebSocketPair;
2008
- const pair = new WebSocketPairCtor;
2009
- const client = pair[0];
2010
- const server = pair[1];
2011
- ws.server = server;
2012
- server.accept();
2013
- for (const data of ws.pendingWrites)
2014
- server.send(data);
2015
- ws.pendingWrites = [];
2016
- server.addEventListener("message", (event) => {
2017
- const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
2018
- if (ws.recvResolve) {
2019
- const res = ws.recvResolve;
2020
- ws.recvResolve = null;
2021
- res(data);
2022
- } else {
2023
- ws.messageQueue.push(data);
1233
+ return;
2024
1234
  }
2025
- });
2026
- server.addEventListener("close", () => {
2027
- if (ws.recvResolve) {
2028
- const res = ws.recvResolve;
2029
- ws.recvResolve = null;
2030
- res(null);
1235
+ if (val === null) {
1236
+ view.setUint32(out, predefined.null, true);
1237
+ view.setUint32(out + 4, NAN_PREFIX, true);
1238
+ return;
1239
+ }
1240
+ if (val === void 0) {
1241
+ view.setUint32(out, predefined.undefined, true);
1242
+ view.setUint32(out + 4, NAN_PREFIX, true);
1243
+ return;
1244
+ }
1245
+ if (typeof val === "boolean") {
1246
+ view.setUint32(out, val ? predefined.true : predefined.false, true);
1247
+ view.setUint32(out + 4, NAN_PREFIX, true);
1248
+ return;
1249
+ }
1250
+ if (typeof val === "bigint") {
1251
+ view.setFloat64(out, Number(val), true);
1252
+ return;
1253
+ }
1254
+ let id = this.idPool.pop();
1255
+ if (id === void 0) {
1256
+ id = this.values.length;
1257
+ }
1258
+ this.values[id] = val;
1259
+ let typeId = 0;
1260
+ switch (typeof val) {
1261
+ case "object":
1262
+ typeId = 1;
1263
+ break;
1264
+ case "string":
1265
+ typeId = 2;
1266
+ break;
1267
+ case "symbol":
1268
+ typeId = 3;
1269
+ break;
1270
+ case "function":
1271
+ typeId = 4;
1272
+ break;
2031
1273
  }
2032
- });
2033
- return { client };
1274
+ view.setUint32(out, Number(id), true);
1275
+ view.setUint32(out + 4, NAN_PREFIX | typeId, true);
1276
+ }
1277
+ loadString(ptr, len) {
1278
+ if (this.memory == null) return "";
1279
+ const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
1280
+ const data = arr.slice();
1281
+ return decoder2.decode(data);
1282
+ }
1283
+ };
1284
+
1285
+ // src/wasm/core.ts
1286
+ var CallbackType = {
1287
+ Event: 0,
1288
+ FetchSuccess: 1,
1289
+ FetchError: 2,
1290
+ Timeout: 3,
1291
+ Interval: 4,
1292
+ WebSocketOpen: 5,
1293
+ WebSocketMessage: 6,
1294
+ WebSocketError: 7,
1295
+ WebSocketClose: 8
1296
+ };
1297
+ var jsz = new ZigJS();
1298
+ var tempRefBuffer = new ArrayBuffer(8);
1299
+ var tempRefView = new DataView(tempRefBuffer);
1300
+ function storeValueGetRef(val) {
1301
+ const originalMemory = jsz.memory;
1302
+ jsz.memory = { buffer: tempRefBuffer };
1303
+ jsz.storeValue(0, val);
1304
+ jsz.memory = originalMemory;
1305
+ return tempRefView.getBigUint64(0, true);
2034
1306
  }
2035
- function buildSysImports(jspi, Suspending) {
2036
- return {
2037
- sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
2038
- };
1307
+ var textDecoder = new TextDecoder();
1308
+ var textEncoder = new TextEncoder();
1309
+ var memoryView = null;
1310
+ var memoryBuffer = null;
1311
+ function getMemoryView() {
1312
+ const buf = jsz.memory.buffer;
1313
+ if (buf !== memoryBuffer) {
1314
+ memoryBuffer = buf;
1315
+ memoryView = new Uint8Array(buf);
1316
+ }
1317
+ return memoryView;
2039
1318
  }
2040
- function executeWasm(instance, jspi, Suspending, wsState) {
2041
- if (!jspi) {
2042
- try {
2043
- instance.exports._start();
2044
- } catch (e) {
2045
- if (!(e instanceof ProcExit))
2046
- throw e;
1319
+ var stringCache = /* @__PURE__ */ new Map();
1320
+ function stringCacheKey(ptr, len) {
1321
+ return ptr * 65536 + len;
1322
+ }
1323
+ function readString(ptr, len) {
1324
+ const key = stringCacheKey(ptr, len);
1325
+ const cached = stringCache.get(key);
1326
+ if (cached !== void 0) return cached;
1327
+ const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
1328
+ stringCache.set(key, str);
1329
+ return str;
1330
+ }
1331
+ function writeBytes(ptr, data) {
1332
+ getMemoryView().set(data, ptr);
1333
+ }
1334
+ function wrapPromisingExport(fn) {
1335
+ if (!fn) return void 0;
1336
+ const promising = WebAssembly.promising;
1337
+ if (typeof promising !== "function") return fn;
1338
+ return promising(fn);
1339
+ }
1340
+ function invokeWasmExport(fn, ...args) {
1341
+ if (!fn) return;
1342
+ const result = fn(...args);
1343
+ if (result && typeof result.then === "function") {
1344
+ void result.then(void 0, (error) => {
1345
+ console.error(error);
1346
+ });
1347
+ }
1348
+ }
1349
+ var ZxBridgeCore = class _ZxBridgeCore {
1350
+ #intervals = /* @__PURE__ */ new Map();
1351
+ #handler;
1352
+ #fetchCompleteHandler;
1353
+ constructor(exports) {
1354
+ this._alloc = exports.__zx_alloc;
1355
+ this.#handler = wrapPromisingExport(exports.__zx_cb);
1356
+ const fetchCompleteHandler = wrapPromisingExport(exports.__zx_fetch_complete);
1357
+ if (!fetchCompleteHandler) {
1358
+ throw new Error("__zx_fetch_complete not exported from WASM");
2047
1359
  }
2048
- return Promise.resolve();
1360
+ this.#fetchCompleteHandler = fetchCompleteHandler;
1361
+ if (exports.memory) jsz.memory = exports.memory;
2049
1362
  }
2050
- const start = WebAssembly.promising(instance.exports._start);
2051
- return start().catch((e) => {
2052
- if (e instanceof Error && e.message.startsWith("proc_exit"))
1363
+ /** Invoke the unified callback handler */
1364
+ #invoke(type, id, data) {
1365
+ const handler = this.#handler;
1366
+ if (!handler) {
1367
+ console.warn("__zx_cb not exported from WASM");
2053
1368
  return;
2054
- throw e;
2055
- }).finally(() => {
2056
- if (wsState.recvResolve) {
2057
- const res = wsState.recvResolve;
2058
- wsState.recvResolve = null;
2059
- res(null);
2060
1369
  }
2061
- });
2062
- }
2063
- function parseZiexMeta(stderrText) {
2064
- const meta = { status: 200, headers: new Headers, streaming: false };
2065
- const metaPrefix = "__ZIEX_META__:";
2066
- const metaLine = stderrText.split(`
2067
- `).find((line) => line.startsWith(metaPrefix));
2068
- if (metaLine) {
1370
+ const dataRef = storeValueGetRef(data);
1371
+ invokeWasmExport(handler, type, id, dataRef);
1372
+ }
1373
+ /**
1374
+ * Async fetch with full options support.
1375
+ * Calls __zx_fetch_complete when done.
1376
+ */
1377
+ fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
1378
+ const url = readString(urlPtr, urlLen);
1379
+ const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
1380
+ const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
1381
+ const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
1382
+ let headers = {};
2069
1383
  try {
2070
- const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
2071
- if (parsed.status)
2072
- meta.status = parsed.status;
2073
- if (parsed.streaming === true)
2074
- meta.streaming = true;
2075
- if (Array.isArray(parsed.headers)) {
2076
- for (const [name, value] of parsed.headers) {
2077
- meta.headers.append(name, value);
1384
+ headers = JSON.parse(headersJson);
1385
+ } catch {
1386
+ for (const line of headersJson.split("\n")) {
1387
+ const colonIdx = line.indexOf(":");
1388
+ if (colonIdx > 0) {
1389
+ headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
2078
1390
  }
2079
1391
  }
2080
- } catch {}
1392
+ }
1393
+ const controller = new AbortController();
1394
+ const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
1395
+ const fetchOptions = {
1396
+ method,
1397
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
1398
+ body: method !== "GET" && method !== "HEAD" ? body : void 0,
1399
+ signal: controller.signal
1400
+ };
1401
+ fetch(url, fetchOptions).then(async (response) => {
1402
+ if (timeout) clearTimeout(timeout);
1403
+ const bytes = new Uint8Array(await response.arrayBuffer());
1404
+ this._notifyFetchComplete(fetchId, response.status, bytes, false);
1405
+ }).catch((error) => {
1406
+ if (timeout) clearTimeout(timeout);
1407
+ const isAbort = error.name === "AbortError";
1408
+ const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
1409
+ this._notifyFetchComplete(fetchId, 0, errorMsg, true);
1410
+ });
2081
1411
  }
2082
- return meta;
2083
- }
2084
- async function run({
2085
- request,
2086
- env,
2087
- ctx,
2088
- module,
2089
- kv: kvBindings,
2090
- db: dbBindings,
2091
- imports,
2092
- wasi,
2093
- websocket: doNamespace
2094
- }) {
2095
- if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
2096
- const id = doNamespace.idFromName(new URL(request.url).pathname);
2097
- return doNamespace.get(id).fetch(request);
1412
+ /** Notify WASM that a fetch completed. `body` is raw bytes on success, text on error. */
1413
+ _notifyFetchComplete(fetchId, statusCode, body, isError) {
1414
+ const handler = this.#fetchCompleteHandler;
1415
+ const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
1416
+ const ptr = this._alloc(encoded.length);
1417
+ writeBytes(ptr, encoded);
1418
+ invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
2098
1419
  }
2099
- const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
2100
- const stdoutChunks = [];
2101
- let streamWriter = null;
2102
- const { wasiImport, setMemory, collectOutput } = createWasiImports({
2103
- request,
2104
- stdinData,
2105
- onStdout: (chunk) => {
2106
- if (streamWriter)
2107
- streamWriter.write(chunk);
2108
- else
2109
- stdoutChunks.push(chunk);
1420
+ /** Set a timeout and callback when it fires */
1421
+ setTimeout(callbackId, delayMs) {
1422
+ setTimeout(() => {
1423
+ this.#invoke(CallbackType.Timeout, callbackId, null);
1424
+ }, delayMs);
1425
+ }
1426
+ /** Set an interval and callback each time it fires */
1427
+ setInterval(callbackId, intervalMs) {
1428
+ const handle = setInterval(() => {
1429
+ this.#invoke(CallbackType.Interval, callbackId, null);
1430
+ }, intervalMs);
1431
+ this.#intervals.set(callbackId, handle);
1432
+ }
1433
+ /** Clear an interval */
1434
+ clearInterval(callbackId) {
1435
+ const handle = this.#intervals.get(callbackId);
1436
+ if (handle !== void 0) {
1437
+ clearInterval(handle);
1438
+ this.#intervals.delete(callbackId);
2110
1439
  }
2111
- });
2112
- let wasmMemory = null;
2113
- const mem = () => wasmMemory;
2114
- const bridgeRef = { current: null };
2115
- const Suspending = WebAssembly.Suspending;
2116
- const jspi = typeof Suspending === "function";
2117
- const wsState = {
2118
- upgraded: false,
2119
- server: null,
2120
- pendingWrites: [],
2121
- messageQueue: [],
2122
- recvResolve: null
2123
- };
2124
- const instance = new WebAssembly.Instance(module, {
2125
- wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
2126
- __zx_sys: buildSysImports(jspi, Suspending),
2127
- __zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder, wsState),
2128
- __zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
2129
- __zx_db: createD1Imports(dbBindings ?? {}, mem),
2130
- __zx_net: createFetchImports(mem),
2131
- ...imports ? imports(mem) : {},
2132
- ...ZxWasiBridge.createImportObject(bridgeRef)
2133
- });
2134
- wasmMemory = instance.exports.memory;
2135
- setMemory(wasmMemory);
2136
- bridgeRef.current = new ZxWasiBridge(instance.exports);
2137
- const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
2138
- if (wsState.upgraded) {
2139
- const server = attachWebSocket(wsState);
2140
- ctx?.waitUntil(wasmPromise);
2141
- return new Response(null, { status: 101, webSocket: server.client });
2142
1440
  }
2143
- const { stderrText: earlyStderrText } = collectOutput();
2144
- const earlyMeta = parseZiexMeta(earlyStderrText);
2145
- if (earlyMeta.streaming) {
2146
- const { readable, writable } = new TransformStream;
2147
- streamWriter = writable.getWriter();
2148
- for (const chunk of stdoutChunks)
2149
- streamWriter.write(chunk);
2150
- stdoutChunks.length = 0;
2151
- wasmPromise.finally(() => streamWriter?.close());
2152
- return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
1441
+ dispose() {
1442
+ for (const handle of this.#intervals.values()) {
1443
+ clearInterval(handle);
1444
+ }
1445
+ this.#intervals.clear();
1446
+ }
1447
+ /** Write a string to WASM memory, returning pointer and length */
1448
+ _writeStringToWasm(str) {
1449
+ return this._writeBytesToWasm(textEncoder.encode(str));
1450
+ }
1451
+ _writeBytesToWasm(data) {
1452
+ const ptr = this._alloc(data.length);
1453
+ writeBytes(ptr, data);
1454
+ return { ptr, len: data.length };
1455
+ }
1456
+ /** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
1457
+ static log(level, ptr, len) {
1458
+ const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
1459
+ switch (level) {
1460
+ case 0:
1461
+ console.error(msg);
1462
+ break;
1463
+ case 1:
1464
+ console.warn(msg);
1465
+ break;
1466
+ case 3:
1467
+ console.debug(msg);
1468
+ break;
1469
+ default:
1470
+ console.log(msg);
1471
+ break;
1472
+ }
1473
+ }
1474
+ /**
1475
+ * Create the core import object for WASM instantiation.
1476
+ * Includes only environment-agnostic bindings: log, fetch, and timers.
1477
+ * Use ZxBridge.createImportObject (from wasm/index.ts) in browser contexts
1478
+ * to additionally include DOM and WebSocket bindings.
1479
+ */
1480
+ static createImportObject(bridgeRef) {
1481
+ return {
1482
+ ...jsz.importObject(),
1483
+ __zx_net: createFetchImports(() => {
1484
+ if (!jsz.memory) throw new Error("WASM memory is not ready");
1485
+ return jsz.memory;
1486
+ }),
1487
+ __zx: {
1488
+ _log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
1489
+ _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
1490
+ bridgeRef.current?.fetchAsync(
1491
+ urlPtr,
1492
+ urlLen,
1493
+ methodPtr,
1494
+ methodLen,
1495
+ headersPtr,
1496
+ headersLen,
1497
+ bodyPtr,
1498
+ bodyLen,
1499
+ timeoutMs,
1500
+ fetchId
1501
+ );
1502
+ },
1503
+ _setTimeout: (callbackId, delayMs) => {
1504
+ bridgeRef.current?.setTimeout(callbackId, delayMs);
1505
+ },
1506
+ _setInterval: (callbackId, intervalMs) => {
1507
+ bridgeRef.current?.setInterval(callbackId, intervalMs);
1508
+ },
1509
+ _clearInterval: (callbackId) => {
1510
+ bridgeRef.current?.clearInterval(callbackId);
1511
+ }
1512
+ }
1513
+ };
2153
1514
  }
2154
- await wasmPromise;
2155
- const { stderrText } = collectOutput();
2156
- const meta = parseZiexMeta(stderrText);
2157
- const body = mergeUint8Arrays(stdoutChunks);
2158
- meta.headers.delete("transfer-encoding");
2159
- const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
2160
- if (nullBody) {
2161
- meta.headers.delete("content-length");
2162
- return new Response(null, { status: meta.status, headers: meta.headers });
1515
+ };
1516
+
1517
+ // src/wasm/index.ts
1518
+ var ZxBridge = class extends ZxBridgeCore {
1519
+ #websockets = /* @__PURE__ */ new Map();
1520
+ #wsOnOpenHandler;
1521
+ #wsOnMessageHandler;
1522
+ #wsOnErrorHandler;
1523
+ #wsOnCloseHandler;
1524
+ #eventbridge;
1525
+ #eventbridgeAsync;
1526
+ constructor(exports) {
1527
+ super(exports);
1528
+ this.#wsOnOpenHandler = wrapPromisingExport(exports.__zx_ws_onopen);
1529
+ this.#wsOnMessageHandler = wrapPromisingExport(exports.__zx_ws_onmessage);
1530
+ this.#wsOnErrorHandler = wrapPromisingExport(exports.__zx_ws_onerror);
1531
+ this.#wsOnCloseHandler = wrapPromisingExport(exports.__zx_ws_onclose);
1532
+ this.#eventbridge = exports.__zx_eventbridge;
1533
+ this.#eventbridgeAsync = wrapPromisingExport(
1534
+ exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
1535
+ );
2163
1536
  }
2164
- if (!meta.headers.has("content-length"))
2165
- meta.headers.set("content-length", String(body.byteLength));
2166
- return new Response(body.buffer, { status: meta.status, headers: meta.headers });
2167
- }
2168
- // src/app.ts
2169
- async function resolveModule(input) {
2170
- if (typeof input === "string") {
2171
- if (input.startsWith("http://") || input.startsWith("https://")) {
2172
- return WebAssembly.compileStreaming(fetch(input));
2173
- }
2174
- const url = input.startsWith("/") ? `file://${input}` : input;
2175
- return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
1537
+ eventMaySuspend(velementId, eventTypeId) {
1538
+ return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
2176
1539
  }
2177
- if (input instanceof URL) {
2178
- return WebAssembly.compileStreaming(fetch(input));
1540
+ setEventHandlerMode(velementId, eventTypeId, maySuspend) {
1541
+ const bit = 1 << eventTypeId;
1542
+ const current = eventHandlerModes.get(velementId) ?? 0;
1543
+ const next = maySuspend ? current | bit : current & ~bit;
1544
+ if (next === 0) eventHandlerModes.delete(velementId);
1545
+ else eventHandlerModes.set(velementId, next);
2179
1546
  }
2180
- if (input instanceof Response) {
2181
- return WebAssembly.compileStreaming(input);
1547
+ clearEventHandlerModes(velementId) {
1548
+ eventHandlerModes.delete(velementId);
2182
1549
  }
2183
- if (input instanceof ArrayBuffer) {
2184
- return WebAssembly.compile(input);
1550
+ /** Submit a form action with bound-state round-trip. */
1551
+ submitFormActionAsync(form, actionId, statesJson, fetchId) {
1552
+ const formData = new FormData(form);
1553
+ formData.append("__$states", statesJson);
1554
+ fetch(window.location.href, {
1555
+ method: "POST",
1556
+ // `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
1557
+ headers: { "x-action": String(actionId >>> 0) },
1558
+ body: formData
1559
+ }).then(async (response) => {
1560
+ const text = await response.text();
1561
+ this._notifyFetchComplete(fetchId, response.status, text, false);
1562
+ }).catch((error) => {
1563
+ const msg = error instanceof Error ? error.message : "Fetch failed";
1564
+ this._notifyFetchComplete(fetchId, 0, msg, true);
1565
+ });
2185
1566
  }
2186
- if (ArrayBuffer.isView(input)) {
2187
- return WebAssembly.compile(input.buffer);
1567
+ /**
1568
+ * Create and connect a WebSocket.
1569
+ * Calls __zx_ws_onopen, __zx_ws_onmessage, __zx_ws_onerror, __zx_ws_onclose.
1570
+ */
1571
+ wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
1572
+ const url = readString(urlPtr, urlLen);
1573
+ const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
1574
+ const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : void 0;
1575
+ try {
1576
+ const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
1577
+ ws.binaryType = "arraybuffer";
1578
+ ws.onopen = () => {
1579
+ const handler = this.#wsOnOpenHandler;
1580
+ if (!handler) return;
1581
+ const protocol = ws.protocol || "";
1582
+ const { ptr, len } = this._writeStringToWasm(protocol);
1583
+ invokeWasmExport(handler, wsId, ptr, len);
1584
+ };
1585
+ ws.onmessage = (event) => {
1586
+ const handler = this.#wsOnMessageHandler;
1587
+ if (!handler) return;
1588
+ const isBinary = event.data instanceof ArrayBuffer;
1589
+ const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
1590
+ const { ptr, len } = this._writeBytesToWasm(data);
1591
+ invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
1592
+ };
1593
+ ws.onerror = (_event) => {
1594
+ const handler = this.#wsOnErrorHandler;
1595
+ if (!handler) return;
1596
+ const { ptr, len } = this._writeStringToWasm("WebSocket error");
1597
+ invokeWasmExport(handler, wsId, ptr, len);
1598
+ };
1599
+ ws.onclose = (event) => {
1600
+ const handler = this.#wsOnCloseHandler;
1601
+ if (!handler) return;
1602
+ const reason = event.reason || "";
1603
+ const { ptr, len } = this._writeStringToWasm(reason);
1604
+ invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
1605
+ this.#websockets.delete(wsId);
1606
+ };
1607
+ this.#websockets.set(wsId, ws);
1608
+ } catch (error) {
1609
+ const handler = this.#wsOnErrorHandler;
1610
+ if (handler) {
1611
+ const msg = error instanceof Error ? error.message : "WebSocket connection failed";
1612
+ const { ptr, len } = this._writeStringToWasm(msg);
1613
+ invokeWasmExport(handler, wsId, ptr, len);
1614
+ }
1615
+ }
2188
1616
  }
2189
- return input;
2190
- }
2191
-
2192
- class Ziex {
2193
- options;
2194
- resolved = null;
2195
- constructor(options) {
2196
- this.options = options;
1617
+ /** Send data over WebSocket */
1618
+ wsSend(wsId, dataPtr, dataLen, isBinary) {
1619
+ const ws = this.#websockets.get(wsId);
1620
+ if (!ws || ws.readyState !== WebSocket.OPEN) return;
1621
+ const memory = getMemoryView();
1622
+ if (isBinary) {
1623
+ ws.send(memory.slice(dataPtr, dataPtr + dataLen));
1624
+ } else {
1625
+ ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
1626
+ }
2197
1627
  }
2198
- async getModule() {
2199
- if (!this.resolved)
2200
- this.resolved = await resolveModule(this.options.module);
2201
- return this.resolved;
1628
+ /** Close WebSocket connection */
1629
+ wsClose(wsId, code, reasonPtr, reasonLen) {
1630
+ const ws = this.#websockets.get(wsId);
1631
+ if (!ws) return;
1632
+ const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : void 0;
1633
+ try {
1634
+ if (reason) ws.close(code, reason);
1635
+ else ws.close(code);
1636
+ } catch {
1637
+ ws.close();
1638
+ }
2202
1639
  }
2203
- resolveKV(env) {
2204
- const { kv } = this.options;
2205
- if (kv === undefined)
2206
- return;
2207
- if (typeof kv === "object" && kv !== null) {
2208
- const result = {};
2209
- for (const [name, key] of Object.entries(kv)) {
2210
- result[name] = env[key];
1640
+ dispose() {
1641
+ super.dispose();
1642
+ eventHandlerModes.clear();
1643
+ for (const ws of this.#websockets.values()) {
1644
+ try {
1645
+ ws.close();
1646
+ } catch {
2211
1647
  }
2212
- return result;
2213
1648
  }
2214
- return { default: env[kv] };
1649
+ this.#websockets.clear();
2215
1650
  }
2216
- resolveDB(env) {
2217
- const { db } = this.options;
2218
- if (db === undefined)
1651
+ /** Handle a DOM event (called by event delegation) */
1652
+ eventbridge(velementId, eventTypeId, event) {
1653
+ const eventRef = storeValueGetRef(event);
1654
+ if (this.eventMaySuspend(velementId, eventTypeId)) {
1655
+ invokeWasmExport(this.#eventbridgeAsync, velementId, eventTypeId, eventRef);
2219
1656
  return;
2220
- if (typeof db === "object" && db !== null) {
2221
- const result = {};
2222
- for (const [name, key] of Object.entries(db)) {
2223
- result[name] = env[key];
1657
+ }
1658
+ invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
1659
+ }
1660
+ /** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
1661
+ static createImportObject(bridgeRef) {
1662
+ return {
1663
+ ...jsz.importObject(),
1664
+ __zx_net: createFetchImports(() => {
1665
+ if (!jsz.memory) throw new Error("WASM memory is not ready");
1666
+ return jsz.memory;
1667
+ }),
1668
+ __zx: {
1669
+ _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
1670
+ _setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
1671
+ bridgeRef.current?.setEventHandlerMode(vnodeId, eventTypeId, maySuspend !== 0);
1672
+ },
1673
+ _clearEventHandlerModes: (vnodeId) => {
1674
+ bridgeRef.current?.clearEventHandlerModes(vnodeId);
1675
+ },
1676
+ _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
1677
+ bridgeRef.current?.fetchAsync(
1678
+ urlPtr,
1679
+ urlLen,
1680
+ methodPtr,
1681
+ methodLen,
1682
+ headersPtr,
1683
+ headersLen,
1684
+ bodyPtr,
1685
+ bodyLen,
1686
+ timeoutMs,
1687
+ fetchId
1688
+ );
1689
+ },
1690
+ _setTimeout: (callbackId, delayMs) => {
1691
+ bridgeRef.current?.setTimeout(callbackId, delayMs);
1692
+ },
1693
+ _setInterval: (callbackId, intervalMs) => {
1694
+ bridgeRef.current?.setInterval(callbackId, intervalMs);
1695
+ },
1696
+ _clearInterval: (callbackId) => {
1697
+ bridgeRef.current?.clearInterval(callbackId);
1698
+ },
1699
+ // WebSocket API
1700
+ _wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
1701
+ bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
1702
+ },
1703
+ _wsSend: (wsId, dataPtr, dataLen, isBinary) => {
1704
+ bridgeRef.current?.wsSend(wsId, dataPtr, dataLen, isBinary);
1705
+ },
1706
+ _wsClose: (wsId, code, reasonPtr, reasonLen) => {
1707
+ bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
1708
+ },
1709
+ _ce: (id, vnodeId) => {
1710
+ const tagName = TAG_NAMES[id];
1711
+ const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
1712
+ el.__zx_ref = Number(vnodeId);
1713
+ domNodes.set(vnodeId, el);
1714
+ return storeValueGetRef(el);
1715
+ },
1716
+ _ct: (ptr, len, vnodeId) => {
1717
+ const text = readString(ptr, len);
1718
+ const node = document.createTextNode(text);
1719
+ node.__zx_ref = Number(vnodeId);
1720
+ domNodes.set(vnodeId, node);
1721
+ return storeValueGetRef(node);
1722
+ },
1723
+ _sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
1724
+ domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
1725
+ },
1726
+ _sp: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
1727
+ const el = domNodes.get(vnodeId);
1728
+ if (el) {
1729
+ const name = readString(namePtr, nameLen);
1730
+ const val = readString(valPtr, valLen);
1731
+ if (name === "checked" || name === "selected" || name === "muted") {
1732
+ el[name] = val !== "false";
1733
+ } else {
1734
+ el[name] = val;
1735
+ }
1736
+ }
1737
+ },
1738
+ _ra: (vnodeId, namePtr, nameLen) => {
1739
+ domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
1740
+ },
1741
+ _snv: (vnodeId, ptr, len) => {
1742
+ const node = domNodes.get(vnodeId);
1743
+ if (node) node.nodeValue = readString(ptr, len);
1744
+ },
1745
+ _srh: (vnodeId, ptr, len) => {
1746
+ const el = domNodes.get(vnodeId);
1747
+ if (el) el.innerHTML = readString(ptr, len);
1748
+ },
1749
+ _ac: (parentId, childId) => {
1750
+ const parent = domNodes.get(parentId);
1751
+ const child = domNodes.get(childId);
1752
+ if (parent && child) parent.appendChild(child);
1753
+ },
1754
+ _ib: (parentId, childId, refId) => {
1755
+ const parent = domNodes.get(parentId);
1756
+ const child = domNodes.get(childId);
1757
+ const ref = domNodes.get(refId) ?? null;
1758
+ if (parent && child) parent.insertBefore(child, ref);
1759
+ },
1760
+ _rc: (parentId, childId) => {
1761
+ const parent = domNodes.get(parentId);
1762
+ const child = domNodes.get(childId);
1763
+ if (parent && child) {
1764
+ parent.removeChild(child);
1765
+ cleanupDomNodes(child);
1766
+ }
1767
+ },
1768
+ _rpc: (parentId, newId, oldId) => {
1769
+ const parent = domNodes.get(parentId);
1770
+ const newChild = domNodes.get(newId);
1771
+ const oldChild = domNodes.get(oldId);
1772
+ if (parent && newChild && oldChild) {
1773
+ parent.replaceChild(newChild, oldChild);
1774
+ cleanupDomNodes(oldChild);
1775
+ }
1776
+ },
1777
+ _getLocationHref: (bufPtr, bufLen) => {
1778
+ const bytes = textEncoder.encode(window.location.href);
1779
+ const len = Math.min(bytes.length, bufLen);
1780
+ writeBytes(bufPtr, bytes.subarray(0, len));
1781
+ return len;
1782
+ },
1783
+ _getFormData: (vnodeId, bufPtr, bufLen) => {
1784
+ const form = domNodes.get(vnodeId);
1785
+ if (!form || !(form instanceof HTMLFormElement)) return 0;
1786
+ const formData = new FormData(form);
1787
+ const urlEncoded = new URLSearchParams(formData).toString();
1788
+ const bytes = textEncoder.encode(urlEncoded);
1789
+ const len = Math.min(bytes.length, bufLen);
1790
+ writeBytes(bufPtr, bytes.subarray(0, len));
1791
+ return len;
1792
+ },
1793
+ _submitFormAction: (vnodeId, actionId) => {
1794
+ const form = domNodes.get(vnodeId);
1795
+ if (!form || !(form instanceof HTMLFormElement)) return;
1796
+ const formData = new FormData(form);
1797
+ fetch(window.location.href, {
1798
+ method: "POST",
1799
+ // `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
1800
+ headers: { "x-action": String(actionId >>> 0) },
1801
+ body: formData
1802
+ }).catch(() => {
1803
+ });
1804
+ },
1805
+ _submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
1806
+ const form = domNodes.get(vnodeId);
1807
+ if (!form || !(form instanceof HTMLFormElement)) return;
1808
+ const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
1809
+ bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
1810
+ }
2224
1811
  }
2225
- return result;
2226
- }
2227
- return { default: env[db] };
1812
+ };
2228
1813
  }
2229
- fetch = async (request, env, ctx) => {
2230
- const module = await this.getModule();
2231
- const { wasi, imports, websocket } = this.options;
2232
- return run({
2233
- request,
2234
- env,
2235
- ctx,
2236
- module,
2237
- wasi,
2238
- imports,
2239
- kv: this.resolveKV(env),
2240
- db: this.resolveDB(env),
2241
- websocket: websocket !== undefined ? env[websocket] : undefined
2242
- });
2243
- };
1814
+ };
1815
+ var domNodes = /* @__PURE__ */ new Map();
1816
+ function cleanupDomNodes(node) {
1817
+ const ref = node.__zx_ref;
1818
+ if (ref !== void 0) domNodes.delete(BigInt(ref));
1819
+ const children = node.childNodes;
1820
+ for (let i = 0; i < children.length; i++) cleanupDomNodes(children[i]);
2244
1821
  }
1822
+ var SVG_TAG_START_INDEX = 140;
1823
+ var TAG_NAMES = [
1824
+ "aside",
1825
+ "fragment",
1826
+ "iframe",
1827
+ "slot",
1828
+ "img",
1829
+ "html",
1830
+ "base",
1831
+ "head",
1832
+ "link",
1833
+ "meta",
1834
+ "script",
1835
+ "style",
1836
+ "title",
1837
+ "address",
1838
+ "article",
1839
+ "body",
1840
+ "h1",
1841
+ "h6",
1842
+ "footer",
1843
+ "header",
1844
+ "h2",
1845
+ "h3",
1846
+ "h4",
1847
+ "h5",
1848
+ "hgroup",
1849
+ "nav",
1850
+ "section",
1851
+ "dd",
1852
+ "dl",
1853
+ "dt",
1854
+ "div",
1855
+ "figcaption",
1856
+ "figure",
1857
+ "hr",
1858
+ "li",
1859
+ "ol",
1860
+ "ul",
1861
+ "menu",
1862
+ "main",
1863
+ "p",
1864
+ "picture",
1865
+ "pre",
1866
+ "a",
1867
+ "abbr",
1868
+ "b",
1869
+ "bdi",
1870
+ "bdo",
1871
+ "br",
1872
+ "cite",
1873
+ "code",
1874
+ "data",
1875
+ "time",
1876
+ "dfn",
1877
+ "em",
1878
+ "i",
1879
+ "kbd",
1880
+ "mark",
1881
+ "q",
1882
+ "blockquote",
1883
+ "rp",
1884
+ "ruby",
1885
+ "rt",
1886
+ "rtc",
1887
+ "rb",
1888
+ "s",
1889
+ "del",
1890
+ "ins",
1891
+ "samp",
1892
+ "small",
1893
+ "span",
1894
+ "strong",
1895
+ "sub",
1896
+ "sup",
1897
+ "u",
1898
+ "var",
1899
+ "wbr",
1900
+ "area",
1901
+ "map",
1902
+ "audio",
1903
+ "source",
1904
+ "track",
1905
+ "video",
1906
+ "embed",
1907
+ "object",
1908
+ "param",
1909
+ "canvas",
1910
+ "noscript",
1911
+ "caption",
1912
+ "table",
1913
+ "col",
1914
+ "colgroup",
1915
+ "tbody",
1916
+ "tr",
1917
+ "thead",
1918
+ "tfoot",
1919
+ "td",
1920
+ "th",
1921
+ "button",
1922
+ "datalist",
1923
+ "option",
1924
+ "fieldset",
1925
+ "label",
1926
+ "form",
1927
+ "input",
1928
+ "keygen",
1929
+ "legend",
1930
+ "meter",
1931
+ "optgroup",
1932
+ "select",
1933
+ "output",
1934
+ "progress",
1935
+ "textarea",
1936
+ "details",
1937
+ "dialog",
1938
+ "menuitem",
1939
+ "summary",
1940
+ "content",
1941
+ "element",
1942
+ "shadow",
1943
+ "template",
1944
+ "acronym",
1945
+ "applet",
1946
+ "basefont",
1947
+ "font",
1948
+ "big",
1949
+ "blink",
1950
+ "center",
1951
+ "command",
1952
+ "dir",
1953
+ "frame",
1954
+ "frameset",
1955
+ "isindex",
1956
+ "listing",
1957
+ "marquee",
1958
+ "noembed",
1959
+ "plaintext",
1960
+ "spacer",
1961
+ "strike",
1962
+ "tt",
1963
+ "xmp",
1964
+ // SVG Tags
1965
+ "animate",
1966
+ "animateMotion",
1967
+ "animateTransform",
1968
+ "circle",
1969
+ "clipPath",
1970
+ "defs",
1971
+ "desc",
1972
+ "ellipse",
1973
+ "feBlend",
1974
+ "feColorMatrix",
1975
+ "feComponentTransfer",
1976
+ "feComposite",
1977
+ "feConvolveMatrix",
1978
+ "feDiffuseLighting",
1979
+ "feDisplacementMap",
1980
+ "feDistantLight",
1981
+ "feDropShadow",
1982
+ "feFlood",
1983
+ "feFuncA",
1984
+ "feFuncB",
1985
+ "feFuncG",
1986
+ "feFuncR",
1987
+ "feGaussianBlur",
1988
+ "feImage",
1989
+ "feMerge",
1990
+ "feMergeNode",
1991
+ "feMorphology",
1992
+ "feOffset",
1993
+ "fePointLight",
1994
+ "feSpecularLighting",
1995
+ "feSpotLight",
1996
+ "feTile",
1997
+ "feTurbulence",
1998
+ "filter",
1999
+ "foreignObject",
2000
+ "g",
2001
+ "image",
2002
+ "line",
2003
+ "linearGradient",
2004
+ "marker",
2005
+ "mask",
2006
+ "metadata",
2007
+ "mpath",
2008
+ "path",
2009
+ "pattern",
2010
+ "polygon",
2011
+ "polyline",
2012
+ "radialGradient",
2013
+ "rect",
2014
+ "set",
2015
+ "stop",
2016
+ "svg",
2017
+ "switch",
2018
+ "symbol",
2019
+ "text",
2020
+ "textPath",
2021
+ "tspan",
2022
+ "use",
2023
+ "view"
2024
+ ];
2025
+ var eventHandlerModes = /* @__PURE__ */ new Map();
2026
+
2245
2027
  // src/cloudflare/do.ts
2246
2028
  function createWebSocketDO(module, options) {
2247
2029
  return class ZxWebSocketDO {
2248
- doState;
2249
- env;
2250
- connections = new Map;
2251
2030
  constructor(state, env) {
2031
+ /** All active connections in this room, keyed by their server-side WebSocket. */
2032
+ this.connections = /* @__PURE__ */ new Map();
2252
2033
  this.doState = state;
2253
2034
  this.env = env;
2254
2035
  }
2255
2036
  async fetch(request) {
2256
- const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
2037
+ const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
2257
2038
  const { wasiImport, setMemory } = createWasiImports({ request, stdinData });
2258
2039
  let wasmMemory = null;
2259
2040
  const mem = () => wasmMemory;
@@ -2261,7 +2042,7 @@ function createWebSocketDO(module, options) {
2261
2042
  const bridgeImports = ZxBridge.createImportObject(bridgeRef);
2262
2043
  const Suspending = WebAssembly.Suspending;
2263
2044
  const jspi = typeof Suspending === "function";
2264
- const decoder3 = new TextDecoder;
2045
+ const decoder3 = new TextDecoder();
2265
2046
  let _resolveFirstSuspend;
2266
2047
  const firstSuspendPromise = new Promise((resolve) => {
2267
2048
  _resolveFirstSuspend = resolve;
@@ -2274,7 +2055,7 @@ function createWebSocketDO(module, options) {
2274
2055
  messageQueue: [],
2275
2056
  recvResolve: null,
2276
2057
  _resolveFirstSuspend,
2277
- topics: new Set,
2058
+ topics: /* @__PURE__ */ new Set(),
2278
2059
  subscribe: (topic) => connState.topics.add(topic),
2279
2060
  unsubscribe: (topic) => connState.topics.delete(topic),
2280
2061
  publish: (topic, data) => {
@@ -2284,7 +2065,8 @@ function createWebSocketDO(module, options) {
2284
2065
  try {
2285
2066
  ws.send(data);
2286
2067
  count++;
2287
- } catch {}
2068
+ } catch {
2069
+ }
2288
2070
  }
2289
2071
  }
2290
2072
  if (!connState.server && connState.topics.has(topic)) {
@@ -2296,7 +2078,8 @@ function createWebSocketDO(module, options) {
2296
2078
  isSubscribed: (topic) => connState.topics.has(topic)
2297
2079
  };
2298
2080
  const sysImports = {
2299
- sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
2081
+ sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
2082
+ }
2300
2083
  };
2301
2084
  const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder3, connState);
2302
2085
  const kvBindings = options?.kv?.(this.env);
@@ -2317,12 +2100,10 @@ function createWebSocketDO(module, options) {
2317
2100
  const start = WebAssembly.promising(instance.exports._start);
2318
2101
  const wasmPromise = start().catch((e) => {
2319
2102
  wasmExited = true;
2320
- if (e instanceof Error && e.message.startsWith("proc_exit"))
2321
- return;
2103
+ if (e instanceof Error && e.message.startsWith("proc_exit")) return;
2322
2104
  console.error("[ZxWebSocketDO] WASM error:", e);
2323
2105
  }).finally(() => {
2324
- if (connState.server)
2325
- this.connections.delete(connState.server);
2106
+ if (connState.server) this.connections.delete(connState.server);
2326
2107
  if (connState.recvResolve) {
2327
2108
  const res = connState.recvResolve;
2328
2109
  connState.recvResolve = null;
@@ -2341,8 +2122,8 @@ function createWebSocketDO(module, options) {
2341
2122
  };
2342
2123
  }
2343
2124
  export {
2344
- exports_runtime as worker,
2345
- exports_kv as kv,
2125
+ Ziex,
2346
2126
  createWebSocketDO,
2347
- Ziex
2127
+ kv_exports as kv,
2128
+ runtime_exports as worker
2348
2129
  };