ziex 0.1.0-dev.1387 → 0.1.0-dev.1458

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 (43) hide show
  1. package/README.md +4 -1
  2. package/app.d.ts +6 -6
  3. package/build.zig.zon +1 -1
  4. package/index.js +477 -169
  5. package/package.json +7 -5
  6. package/{aws-lambda → platforms/aws-lambda}/index.js +1 -1
  7. package/platforms/cloudflare/app.d.ts +2 -0
  8. package/platforms/cloudflare/db.d.ts +6 -0
  9. package/{cloudflare → platforms/cloudflare}/do.d.ts +5 -5
  10. package/platforms/cloudflare/index.d.ts +4 -0
  11. package/{cloudflare → platforms/cloudflare}/index.js +1666 -1293
  12. package/platforms/cloudflare/kv.d.ts +5 -0
  13. package/platforms/cloudflare/worker.d.ts +3 -0
  14. package/{vercel → platforms/vercel}/index.js +1 -1
  15. package/runtime/db/extern.d.ts +38 -0
  16. package/runtime/db/sqlite.d.ts +7 -0
  17. package/runtime/db.d.ts +3 -0
  18. package/runtime/db.js +419 -0
  19. package/{fetch.d.ts → runtime/fetch.d.ts} +1 -1
  20. package/{runtime.d.ts → runtime/index.d.ts} +6 -15
  21. package/runtime/kv/extern.d.ts +11 -0
  22. package/runtime/kv/indexdb.d.ts +7 -0
  23. package/runtime/kv/localstorage.d.ts +6 -0
  24. package/runtime/kv/memory.d.ts +6 -0
  25. package/runtime/kv.d.ts +44 -0
  26. package/runtime/kv.js +542 -0
  27. package/wasm/core.d.ts +29 -27
  28. package/wasm/index.d.ts +13 -12
  29. package/wasm/index.js +431 -240
  30. package/wasm/init.dev.js +407 -238
  31. package/wasm/init.js +3 -3
  32. package/wasm/wasi.d.ts +1 -5
  33. package/browser/kv.d.ts +0 -13
  34. package/cloudflare/app.d.ts +0 -2
  35. package/cloudflare/db.d.ts +0 -2
  36. package/cloudflare/index.d.ts +0 -4
  37. package/cloudflare/kv.d.ts +0 -2
  38. package/cloudflare/worker.d.ts +0 -3
  39. package/db.d.ts +0 -22
  40. package/kv.d.ts +0 -42
  41. /package/{aws-lambda → platforms/aws-lambda}/index.d.ts +0 -0
  42. /package/{vercel → platforms/vercel}/index.d.ts +0 -0
  43. /package/{wasi.d.ts → runtime/wasi.d.ts} +0 -0
@@ -4,7 +4,7 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/runtime.ts
7
+ // src/runtime/index.ts
8
8
  var runtime_exports = {};
9
9
  __export(runtime_exports, {
10
10
  attachWebSocket: () => attachWebSocket,
@@ -39,10 +39,18 @@ var ZxWasiBridge = class {
39
39
  return this.#memView;
40
40
  }
41
41
  #readString(ptr, len) {
42
- return decoder.decode(this.#view().subarray(ptr, ptr + len));
42
+ const start = ptr >>> 0;
43
+ const length = len >>> 0;
44
+ if (length === 0) return "";
45
+ const view = this.#view();
46
+ if (start + length > view.byteLength) return "";
47
+ return decoder.decode(view.subarray(start, start + length));
43
48
  }
44
49
  #writeBytes(ptr, data) {
45
- this.#view().set(data, ptr);
50
+ const start = ptr >>> 0;
51
+ const view = this.#view();
52
+ if (start + data.length > view.byteLength) return;
53
+ view.set(data, start);
46
54
  }
47
55
  log(level, ptr, len) {
48
56
  const msg = decoder.decode(this.#view().subarray(ptr, ptr + len));
@@ -122,10 +130,10 @@ var ZxWasiBridge = class {
122
130
  return {
123
131
  __zx: {
124
132
  _log: (level, ptr, len) => {
125
- bridgeRef.current?.log(level, ptr, len);
133
+ bridgeRef[0]?.log(level, ptr, len);
126
134
  },
127
135
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
128
- bridgeRef.current?.fetchAsync(
136
+ bridgeRef[0]?.fetchAsync(
129
137
  urlPtr,
130
138
  urlLen,
131
139
  methodPtr,
@@ -139,153 +147,20 @@ var ZxWasiBridge = class {
139
147
  );
140
148
  },
141
149
  _setTimeout: (callbackId, delayMs) => {
142
- bridgeRef.current?.setTimeout(callbackId, delayMs);
150
+ bridgeRef[0]?.setTimeout(callbackId, delayMs);
143
151
  },
144
152
  _setInterval: (callbackId, intervalMs) => {
145
- bridgeRef.current?.setInterval(callbackId, intervalMs);
153
+ bridgeRef[0]?.setInterval(callbackId, intervalMs);
146
154
  },
147
155
  _clearInterval: (callbackId) => {
148
- bridgeRef.current?.clearInterval(callbackId);
156
+ bridgeRef[0]?.clearInterval(callbackId);
149
157
  }
150
158
  }
151
159
  };
152
160
  }
153
161
  };
154
162
 
155
- // src/kv.ts
156
- var kv_exports = {};
157
- __export(kv_exports, {
158
- createKVImports: () => createKVImports,
159
- createMemoryKV: () => createMemoryKV
160
- });
161
- function putOptions(ttlSeconds) {
162
- if (ttlSeconds < 60) return void 0;
163
- return { expirationTtl: ttlSeconds };
164
- }
165
- function createMemoryKV() {
166
- const store = /* @__PURE__ */ new Map();
167
- function read(key) {
168
- const entry = store.get(key);
169
- if (!entry) return null;
170
- if (entry.expiresAt !== void 0 && Date.now() >= entry.expiresAt) {
171
- store.delete(key);
172
- return null;
173
- }
174
- return entry.value;
175
- }
176
- function write(key, value, options) {
177
- let expiresAt;
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;
182
- }
183
- store.set(key, { value, expiresAt });
184
- }
185
- return {
186
- async get(key) {
187
- return read(key);
188
- },
189
- async put(key, value, options) {
190
- write(key, value, options);
191
- },
192
- async delete(key) {
193
- store.delete(key);
194
- },
195
- async list(options) {
196
- const keys = [...store.keys()].filter((k) => {
197
- if (options?.prefix && !k.startsWith(options.prefix)) return false;
198
- return read(k) !== null;
199
- }).map((name) => ({ name }));
200
- return { keys };
201
- }
202
- };
203
- }
204
- function isSyncKVNamespace(binding) {
205
- const candidate = binding;
206
- return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
207
- }
208
- function createKVImports(bindings, getMemory) {
209
- const encoder3 = new TextEncoder();
210
- const decoder3 = new TextDecoder();
211
- function readStr(ptr, len) {
212
- return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
213
- }
214
- function writeBytes2(buf_ptr, buf_max, data) {
215
- if (data.length > buf_max) return -2;
216
- new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
217
- return data.length;
218
- }
219
- function binding(ns) {
220
- return bindings[ns] ?? bindings["default"] ?? null;
221
- }
222
- const Suspending = WebAssembly.Suspending;
223
- if (typeof Suspending !== "function") {
224
- let syncBinding2 = function(ns) {
225
- const candidate = binding(ns);
226
- return candidate && isSyncKVNamespace(candidate) ? candidate : null;
227
- };
228
- var syncBinding = syncBinding2;
229
- return {
230
- kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
231
- const b = syncBinding2(readStr(ns_ptr, ns_len));
232
- if (!b) return -1;
233
- const value = b.getSync(readStr(key_ptr, key_len));
234
- if (value === null) return -1;
235
- return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
236
- },
237
- kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
238
- const b = syncBinding2(readStr(ns_ptr, ns_len));
239
- if (!b) return 0;
240
- b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
241
- return 0;
242
- },
243
- kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
244
- const b = syncBinding2(readStr(ns_ptr, ns_len));
245
- if (!b) return 0;
246
- b.deleteSync(readStr(key_ptr, key_len));
247
- return 0;
248
- },
249
- kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
250
- const b = syncBinding2(readStr(ns_ptr, ns_len));
251
- if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
252
- const prefix = readStr(pfx_ptr, pfx_len);
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))));
255
- }
256
- };
257
- }
258
- return {
259
- kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
260
- const b = binding(readStr(ns_ptr, ns_len));
261
- if (!b) return -1;
262
- const value = await b.get(readStr(key_ptr, key_len));
263
- if (value === null) return -1;
264
- return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
265
- }),
266
- kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
267
- const b = binding(readStr(ns_ptr, ns_len));
268
- if (!b) return -1;
269
- await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
270
- return 0;
271
- }),
272
- kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
273
- const b = binding(readStr(ns_ptr, ns_len));
274
- if (!b) return -1;
275
- await b.delete(readStr(key_ptr, key_len));
276
- return 0;
277
- }),
278
- kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
279
- const b = binding(readStr(ns_ptr, ns_len));
280
- if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
281
- const prefix = readStr(prefix_ptr, prefix_len);
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))));
284
- })
285
- };
286
- }
287
-
288
- // src/fetch.ts
163
+ // src/runtime/fetch.ts
289
164
  function createFetchImports(getMemory) {
290
165
  const encoder3 = new TextEncoder();
291
166
  const decoder3 = new TextDecoder();
@@ -351,1166 +226,1514 @@ function createFetchImports(getMemory) {
351
226
  };
352
227
  }
353
228
 
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;
229
+ // ../../vendor/jsz/js/src/zigjs.ts
230
+ var NAN_PREFIX = 2146959360;
231
+ var predefined = {
232
+ "nan": 0,
233
+ "null": 1,
234
+ "true": 2,
235
+ "false": 3,
236
+ "undefined": 4,
237
+ "globalThis": 5,
238
+ "runtime": 6
239
+ };
240
+ var PREDEFINED_ID_MAX = 6;
241
+ var encoder2 = new TextEncoder();
242
+ var decoder2 = new TextDecoder("utf-8");
243
+ var ZigJS = class {
244
+ constructor() {
245
+ /**
246
+ * The values, indexed by ID (number). Duplicate values can be in this
247
+ * if they are loaded multiple times. That just acts as duplicate references.
248
+ * */
249
+ this.values = [NaN, null, true, false, void 0, globalThis, this];
250
+ /**
251
+ * When a value is removed from the values array, its ID is put
252
+ * in the pool so that we can use it next. This avoids fragmentation in
253
+ * our array keys.
254
+ * */
255
+ this.idPool = [];
375
256
  }
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");
257
+ /**
258
+ * Returns the import object that should be merged with your import
259
+ * object when instantiating your wasm instance. This injects the required
260
+ * functions into the wasm environment.
261
+ * */
262
+ importObject() {
263
+ return {
264
+ "zig-js": {
265
+ valueGet: this.valueGet.bind(this),
266
+ valueSet: this.valueSet.bind(this),
267
+ valueDeinit: this.valueDeinit.bind(this),
268
+ valueObjectCreate: this.valueObjectCreate.bind(this),
269
+ valueStringCreate: this.valueStringCreate.bind(this),
270
+ valueStringLen: this.valueStringLen.bind(this),
271
+ valueStringCopy: this.valueStringCopy.bind(this),
272
+ valueNew: this.valueNew.bind(this),
273
+ funcApply: this.funcApply.bind(this)
274
+ }
275
+ };
385
276
  }
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 };
277
+ /**
278
+ * Get a value from the JS environment.
279
+ * */
280
+ valueGet(out, id, ptr, len) {
281
+ const val = this.loadValue(id);
282
+ if (val === null || val === void 0 || typeof val !== "object" && typeof val !== "function") {
283
+ this.storeValue(out, void 0);
284
+ return;
285
+ }
286
+ const str = this.loadString(ptr, len);
287
+ const result = Reflect.get(val, str);
288
+ this.storeValue(out, result);
393
289
  }
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) };
290
+ /**
291
+ * Set a value on an object.
292
+ * */
293
+ valueSet(id, ptr, len, refAddr) {
294
+ const obj = this.loadValue(id);
295
+ const str = this.loadString(ptr, len);
296
+ const val = this.loadRef(refAddr);
297
+ Reflect.set(obj, str, val);
399
298
  }
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) };
299
+ /**
300
+ * Dereference a value, allowing the JS environment to potentially GC it.
301
+ * */
302
+ valueDeinit(id) {
303
+ if (id > PREDEFINED_ID_MAX) {
304
+ this.values[id] = null;
305
+ this.idPool.push(id);
306
+ }
405
307
  }
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));
308
+ /**
309
+ * Create an empty object.
310
+ * */
311
+ valueObjectCreate(out) {
312
+ this.storeValue(out, new Object());
424
313
  }
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;
314
+ /**
315
+ * Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
316
+ * */
317
+ valueStringCreate(out, ptr, len) {
318
+ const str = this.loadString(ptr, len);
319
+ this.storeValue(out, str);
430
320
  }
