ziex 0.1.0-dev.1466 → 0.1.0-dev.1568
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.
- package/README.md +3 -9
- package/app.d.ts +37 -22
- package/build.zig.zon +1 -1
- package/index.d.ts +1 -1
- package/index.js +239 -218
- package/package.json +2 -2
- package/platforms/aws-lambda/index.d.ts +1 -1
- package/platforms/cloudflare/app.d.ts +31 -1
- package/platforms/cloudflare/index.d.ts +5 -4
- package/platforms/cloudflare/index.js +1722 -1645
- package/platforms/cloudflare/kv.d.ts +4 -2
- package/platforms/cloudflare/stateful.d.ts +26 -0
- package/platforms/cloudflare/worker.d.ts +1 -2
- package/platforms/vercel/index.d.ts +1 -1
- package/runtime/index.d.ts +20 -10
- package/runtime/kv/indexdb.d.ts +11 -3
- package/runtime/kv/localstorage.d.ts +11 -3
- package/runtime/kv/memory.d.ts +13 -6
- package/runtime/kv.d.ts +16 -18
- package/runtime/kv.js +178 -241
- package/runtime/wasi.d.ts +2 -7
- package/wasm/dom_cmd.d.ts +0 -9
- package/wasm/index.js +224 -188
- package/wasm/init.dev.js +224 -188
- package/wasm/init.js +3 -3
- package/platforms/cloudflare/do.d.ts +0 -50
package/index.js
CHANGED
|
@@ -158,7 +158,7 @@ var ZxWasiBridge = class {
|
|
|
158
158
|
function createFetchImports(getMemory) {
|
|
159
159
|
const encoder3 = new TextEncoder();
|
|
160
160
|
const decoder3 = new TextDecoder();
|
|
161
|
-
function
|
|
161
|
+
function readStr2(ptr, len) {
|
|
162
162
|
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
163
163
|
}
|
|
164
164
|
function writeBytes(buf_ptr, buf_max, data) {
|
|
@@ -184,9 +184,9 @@ function createFetchImports(getMemory) {
|
|
|
184
184
|
return headers;
|
|
185
185
|
}
|
|
186
186
|
async function doFetch(url_ptr, url_len, method_ptr, method_len, headers_ptr, headers_len, body_ptr, body_len, timeout_ms, status_out, buf_ptr, buf_max) {
|
|
187
|
-
const url =
|
|
188
|
-
const method = method_len > 0 ?
|
|
189
|
-
const headersJson = headers_len > 0 ?
|
|
187
|
+
const url = readStr2(url_ptr, url_len);
|
|
188
|
+
const method = method_len > 0 ? readStr2(method_ptr, method_len) : "GET";
|
|
189
|
+
const headersJson = headers_len > 0 ? readStr2(headers_ptr, headers_len) : "{}";
|
|
190
190
|
const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
|
|
191
191
|
const headers = parseHeaders(headersJson);
|
|
192
192
|
const controller = new AbortController();
|
|
@@ -209,14 +209,14 @@ function createFetchImports(getMemory) {
|
|
|
209
209
|
return -1;
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
|
-
const
|
|
213
|
-
if (typeof
|
|
212
|
+
const Suspending2 = WebAssembly.Suspending;
|
|
213
|
+
if (typeof Suspending2 !== "function") {
|
|
214
214
|
return {
|
|
215
215
|
fetch: (_url_ptr, _url_len, _method_ptr, _method_len, _headers_ptr, _headers_len, _body_ptr, _body_len, _timeout_ms, _status_out, _buf_ptr, _buf_max) => -1
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
218
|
return {
|
|
219
|
-
fetch: new
|
|
219
|
+
fetch: new Suspending2(doFetch)
|
|
220
220
|
};
|
|
221
221
|
}
|
|
222
222
|
|
|
@@ -498,90 +498,96 @@ function bindWasmAlloc(allocRef, exports) {
|
|
|
498
498
|
}
|
|
499
499
|
|
|
500
500
|
// src/runtime/kv/extern.ts
|
|
501
|
+
var Suspending = WebAssembly.Suspending;
|
|
502
|
+
var jspi = typeof Suspending === "function";
|
|
503
|
+
var miss = jspi ? -1 : 0;
|
|
501
504
|
function putOptions(ttlSeconds) {
|
|
502
505
|
if (ttlSeconds < 60) return void 0;
|
|
503
506
|
return { expirationTtl: ttlSeconds };
|
|
504
507
|
}
|
|
508
|
+
function kvDel(binding, key) {
|
|
509
|
+
const b = binding;
|
|
510
|
+
return (b.del ?? b.delete).call(b, key);
|
|
511
|
+
}
|
|
505
512
|
function isSyncKVNamespace(binding) {
|
|
506
|
-
|
|
507
|
-
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
513
|
+
return typeof binding.get === "function" && binding.get.constructor.name !== "AsyncFunction";
|
|
508
514
|
}
|
|
509
|
-
function
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
function listOpts(prefix) {
|
|
516
|
+
return prefix.length > 0 ? { prefix } : void 0;
|
|
517
|
+
}
|
|
518
|
+
function maybeThen(r, f) {
|
|
519
|
+
return r instanceof Promise ? r.then(f) : f(r);
|
|
520
|
+
}
|
|
521
|
+
function readStr(getMemory, ptr, len) {
|
|
522
|
+
return textDecoder.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
523
|
+
}
|
|
524
|
+
function resolve(bindings, ns) {
|
|
525
|
+
const b = bindings[ns] ?? bindings["default"] ?? null;
|
|
526
|
+
if (!b || jspi) return b;
|
|
527
|
+
return isSyncKVNamespace(b) ? b : null;
|
|
528
|
+
}
|
|
529
|
+
function encodeGet(getMemory, allocRef, value, out_ptr) {
|
|
530
|
+
if (value === null) return -1;
|
|
531
|
+
return writeBytesOut(getMemory, allocRef, out_ptr, textEncoder.encode(value));
|
|
532
|
+
}
|
|
533
|
+
function encodeList(getMemory, allocRef, names, out_ptr) {
|
|
534
|
+
if (names.length === 0) {
|
|
535
|
+
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
536
|
+
return 0;
|
|
517
537
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
b.deleteSync(readStr(key_ptr, key_len));
|
|
543
|
-
return 0;
|
|
544
|
-
},
|
|
545
|
-
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
|
|
546
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
547
|
-
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
548
|
-
const prefix = readStr(pfx_ptr, pfx_len);
|
|
549
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
550
|
-
return writeJsonOut(getMemory, allocRef, out_ptr, result.keys.map((k) => k.name));
|
|
551
|
-
}
|
|
552
|
-
};
|
|
538
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, names);
|
|
539
|
+
}
|
|
540
|
+
function get(b, key, out_ptr, getMemory, allocRef) {
|
|
541
|
+
return maybeThen(b.get(key), (v) => encodeGet(getMemory, allocRef, v, out_ptr));
|
|
542
|
+
}
|
|
543
|
+
function put(b, key, val, ttl) {
|
|
544
|
+
return maybeThen(b.put(key, val, putOptions(ttl)), () => 0);
|
|
545
|
+
}
|
|
546
|
+
function del(b, key) {
|
|
547
|
+
return maybeThen(kvDel(b, key), () => 0);
|
|
548
|
+
}
|
|
549
|
+
function list(b, prefix, out_ptr, getMemory, allocRef) {
|
|
550
|
+
return maybeThen(
|
|
551
|
+
b.list(listOpts(prefix)),
|
|
552
|
+
(result) => encodeList(getMemory, allocRef, result.keys.map((k) => k.name), out_ptr)
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
function wrapImport(impl) {
|
|
556
|
+
if (!jspi) {
|
|
557
|
+
return ((...args) => {
|
|
558
|
+
const r = impl(...args);
|
|
559
|
+
if (r instanceof Promise) throw new Error("async kv binding requires JSPI");
|
|
560
|
+
return r;
|
|
561
|
+
});
|
|
553
562
|
}
|
|
563
|
+
return new Suspending(impl);
|
|
564
|
+
}
|
|
565
|
+
function createKVImports(bindings, getMemory, allocRef) {
|
|
554
566
|
return {
|
|
555
|
-
kv_get:
|
|
556
|
-
const b =
|
|
567
|
+
kv_get: wrapImport((ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
|
|
568
|
+
const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
|
|
557
569
|
if (!b) return -1;
|
|
558
|
-
|
|
559
|
-
if (value === null) return -1;
|
|
560
|
-
return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
|
|
570
|
+
return get(b, readStr(getMemory, key_ptr, key_len), out_ptr, getMemory, allocRef);
|
|
561
571
|
}),
|
|
562
|
-
kv_put:
|
|
563
|
-
const b =
|
|
564
|
-
if (!b) return
|
|
565
|
-
|
|
566
|
-
|
|
572
|
+
kv_put: wrapImport((ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
573
|
+
const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
|
|
574
|
+
if (!b) return miss;
|
|
575
|
+
return put(
|
|
576
|
+
b,
|
|
577
|
+
readStr(getMemory, key_ptr, key_len),
|
|
578
|
+
readStr(getMemory, val_ptr, val_len),
|
|
579
|
+
ttl_seconds
|
|
580
|
+
);
|
|
567
581
|
}),
|
|
568
|
-
kv_delete:
|
|
569
|
-
const b =
|
|
570
|
-
if (!b) return
|
|
571
|
-
|
|
572
|
-
return 0;
|
|
582
|
+
kv_delete: wrapImport((ns_ptr, ns_len, key_ptr, key_len) => {
|
|
583
|
+
const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
|
|
584
|
+
if (!b) return miss;
|
|
585
|
+
return del(b, readStr(getMemory, key_ptr, key_len));
|
|
573
586
|
}),
|
|
574
|
-
kv_list:
|
|
575
|
-
const b =
|
|
587
|
+
kv_list: wrapImport((ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
|
|
588
|
+
const b = resolve(bindings, readStr(getMemory, ns_ptr, ns_len));
|
|
576
589
|
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
577
|
-
|
|
578
|
-
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
579
|
-
const names = result.keys.map((k) => k.name);
|
|
580
|
-
if (names.length === 0) {
|
|
581
|
-
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
582
|
-
return 0;
|
|
583
|
-
}
|
|
584
|
-
return writeJsonOut(getMemory, allocRef, out_ptr, names);
|
|
590
|
+
return list(b, readStr(getMemory, pfx_ptr, pfx_len), out_ptr, getMemory, allocRef);
|
|
585
591
|
})
|
|
586
592
|
};
|
|
587
593
|
}
|
|
@@ -653,21 +659,21 @@ function valuesToWireRows(rows) {
|
|
|
653
659
|
}
|
|
654
660
|
function createDbImports(bindings, getMemory, allocRef) {
|
|
655
661
|
const decoder3 = new TextDecoder();
|
|
656
|
-
function
|
|
662
|
+
function readStr2(ptr, len) {
|
|
657
663
|
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
658
664
|
}
|
|
659
665
|
function binding(ns) {
|
|
660
666
|
return bindings[ns] ?? bindings["default"] ?? null;
|
|
661
667
|
}
|
|
662
668
|
async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
|
|
663
|
-
const database = binding(
|
|
669
|
+
const database = binding(readStr2(ns_ptr, ns_len));
|
|
664
670
|
if (!database) return null;
|
|
665
|
-
const sql =
|
|
666
|
-
const bindingsJson = JSON.parse(
|
|
671
|
+
const sql = readStr2(sql_ptr, sql_len);
|
|
672
|
+
const bindingsJson = JSON.parse(readStr2(bindings_ptr, bindings_len));
|
|
667
673
|
return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
|
|
668
674
|
}
|
|
669
|
-
const
|
|
670
|
-
if (typeof
|
|
675
|
+
const Suspending2 = WebAssembly.Suspending;
|
|
676
|
+
if (typeof Suspending2 !== "function") {
|
|
671
677
|
return {
|
|
672
678
|
db_open: (_ns, _ns_len) => -1,
|
|
673
679
|
db_run: (_a, _b, _c, _d, _e, _f, _g) => -1,
|
|
@@ -677,8 +683,8 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
677
683
|
};
|
|
678
684
|
}
|
|
679
685
|
return {
|
|
680
|
-
db_open: (ns_ptr, ns_len) => binding(
|
|
681
|
-
db_run: new
|
|
686
|
+
db_open: (ns_ptr, ns_len) => binding(readStr2(ns_ptr, ns_len)) ? 0 : -1,
|
|
687
|
+
db_run: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
682
688
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
683
689
|
if (!stmt) return -1;
|
|
684
690
|
const result = await stmt.run();
|
|
@@ -687,7 +693,7 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
687
693
|
changes: result.meta?.changes ?? 0
|
|
688
694
|
});
|
|
689
695
|
}),
|
|
690
|
-
db_get: new
|
|
696
|
+
db_get: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
691
697
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
692
698
|
if (!stmt) return -1;
|
|
693
699
|
const row = await stmt.first();
|
|
@@ -697,7 +703,7 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
697
703
|
}
|
|
698
704
|
return writeJsonOut(getMemory, allocRef, out_ptr, [objectToWireRow(row)]);
|
|
699
705
|
}),
|
|
700
|
-
db_all: new
|
|
706
|
+
db_all: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
701
707
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
702
708
|
if (!stmt) return -1;
|
|
703
709
|
const result = await stmt.all();
|
|
@@ -708,7 +714,7 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
708
714
|
}
|
|
709
715
|
return writeJsonOut(getMemory, allocRef, out_ptr, rows);
|
|
710
716
|
}),
|
|
711
|
-
db_values: new
|
|
717
|
+
db_values: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
712
718
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
713
719
|
if (!stmt) return -1;
|
|
714
720
|
const rows = await stmt.raw();
|
|
@@ -730,8 +736,7 @@ var ProcExit = class extends Error {
|
|
|
730
736
|
};
|
|
731
737
|
function createWasiImports({
|
|
732
738
|
request,
|
|
733
|
-
stdinData
|
|
734
|
-
onStdout
|
|
739
|
+
stdinData
|
|
735
740
|
}) {
|
|
736
741
|
const encoder3 = new TextEncoder();
|
|
737
742
|
const url = new URL(request.url);
|
|
@@ -755,8 +760,6 @@ function createWasiImports({
|
|
|
755
760
|
const setMemory = (m2) => {
|
|
756
761
|
wasmMemory = m2;
|
|
757
762
|
};
|
|
758
|
-
const stdoutChunks = [];
|
|
759
|
-
let stderrMeta = "";
|
|
760
763
|
let stderrPartial = "";
|
|
761
764
|
const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
762
765
|
function processStderrChunk(chunk) {
|
|
@@ -764,9 +767,7 @@ function createWasiImports({
|
|
|
764
767
|
const lines = (stderrPartial + text).split("\n");
|
|
765
768
|
stderrPartial = lines.pop() ?? "";
|
|
766
769
|
for (const line of lines) {
|
|
767
|
-
if (line.
|
|
768
|
-
stderrMeta += line + "\n";
|
|
769
|
-
} else if (line.length > 0) {
|
|
770
|
+
if (line.length > 0) {
|
|
770
771
|
console.error("[ziex]", line);
|
|
771
772
|
}
|
|
772
773
|
}
|
|
@@ -812,10 +813,7 @@ function createWasiImports({
|
|
|
812
813
|
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
813
814
|
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
814
815
|
const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
|
|
815
|
-
if (fd ===
|
|
816
|
-
if (onStdout) onStdout(chunk);
|
|
817
|
-
else stdoutChunks.push(chunk);
|
|
818
|
-
} else if (fd === 2) processStderrChunk(chunk);
|
|
816
|
+
if (fd === 2) processStderrChunk(chunk);
|
|
819
817
|
written += buf_len;
|
|
820
818
|
}
|
|
821
819
|
dv.setUint32(nwritten_ptr, written, true);
|
|
@@ -983,26 +981,12 @@ function createWasiImports({
|
|
|
983
981
|
v().setUint32(bufused_ptr, 0, true);
|
|
984
982
|
return 76;
|
|
985
983
|
},
|
|
986
|
-
// Stub for poll_oneoff - no blocking I/O in edge runtimes.
|
|
987
984
|
poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
|
|
988
985
|
v().setUint32(nevents_ptr, 0, true);
|
|
989
986
|
return 0;
|
|
990
987
|
}
|
|
991
988
|
};
|
|
992
|
-
|
|
993
|
-
const remaining = stderrDecoder.decode(void 0, { stream: false });
|
|
994
|
-
const tail = stderrPartial + remaining;
|
|
995
|
-
if (tail.length > 0) {
|
|
996
|
-
if (tail.startsWith("__ZIEX_META__:")) stderrMeta += tail;
|
|
997
|
-
else console.error("[ziex]", tail);
|
|
998
|
-
stderrPartial = "";
|
|
999
|
-
}
|
|
1000
|
-
return {
|
|
1001
|
-
stdout: mergeUint8Arrays(stdoutChunks),
|
|
1002
|
-
stderrText: stderrMeta
|
|
1003
|
-
};
|
|
1004
|
-
}
|
|
1005
|
-
return { wasiImport, setMemory, collectOutput };
|
|
989
|
+
return { wasiImport, setMemory };
|
|
1006
990
|
}
|
|
1007
991
|
function mergeUint8Arrays(arrays) {
|
|
1008
992
|
const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
@@ -1016,50 +1000,78 @@ function mergeUint8Arrays(arrays) {
|
|
|
1016
1000
|
}
|
|
1017
1001
|
|
|
1018
1002
|
// src/runtime/kv/memory.ts
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1003
|
+
var store = /* @__PURE__ */ new Map();
|
|
1004
|
+
async function get2(key) {
|
|
1005
|
+
const entry = store.get(key);
|
|
1006
|
+
if (!entry) return null;
|
|
1007
|
+
const expiresAt = entry[1];
|
|
1008
|
+
if (expiresAt !== void 0 && Date.now() >= expiresAt) {
|
|
1009
|
+
store.delete(key);
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
return entry[0];
|
|
1013
|
+
}
|
|
1014
|
+
async function put2(key, value, options) {
|
|
1015
|
+
let expiresAt;
|
|
1016
|
+
if (options?.expiration !== void 0) {
|
|
1017
|
+
expiresAt = options.expiration * 1e3;
|
|
1018
|
+
} else if (options?.expirationTtl !== void 0) {
|
|
1019
|
+
expiresAt = Date.now() + options.expirationTtl * 1e3;
|
|
1020
|
+
}
|
|
1021
|
+
store.set(key, [value, expiresAt]);
|
|
1022
|
+
}
|
|
1023
|
+
async function del2(key) {
|
|
1024
|
+
store.delete(key);
|
|
1025
|
+
}
|
|
1026
|
+
async function list2(options) {
|
|
1027
|
+
const keys = [];
|
|
1028
|
+
for (const name of [...store.keys()]) {
|
|
1029
|
+
if (options?.prefix && !name.startsWith(options.prefix)) continue;
|
|
1030
|
+
if (await get2(name) !== null) keys.push({ name });
|
|
1039
1031
|
}
|
|
1032
|
+
return { keys };
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// src/runtime/index.ts
|
|
1036
|
+
function buildHttpImports(mem, http) {
|
|
1037
|
+
const decoder3 = new TextDecoder();
|
|
1040
1038
|
return {
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1039
|
+
commit: (status, meta_ptr, meta_len) => {
|
|
1040
|
+
http.status = status >>> 0;
|
|
1041
|
+
http.committed = true;
|
|
1042
|
+
http.headers = new Headers();
|
|
1043
|
+
http.streaming = false;
|
|
1044
|
+
if (meta_len > 0) {
|
|
1045
|
+
try {
|
|
1046
|
+
const raw = decoder3.decode(new Uint8Array(mem().buffer, meta_ptr >>> 0, meta_len >>> 0));
|
|
1047
|
+
const parsed = JSON.parse(raw);
|
|
1048
|
+
if (parsed.streaming === true) http.streaming = true;
|
|
1049
|
+
if (Array.isArray(parsed.headers)) {
|
|
1050
|
+
for (const [name, value] of parsed.headers) {
|
|
1051
|
+
http.headers.append(name, value);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
} catch {
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1046
1057
|
},
|
|
1047
|
-
|
|
1048
|
-
|
|
1058
|
+
write: (ptr, len) => {
|
|
1059
|
+
if (len <= 0) return;
|
|
1060
|
+
const chunk = new Uint8Array(mem().buffer, ptr >>> 0, len >>> 0).slice();
|
|
1061
|
+
if (http.streamWriter) void http.streamWriter.write(chunk);
|
|
1062
|
+
else http.bodyChunks.push(chunk);
|
|
1049
1063
|
},
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1064
|
+
end: () => {
|
|
1065
|
+
http.ended = true;
|
|
1066
|
+
if (http.streamWriter) {
|
|
1067
|
+
void http.streamWriter.close();
|
|
1068
|
+
http.streamWriter = null;
|
|
1069
|
+
}
|
|
1056
1070
|
}
|
|
1057
1071
|
};
|
|
1058
1072
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
1062
|
-
const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
1073
|
+
function buildWsImports(Suspending2, mem, decoder3, ws) {
|
|
1074
|
+
const readStr2 = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
1063
1075
|
return {
|
|
1064
1076
|
ws_upgrade: () => {
|
|
1065
1077
|
ws.upgraded = true;
|
|
@@ -1075,7 +1087,7 @@ function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
|
1075
1087
|
ws_close: (code, reason_ptr, reason_len) => {
|
|
1076
1088
|
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
1077
1089
|
},
|
|
1078
|
-
ws_recv:
|
|
1090
|
+
ws_recv: Suspending2 ? new Suspending2(async (buf_ptr, buf_max) => {
|
|
1079
1091
|
if (ws._resolveFirstSuspend) {
|
|
1080
1092
|
const fn = ws._resolveFirstSuspend;
|
|
1081
1093
|
ws._resolveFirstSuspend = void 0;
|
|
@@ -1088,23 +1100,23 @@ function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
|
1088
1100
|
return n;
|
|
1089
1101
|
};
|
|
1090
1102
|
if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
|
|
1091
|
-
return new Promise((
|
|
1092
|
-
ws.recvResolve = (bytes) =>
|
|
1103
|
+
return new Promise((resolve2) => {
|
|
1104
|
+
ws.recvResolve = (bytes) => resolve2(deliver(bytes));
|
|
1093
1105
|
});
|
|
1094
1106
|
}) : (_buf_ptr, _buf_max) => -1,
|
|
1095
1107
|
// Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
|
|
1096
1108
|
ws_subscribe: (ptr, len) => {
|
|
1097
|
-
ws.subscribe?.(
|
|
1109
|
+
ws.subscribe?.(readStr2(ptr, len));
|
|
1098
1110
|
},
|
|
1099
1111
|
ws_unsubscribe: (ptr, len) => {
|
|
1100
|
-
ws.unsubscribe?.(
|
|
1112
|
+
ws.unsubscribe?.(readStr2(ptr, len));
|
|
1101
1113
|
},
|
|
1102
1114
|
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
1103
|
-
const topic =
|
|
1115
|
+
const topic = readStr2(topic_ptr, topic_len);
|
|
1104
1116
|
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
1105
1117
|
return ws.publish?.(topic, data) ?? 0;
|
|
1106
1118
|
},
|
|
1107
|
-
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(
|
|
1119
|
+
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr2(ptr, len)) ? 1 : 0
|
|
1108
1120
|
};
|
|
1109
1121
|
}
|
|
1110
1122
|
function attachWebSocket(ws) {
|
|
@@ -1135,14 +1147,14 @@ function attachWebSocket(ws) {
|
|
|
1135
1147
|
});
|
|
1136
1148
|
return { client };
|
|
1137
1149
|
}
|
|
1138
|
-
function buildSysImports(
|
|
1150
|
+
function buildSysImports(jspi2, Suspending2) {
|
|
1139
1151
|
return {
|
|
1140
|
-
sleep_ms:
|
|
1152
|
+
sleep_ms: jspi2 ? new Suspending2(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
|
|
1141
1153
|
}
|
|
1142
1154
|
};
|
|
1143
1155
|
}
|
|
1144
|
-
function executeWasm(instance,
|
|
1145
|
-
if (!
|
|
1156
|
+
function executeWasm(instance, jspi2, Suspending2, wsState) {
|
|
1157
|
+
if (!jspi2) {
|
|
1146
1158
|
try {
|
|
1147
1159
|
instance.exports._start();
|
|
1148
1160
|
} catch (e) {
|
|
@@ -1162,25 +1174,6 @@ function executeWasm(instance, jspi, Suspending, wsState) {
|
|
|
1162
1174
|
}
|
|
1163
1175
|
});
|
|
1164
1176
|
}
|
|
1165
|
-
function parseZiexMeta(stderrText) {
|
|
1166
|
-
const meta = { status: 200, headers: new Headers(), streaming: false };
|
|
1167
|
-
const metaPrefix = "__ZIEX_META__:";
|
|
1168
|
-
const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
|
|
1169
|
-
if (metaLine) {
|
|
1170
|
-
try {
|
|
1171
|
-
const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
|
|
1172
|
-
if (parsed.status) meta.status = parsed.status;
|
|
1173
|
-
if (parsed.streaming === true) meta.streaming = true;
|
|
1174
|
-
if (Array.isArray(parsed.headers)) {
|
|
1175
|
-
for (const [name, value] of parsed.headers) {
|
|
1176
|
-
meta.headers.append(name, value);
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
} catch {
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
return meta;
|
|
1183
|
-
}
|
|
1184
1177
|
async function run({
|
|
1185
1178
|
request,
|
|
1186
1179
|
env,
|
|
@@ -1190,29 +1183,32 @@ async function run({
|
|
|
1190
1183
|
db: dbBindings,
|
|
1191
1184
|
imports,
|
|
1192
1185
|
wasi,
|
|
1193
|
-
|
|
1186
|
+
sticky
|
|
1194
1187
|
}) {
|
|
1195
|
-
if (
|
|
1196
|
-
const id =
|
|
1197
|
-
return
|
|
1188
|
+
if (sticky && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
1189
|
+
const id = sticky.idFromName(new URL(request.url).pathname);
|
|
1190
|
+
return sticky.get(id).fetch(request);
|
|
1198
1191
|
}
|
|
1199
1192
|
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
|
|
1200
|
-
const
|
|
1201
|
-
|
|
1202
|
-
|
|
1193
|
+
const httpState = {
|
|
1194
|
+
committed: false,
|
|
1195
|
+
ended: false,
|
|
1196
|
+
status: 200,
|
|
1197
|
+
streaming: false,
|
|
1198
|
+
headers: new Headers(),
|
|
1199
|
+
bodyChunks: [],
|
|
1200
|
+
streamWriter: null
|
|
1201
|
+
};
|
|
1202
|
+
const { wasiImport, setMemory } = createWasiImports({
|
|
1203
1203
|
request,
|
|
1204
|
-
stdinData
|
|
1205
|
-
onStdout: (chunk) => {
|
|
1206
|
-
if (streamWriter) void streamWriter.write(chunk);
|
|
1207
|
-
else stdoutChunks.push(chunk);
|
|
1208
|
-
}
|
|
1204
|
+
stdinData
|
|
1209
1205
|
});
|
|
1210
1206
|
let wasmMemory = null;
|
|
1211
1207
|
const mem = () => wasmMemory;
|
|
1212
1208
|
const bridgeRef = [null];
|
|
1213
1209
|
const allocRef = [null];
|
|
1214
|
-
const
|
|
1215
|
-
const
|
|
1210
|
+
const Suspending2 = WebAssembly.Suspending;
|
|
1211
|
+
const jspi2 = typeof Suspending2 === "function";
|
|
1216
1212
|
const wsState = {
|
|
1217
1213
|
upgraded: false,
|
|
1218
1214
|
server: null,
|
|
@@ -1222,15 +1218,16 @@ async function run({
|
|
|
1222
1218
|
};
|
|
1223
1219
|
const importObject = {
|
|
1224
1220
|
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
1225
|
-
__zx_sys: buildSysImports(
|
|
1226
|
-
__zx_ws: buildWsImports(
|
|
1221
|
+
__zx_sys: buildSysImports(jspi2, Suspending2),
|
|
1222
|
+
__zx_ws: buildWsImports(jspi2 ? Suspending2 : null, mem, new TextDecoder(), wsState),
|
|
1223
|
+
__zx_http: buildHttpImports(mem, httpState),
|
|
1227
1224
|
__zx_net: createFetchImports(mem),
|
|
1228
1225
|
...imports ? imports(mem) : {},
|
|
1229
1226
|
...ZxWasiBridge.createImportObject(bridgeRef)
|
|
1230
1227
|
};
|
|
1231
1228
|
if (true) {
|
|
1232
1229
|
importObject.__zx_kv = createKVImports(
|
|
1233
|
-
kvBindings ?? { default:
|
|
1230
|
+
kvBindings ?? { default: { get: get2, put: put2, del: del2, list: list2 } },
|
|
1234
1231
|
mem,
|
|
1235
1232
|
allocRef
|
|
1236
1233
|
);
|
|
@@ -1247,34 +1244,37 @@ async function run({
|
|
|
1247
1244
|
setMemory(wasmMemory);
|
|
1248
1245
|
bridgeRef[0] = new ZxWasiBridge(instance.exports);
|
|
1249
1246
|
bindWasmAlloc(allocRef, instance.exports);
|
|
1250
|
-
const wasmPromise = executeWasm(instance,
|
|
1247
|
+
const wasmPromise = executeWasm(instance, jspi2, Suspending2, wsState);
|
|
1251
1248
|
if (wsState.upgraded) {
|
|
1252
1249
|
const server = attachWebSocket(wsState);
|
|
1253
1250
|
ctx?.waitUntil(wasmPromise);
|
|
1254
1251
|
return new Response(null, { status: 101, webSocket: server.client });
|
|
1255
1252
|
}
|
|
1256
|
-
|
|
1257
|
-
const earlyMeta = parseZiexMeta(earlyStderrText);
|
|
1258
|
-
if (earlyMeta.streaming) {
|
|
1253
|
+
if (httpState.committed && httpState.streaming) {
|
|
1259
1254
|
const { readable, writable } = new TransformStream();
|
|
1260
|
-
streamWriter = writable.getWriter();
|
|
1261
|
-
for (const chunk of
|
|
1262
|
-
|
|
1263
|
-
void wasmPromise.finally(() =>
|
|
1264
|
-
|
|
1255
|
+
httpState.streamWriter = writable.getWriter();
|
|
1256
|
+
for (const chunk of httpState.bodyChunks) void httpState.streamWriter.write(chunk);
|
|
1257
|
+
httpState.bodyChunks.length = 0;
|
|
1258
|
+
void wasmPromise.finally(() => {
|
|
1259
|
+
if (httpState.streamWriter) {
|
|
1260
|
+
void httpState.streamWriter.close();
|
|
1261
|
+
httpState.streamWriter = null;
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
return new Response(readable, { status: httpState.status, headers: httpState.headers });
|
|
1265
1265
|
}
|
|
1266
1266
|
await wasmPromise;
|
|
1267
|
-
const
|
|
1268
|
-
const
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
|
|
1267
|
+
const status = httpState.status;
|
|
1268
|
+
const headers = httpState.headers;
|
|
1269
|
+
headers.delete("transfer-encoding");
|
|
1270
|
+
const nullBody = status === 101 || status === 204 || status === 205 || status === 304;
|
|
1272
1271
|
if (nullBody) {
|
|
1273
|
-
|
|
1274
|
-
return new Response(null, { status
|
|
1272
|
+
headers.delete("content-length");
|
|
1273
|
+
return new Response(null, { status, headers });
|
|
1275
1274
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1275
|
+
const body = mergeUint8Arrays(httpState.bodyChunks);
|
|
1276
|
+
if (!headers.has("content-length")) headers.set("content-length", String(body.byteLength));
|
|
1277
|
+
return new Response(body.buffer, { status, headers });
|
|
1278
1278
|
}
|
|
1279
1279
|
|
|
1280
1280
|
// src/app.ts
|
|
@@ -1311,7 +1311,7 @@ var Ziex = class {
|
|
|
1311
1311
|
*/
|
|
1312
1312
|
this.fetch = async (request, env, ctx) => {
|
|
1313
1313
|
const module = await this.getModule();
|
|
1314
|
-
const { wasi, imports,
|
|
1314
|
+
const { wasi, imports, sticky } = this.options;
|
|
1315
1315
|
return run({
|
|
1316
1316
|
request,
|
|
1317
1317
|
env,
|
|
@@ -1321,7 +1321,7 @@ var Ziex = class {
|
|
|
1321
1321
|
imports,
|
|
1322
1322
|
kv: this.resolveKV(env),
|
|
1323
1323
|
db: this.resolveDB(env),
|
|
1324
|
-
|
|
1324
|
+
sticky: sticky !== void 0 ? env[sticky] : void 0
|
|
1325
1325
|
});
|
|
1326
1326
|
};
|
|
1327
1327
|
this.options = options;
|
|
@@ -1330,6 +1330,27 @@ var Ziex = class {
|
|
|
1330
1330
|
if (!this.resolved) this.resolved = await resolveModule(this.options.module);
|
|
1331
1331
|
return this.resolved;
|
|
1332
1332
|
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Enable sticky upgrade forwarding and return host config for platform adapters
|
|
1335
|
+
* (e.g. Cloudflare {@linkcode stateful}).
|
|
1336
|
+
*
|
|
1337
|
+
* Requires `options.module` to already be a compiled `WebAssembly.Module`.
|
|
1338
|
+
*/
|
|
1339
|
+
stickyHost(binding) {
|
|
1340
|
+
this.options.sticky = binding;
|
|
1341
|
+
const mod = this.options.module;
|
|
1342
|
+
if (mod instanceof ArrayBuffer || ArrayBuffer.isView(mod) || mod instanceof Response || mod instanceof URL || typeof mod === "string") {
|
|
1343
|
+
throw new Error(
|
|
1344
|
+
'sticky handlers require a compiled WebAssembly.Module (e.g. `import module from "./app.wasm"` under wrangler)'
|
|
1345
|
+
);
|
|
1346
|
+
}
|
|
1347
|
+
return {
|
|
1348
|
+
module: mod,
|
|
1349
|
+
imports: this.options.imports,
|
|
1350
|
+
kv: (env) => this.resolveKV(env),
|
|
1351
|
+
db: (env) => this.resolveDB(env)
|
|
1352
|
+
};
|
|
1353
|
+
}
|
|
1333
1354
|
resolveKV(env) {
|
|
1334
1355
|
const { kv } = this.options;
|
|
1335
1356
|
if (kv === void 0) return void 0;
|