431
- function binding(ns) {
432
- return bindings[ns] ?? bindings["default"] ?? null;
321
+ /**
322
+ * Returns the length of the string given by id.
323
+ * */
324
+ valueStringLen(id) {
325
+ const val = this.loadValue(id);
326
+ const buf = encoder2.encode(val);
327
+ return buf.byteLength;
433
328
  }
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));
329
+ /**
330
+ * Copy the string at id "id" into the shared memory at ptr.
331
+ * */
332
+ valueStringCopy(id, ptr, max) {
333
+ if (this.memory == null) return;
334
+ const dest = ptr >>> 0;
335
+ const cap = max >>> 0;
336
+ const val = this.loadValue(id);
337
+ if (typeof val !== "string") return;
338
+ const bytes = encoder2.encode(val);
339
+ if (bytes.byteLength > cap || bytes.length === 0) return;
340
+ const buf = this.memory.buffer;
341
+ if (dest + bytes.length > buf.byteLength) return;
342
+ new Uint8Array(buf, dest, bytes.length).set(bytes);
440
343
  }
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
- };
344
+ /**
345
+ * Call a constructor given by id.
346
+ * */
347
+ valueNew(out, id, argsAddr, argsLen) {
348
+ const fn = this.loadValue(id);
349
+ const args = [];
350
+ const base = argsAddr >>> 0;
351
+ const count = argsLen >>> 0;
352
+ for (let i = 0; i < count; i++) {
353
+ args.push(this.loadRef(base + i * 8));
354
+ }
355
+ const result = Reflect.construct(fn, args);
356
+ this.storeValue(out, result);
450
357
  }
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;
358
+ /**
359
+ * Call a function given by id.
360
+ * */
361
+ funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
362
+ const fn = this.loadValue(id);
363
+ const thisVal = this.loadRef(thisRefAddr >>> 0);
364
+ const args = [];
365
+ const base = argsAddr >>> 0;
366
+ const count = argsLen >>> 0;
367
+ for (let i = 0; i < count; i++) {
368
+ args.push(this.loadRef(base + i * 8));
369
+ }
370
+ if (typeof fn !== "function") {
371
+ this.storeValue(out, void 0);
372
+ return;
373
+ }
374
+ try {
375
+ const result = Reflect.apply(fn, thisVal, args);
376
+ this.storeValue(out, result);
377
+ } catch {
378
+ this.storeValue(out, void 0);
379
+ }
489
380
  }
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);
381
+ /**
382
+ * This can be used to load a value given by an ID. A WASM function
383
+ * might return a value as an ID. This can be used to retrieve it.
384
+ * */
385
+ loadValue(id) {
386
+ return this.values[id];
387
+ }
388
+ /**
389
+ * This removes the value from the values list and returns it. This
390
+ * will not remove predefined values but can still be used to retrieve
391
+ * them.
392
+ * */
393
+ deleteValue(id) {
394
+ const val = this.values[id];
395
+ this.valueDeinit(id);
396
+ return val;
397
+ }
398
+ loadRef(refAddr) {
399
+ if (this.memory == null) return;
400
+ const addr = refAddr >>> 0;
401
+ const view = new DataView(this.memory.buffer);
402
+ const floatVal = view.getFloat64(addr, true);
403
+ if (!isNaN(floatVal)) return floatVal;
404
+ const id = this.loadRefId(addr);
405
+ return this.values[id];
406
+ }
407
+ loadRefId(refAddr) {
408
+ if (this.memory == null) return 0;
409
+ return new DataView(this.memory.buffer).getUint32(refAddr >>> 0, true);
410
+ }
411
+ storeValue(out, val) {
412
+ if (this.memory == null) return;
413
+ const view = new DataView(this.memory.buffer);
414
+ out = out >>> 0;
415
+ if (typeof val === "number") {
416
+ if (isNaN(val)) {
417
+ view.setUint32(out, predefined.nan, true);
418
+ view.setUint32(out + 4, NAN_PREFIX, true);
419
+ } else {
420
+ view.setFloat64(out, val, true);
531
421
  }
422
+ return;
423
+ }
424
+ if (val === null) {
425
+ view.setUint32(out, predefined.null, true);
426
+ view.setUint32(out + 4, NAN_PREFIX, true);
427
+ return;
428
+ }
429
+ if (val === void 0) {
430
+ view.setUint32(out, predefined.undefined, true);
431
+ view.setUint32(out + 4, NAN_PREFIX, true);
432
+ return;
433
+ }
434
+ if (typeof val === "boolean") {
435
+ view.setUint32(out, val ? predefined.true : predefined.false, true);
436
+ view.setUint32(out + 4, NAN_PREFIX, true);
437
+ return;
438
+ }
439
+ if (typeof val === "bigint") {
440
+ view.setFloat64(out, Number(val), true);
441
+ return;
442
+ }
443
+ let id = this.idPool.pop();
444
+ if (id === void 0) {
445
+ id = this.values.length;
446
+ }
447
+ this.values[id] = val;
448
+ let typeId = 0;
449
+ switch (typeof val) {
450
+ case "object":
451
+ typeId = 1;
452
+ break;
453
+ case "string":
454
+ typeId = 2;
455
+ break;
456
+ case "symbol":
457
+ typeId = 3;
458
+ break;
459
+ case "function":
460
+ typeId = 4;
461
+ break;
532
462
  }
463
+ view.setUint32(out, Number(id), true);
464
+ view.setUint32(out + 4, NAN_PREFIX | typeId, true);
533
465
  }
534
- let stdinOffset = 0;
535
- function v() {
536
- return new DataView(wasmMemory.buffer);
466
+ loadString(ptr, len) {
467
+ if (this.memory == null) return "";
468
+ const start = ptr >>> 0;
469
+ const length = Number(len) >>> 0;
470
+ const buf = this.memory.buffer;
471
+ if (length === 0 || start + length > buf.byteLength) return "";
472
+ const arr = new Uint8ClampedArray(buf, start, length);
473
+ const data = arr.slice();
474
+ return decoder2.decode(data);
537
475
  }
538
- function m() {
539
- return new Uint8Array(wasmMemory.buffer);
476
+ };
477
+
478
+ // src/wasm/core.ts
479
+ var jsz = new ZigJS();
480
+ var tempRefBuffer = new ArrayBuffer(8);
481
+ var tempRefView = new DataView(tempRefBuffer);
482
+ function storeValueGetRef(val) {
483
+ const originalMemory = jsz.memory;
484
+ jsz.memory = { buffer: tempRefBuffer };
485
+ jsz.storeValue(0, val);
486
+ jsz.memory = originalMemory;
487
+ return tempRefView.getBigUint64(0, true);
488
+ }
489
+ function loadValueFromRef(ref) {
490
+ tempRefView.setBigUint64(0, ref, true);
491
+ const originalMemory = jsz.memory;
492
+ jsz.memory = { buffer: tempRefBuffer };
493
+ const val = jsz.loadRef(0);
494
+ jsz.memory = originalMemory;
495
+ return val;
496
+ }
497
+ function releaseValueRef(ref) {
498
+ tempRefView.setBigUint64(0, ref, true);
499
+ if (!Number.isNaN(tempRefView.getFloat64(0, true))) return;
500
+ const id = tempRefView.getUint32(0, true);
501
+ if (id > 6) jsz.deleteValue(id);
502
+ }
503
+ var textDecoder = new TextDecoder();
504
+ var textEncoder = new TextEncoder();
505
+ var memoryView = null;
506
+ var memoryBuffer = null;
507
+ function getMemoryView() {
508
+ const buf = jsz.memory.buffer;
509
+ if (buf !== memoryBuffer) {
510
+ memoryBuffer = buf;
511
+ memoryView = new Uint8Array(buf);
540
512
  }
541
- const wasiImport = {
542
- args_sizes_get(argc_ptr, argv_buf_size_ptr) {
543
- v().setUint32(argc_ptr, encodedArgs.length, true);
544
- v().setUint32(argv_buf_size_ptr, argBufSize, true);
545
- return 0;
546
- },
547
- args_get(argv_ptr, argv_buf_ptr) {
548
- const dv = v();
549
- const mem = m();
550
- let offset = argv_buf_ptr;
551
- for (const arg of encodedArgs) {
552
- dv.setUint32(argv_ptr, offset, true);
553
- mem.set(arg, offset);
554
- argv_ptr += 4;
555
- offset += arg.length;
556
- }
557
- return 0;
558
- },
559
- environ_sizes_get(count_ptr, buf_size_ptr) {
560
- v().setUint32(count_ptr, 0, true);
561
- v().setUint32(buf_size_ptr, 0, true);
562
- return 0;
563
- },
564
- environ_get(_environ_ptr, _environ_buf_ptr) {
565
- return 0;
566
- },
567
- fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) {
568
- const dv = v();
569
- const mem = m();
570
- let written = 0;
571
- for (let i = 0; i < iovs_len; i++) {
572
- const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
573
- const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
574
- const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
575
- if (fd === 1) {
576
- if (onStdout) onStdout(chunk);
577
- else stdoutChunks.push(chunk);
578
- } else if (fd === 2) processStderrChunk(chunk);
579
- written += buf_len;
580
- }
581
- dv.setUint32(nwritten_ptr, written, true);
582
- return 0;
583
- },
584
- fd_read(fd, iovs_ptr, iovs_len, nread_ptr) {
585
- const dv = v();
586
- const mem = m();
587
- const stdin = stdinData ?? new Uint8Array(0);
588
- let totalRead = 0;
589
- for (let i = 0; i < iovs_len; i++) {
590
- const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
591
- const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
592
- if (fd === 0 && stdinOffset < stdin.length) {
593
- const toRead = Math.min(buf_len, stdin.length - stdinOffset);
594
- mem.set(stdin.subarray(stdinOffset, stdinOffset + toRead), buf_ptr);
595
- stdinOffset += toRead;
596
- totalRead += toRead;
513
+ return memoryView;
514
+ }
515
+ function readString(ptr, len) {
516
+ const start = ptr >>> 0;
517
+ const length = len >>> 0;
518
+ if (length === 0) return "";
519
+ const view = getMemoryView();
520
+ if (start + length > view.byteLength) return "";
521
+ return textDecoder.decode(view.subarray(start, start + length));
522
+ }
523
+ function writeBytes(ptr, data) {
524
+ const start = ptr >>> 0;
525
+ const view = getMemoryView();
526
+ if (start + data.length > view.byteLength) return;
527
+ view.set(data, start);
528
+ }
529
+ function wrapPromisingExport(fn) {
530
+ if (!fn) return void 0;
531
+ const promising = WebAssembly.promising;
532
+ if (typeof promising !== "function") return fn;
533
+ return promising(fn);
534
+ }
535
+ function invokeWasmExport(fn, ...args) {
536
+ if (!fn) return;
537
+ const result = fn(...args);
538
+ if (result && typeof result.then === "function") {
539
+ void result.then(void 0, (error) => {
540
+ console.error(error);
541
+ });
542
+ }
543
+ }
544
+ var ZxBridgeCore = class _ZxBridgeCore {
545
+ #intervals = /* @__PURE__ */ new Map();
546
+ #handler;
547
+ #fetchCompleteHandler;
548
+ constructor(exports) {
549
+ this._alloc = exports.__zx_alloc;
550
+ this.#handler = wrapPromisingExport(exports.__zx_cb);
551
+ const fetchCompleteHandler = wrapPromisingExport(exports.__zx_fetch_complete);
552
+ if (!fetchCompleteHandler) {
553
+ throw new Error("__zx_fetch_complete not exported from WASM");
554
+ }
555
+ this.#fetchCompleteHandler = fetchCompleteHandler;
556
+ if (exports.memory) jsz.memory = exports.memory;
557
+ }
558
+ /** Invoke the unified callback handler */
559
+ #invoke(type, id, data) {
560
+ const handler = this.#handler;
561
+ if (!handler) {
562
+ console.warn("__zx_cb not exported from WASM");
563
+ return;
564
+ }
565
+ const dataRef = storeValueGetRef(data);
566
+ invokeWasmExport(handler, type, id, dataRef);
567
+ }
568
+ /**
569
+ * Async fetch with full options support.
570
+ * Calls __zx_fetch_complete when done.
571
+ */
572
+ fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
573
+ const url = readString(urlPtr, urlLen);
574
+ const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
575
+ const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
576
+ const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
577
+ let headers = {};
578
+ try {
579
+ headers = JSON.parse(headersJson);
580
+ } catch {
581
+ for (const line of headersJson.split("\n")) {
582
+ const colonIdx = line.indexOf(":");
583
+ if (colonIdx > 0) {
584
+ headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
597
585
  }
598
586
  }
599
- dv.setUint32(nread_ptr, totalRead, true);
600
- return 0;
601
- },
602
- fd_fdstat_get(_fd, fdstat_ptr) {
603
- const dv = v();
604
- dv.setUint8(fdstat_ptr, 2);
605
- dv.setUint8(fdstat_ptr + 1, 0);
606
- dv.setUint16(fdstat_ptr + 2, 0, true);
607
- dv.setUint32(fdstat_ptr + 4, 0, true);
608
- dv.setBigUint64(fdstat_ptr + 8, 0n, true);
609
- dv.setBigUint64(fdstat_ptr + 16, 0n, true);
610
- return 0;
611
- },
612
- fd_prestat_get(_fd, _bufptr) {
613
- return 8;
614
- },
615
- fd_prestat_dir_name(_fd, _path, _path_len) {
616
- return 8;
617
- },
618
- fd_close(_fd) {
619
- return 0;
620
- },
621
- fd_pread(_fd, _iovs, _iovs_len, _offset, nread_ptr) {
622
- v().setUint32(nread_ptr, 0, true);
623
- return 0;
624
- },
625
- fd_pwrite(_fd, _iovs, _iovs_len, _offset, nwritten_ptr) {
626
- v().setUint32(nwritten_ptr, 0, true);
627
- return 0;
628
- },
629
- fd_filestat_get(_fd, filestat_ptr) {
630
- const dv = v();
631
- dv.setBigUint64(filestat_ptr, 0n, true);
632
- dv.setBigUint64(filestat_ptr + 8, 0n, true);
633
- dv.setUint8(filestat_ptr + 16, 2);
634
- dv.setBigUint64(filestat_ptr + 24, 1n, true);
635
- dv.setBigUint64(filestat_ptr + 32, 0n, true);
636
- dv.setBigUint64(filestat_ptr + 40, 0n, true);
637
- dv.setBigUint64(filestat_ptr + 48, 0n, true);
638
- dv.setBigUint64(filestat_ptr + 56, 0n, true);
639
- return 0;
640
- },
641
- fd_filestat_set_size(_fd, _size) {
642
- return 76;
643
- },
644
- fd_filestat_set_times(_fd, _atim, _mtim, _fst_flags) {
645
- return 76;
646
- },
647
- fd_fdstat_set_flags(_fd, _flags) {
648
- return 0;
649
- },
650
- fd_fdstat_set_rights(_fd, _rights_base, _rights_inheriting) {
651
- return 0;
652
- },
653
- fd_sync(_fd) {
654
- return 0;
655
- },
656
- fd_datasync(_fd) {
657
- return 0;
658
- },
659
- fd_advise(_fd, _offset, _len, _advice) {
660
- return 0;
661
- },
662
- fd_allocate(_fd, _offset, _len) {
663
- return 76;
664
- },
665
- fd_tell(_fd, offset_ptr) {
666
- v().setBigUint64(offset_ptr, 0n, true);
667
- return 0;
668
- },
669
- fd_renumber(_from, _to) {
670
- return 0;
671
- },
672
- path_filestat_set_times(_fd, _flags, _path, _path_len, _atim, _mtim, _fst_flags) {
673
- return 76;
674
- },
675
- path_link(_old_fd, _old_flags, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
676
- return 76;
677
- },
678
- path_symlink(_old_path, _old_path_len, _fd, _new_path, _new_path_len) {
679
- return 76;
680
- },
681
- proc_raise(_sig) {
682
- return 0;
683
- },
684
- sock_recv(_fd, _ri_data, _ri_data_len, _ri_flags, ro_datalen_ptr, ro_flags_ptr) {
685
- v().setUint32(ro_datalen_ptr, 0, true);
686
- v().setUint32(ro_flags_ptr, 0, true);
687
- return 76;
688
- },
689
- sock_send(_fd, _si_data, _si_data_len, _si_flags, so_datalen_ptr) {
690
- v().setUint32(so_datalen_ptr, 0, true);
691
- return 76;
692
- },
693
- sock_shutdown(_fd, _how) {
694
- return 76;
695
- },
696
- fd_seek(_fd, _offset, _whence, newoffset_ptr) {
697
- v().setBigInt64(newoffset_ptr, 0n, true);
698
- return 0;
699
- },
700
- proc_exit(code) {
701
- throw new ProcExit(code);
702
- },
703
- sched_yield() {
704
- return 0;
705
- },
706
- clock_time_get(_id, _precision, time_ptr) {
707
- v().setBigUint64(time_ptr, BigInt(Date.now()) * 1000000n, true);
708
- return 0;
709
- },
710
- clock_res_get(_id, res_ptr) {
711
- v().setBigUint64(res_ptr, 1000000n, true);
712
- return 0;
713
- },
714
- random_get(buf_ptr, buf_len) {
715
- crypto.getRandomValues(new Uint8Array(wasmMemory.buffer, buf_ptr, buf_len));
716
- return 0;
717
- },
718
- path_open(_fd, _dirflags, _path, _path_len, _oflags, _rights_base, _rights_inheriting, _fdflags, opened_fd_ptr) {
719
- v().setInt32(opened_fd_ptr, -1, true);
720
- return 76;
721
- },
722
- path_create_directory(_fd, _path, _path_len) {
723
- return 76;
724
- },
725
- path_unlink_file(_fd, _path, _path_len) {
726
- return 76;
727
- },
728
- path_remove_directory(_fd, _path, _path_len) {
729
- return 76;
730
- },
731
- path_rename(_fd, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
732
- return 76;
733
- },
734
- path_filestat_get(_fd, _flags, _path, _path_len, filestat_ptr) {
735
- new Uint8Array(wasmMemory.buffer, filestat_ptr, 64).fill(0);
736
- return 76;
737
- },
738
- path_readlink(_fd, _path, _path_len, _buf, _buf_len, nread_ptr) {
739
- v().setUint32(nread_ptr, 0, true);
740
- return 76;
741
- },
742
- fd_readdir(_fd, _buf, _buf_len, _cookie, bufused_ptr) {
743
- v().setUint32(bufused_ptr, 0, true);
744
- return 76;
745
- },
746
- // Stub for poll_oneoff - no blocking I/O in edge runtimes.
747
- poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
748
- v().setUint32(nevents_ptr, 0, true);
749
- return 0;
750
587
  }
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 = "";
588
+ const controller = new AbortController();
589
+ const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
590
+ const fetchOptions = {
591
+ method,
592
+ headers: Object.keys(headers).length > 0 ? headers : void 0,
593
+ body: method !== "GET" && method !== "HEAD" ? body : void 0,
594
+ signal: controller.signal
595
+ };
596
+ fetch(url, fetchOptions).then(async (response) => {
597
+ if (timeout) clearTimeout(timeout);
598
+ const bytes = new Uint8Array(await response.arrayBuffer());
599
+ this._notifyFetchComplete(fetchId, response.status, bytes, false);
600
+ }).catch((error) => {
601
+ if (timeout) clearTimeout(timeout);
602
+ const isAbort = error.name === "AbortError";
603
+ const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
604
+ this._notifyFetchComplete(fetchId, 0, errorMsg, true);
605
+ });
606
+ }
607
+ /** Notify WASM that a fetch completed. `body` is raw bytes on success, text on error. */
608
+ _notifyFetchComplete(fetchId, statusCode, body, isError) {
609
+ const handler = this.#fetchCompleteHandler;
610
+ const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
611
+ const ptr = this._alloc(encoded.length) >>> 0;
612
+ if (!ptr && encoded.length > 0) return;
613
+ writeBytes(ptr, encoded);
614
+ invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
615
+ }
616
+ /** Set a timeout and callback when it fires */
617
+ setTimeout(callbackId, delayMs) {
618
+ setTimeout(() => {
619
+ this.#invoke(3, callbackId, null);
620
+ }, delayMs);
621
+ }
622
+ /** Set an interval and callback each time it fires */
623
+ setInterval(callbackId, intervalMs) {
624
+ const handle = setInterval(() => {
625
+ this.#invoke(4, callbackId, null);
626
+ }, intervalMs);
627
+ this.#intervals.set(callbackId, handle);
628
+ }
629
+ /** Clear an interval */
630
+ clearInterval(callbackId) {
631
+ const handle = this.#intervals.get(callbackId);
632
+ if (handle !== void 0) {
633
+ clearInterval(handle);
634
+ this.#intervals.delete(callbackId);
635
+ }
636
+ }
637
+ dispose() {
638
+ for (const handle of this.#intervals.values()) {
639
+ clearInterval(handle);
640
+ }
641
+ this.#intervals.clear();
642
+ }
643
+ /** Write a string to WASM memory, returning `[ptr, len]`. */
644
+ _writeStringToWasm(str) {
645
+ return this.writeBytesToWasm(textEncoder.encode(str));
646
+ }
647
+ writeBytesToWasm(data) {
648
+ if (data.length === 0) return [0, 0];
649
+ const ptr = this._alloc(data.length) >>> 0;
650
+ if (!ptr) return [0, 0];
651
+ writeBytes(ptr, data);
652
+ return [ptr, data.length];
653
+ }
654
+ /** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
655
+ static log(level, ptr, len) {
656
+ const start = ptr >>> 0;
657
+ const length = len >>> 0;
658
+ const view = getMemoryView();
659
+ if (start + length > view.byteLength) return;
660
+ const msg = textDecoder.decode(view.subarray(start, start + length));
661
+ switch (level) {
662
+ case 0:
663
+ console.error(msg);
664
+ break;
665
+ case 1:
666
+ console.warn(msg);
667
+ break;
668
+ case 3:
669
+ console.debug(msg);
670
+ break;
671
+ default:
672
+ console.log(msg);
673
+ break;
759
674
  }
675
+ }
676
+ /**
677
+ * Create the core import object for WASM instantiation.
678
+ * Includes only environment-agnostic bindings: log, fetch, and timers.
679
+ * Use ZxBridge.createImportObject (from wasm/index.ts) in browser contexts
680
+ * to additionally include DOM and WebSocket bindings.
681
+ */
682
+ static createImportObject(bridgeRef) {
760
683
  return {
761
- stdout: mergeUint8Arrays(stdoutChunks),
762
- stderrText: stderrMeta
684
+ ...jsz.importObject(),
685
+ __zx_net: createFetchImports(() => {
686
+ if (!jsz.memory) throw new Error("WASM memory is not ready");
687
+ return jsz.memory;
688
+ }),
689
+ __zx: {
690
+ _log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
691
+ _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
692
+ bridgeRef[0]?.fetchAsync(
693
+ urlPtr,
694
+ urlLen,
695
+ methodPtr,
696
+ methodLen,
697
+ headersPtr,
698
+ headersLen,
699
+ bodyPtr,
700
+ bodyLen,
701
+ timeoutMs,
702
+ fetchId
703
+ );
704
+ },
705
+ _setTimeout: (callbackId, delayMs) => {
706
+ bridgeRef[0]?.setTimeout(callbackId, delayMs);
707
+ },
708
+ _setInterval: (callbackId, intervalMs) => {
709
+ bridgeRef[0]?.setInterval(callbackId, intervalMs);
710
+ },
711
+ _clearInterval: (callbackId) => {
712
+ bridgeRef[0]?.clearInterval(callbackId);
713
+ }
714
+ }
763
715
  };
764
716
  }
765
- return { wasiImport, setMemory, collectOutput };
717
+ };
718
+ function writeBytesOut(getMemory, allocRef, outPtrAddr, data) {
719
+ if (data.length === 0) {
720
+ new DataView(getMemory().buffer).setUint32(outPtrAddr, 0, true);
721
+ return 0;
722
+ }
723
+ const alloc = allocRef[0];
724
+ if (!alloc) return -1;
725
+ const ptr = alloc(data.length) >>> 0;
726
+ if (!ptr) return -1;
727
+ const buffer = getMemory().buffer;
728
+ if (ptr + data.length > buffer.byteLength) return -1;
729
+ new Uint8Array(buffer, ptr, data.length).set(data);
730
+ new DataView(buffer).setUint32(outPtrAddr >>> 0, ptr, true);
731
+ return data.length;
766
732
  }
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;
733
+ function writeJsonOut(getMemory, allocRef, outPtrAddr, value) {
734
+ return writeBytesOut(getMemory, allocRef, outPtrAddr, textEncoder.encode(JSON.stringify(value)));
776
735
  }
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
- };
736
+ function bindWasmAlloc(allocRef, exports) {
737
+ allocRef[0] = exports.__zx_alloc;
827
738
  }
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 };
739
+
740
+ // src/runtime/kv/extern.ts
741
+ function putOptions(ttlSeconds) {
742
+ if (ttlSeconds < 60) return void 0;
743
+ return { expirationTtl: ttlSeconds };
855
744
  }
856
- function buildSysImports(jspi, Suspending) {
857
- return {
858
- sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
859
- }
860
- };
745
+ function isSyncKVNamespace(binding) {
746
+ const candidate = binding;
747
+ return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
861
748
  }
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();
749
+ function createKVImports(bindings, getMemory, allocRef) {
750
+ const encoder3 = new TextEncoder();
751
+ const decoder3 = new TextDecoder();
752
+ function readStr(ptr, len) {
753
+ return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
870
754
  }
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
- }
755
+ function binding(ns) {
756
+ return bindings[ns] ?? bindings["default"] ?? null;
757
+ }
758
+ const Suspending = WebAssembly.Suspending;
759
+ if (typeof Suspending !== "function") {
760
+ let syncBinding2 = function(ns) {
761
+ const candidate = binding(ns);
762
+ return candidate && isSyncKVNamespace(candidate) ? candidate : null;
763
+ };
764
+ var syncBinding = syncBinding2;
765
+ return {
766
+ kv_get: (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
767
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
768
+ if (!b) return -1;
769
+ const value = b.getSync(readStr(key_ptr, key_len));
770
+ if (value === null) return -1;
771
+ return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
772
+ },
773
+ kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
774
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
775
+ if (!b) return 0;
776
+ b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
777
+ return 0;
778
+ },
779
+ kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
780
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
781
+ if (!b) return 0;
782
+ b.deleteSync(readStr(key_ptr, key_len));
783
+ return 0;
784
+ },
785
+ kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
786
+ const b = syncBinding2(readStr(ns_ptr, ns_len));
787
+ if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
788
+ const prefix = readStr(pfx_ptr, pfx_len);
789
+ const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
790
+ return writeJsonOut(getMemory, allocRef, out_ptr, result.keys.map((k) => k.name));
791
+ }
792
+ };
793
+ }
794
+ return {
795
+ kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
796
+ const b = binding(readStr(ns_ptr, ns_len));
797
+ if (!b) return -1;
798
+ const value = await b.get(readStr(key_ptr, key_len));
799
+ if (value === null) return -1;
800
+ return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
801
+ }),
802
+ kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
803
+ const b = binding(readStr(ns_ptr, ns_len));
804
+ if (!b) return -1;
805
+ await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
806
+ return 0;
807
+ }),
808
+ kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
809
+ const b = binding(readStr(ns_ptr, ns_len));
810
+ if (!b) return -1;
811
+ await b.delete(readStr(key_ptr, key_len));
812
+ return 0;
813
+ }),
814
+ kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, out_ptr) => {
815
+ const b = binding(readStr(ns_ptr, ns_len));
816
+ if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
817
+ const prefix = readStr(prefix_ptr, prefix_len);
818
+ const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
819
+ const names = result.keys.map((k) => k.name);
820
+ if (names.length === 0) {
821
+ new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
822
+ return 0;
896
823
  }
897
- } catch {
898
- }
824
+ return writeJsonOut(getMemory, allocRef, out_ptr, names);
825
+ })
826
+ };
827
+ }
828
+
829
+ // src/runtime/db/extern.ts
830
+ function decodeBlob(base64) {
831
+ const binary = atob(base64);
832
+ const bytes = new Uint8Array(binary.length);
833
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
834
+ return bytes;
835
+ }
836
+ function toDbValue(value) {
837
+ switch (value.kind) {
838
+ case "null":
839
+ return null;
840
+ case "integer":
841
+ return value.integer;
842
+ case "float":
843
+ return value.float;
844
+ case "text":
845
+ return value.text;
846
+ case "blob":
847
+ return decodeBlob(value.blob);
848
+ case "boolean":
849
+ return value.boolean;
899
850
  }
900
- return meta;
901
851
  }
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);
852
+ function toPositionalBindings(json) {
853
+ switch (json.kind) {
854
+ case "none":
855
+ return [];
856
+ case "positional":
857
+ return json.values.map(toDbValue);
858
+ case "named":
859
+ throw new Error("named SQL bindings are not supported yet");
916
860
  }
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 });
861
+ }
862
+ function toWireValue(value) {
863
+ if (value === null || value === void 0) return { kind: "null" };
864
+ if (typeof value === "string") return { kind: "text", text: value };
865
+ if (typeof value === "boolean") return { kind: "boolean", boolean: value };
866
+ if (typeof value === "number") {
867
+ return Number.isInteger(value) ? { kind: "integer", integer: value } : { kind: "float", float: value };
958
868
  }
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 });
869
+ if (value instanceof ArrayBuffer) {
870
+ const bytes = new Uint8Array(value);
871
+ let binary = "";
872
+ for (const byte of bytes) binary += String.fromCharCode(byte);
873
+ return { kind: "blob", blob: btoa(binary) };
968
874
  }
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 });
875
+ if (ArrayBuffer.isView(value)) {
876
+ const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
877
+ let binary = "";
878
+ for (const byte of bytes) binary += String.fromCharCode(byte);
879
+ return { kind: "blob", blob: btoa(binary) };
978
880
  }
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 });
881
+ return { kind: "text", text: String(value) };
981
882
  }
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()));
883
+ function objectToWireRow(record) {
884
+ return {
885
+ fields: Object.entries(record).map(([name, value]) => ({
886
+ name,
887
+ value: toWireValue(value)
888
+ }))
889
+ };
890
+ }
891
+ function valuesToWireRows(rows) {
892
+ return rows.map((row) => row.map((value) => toWireValue(value)));
893
+ }
894
+ function createDbImports(bindings, getMemory, allocRef) {
895
+ const decoder3 = new TextDecoder();
896
+ function readStr(ptr, len) {
897
+ return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
991
898
  }
992
- if (input instanceof URL) {
993
- return WebAssembly.compileStreaming(fetch(input));
899
+ function binding(ns) {
900
+ return bindings[ns] ?? bindings["default"] ?? null;
994
901
  }
995
- if (input instanceof Response) {
996
- return WebAssembly.compileStreaming(input);
902
+ async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
903
+ const database = binding(readStr(ns_ptr, ns_len));
904
+ if (!database) return null;
905
+ const sql = readStr(sql_ptr, sql_len);
906
+ const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
907
+ return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
997
908
  }
998
- if (input instanceof ArrayBuffer) {
999
- return WebAssembly.compile(input);
909
+ const Suspending = WebAssembly.Suspending;
910
+ if (typeof Suspending !== "function") {
911
+ return {
912
+ db_open: (_ns, _ns_len) => -1,
913
+ db_run: (_a, _b, _c, _d, _e, _f, _g) => -1,
914
+ db_get: (_a, _b, _c, _d, _e, _f, _g) => -1,
915
+ db_all: (_a, _b, _c, _d, _e, _f, _g) => -1,
916
+ db_values: (_a, _b, _c, _d, _e, _f, _g) => -1
917
+ };
1000
918
  }
1001
- if (ArrayBuffer.isView(input)) {
1002
- return WebAssembly.compile(input.buffer);
919
+ return {
920
+ db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
921
+ db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
922
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
923
+ if (!stmt) return -1;
924
+ const result = await stmt.run();
925
+ return writeJsonOut(getMemory, allocRef, out_ptr, {
926
+ last_insert_rowid: result.meta?.last_row_id ?? 0,
927
+ changes: result.meta?.changes ?? 0
928
+ });
929
+ }),
930
+ db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
931
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
932
+ if (!stmt) return -1;
933
+ const row = await stmt.first();
934
+ if (!row) {
935
+ new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
936
+ return 0;
937
+ }
938
+ return writeJsonOut(getMemory, allocRef, out_ptr, [objectToWireRow(row)]);
939
+ }),
940
+ db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
941
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
942
+ if (!stmt) return -1;
943
+ const result = await stmt.all();
944
+ const rows = (result.results ?? []).map(objectToWireRow);
945
+ if (rows.length === 0) {
946
+ new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
947
+ return 0;
948
+ }
949
+ return writeJsonOut(getMemory, allocRef, out_ptr, rows);
950
+ }),
951
+ db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
952
+ const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
953
+ if (!stmt) return -1;
954
+ const rows = await stmt.raw();
955
+ if (rows.length === 0) {
956
+ new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
957
+ return 0;
958
+ }
959
+ return writeJsonOut(getMemory, allocRef, out_ptr, valuesToWireRows(rows));
960
+ })
961
+ };
962
+ }
963
+
964
+ // src/runtime/wasi.ts
965
+ var ProcExit = class extends Error {
966
+ constructor(code) {
967
+ super(`proc_exit(${code})`);
968
+ this.code = code;
969
+ }
970
+ };
971
+ function createWasiImports({
972
+ request,
973
+ stdinData,
974
+ onStdout
975
+ }) {
976
+ const encoder3 = new TextEncoder();
977
+ const url = new URL(request.url);
978
+ const argStrings = [
979
+ "wasm",
980
+ "--pathname",
981
+ url.pathname,
982
+ "--method",
983
+ request.method,
984
+ "--search",
985
+ url.search,
986
+ "--url",
987
+ url.href
988
+ ];
989
+ request.headers.forEach((value, name) => {
990
+ if (value) argStrings.push("--header", `${name}:${value}`);
991
+ });
992
+ const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\0"));
993
+ const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
994
+ let wasmMemory = null;
995
+ const setMemory = (m2) => {
996
+ wasmMemory = m2;
997
+ };
998
+ const stdoutChunks = [];
999
+ let stderrMeta = "";
1000
+ let stderrPartial = "";
1001
+ const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
1002
+ function processStderrChunk(chunk) {
1003
+ const text = stderrDecoder.decode(chunk, { stream: true });
1004
+ const lines = (stderrPartial + text).split("\n");
1005
+ stderrPartial = lines.pop() ?? "";
1006
+ for (const line of lines) {
1007
+ if (line.startsWith("__ZIEX_META__:")) {
1008
+ stderrMeta += line + "\n";
1009
+ } else if (line.length > 0) {
1010
+ console.error("[ziex]", line);
1011
+ }
1012
+ }
1003
1013
  }
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;
1014
+ let stdinOffset = 0;
1015
+ function v() {
1016
+ return new DataView(wasmMemory.buffer);
1031
1017
  }
1032
- async getModule() {
1033
- if (!this.resolved) this.resolved = await resolveModule(this.options.module);
1034
- return this.resolved;
1018
+ function m() {
1019
+ return new Uint8Array(wasmMemory.buffer);
1035
1020
  }
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];
1021
+ const wasiImport = {
1022
+ args_sizes_get(argc_ptr, argv_buf_size_ptr) {
1023
+ v().setUint32(argc_ptr, encodedArgs.length, true);
1024
+ v().setUint32(argv_buf_size_ptr, argBufSize, true);
1025
+ return 0;
1026
+ },
1027
+ args_get(argv_ptr, argv_buf_ptr) {
1028
+ const dv = v();
1029
+ const mem = m();
1030
+ let offset = argv_buf_ptr;
1031
+ for (const arg of encodedArgs) {
1032
+ dv.setUint32(argv_ptr, offset, true);
1033
+ mem.set(arg, offset);
1034
+ argv_ptr += 4;
1035
+ offset += arg.length;
1043
1036
  }
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];
1037
+ return 0;
1038
+ },
1039
+ environ_sizes_get(count_ptr, buf_size_ptr) {
1040
+ v().setUint32(count_ptr, 0, true);
1041
+ v().setUint32(buf_size_ptr, 0, true);
1042
+ return 0;
1043
+ },
1044
+ environ_get(_environ_ptr, _environ_buf_ptr) {
1045
+ return 0;
1046
+ },
1047
+ fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) {
1048
+ const dv = v();
1049
+ const mem = m();
1050
+ let written = 0;
1051
+ for (let i = 0; i < iovs_len; i++) {
1052
+ const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
1053
+ const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
1054
+ const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
1055
+ if (fd === 1) {
1056
+ if (onStdout) onStdout(chunk);
1057
+ else stdoutChunks.push(chunk);
1058
+ } else if (fd === 2) processStderrChunk(chunk);
1059
+ written += buf_len;
1055
1060
  }
1056
- return result;
1061
+ dv.setUint32(nwritten_ptr, written, true);
1062
+ return 0;
1063
+ },
1064
+ fd_read(fd, iovs_ptr, iovs_len, nread_ptr) {
1065
+ const dv = v();
1066
+ const mem = m();
1067
+ const stdin = stdinData ?? new Uint8Array(0);
1068
+ let totalRead = 0;
1069
+ for (let i = 0; i < iovs_len; i++) {
1070
+ const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
1071
+ const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
1072
+ if (fd === 0 && stdinOffset < stdin.length) {
1073
+ const toRead = Math.min(buf_len, stdin.length - stdinOffset);
1074
+ mem.set(stdin.subarray(stdinOffset, stdinOffset + toRead), buf_ptr);
1075
+ stdinOffset += toRead;
1076
+ totalRead += toRead;
1077
+ }
1078
+ }
1079
+ dv.setUint32(nread_ptr, totalRead, true);
1080
+ return 0;
1081
+ },
1082
+ fd_fdstat_get(_fd, fdstat_ptr) {
1083
+ const dv = v();
1084
+ dv.setUint8(fdstat_ptr, 2);
1085
+ dv.setUint8(fdstat_ptr + 1, 0);
1086
+ dv.setUint16(fdstat_ptr + 2, 0, true);
1087
+ dv.setUint32(fdstat_ptr + 4, 0, true);
1088
+ dv.setBigUint64(fdstat_ptr + 8, 0n, true);
1089
+ dv.setBigUint64(fdstat_ptr + 16, 0n, true);
1090
+ return 0;
1091
+ },
1092
+ fd_prestat_get(_fd, _bufptr) {
1093
+ return 8;
1094
+ },
1095
+ fd_prestat_dir_name(_fd, _path, _path_len) {
1096
+ return 8;
1097
+ },
1098
+ fd_close(_fd) {
1099
+ return 0;
1100
+ },
1101
+ fd_pread(_fd, _iovs, _iovs_len, _offset, nread_ptr) {
1102
+ v().setUint32(nread_ptr, 0, true);
1103
+ return 0;
1104
+ },
1105
+ fd_pwrite(_fd, _iovs, _iovs_len, _offset, nwritten_ptr) {
1106
+ v().setUint32(nwritten_ptr, 0, true);
1107
+ return 0;
1108
+ },
1109
+ fd_filestat_get(_fd, filestat_ptr) {
1110
+ const dv = v();
1111
+ dv.setBigUint64(filestat_ptr, 0n, true);
1112
+ dv.setBigUint64(filestat_ptr + 8, 0n, true);
1113
+ dv.setUint8(filestat_ptr + 16, 2);
1114
+ dv.setBigUint64(filestat_ptr + 24, 1n, true);
1115
+ dv.setBigUint64(filestat_ptr + 32, 0n, true);
1116
+ dv.setBigUint64(filestat_ptr + 40, 0n, true);
1117
+ dv.setBigUint64(filestat_ptr + 48, 0n, true);
1118
+ dv.setBigUint64(filestat_ptr + 56, 0n, true);
1119
+ return 0;
1120
+ },
1121
+ fd_filestat_set_size(_fd, _size) {
1122
+ return 76;
1123
+ },
1124
+ fd_filestat_set_times(_fd, _atim, _mtim, _fst_flags) {
1125
+ return 76;
1126
+ },
1127
+ fd_fdstat_set_flags(_fd, _flags) {
1128
+ return 0;
1129
+ },
1130
+ fd_fdstat_set_rights(_fd, _rights_base, _rights_inheriting) {
1131
+ return 0;
1132
+ },
1133
+ fd_sync(_fd) {
1134
+ return 0;
1135
+ },
1136
+ fd_datasync(_fd) {
1137
+ return 0;
1138
+ },
1139
+ fd_advise(_fd, _offset, _len, _advice) {
1140
+ return 0;
1141
+ },
1142
+ fd_allocate(_fd, _offset, _len) {
1143
+ return 76;
1144
+ },
1145
+ fd_tell(_fd, offset_ptr) {
1146
+ v().setBigUint64(offset_ptr, 0n, true);
1147
+ return 0;
1148
+ },
1149
+ fd_renumber(_from, _to) {
1150
+ return 0;
1151
+ },
1152
+ path_filestat_set_times(_fd, _flags, _path, _path_len, _atim, _mtim, _fst_flags) {
1153
+ return 76;
1154
+ },
1155
+ path_link(_old_fd, _old_flags, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
1156
+ return 76;
1157
+ },
1158
+ path_symlink(_old_path, _old_path_len, _fd, _new_path, _new_path_len) {
1159
+ return 76;
1160
+ },
1161
+ proc_raise(_sig) {
1162
+ return 0;
1163
+ },
1164
+ sock_recv(_fd, _ri_data, _ri_data_len, _ri_flags, ro_datalen_ptr, ro_flags_ptr) {
1165
+ v().setUint32(ro_datalen_ptr, 0, true);
1166
+ v().setUint32(ro_flags_ptr, 0, true);
1167
+ return 76;
1168
+ },
1169
+ sock_send(_fd, _si_data, _si_data_len, _si_flags, so_datalen_ptr) {
1170
+ v().setUint32(so_datalen_ptr, 0, true);
1171
+ return 76;
1172
+ },
1173
+ sock_shutdown(_fd, _how) {
1174
+ return 76;
1175
+ },
1176
+ fd_seek(_fd, _offset, _whence, newoffset_ptr) {
1177
+ v().setBigInt64(newoffset_ptr, 0n, true);
1178
+ return 0;
1179
+ },
1180
+ proc_exit(code) {
1181
+ throw new ProcExit(code);
1182
+ },
1183
+ sched_yield() {
1184
+ return 0;
1185
+ },
1186
+ clock_time_get(_id, _precision, time_ptr) {
1187
+ v().setBigUint64(time_ptr, BigInt(Date.now()) * 1000000n, true);
1188
+ return 0;
1189
+ },
1190
+ clock_res_get(_id, res_ptr) {
1191
+ v().setBigUint64(res_ptr, 1000000n, true);
1192
+ return 0;
1193
+ },
1194
+ random_get(buf_ptr, buf_len) {
1195
+ crypto.getRandomValues(new Uint8Array(wasmMemory.buffer, buf_ptr, buf_len));
1196
+ return 0;
1197
+ },
1198
+ path_open(_fd, _dirflags, _path, _path_len, _oflags, _rights_base, _rights_inheriting, _fdflags, opened_fd_ptr) {
1199
+ v().setInt32(opened_fd_ptr, -1, true);
1200
+ return 76;
1201
+ },
1202
+ path_create_directory(_fd, _path, _path_len) {
1203
+ return 76;
1204
+ },
1205
+ path_unlink_file(_fd, _path, _path_len) {
1206
+ return 76;
1207
+ },
1208
+ path_remove_directory(_fd, _path, _path_len) {
1209
+ return 76;
1210
+ },
1211
+ path_rename(_fd, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
1212
+ return 76;
1213
+ },
1214
+ path_filestat_get(_fd, _flags, _path, _path_len, filestat_ptr) {
1215
+ new Uint8Array(wasmMemory.buffer, filestat_ptr, 64).fill(0);
1216
+ return 76;
1217
+ },
1218
+ path_readlink(_fd, _path, _path_len, _buf, _buf_len, nread_ptr) {
1219
+ v().setUint32(nread_ptr, 0, true);
1220
+ return 76;
1221
+ },
1222
+ fd_readdir(_fd, _buf, _buf_len, _cookie, bufused_ptr) {
1223
+ v().setUint32(bufused_ptr, 0, true);
1224
+ return 76;
1225
+ },
1226
+ // Stub for poll_oneoff - no blocking I/O in edge runtimes.
1227
+ poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
1228
+ v().setUint32(nevents_ptr, 0, true);
1229
+ return 0;
1230
+ }
1231
+ };
1232
+ function collectOutput() {
1233
+ const remaining = stderrDecoder.decode(void 0, { stream: false });
1234
+ const tail = stderrPartial + remaining;
1235
+ if (tail.length > 0) {
1236
+ if (tail.startsWith("__ZIEX_META__:")) stderrMeta += tail;
1237
+ else console.error("[ziex]", tail);
1238
+ stderrPartial = "";
1057
1239
  }
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() {
1096
1240
  return {
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
- }
1241
+ stdout: mergeUint8Arrays(stdoutChunks),
1242
+ stderrText: stderrMeta
1108
1243
  };
1109
1244
  }
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);
1118
- }
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);
1245
+ return { wasiImport, setMemory, collectOutput };
1246
+ }
1247
+ function mergeUint8Arrays(arrays) {
1248
+ const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
1249
+ const result = new Uint8Array(totalLen);
1250
+ let offset = 0;
1251
+ for (const arr of arrays) {
1252
+ result.set(arr, offset);
1253
+ offset += arr.length;
1168
1254
  }
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));
1255
+ return result;
1256
+ }
1257
+
1258
+ // src/runtime/kv.ts
1259
+ var kv_exports = {};
1260
+ __export(kv_exports, {
1261
+ createBrowserKVBindings: () => createBrowserKVBindings,
1262
+ createIndexedDbKV: () => createIndexedDbKV,
1263
+ createKVImports: () => createKVImports,
1264
+ createLocalStorageKV: () => createLocalStorageKV,
1265
+ createMemoryKV: () => createMemoryKV,
1266
+ hasJSPI: () => hasJSPI
1267
+ });
1268
+
1269
+ // src/runtime/kv/memory.ts
1270
+ function createMemoryKV() {
1271
+ const store = /* @__PURE__ */ new Map();
1272
+ function read(key) {
1273
+ const entry = store.get(key);
1274
+ if (!entry) return null;
1275
+ const expiresAt = entry[1];
1276
+ if (expiresAt !== void 0 && Date.now() >= expiresAt) {
1277
+ store.delete(key);
1278
+ return null;
1177
1279
  }
1178
- const result = Reflect.construct(fn, args);
1179
- this.storeValue(out, result);
1280
+ return entry[0];
1180
1281
  }
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));
1282
+ function write(key, value, options) {
1283
+ let expiresAt;
1284
+ if (options?.expiration !== void 0) {
1285
+ expiresAt = options.expiration * 1e3;
1286
+ } else if (options?.expirationTtl !== void 0) {
1287
+ expiresAt = Date.now() + options.expirationTtl * 1e3;
1190
1288
  }
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];
1289
+ store.set(key, [value, expiresAt]);
1218
1290
  }
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);
1230
- } else {
1231
- view.setFloat64(out, val, true);
1232
- }
1233
- return;
1234
- }
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;
1291
+ return {
1292
+ async get(key) {
1293
+ return read(key);
1294
+ },
1295
+ async put(key, value, options) {
1296
+ write(key, value, options);
1297
+ },
1298
+ async delete(key) {
1299
+ store.delete(key);
1300
+ },
1301
+ async list(options) {
1302
+ const keys = [...store.keys()].filter((k) => {
1303
+ if (options?.prefix && !k.startsWith(options.prefix)) return false;
1304
+ return read(k) !== null;
1305
+ }).map((name) => ({ name }));
1306
+ return { keys };
1273
1307
  }
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
- };
1308
+ };
1309
+ }
1284
1310
 
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);
1311
+ // src/runtime/kv/localstorage.ts
1312
+ function getLocalStorage() {
1313
+ if (typeof localStorage === "undefined") {
1314
+ throw new Error("localStorage is not available in this environment");
1315
+ }
1316
+ return localStorage;
1306
1317
  }
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);
1318
+ function createLocalStorageKV(options = {}) {
1319
+ const storage = getLocalStorage();
1320
+ const namespace = options.namespace ?? "default";
1321
+ const storagePrefix = options.storagePrefix ?? "ziex-kv";
1322
+ const scopedKey = (key) => `${storagePrefix}:${namespace}:${key}`;
1323
+ const namespacePrefix = scopedKey("");
1324
+ return {
1325
+ getSync(key) {
1326
+ return storage.getItem(scopedKey(key));
1327
+ },
1328
+ async get(key) {
1329
+ return this.getSync(key);
1330
+ },
1331
+ putSync(key, value) {
1332
+ storage.setItem(scopedKey(key), value);
1333
+ },
1334
+ async put(key, value) {
1335
+ this.putSync(key, value);
1336
+ },
1337
+ deleteSync(key) {
1338
+ storage.removeItem(scopedKey(key));
1339
+ },
1340
+ async delete(key) {
1341
+ this.deleteSync(key);
1342
+ },
1343
+ listSync(options2) {
1344
+ const prefix = namespacePrefix + (options2?.prefix ?? "");
1345
+ const keys = [];
1346
+ for (let i = 0; i < storage.length; i += 1) {
1347
+ const key = storage.key(i);
1348
+ if (!key || !key.startsWith(prefix)) continue;
1349
+ keys.push({ name: key.slice(namespacePrefix.length) });
1350
+ }
1351
+ return { keys };
1352
+ },
1353
+ async list(options2) {
1354
+ return this.listSync(options2);
1355
+ }
1356
+ };
1357
+ }
1358
+
1359
+ // src/runtime/kv/indexdb.ts
1360
+ function getIndexedDb() {
1361
+ if (typeof indexedDB === "undefined") {
1362
+ throw new Error("IndexedDB is not available in this environment");
1316
1363
  }
1317
- return memoryView;
1364
+ return indexedDB;
1318
1365
  }
1319
- var stringCache = /* @__PURE__ */ new Map();
1320
- function stringCacheKey(ptr, len) {
1321
- return ptr * 65536 + len;
1366
+ function requestToPromise(request) {
1367
+ return new Promise((resolve, reject) => {
1368
+ request.onsuccess = () => resolve(request.result);
1369
+ request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
1370
+ });
1322
1371
  }
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;
1372
+ function transactionToPromise(transaction) {
1373
+ return new Promise((resolve, reject) => {
1374
+ transaction.oncomplete = () => resolve();
1375
+ transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
1376
+ transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
1377
+ });
1330
1378
  }
1331
- function writeBytes(ptr, data) {
1332
- getMemoryView().set(data, ptr);
1379
+ function createIndexedDbKV(options = {}) {
1380
+ const databaseName = options.databaseName ?? "ziex-kv";
1381
+ const storeName = options.storeName ?? "kv";
1382
+ const namespace = options.namespace ?? "default";
1383
+ const dbPromise = new Promise((resolve, reject) => {
1384
+ const request = getIndexedDb().open(databaseName, 1);
1385
+ request.onupgradeneeded = () => {
1386
+ const db = request.result;
1387
+ if (!db.objectStoreNames.contains(storeName)) {
1388
+ db.createObjectStore(storeName);
1389
+ }
1390
+ };
1391
+ request.onsuccess = () => resolve(request.result);
1392
+ request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
1393
+ });
1394
+ const scopedKey = (key) => `${namespace}:${key}`;
1395
+ return {
1396
+ async get(key) {
1397
+ const db = await dbPromise;
1398
+ const tx = db.transaction(storeName, "readonly");
1399
+ const store = tx.objectStore(storeName);
1400
+ const value = await requestToPromise(store.get(scopedKey(key)));
1401
+ await transactionToPromise(tx);
1402
+ return typeof value === "string" ? value : null;
1403
+ },
1404
+ async put(key, value) {
1405
+ const db = await dbPromise;
1406
+ const tx = db.transaction(storeName, "readwrite");
1407
+ tx.objectStore(storeName).put(value, scopedKey(key));
1408
+ await transactionToPromise(tx);
1409
+ },
1410
+ async delete(key) {
1411
+ const db = await dbPromise;
1412
+ const tx = db.transaction(storeName, "readwrite");
1413
+ tx.objectStore(storeName).delete(scopedKey(key));
1414
+ await transactionToPromise(tx);
1415
+ },
1416
+ async list(options2) {
1417
+ const db = await dbPromise;
1418
+ const tx = db.transaction(storeName, "readonly");
1419
+ const store = tx.objectStore(storeName);
1420
+ const keys = await requestToPromise(store.getAllKeys());
1421
+ await transactionToPromise(tx);
1422
+ const prefix = scopedKey(options2?.prefix ?? "");
1423
+ return {
1424
+ keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
1425
+ };
1426
+ }
1427
+ };
1333
1428
  }
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);
1429
+
1430
+ // src/runtime/kv.ts
1431
+ function hasJSPI() {
1432
+ return typeof WebAssembly.Suspending === "function" && typeof WebAssembly.promising === "function";
1339
1433
  }
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
- }
1434
+ function createBrowserKVBindings(options = {}) {
1435
+ const namespace = options.namespace ?? "default";
1436
+ return {
1437
+ [namespace]: hasJSPI() ? createIndexedDbKV(options) : createLocalStorageKV(options)
1438
+ };
1348
1439
  }
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");
1440
+
1441
+ // src/runtime/index.ts
1442
+ function buildWsImports(Suspending, mem, decoder3, ws) {
1443
+ const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
1444
+ return {
1445
+ ws_upgrade: () => {
1446
+ ws.upgraded = true;
1447
+ },
1448
+ ws_write: (ptr, len) => {
1449
+ const data = new Uint8Array(mem().buffer, ptr, len).slice();
1450
+ if (!ws.server) {
1451
+ ws.pendingWrites.push(data);
1452
+ } else {
1453
+ ws.server.send(data);
1454
+ }
1455
+ },
1456
+ ws_close: (code, reason_ptr, reason_len) => {
1457
+ ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
1458
+ },
1459
+ ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
1460
+ if (ws._resolveFirstSuspend) {
1461
+ const fn = ws._resolveFirstSuspend;
1462
+ ws._resolveFirstSuspend = void 0;
1463
+ fn();
1464
+ }
1465
+ const deliver = (bytes) => {
1466
+ if (bytes === null) return -1;
1467
+ const n = Math.min(bytes.length, buf_max);
1468
+ new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
1469
+ return n;
1470
+ };
1471
+ if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
1472
+ return new Promise((resolve) => {
1473
+ ws.recvResolve = (bytes) => resolve(deliver(bytes));
1474
+ });
1475
+ }) : (_buf_ptr, _buf_max) => -1,
1476
+ // Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
1477
+ ws_subscribe: (ptr, len) => {
1478
+ ws.subscribe?.(readStr(ptr, len));
1479
+ },
1480
+ ws_unsubscribe: (ptr, len) => {
1481
+ ws.unsubscribe?.(readStr(ptr, len));
1482
+ },
1483
+ ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
1484
+ const topic = readStr(topic_ptr, topic_len);
1485
+ const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
1486
+ return ws.publish?.(topic, data) ?? 0;
1487
+ },
1488
+ ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
1489
+ };
1490
+ }
1491
+ function attachWebSocket(ws) {
1492
+ const WebSocketPairCtor = globalThis.WebSocketPair;
1493
+ const pair = new WebSocketPairCtor();
1494
+ const client = pair[0];
1495
+ const server = pair[1];
1496
+ ws.server = server;
1497
+ server.accept();
1498
+ for (const data of ws.pendingWrites) server.send(data);
1499
+ ws.pendingWrites = [];
1500
+ server.addEventListener("message", (event) => {
1501
+ const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
1502
+ if (ws.recvResolve) {
1503
+ const res = ws.recvResolve;
1504
+ ws.recvResolve = null;
1505
+ res(data);
1506
+ } else {
1507
+ ws.messageQueue.push(data);
1359
1508
  }
1360
- this.#fetchCompleteHandler = fetchCompleteHandler;
1361
- if (exports.memory) jsz.memory = exports.memory;
1362
- }
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");
1368
- return;
1509
+ });
1510
+ server.addEventListener("close", () => {
1511
+ if (ws.recvResolve) {
1512
+ const res = ws.recvResolve;
1513
+ ws.recvResolve = null;
1514
+ res(null);
1369
1515
  }
1370
- const dataRef = storeValueGetRef(data);
1371
- invokeWasmExport(handler, type, id, dataRef);
1516
+ });
1517
+ return { client };
1518
+ }
1519
+ function buildSysImports(jspi, Suspending) {
1520
+ return {
1521
+ sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
1522
+ }
1523
+ };
1524
+ }
1525
+ function executeWasm(instance, jspi, Suspending, wsState) {
1526
+ if (!jspi) {
1527
+ try {
1528
+ instance.exports._start();
1529
+ } catch (e) {
1530
+ if (!(e instanceof ProcExit)) throw e;
1531
+ }
1532
+ return Promise.resolve();
1372
1533
  }
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 = {};
1534
+ const start = WebAssembly.promising(instance.exports._start);
1535
+ return start().catch((e) => {
1536
+ if (e instanceof Error && e.message.startsWith("proc_exit")) return;
1537
+ throw e;
1538
+ }).finally(() => {
1539
+ if (wsState.recvResolve) {
1540
+ const res = wsState.recvResolve;
1541
+ wsState.recvResolve = null;
1542
+ res(null);
1543
+ }
1544
+ });
1545
+ }
1546
+ function parseZiexMeta(stderrText) {
1547
+ const meta = { status: 200, headers: new Headers(), streaming: false };
1548
+ const metaPrefix = "__ZIEX_META__:";
1549
+ const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
1550
+ if (metaLine) {
1383
1551
  try {
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);
1552
+ const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
1553
+ if (parsed.status) meta.status = parsed.status;
1554
+ if (parsed.streaming === true) meta.streaming = true;
1555
+ if (Array.isArray(parsed.headers)) {
1556
+ for (const [name, value] of parsed.headers) {
1557
+ meta.headers.append(name, value);
1390
1558
  }
1391
1559
  }
1560
+ } catch {
1561
+ }
1562
+ }
1563
+ return meta;
1564
+ }
1565
+ async function run({
1566
+ request,
1567
+ env,
1568
+ ctx,
1569
+ module,
1570
+ kv: kvBindings,
1571
+ db: dbBindings,
1572
+ imports,
1573
+ wasi,
1574
+ websocket: doNamespace
1575
+ }) {
1576
+ if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
1577
+ const id = doNamespace.idFromName(new URL(request.url).pathname);
1578
+ return doNamespace.get(id).fetch(request);
1579
+ }
1580
+ const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
1581
+ const stdoutChunks = [];
1582
+ let streamWriter = null;
1583
+ const { wasiImport, setMemory, collectOutput } = createWasiImports({
1584
+ request,
1585
+ stdinData,
1586
+ onStdout: (chunk) => {
1587
+ if (streamWriter) void streamWriter.write(chunk);
1588
+ else stdoutChunks.push(chunk);
1392
1589
  }
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
- });
1590
+ });
1591
+ let wasmMemory = null;
1592
+ const mem = () => wasmMemory;
1593
+ const bridgeRef = [null];
1594
+ const allocRef = [null];
1595
+ const Suspending = WebAssembly.Suspending;
1596
+ const jspi = typeof Suspending === "function";
1597
+ const wsState = {
1598
+ upgraded: false,
1599
+ server: null,
1600
+ pendingWrites: [],
1601
+ messageQueue: [],
1602
+ recvResolve: null
1603
+ };
1604
+ const importObject = {
1605
+ wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
1606
+ __zx_sys: buildSysImports(jspi, Suspending),
1607
+ __zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder(), wsState),
1608
+ __zx_net: createFetchImports(mem),
1609
+ ...imports ? imports(mem) : {},
1610
+ ...ZxWasiBridge.createImportObject(bridgeRef)
1611
+ };
1612
+ if (true) {
1613
+ importObject.__zx_kv = createKVImports(
1614
+ kvBindings ?? { default: createMemoryKV() },
1615
+ mem,
1616
+ allocRef
1617
+ );
1411
1618
  }
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);
1619
+ if (true) {
1620
+ importObject.__zx_db = createDbImports(
1621
+ dbBindings ?? {},
1622
+ mem,
1623
+ allocRef
1624
+ );
1419
1625
  }
1420
- /** Set a timeout and callback when it fires */
1421
- setTimeout(callbackId, delayMs) {
1422
- setTimeout(() => {
1423
- this.#invoke(CallbackType.Timeout, callbackId, null);
1424
- }, delayMs);
1626
+ const instance = new WebAssembly.Instance(module, importObject);
1627
+ wasmMemory = instance.exports.memory;
1628
+ setMemory(wasmMemory);
1629
+ bridgeRef[0] = new ZxWasiBridge(instance.exports);
1630
+ bindWasmAlloc(allocRef, instance.exports);
1631
+ const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
1632
+ if (wsState.upgraded) {
1633
+ const server = attachWebSocket(wsState);
1634
+ ctx?.waitUntil(wasmPromise);
1635
+ return new Response(null, { status: 101, webSocket: server.client });
1425
1636
  }
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);
1637
+ const { stderrText: earlyStderrText } = collectOutput();
1638
+ const earlyMeta = parseZiexMeta(earlyStderrText);
1639
+ if (earlyMeta.streaming) {
1640
+ const { readable, writable } = new TransformStream();
1641
+ streamWriter = writable.getWriter();
1642
+ for (const chunk of stdoutChunks) void streamWriter.write(chunk);
1643
+ stdoutChunks.length = 0;
1644
+ void wasmPromise.finally(() => streamWriter?.close());
1645
+ return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
1432
1646
  }
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);
1439
- }
1647
+ await wasmPromise;
1648
+ const { stderrText } = collectOutput();
1649
+ const meta = parseZiexMeta(stderrText);
1650
+ const body = mergeUint8Arrays(stdoutChunks);
1651
+ meta.headers.delete("transfer-encoding");
1652
+ const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
1653
+ if (nullBody) {
1654
+ meta.headers.delete("content-length");
1655
+ return new Response(null, { status: meta.status, headers: meta.headers });
1440
1656
  }
1441
- dispose() {
1442
- for (const handle of this.#intervals.values()) {
1443
- clearInterval(handle);
1657
+ if (!meta.headers.has("content-length")) meta.headers.set("content-length", String(body.byteLength));
1658
+ return new Response(body.buffer, { status: meta.status, headers: meta.headers });
1659
+ }
1660
+
1661
+ // src/app.ts
1662
+ async function resolveModule(input) {
1663
+ if (typeof input === "string") {
1664
+ if (input.startsWith("http://") || input.startsWith("https://")) {
1665
+ return WebAssembly.compileStreaming(fetch(input));
1444
1666
  }
1445
- this.#intervals.clear();
1667
+ const url = input.startsWith("/") ? `file://${input}` : input;
1668
+ return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
1446
1669
  }
1447
- /** Write a string to WASM memory, returning pointer and length */
1448
- _writeStringToWasm(str) {
1449
- return this._writeBytesToWasm(textEncoder.encode(str));
1670
+ if (input instanceof URL) {
1671
+ return WebAssembly.compileStreaming(fetch(input));
1450
1672
  }
1451
- _writeBytesToWasm(data) {
1452
- const ptr = this._alloc(data.length);
1453
- writeBytes(ptr, data);
1454
- return { ptr, len: data.length };
1673
+ if (input instanceof Response) {
1674
+ return WebAssembly.compileStreaming(input);
1455
1675
  }
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;
1676
+ if (input instanceof ArrayBuffer) {
1677
+ return WebAssembly.compile(input);
1678
+ }
1679
+ if (ArrayBuffer.isView(input)) {
1680
+ return WebAssembly.compile(input.buffer);
1681
+ }
1682
+ return input;
1683
+ }
1684
+ var Ziex = class {
1685
+ constructor(options) {
1686
+ this.resolved = null;
1687
+ /**
1688
+ * Fetch handler called by the runtime on every request.
1689
+ *
1690
+ * Arrow function so `this` is always the class instance, even when the
1691
+ * runtime extracts `fetch` from the exported object (e.g. Bun).
1692
+ */
1693
+ this.fetch = async (request, env, ctx) => {
1694
+ const module = await this.getModule();
1695
+ const { wasi, imports, websocket } = this.options;
1696
+ return run({
1697
+ request,
1698
+ env,
1699
+ ctx,
1700
+ module,
1701
+ wasi,
1702
+ imports,
1703
+ kv: this.resolveKV(env),
1704
+ db: this.resolveDB(env),
1705
+ websocket: websocket !== void 0 ? env[websocket] : void 0
1706
+ });
1707
+ };
1708
+ this.options = options;
1709
+ }
1710
+ async getModule() {
1711
+ if (!this.resolved) this.resolved = await resolveModule(this.options.module);
1712
+ return this.resolved;
1713
+ }
1714
+ resolveKV(env) {
1715
+ const { kv } = this.options;
1716
+ if (kv === void 0) return void 0;
1717
+ if (typeof kv === "object" && kv !== null) {
1718
+ const result = {};
1719
+ for (const [name, key] of Object.entries(kv)) {
1720
+ result[name] = env[key];
1721
+ }
1722
+ return result;
1472
1723
  }
1724
+ return { default: env[kv] };
1473
1725
  }
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
- }
1726
+ resolveDB(env) {
1727
+ const { db } = this.options;
1728
+ if (db === void 0) return void 0;
1729
+ if (typeof db === "object" && db !== null) {
1730
+ const result = {};
1731
+ for (const [name, key] of Object.entries(db)) {
1732
+ result[name] = env[key];
1512
1733
  }
1513
- };
1734
+ return result;
1735
+ }
1736
+ return { default: env[db] };
1514
1737
  }
1515
1738
  };
1516
1739
 
@@ -1534,18 +1757,29 @@ var ZxBridge = class extends ZxBridgeCore {
1534
1757
  exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
1535
1758
  );
1536
1759
  }
1760
+ hasEventHandler(velementId, eventTypeId) {
1761
+ return !!((eventHandlersPresent.get(velementId) ?? 0) & 1 << eventTypeId);
1762
+ }
1537
1763
  eventMaySuspend(velementId, eventTypeId) {
1538
- return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
1764
+ return !!((eventHandlersSuspend.get(velementId) ?? 0) & 1 << eventTypeId);
1539
1765
  }
1540
1766
  setEventHandlerMode(velementId, eventTypeId, maySuspend) {
1541
1767
  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);
1768
+ const present = (eventHandlersPresent.get(velementId) ?? 0) | bit;
1769
+ eventHandlersPresent.set(velementId, present);
1770
+ const suspendBits = eventHandlersSuspend.get(velementId) ?? 0;
1771
+ const nextSuspend = maySuspend ? suspendBits | bit : suspendBits & ~bit;
1772
+ if (nextSuspend === 0) eventHandlersSuspend.delete(velementId);
1773
+ else eventHandlersSuspend.set(velementId, nextSuspend);
1774
+ ensureDelegatedListener(eventTypeId);
1546
1775
  }
1547
1776
  clearEventHandlerModes(velementId) {
1548
- eventHandlerModes.delete(velementId);
1777
+ const present = eventHandlersPresent.get(velementId) ?? 0;
1778
+ eventHandlersPresent.delete(velementId);
1779
+ eventHandlersSuspend.delete(velementId);
1780
+ for (const eventTypeId of HIGH_FREQ_EVENT_IDS) {
1781
+ if (present & 1 << eventTypeId) maybeRemoveHighFreqListener(eventTypeId);
1782
+ }
1549
1783
  }
1550
1784
  /** Submit a form action with bound-state round-trip. */
1551
1785
  submitFormActionAsync(form, actionId, statesJson, fetchId) {
@@ -1579,7 +1813,7 @@ var ZxBridge = class extends ZxBridgeCore {
1579
1813
  const handler = this.#wsOnOpenHandler;
1580
1814
  if (!handler) return;
1581
1815
  const protocol = ws.protocol || "";
1582
- const { ptr, len } = this._writeStringToWasm(protocol);
1816
+ const [ptr, len] = this._writeStringToWasm(protocol);
1583
1817
  invokeWasmExport(handler, wsId, ptr, len);
1584
1818
  };
1585
1819
  ws.onmessage = (event) => {
@@ -1587,20 +1821,20 @@ var ZxBridge = class extends ZxBridgeCore {
1587
1821
  if (!handler) return;
1588
1822
  const isBinary = event.data instanceof ArrayBuffer;
1589
1823
  const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
1590
- const { ptr, len } = this._writeBytesToWasm(data);
1824
+ const [ptr, len] = this.writeBytesToWasm(data);
1591
1825
  invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
1592
1826
  };
1593
1827
  ws.onerror = (_event) => {
1594
1828
  const handler = this.#wsOnErrorHandler;
1595
1829
  if (!handler) return;
1596
- const { ptr, len } = this._writeStringToWasm("WebSocket error");
1830
+ const [ptr, len] = this._writeStringToWasm("WebSocket error");
1597
1831
  invokeWasmExport(handler, wsId, ptr, len);
1598
1832
  };
1599
1833
  ws.onclose = (event) => {
1600
1834
  const handler = this.#wsOnCloseHandler;
1601
1835
  if (!handler) return;
1602
1836
  const reason = event.reason || "";
1603
- const { ptr, len } = this._writeStringToWasm(reason);
1837
+ const [ptr, len] = this._writeStringToWasm(reason);
1604
1838
  invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
1605
1839
  this.#websockets.delete(wsId);
1606
1840
  };
@@ -1609,7 +1843,7 @@ var ZxBridge = class extends ZxBridgeCore {
1609
1843
  const handler = this.#wsOnErrorHandler;
1610
1844
  if (handler) {
1611
1845
  const msg = error instanceof Error ? error.message : "WebSocket connection failed";
1612
- const { ptr, len } = this._writeStringToWasm(msg);
1846
+ const [ptr, len] = this._writeStringToWasm(msg);
1613
1847
  invokeWasmExport(handler, wsId, ptr, len);
1614
1848
  }
1615
1849
  }
@@ -1619,10 +1853,13 @@ var ZxBridge = class extends ZxBridgeCore {
1619
1853
  const ws = this.#websockets.get(wsId);
1620
1854
  if (!ws || ws.readyState !== WebSocket.OPEN) return;
1621
1855
  const memory = getMemoryView();
1856
+ const start = dataPtr >>> 0;
1857
+ const length = dataLen >>> 0;
1858
+ if (start + length > memory.byteLength) return;
1622
1859
  if (isBinary) {
1623
- ws.send(memory.slice(dataPtr, dataPtr + dataLen));
1860
+ ws.send(memory.slice(start, start + length));
1624
1861
  } else {
1625
- ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
1862
+ ws.send(textDecoder.decode(memory.subarray(start, start + length)));
1626
1863
  }
1627
1864
  }
1628
1865
  /** Close WebSocket connection */
@@ -1639,7 +1876,8 @@ var ZxBridge = class extends ZxBridgeCore {
1639
1876
  }
1640
1877
  dispose() {
1641
1878
  super.dispose();
1642
- eventHandlerModes.clear();
1879
+ eventHandlersPresent.clear();
1880
+ eventHandlersSuspend.clear();
1643
1881
  for (const ws of this.#websockets.values()) {
1644
1882
  try {
1645
1883
  ws.close();
@@ -1648,14 +1886,16 @@ var ZxBridge = class extends ZxBridgeCore {
1648
1886
  }
1649
1887
  this.#websockets.clear();
1650
1888
  }
1651
- /** Handle a DOM event (called by event delegation) */
1652
- eventbridge(velementId, eventTypeId, event) {
1653
- const eventRef = storeValueGetRef(event);
1889
+ /**
1890
+ * Dispatch to WASM for one vnode. Caller owns `eventRef` lifetime
1891
+ * (store once per bubble, release after sync/async work completes).
1892
+ */
1893
+ eventbridge(velementId, eventTypeId, eventRef) {
1894
+ const id = BigInt(velementId >>> 0);
1654
1895
  if (this.eventMaySuspend(velementId, eventTypeId)) {
1655
- invokeWasmExport(this.#eventbridgeAsync, velementId, eventTypeId, eventRef);
1656
- return;
1896
+ return invokeWasmExport(this.#eventbridgeAsync, id, eventTypeId, eventRef);
1657
1897
  }
1658
- invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
1898
+ invokeWasmExport(this.#eventbridge, id, eventTypeId, eventRef);
1659
1899
  }
1660
1900
  /** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
1661
1901
  static createImportObject(bridgeRef) {
@@ -1668,13 +1908,13 @@ var ZxBridge = class extends ZxBridgeCore {
1668
1908
  __zx: {
1669
1909
  _log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
1670
1910
  _setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
1671
- bridgeRef.current?.setEventHandlerMode(vnodeId, eventTypeId, maySuspend !== 0);
1911
+ bridgeRef[0]?.setEventHandlerMode(Number(vnodeId), eventTypeId, maySuspend !== 0);
1672
1912
  },
1673
1913
  _clearEventHandlerModes: (vnodeId) => {
1674
- bridgeRef.current?.clearEventHandlerModes(vnodeId);
1914
+ bridgeRef[0]?.clearEventHandlerModes(Number(vnodeId));
1675
1915
  },
1676
1916
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
1677
- bridgeRef.current?.fetchAsync(
1917
+ bridgeRef[0]?.fetchAsync(
1678
1918
  urlPtr,
1679
1919
  urlLen,
1680
1920
  methodPtr,
@@ -1688,43 +1928,49 @@ var ZxBridge = class extends ZxBridgeCore {
1688
1928
  );
1689
1929
  },
1690
1930
  _setTimeout: (callbackId, delayMs) => {
1691
- bridgeRef.current?.setTimeout(callbackId, delayMs);
1931
+ bridgeRef[0]?.setTimeout(callbackId, delayMs);
1692
1932
  },
1693
1933
  _setInterval: (callbackId, intervalMs) => {
1694
- bridgeRef.current?.setInterval(callbackId, intervalMs);
1934
+ bridgeRef[0]?.setInterval(callbackId, intervalMs);
1695
1935
  },
1696
1936
  _clearInterval: (callbackId) => {
1697
- bridgeRef.current?.clearInterval(callbackId);
1937
+ bridgeRef[0]?.clearInterval(callbackId);
1698
1938
  },
1699
1939
  // WebSocket API
1700
1940
  _wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
1701
- bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
1941
+ bridgeRef[0]?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
1702
1942
  },
1703
1943
  _wsSend: (wsId, dataPtr, dataLen, isBinary) => {
1704
- bridgeRef.current?.wsSend(wsId, dataPtr, dataLen, isBinary);
1944
+ bridgeRef[0]?.wsSend(wsId, dataPtr, dataLen, isBinary);
1705
1945
  },
1706
1946
  _wsClose: (wsId, code, reasonPtr, reasonLen) => {
1707
- bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
1947
+ bridgeRef[0]?.wsClose(wsId, code, reasonPtr, reasonLen);
1708
1948
  },
1709
1949
  _ce: (id, vnodeId) => {
1950
+ const nid = Number(vnodeId);
1710
1951
  const tagName = TAG_NAMES[id];
1711
1952
  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);
1953
+ el.__zx_ref = nid;
1954
+ domNodes.set(nid, el);
1715
1955
  },
1716
1956
  _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);
1957
+ const nid = Number(vnodeId);
1958
+ const node = document.createTextNode(readString(ptr, len));
1959
+ node.__zx_ref = nid;
1960
+ domNodes.set(nid, node);
1961
+ },
1962
+ /** Insert vnode before a jsz-held end comment (hydration). */
1963
+ _ih: (vnodeId, endCommentRef) => {
1964
+ const child = domNodes.get(Number(vnodeId));
1965
+ const end = loadValueFromRef(endCommentRef);
1966
+ if (!child || !end?.parentNode) return;
1967
+ end.parentNode.insertBefore(child, end);
1722
1968
  },
1723
1969
  _sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
1724
- domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
1970
+ domNodes.get(Number(vnodeId))?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
1725
1971
  },
1726
1972
  _sp: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
1727
- const el = domNodes.get(vnodeId);
1973
+ const el = domNodes.get(Number(vnodeId));
1728
1974
  if (el) {
1729
1975
  const name = readString(namePtr, nameLen);
1730
1976
  const val = readString(valPtr, valLen);
@@ -1736,39 +1982,39 @@ var ZxBridge = class extends ZxBridgeCore {
1736
1982
  }
1737
1983
  },
1738
1984
  _ra: (vnodeId, namePtr, nameLen) => {
1739
- domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
1985
+ domNodes.get(Number(vnodeId))?.removeAttribute(readString(namePtr, nameLen));
1740
1986
  },
1741
1987
  _snv: (vnodeId, ptr, len) => {
1742
- const node = domNodes.get(vnodeId);
1988
+ const node = domNodes.get(Number(vnodeId));
1743
1989
  if (node) node.nodeValue = readString(ptr, len);
1744
1990
  },
1745
1991
  _srh: (vnodeId, ptr, len) => {
1746
- const el = domNodes.get(vnodeId);
1992
+ const el = domNodes.get(Number(vnodeId));
1747
1993
  if (el) el.innerHTML = readString(ptr, len);
1748
1994
  },
1749
1995
  _ac: (parentId, childId) => {
1750
- const parent = domNodes.get(parentId);
1751
- const child = domNodes.get(childId);
1996
+ const parent = domNodes.get(Number(parentId));
1997
+ const child = domNodes.get(Number(childId));
1752
1998
  if (parent && child) parent.appendChild(child);
1753
1999
  },
1754
2000
  _ib: (parentId, childId, refId) => {
1755
- const parent = domNodes.get(parentId);
1756
- const child = domNodes.get(childId);
1757
- const ref = domNodes.get(refId) ?? null;
2001
+ const parent = domNodes.get(Number(parentId));
2002
+ const child = domNodes.get(Number(childId));
2003
+ const ref = domNodes.get(Number(refId)) ?? null;
1758
2004
  if (parent && child) parent.insertBefore(child, ref);
1759
2005
  },
1760
2006
  _rc: (parentId, childId) => {
1761
- const parent = domNodes.get(parentId);
1762
- const child = domNodes.get(childId);
2007
+ const parent = domNodes.get(Number(parentId));
2008
+ const child = domNodes.get(Number(childId));
1763
2009
  if (parent && child) {
1764
2010
  parent.removeChild(child);
1765
2011
  cleanupDomNodes(child);
1766
2012
  }
1767
2013
  },
1768
2014
  _rpc: (parentId, newId, oldId) => {
1769
- const parent = domNodes.get(parentId);
1770
- const newChild = domNodes.get(newId);
1771
- const oldChild = domNodes.get(oldId);
2015
+ const parent = domNodes.get(Number(parentId));
2016
+ const newChild = domNodes.get(Number(newId));
2017
+ const oldChild = domNodes.get(Number(oldId));
1772
2018
  if (parent && newChild && oldChild) {
1773
2019
  parent.replaceChild(newChild, oldChild);
1774
2020
  cleanupDomNodes(oldChild);
@@ -1780,18 +2026,22 @@ var ZxBridge = class extends ZxBridgeCore {
1780
2026
  writeBytes(bufPtr, bytes.subarray(0, len));
1781
2027
  return len;
1782
2028
  },
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));
2029
+ _getFormData: (eventRef, outPtrAddr) => {
2030
+ const event = loadValueFromRef(eventRef);
2031
+ const el = event?.target;
2032
+ const form = el instanceof HTMLFormElement ? el : el?.closest?.("form") ?? null;
2033
+ if (!form) return 0;
2034
+ const entries = [];
2035
+ for (const [k, v] of new FormData(form).entries()) {
2036
+ entries.push(k, String(v));
2037
+ }
2038
+ const bytes = textEncoder.encode(JSON.stringify(entries));
2039
+ const [ptr, len] = bridgeRef[0].writeBytesToWasm(bytes);
2040
+ new DataView(jsz.memory.buffer).setUint32(outPtrAddr, ptr, true);
1791
2041
  return len;
1792
2042
  },
1793
2043
  _submitFormAction: (vnodeId, actionId) => {
1794
- const form = domNodes.get(vnodeId);
2044
+ const form = domNodes.get(Number(vnodeId));
1795
2045
  if (!form || !(form instanceof HTMLFormElement)) return;
1796
2046
  const formData = new FormData(form);
1797
2047
  fetch(window.location.href, {
@@ -1803,21 +2053,39 @@ var ZxBridge = class extends ZxBridgeCore {
1803
2053
  });
1804
2054
  },
1805
2055
  _submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
1806
- const form = domNodes.get(vnodeId);
2056
+ const form = domNodes.get(Number(vnodeId));
1807
2057
  if (!form || !(form instanceof HTMLFormElement)) return;
1808
2058
  const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
1809
- bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
2059
+ bridgeRef[0]?.submitFormActionAsync(form, actionId, statesJson, fetchId);
1810
2060
  }
1811
2061
  }
1812
2062
  };
1813
2063
  }
1814
2064
  };
1815
2065
  var domNodes = /* @__PURE__ */ new Map();
2066
+ var eventHandlersPresent = /* @__PURE__ */ new Map();
2067
+ var eventHandlersSuspend = /* @__PURE__ */ new Map();
1816
2068
  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]);
2069
+ const stack = [node];
2070
+ let highFreqBits = 0;
2071
+ while (stack.length > 0) {
2072
+ const n = stack.pop();
2073
+ const ref = n.__zx_ref;
2074
+ if (typeof ref === "number") {
2075
+ const present = eventHandlersPresent.get(ref);
2076
+ if (present !== void 0) {
2077
+ highFreqBits |= present;
2078
+ eventHandlersPresent.delete(ref);
2079
+ eventHandlersSuspend.delete(ref);
2080
+ }
2081
+ domNodes.delete(ref);
2082
+ }
2083
+ const children = n.childNodes;
2084
+ for (let i = 0; i < children.length; i++) stack.push(children[i]);
2085
+ }
2086
+ for (const eventTypeId of HIGH_FREQ_EVENT_IDS) {
2087
+ if (highFreqBits & 1 << eventTypeId) maybeRemoveHighFreqListener(eventTypeId);
2088
+ }
1821
2089
  }
1822
2090
  var SVG_TAG_START_INDEX = 140;
1823
2091
  var TAG_NAMES = [
@@ -2022,9 +2290,99 @@ var TAG_NAMES = [
2022
2290
  "use",
2023
2291
  "view"
2024
2292
  ];
2025
- var eventHandlerModes = /* @__PURE__ */ new Map();
2293
+ var DELEGATED_EVENTS = [
2294
+ "click",
2295
+ "dblclick",
2296
+ "input",
2297
+ "change",
2298
+ "submit",
2299
+ // focus/blur do not bubble - listen to focusin/focusout instead.
2300
+ "focusin",
2301
+ "focusout",
2302
+ "keydown",
2303
+ "keyup",
2304
+ "keypress",
2305
+ "mouseenter",
2306
+ "mouseleave",
2307
+ "mousedown",
2308
+ "mouseup",
2309
+ "mousemove",
2310
+ "touchstart",
2311
+ "touchend",
2312
+ "touchmove",
2313
+ "scroll",
2314
+ "wheel",
2315
+ "pointerdown",
2316
+ "pointermove",
2317
+ "pointerup",
2318
+ "pointercancel"
2319
+ ];
2320
+ var HIGH_FREQ_EVENT_IDS = new Set([
2321
+ DELEGATED_EVENTS.indexOf("mousemove"),
2322
+ DELEGATED_EVENTS.indexOf("pointermove"),
2323
+ DELEGATED_EVENTS.indexOf("wheel"),
2324
+ DELEGATED_EVENTS.indexOf("scroll"),
2325
+ DELEGATED_EVENTS.indexOf("touchmove")
2326
+ ].filter((id) => id >= 0));
2327
+ var delegationState = null;
2328
+ function makeDelegatedListener(bridge, eventTypeId) {
2329
+ return (event) => {
2330
+ let eventRef;
2331
+ const pending = [];
2332
+ let target = event.target;
2333
+ while (target && target !== document.body) {
2334
+ const zxRef = target.__zx_ref;
2335
+ if (typeof zxRef === "number" && bridge.hasEventHandler(zxRef, eventTypeId)) {
2336
+ if (eventRef === void 0) eventRef = storeValueGetRef(event);
2337
+ const result = bridge.eventbridge(zxRef, eventTypeId, eventRef);
2338
+ if (result && typeof result.then === "function") {
2339
+ pending.push(result);
2340
+ }
2341
+ if (event.cancelBubble) break;
2342
+ }
2343
+ target = target.parentElement;
2344
+ }
2345
+ if (eventRef !== void 0) {
2346
+ const ref = eventRef;
2347
+ if (pending.length > 0) {
2348
+ Promise.all(pending).finally(() => releaseValueRef(ref));
2349
+ } else {
2350
+ releaseValueRef(ref);
2351
+ }
2352
+ }
2353
+ };
2354
+ }
2355
+ function ensureDelegatedListener(eventTypeId) {
2356
+ const state = delegationState;
2357
+ if (!state || state.attached.has(eventTypeId)) return;
2358
+ const domType = DELEGATED_EVENTS[eventTypeId];
2359
+ if (!domType) return;
2360
+ const passive = domType.startsWith("touch") || domType === "scroll";
2361
+ const options = { passive };
2362
+ const listener = makeDelegatedListener(state.bridge, eventTypeId);
2363
+ state.root.addEventListener(domType, listener, options);
2364
+ state.attached.set(eventTypeId, { listener, options });
2365
+ }
2366
+ function anyHandlerForType(eventTypeId) {
2367
+ const bit = 1 << eventTypeId;
2368
+ for (const mask of eventHandlersPresent.values()) {
2369
+ if (mask & bit) return true;
2370
+ }
2371
+ return false;
2372
+ }
2373
+ function maybeRemoveHighFreqListener(eventTypeId) {
2374
+ if (!HIGH_FREQ_EVENT_IDS.has(eventTypeId)) return;
2375
+ if (anyHandlerForType(eventTypeId)) return;
2376
+ const state = delegationState;
2377
+ if (!state) return;
2378
+ const entry = state.attached.get(eventTypeId);
2379
+ if (!entry) return;
2380
+ const domType = DELEGATED_EVENTS[eventTypeId];
2381
+ state.root.removeEventListener(domType, entry.listener, entry.options);
2382
+ state.attached.delete(eventTypeId);
2383
+ }
2026
2384
 
2027
- // src/cloudflare/do.ts
2385
+ // src/platforms/cloudflare/do.ts
2028
2386
  function createWebSocketDO(module, options) {
2029
2387
  return class ZxWebSocketDO {
2030
2388
  constructor(state, env) {
@@ -2038,7 +2396,7 @@ function createWebSocketDO(module, options) {
2038
2396
  const { wasiImport, setMemory } = createWasiImports({ request, stdinData });
2039
2397
  let wasmMemory = null;
2040
2398
  const mem = () => wasmMemory;
2041
- const bridgeRef = { current: null };
2399
+ const bridgeRef = [null];
2042
2400
  const bridgeImports = ZxBridge.createImportObject(bridgeRef);
2043
2401
  const Suspending = WebAssembly.Suspending;
2044
2402
  const jspi = typeof Suspending === "function";
@@ -2084,19 +2442,34 @@ function createWebSocketDO(module, options) {
2084
2442
  const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder3, connState);
2085
2443
  const kvBindings = options?.kv?.(this.env);
2086
2444
  const dbBindings = options?.db?.(this.env);
2087
- const instance = new WebAssembly.Instance(module, {
2445
+ const allocRef = [null];
2446
+ const importObject = {
2088
2447
  wasi_snapshot_preview1: wasiImport,
2089
2448
  __zx_sys: sysImports,
2090
2449
  __zx_ws: wsImports,
2091
- __zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
2092
- __zx_db: createD1Imports(dbBindings ?? {}, mem),
2093
2450
  __zx_net: createFetchImports(mem),
2094
2451
  ...options?.imports ? options.imports(mem) : {},
2095
2452
  ...bridgeImports
2096
- });
2453
+ };
2454
+ if (true) {
2455
+ importObject.__zx_kv = createKVImports(
2456
+ kvBindings ?? { default: createMemoryKV() },
2457
+ mem,
2458
+ allocRef
2459
+ );
2460
+ }
2461
+ if (true) {
2462
+ importObject.__zx_db = createDbImports(
2463
+ dbBindings ?? {},
2464
+ mem,
2465
+ allocRef
2466
+ );
2467
+ }
2468
+ const instance = new WebAssembly.Instance(module, importObject);
2097
2469
  wasmMemory = instance.exports.memory;
2098
2470
  setMemory(wasmMemory);
2099
- bridgeRef.current = new ZxBridge(instance.exports);
2471
+ bridgeRef[0] = new ZxBridge(instance.exports);
2472
+ bindWasmAlloc(allocRef, instance.exports);
2100
2473
  const start = WebAssembly.promising(instance.exports._start);
2101
2474
  const wasmPromise = start().catch((e) => {
2102
2475
  wasmExited = true;