ziex 0.1.0-dev.1458 → 0.1.0-dev.1567
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 +252 -223
- 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 +1801 -1670
- 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 +17 -18
- package/runtime/kv.js +178 -240
- package/runtime/wasi.d.ts +2 -7
- package/wasm/constants.d.ts +33 -0
- package/wasm/core.d.ts +7 -19
- package/wasm/dom_cmd.d.ts +6 -0
- package/wasm/generated/event_bits.d.ts +2 -0
- package/wasm/generated/events.d.ts +1 -0
- package/wasm/generated/tag_indices.d.ts +2 -0
- package/wasm/generated/tags.d.ts +1 -0
- package/wasm/index.d.ts +3 -2
- package/wasm/index.js +635 -555
- package/wasm/init.dev.js +650 -562
- package/wasm/init.js +3 -3
- package/platforms/cloudflare/do.d.ts +0 -50
package/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
// src/wasm/constants.ts
|
|
2
|
+
var CallbackType_FetchSuccess = 1;
|
|
3
|
+
var CallbackType_FetchError = 2;
|
|
4
|
+
var CallbackType_Timeout = 3;
|
|
5
|
+
var CallbackType_Interval = 4;
|
|
6
|
+
|
|
1
7
|
// src/wasm/wasi.ts
|
|
2
8
|
var decoder = new TextDecoder();
|
|
3
9
|
var encoder = new TextEncoder();
|
|
4
10
|
var ZxWasiBridge = class {
|
|
5
11
|
#alloc;
|
|
6
|
-
#fetchCompleteHandler;
|
|
7
12
|
#memory;
|
|
8
13
|
#cb;
|
|
9
14
|
#intervals = /* @__PURE__ */ new Map();
|
|
@@ -13,7 +18,6 @@ var ZxWasiBridge = class {
|
|
|
13
18
|
constructor(exports) {
|
|
14
19
|
this.#memory = exports.memory;
|
|
15
20
|
this.#alloc = exports.__zx_alloc;
|
|
16
|
-
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
17
21
|
this.#cb = exports.__zx_cb;
|
|
18
22
|
}
|
|
19
23
|
#view() {
|
|
@@ -38,6 +42,9 @@ var ZxWasiBridge = class {
|
|
|
38
42
|
if (start + data.length > view.byteLength) return;
|
|
39
43
|
view.set(data, start);
|
|
40
44
|
}
|
|
45
|
+
#invoke(type, id, a = 0n, b = 0n, c = 0n) {
|
|
46
|
+
this.#cb?.(type, id, a, b, c);
|
|
47
|
+
}
|
|
41
48
|
log(level, ptr, len) {
|
|
42
49
|
const msg = decoder.decode(this.#view().subarray(ptr, ptr + len));
|
|
43
50
|
switch (level) {
|
|
@@ -90,13 +97,14 @@ var ZxWasiBridge = class {
|
|
|
90
97
|
const encoded = typeof body === "string" ? encoder.encode(body) : body;
|
|
91
98
|
const ptr = this.#alloc(encoded.length);
|
|
92
99
|
this.#writeBytes(ptr, encoded);
|
|
93
|
-
|
|
100
|
+
const type = isError ? CallbackType_FetchError : CallbackType_FetchSuccess;
|
|
101
|
+
this.#invoke(type, fetchId, BigInt(status), BigInt(ptr), BigInt(encoded.length));
|
|
94
102
|
}
|
|
95
103
|
setTimeout(callbackId, delayMs) {
|
|
96
|
-
setTimeout(() => this.#
|
|
104
|
+
setTimeout(() => this.#invoke(CallbackType_Timeout, callbackId), delayMs);
|
|
97
105
|
}
|
|
98
106
|
setInterval(callbackId, intervalMs) {
|
|
99
|
-
const handle = setInterval(() => this.#
|
|
107
|
+
const handle = setInterval(() => this.#invoke(CallbackType_Interval, callbackId), intervalMs);
|
|
100
108
|
this.#intervals.set(callbackId, handle);
|
|
101
109
|
}
|
|
102
110
|
clearInterval(callbackId) {
|
|
@@ -150,7 +158,7 @@ var ZxWasiBridge = class {
|
|
|
150
158
|
function createFetchImports(getMemory) {
|
|
151
159
|
const encoder3 = new TextEncoder();
|
|
152
160
|
const decoder3 = new TextDecoder();
|
|
153
|
-
function
|
|
161
|
+
function readStr2(ptr, len) {
|
|
154
162
|
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
155
163
|
}
|
|
156
164
|
function writeBytes(buf_ptr, buf_max, data) {
|
|
@@ -176,9 +184,9 @@ function createFetchImports(getMemory) {
|
|
|
176
184
|
return headers;
|
|
177
185
|
}
|
|
178
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) {
|
|
179
|
-
const url =
|
|
180
|
-
const method = method_len > 0 ?
|
|
181
|
-
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) : "{}";
|
|
182
190
|
const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
|
|
183
191
|
const headers = parseHeaders(headersJson);
|
|
184
192
|
const controller = new AbortController();
|
|
@@ -201,14 +209,14 @@ function createFetchImports(getMemory) {
|
|
|
201
209
|
return -1;
|
|
202
210
|
}
|
|
203
211
|
}
|
|
204
|
-
const
|
|
205
|
-
if (typeof
|
|
212
|
+
const Suspending2 = WebAssembly.Suspending;
|
|
213
|
+
if (typeof Suspending2 !== "function") {
|
|
206
214
|
return {
|
|
207
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
|
|
208
216
|
};
|
|
209
217
|
}
|
|
210
218
|
return {
|
|
211
|
-
fetch: new
|
|
219
|
+
fetch: new Suspending2(doFetch)
|
|
212
220
|
};
|
|
213
221
|
}
|
|
214
222
|
|
|
@@ -490,90 +498,96 @@ function bindWasmAlloc(allocRef, exports) {
|
|
|
490
498
|
}
|
|
491
499
|
|
|
492
500
|
// src/runtime/kv/extern.ts
|
|
501
|
+
var Suspending = WebAssembly.Suspending;
|
|
502
|
+
var jspi = typeof Suspending === "function";
|
|
503
|
+
var miss = jspi ? -1 : 0;
|
|
493
504
|
function putOptions(ttlSeconds) {
|
|
494
505
|
if (ttlSeconds < 60) return void 0;
|
|
495
506
|
return { expirationTtl: ttlSeconds };
|
|
496
507
|
}
|
|
508
|
+
function kvDel(binding, key) {
|
|
509
|
+
const b = binding;
|
|
510
|
+
return (b.del ?? b.delete).call(b, key);
|
|
511
|
+
}
|
|
497
512
|
function isSyncKVNamespace(binding) {
|
|
498
|
-
|
|
499
|
-
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";
|
|
500
514
|
}
|
|
501
|
-
function
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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;
|
|
509
537
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
b.deleteSync(readStr(key_ptr, key_len));
|
|
535
|
-
return 0;
|
|
536
|
-
},
|
|
537
|
-
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
|
|
538
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
539
|
-
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
540
|
-
const prefix = readStr(pfx_ptr, pfx_len);
|
|
541
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
542
|
-
return writeJsonOut(getMemory, allocRef, out_ptr, result.keys.map((k) => k.name));
|
|
543
|
-
}
|
|
544
|
-
};
|
|
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
|
+
});
|
|
545
562
|
}
|
|
563
|
+
return new Suspending(impl);
|
|
564
|
+
}
|
|
565
|
+
function createKVImports(bindings, getMemory, allocRef) {
|
|
546
566
|
return {
|
|
547
|
-
kv_get:
|
|
548
|
-
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));
|
|
549
569
|
if (!b) return -1;
|
|
550
|
-
|
|
551
|
-
if (value === null) return -1;
|
|
552
|
-
return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
|
|
570
|
+
return get(b, readStr(getMemory, key_ptr, key_len), out_ptr, getMemory, allocRef);
|
|
553
571
|
}),
|
|
554
|
-
kv_put:
|
|
555
|
-
const b =
|
|
556
|
-
if (!b) return
|
|
557
|
-
|
|
558
|
-
|
|
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
|
+
);
|
|
559
581
|
}),
|
|
560
|
-
kv_delete:
|
|
561
|
-
const b =
|
|
562
|
-
if (!b) return
|
|
563
|
-
|
|
564
|
-
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));
|
|
565
586
|
}),
|
|
566
|
-
kv_list:
|
|
567
|
-
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));
|
|
568
589
|
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
569
|
-
|
|
570
|
-
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
571
|
-
const names = result.keys.map((k) => k.name);
|
|
572
|
-
if (names.length === 0) {
|
|
573
|
-
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
574
|
-
return 0;
|
|
575
|
-
}
|
|
576
|
-
return writeJsonOut(getMemory, allocRef, out_ptr, names);
|
|
590
|
+
return list(b, readStr(getMemory, pfx_ptr, pfx_len), out_ptr, getMemory, allocRef);
|
|
577
591
|
})
|
|
578
592
|
};
|
|
579
593
|
}
|
|
@@ -645,21 +659,21 @@ function valuesToWireRows(rows) {
|
|
|
645
659
|
}
|
|
646
660
|
function createDbImports(bindings, getMemory, allocRef) {
|
|
647
661
|
const decoder3 = new TextDecoder();
|
|
648
|
-
function
|
|
662
|
+
function readStr2(ptr, len) {
|
|
649
663
|
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
650
664
|
}
|
|
651
665
|
function binding(ns) {
|
|
652
666
|
return bindings[ns] ?? bindings["default"] ?? null;
|
|
653
667
|
}
|
|
654
668
|
async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
|
|
655
|
-
const database = binding(
|
|
669
|
+
const database = binding(readStr2(ns_ptr, ns_len));
|
|
656
670
|
if (!database) return null;
|
|
657
|
-
const sql =
|
|
658
|
-
const bindingsJson = JSON.parse(
|
|
671
|
+
const sql = readStr2(sql_ptr, sql_len);
|
|
672
|
+
const bindingsJson = JSON.parse(readStr2(bindings_ptr, bindings_len));
|
|
659
673
|
return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
|
|
660
674
|
}
|
|
661
|
-
const
|
|
662
|
-
if (typeof
|
|
675
|
+
const Suspending2 = WebAssembly.Suspending;
|
|
676
|
+
if (typeof Suspending2 !== "function") {
|
|
663
677
|
return {
|
|
664
678
|
db_open: (_ns, _ns_len) => -1,
|
|
665
679
|
db_run: (_a, _b, _c, _d, _e, _f, _g) => -1,
|
|
@@ -669,8 +683,8 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
669
683
|
};
|
|
670
684
|
}
|
|
671
685
|
return {
|
|
672
|
-
db_open: (ns_ptr, ns_len) => binding(
|
|
673
|
-
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) => {
|
|
674
688
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
675
689
|
if (!stmt) return -1;
|
|
676
690
|
const result = await stmt.run();
|
|
@@ -679,7 +693,7 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
679
693
|
changes: result.meta?.changes ?? 0
|
|
680
694
|
});
|
|
681
695
|
}),
|
|
682
|
-
db_get: new
|
|
696
|
+
db_get: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
683
697
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
684
698
|
if (!stmt) return -1;
|
|
685
699
|
const row = await stmt.first();
|
|
@@ -689,7 +703,7 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
689
703
|
}
|
|
690
704
|
return writeJsonOut(getMemory, allocRef, out_ptr, [objectToWireRow(row)]);
|
|
691
705
|
}),
|
|
692
|
-
db_all: new
|
|
706
|
+
db_all: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
693
707
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
694
708
|
if (!stmt) return -1;
|
|
695
709
|
const result = await stmt.all();
|
|
@@ -700,7 +714,7 @@ function createDbImports(bindings, getMemory, allocRef) {
|
|
|
700
714
|
}
|
|
701
715
|
return writeJsonOut(getMemory, allocRef, out_ptr, rows);
|
|
702
716
|
}),
|
|
703
|
-
db_values: new
|
|
717
|
+
db_values: new Suspending2(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
704
718
|
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
705
719
|
if (!stmt) return -1;
|
|
706
720
|
const rows = await stmt.raw();
|
|
@@ -722,8 +736,7 @@ var ProcExit = class extends Error {
|
|
|
722
736
|
};
|
|
723
737
|
function createWasiImports({
|
|
724
738
|
request,
|
|
725
|
-
stdinData
|
|
726
|
-
onStdout
|
|
739
|
+
stdinData
|
|
727
740
|
}) {
|
|
728
741
|
const encoder3 = new TextEncoder();
|
|
729
742
|
const url = new URL(request.url);
|
|
@@ -747,8 +760,6 @@ function createWasiImports({
|
|
|
747
760
|
const setMemory = (m2) => {
|
|
748
761
|
wasmMemory = m2;
|
|
749
762
|
};
|
|
750
|
-
const stdoutChunks = [];
|
|
751
|
-
let stderrMeta = "";
|
|
752
763
|
let stderrPartial = "";
|
|
753
764
|
const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
754
765
|
function processStderrChunk(chunk) {
|
|
@@ -756,9 +767,7 @@ function createWasiImports({
|
|
|
756
767
|
const lines = (stderrPartial + text).split("\n");
|
|
757
768
|
stderrPartial = lines.pop() ?? "";
|
|
758
769
|
for (const line of lines) {
|
|
759
|
-
if (line.
|
|
760
|
-
stderrMeta += line + "\n";
|
|
761
|
-
} else if (line.length > 0) {
|
|
770
|
+
if (line.length > 0) {
|
|
762
771
|
console.error("[ziex]", line);
|
|
763
772
|
}
|
|
764
773
|
}
|
|
@@ -804,10 +813,7 @@ function createWasiImports({
|
|
|
804
813
|
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
805
814
|
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
806
815
|
const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
|
|
807
|
-
if (fd ===
|
|
808
|
-
if (onStdout) onStdout(chunk);
|
|
809
|
-
else stdoutChunks.push(chunk);
|
|
810
|
-
} else if (fd === 2) processStderrChunk(chunk);
|
|
816
|
+
if (fd === 2) processStderrChunk(chunk);
|
|
811
817
|
written += buf_len;
|
|
812
818
|
}
|
|
813
819
|
dv.setUint32(nwritten_ptr, written, true);
|
|
@@ -975,26 +981,12 @@ function createWasiImports({
|
|
|
975
981
|
v().setUint32(bufused_ptr, 0, true);
|
|
976
982
|
return 76;
|
|
977
983
|
},
|
|
978
|
-
// Stub for poll_oneoff - no blocking I/O in edge runtimes.
|
|
979
984
|
poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
|
|
980
985
|
v().setUint32(nevents_ptr, 0, true);
|
|
981
986
|
return 0;
|
|
982
987
|
}
|
|
983
988
|
};
|
|
984
|
-
|
|
985
|
-
const remaining = stderrDecoder.decode(void 0, { stream: false });
|
|
986
|
-
const tail = stderrPartial + remaining;
|
|
987
|
-
if (tail.length > 0) {
|
|
988
|
-
if (tail.startsWith("__ZIEX_META__:")) stderrMeta += tail;
|
|
989
|
-
else console.error("[ziex]", tail);
|
|
990
|
-
stderrPartial = "";
|
|
991
|
-
}
|
|
992
|
-
return {
|
|
993
|
-
stdout: mergeUint8Arrays(stdoutChunks),
|
|
994
|
-
stderrText: stderrMeta
|
|
995
|
-
};
|
|
996
|
-
}
|
|
997
|
-
return { wasiImport, setMemory, collectOutput };
|
|
989
|
+
return { wasiImport, setMemory };
|
|
998
990
|
}
|
|
999
991
|
function mergeUint8Arrays(arrays) {
|
|
1000
992
|
const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
@@ -1008,50 +1000,78 @@ function mergeUint8Arrays(arrays) {
|
|
|
1008
1000
|
}
|
|
1009
1001
|
|
|
1010
1002
|
// src/runtime/kv/memory.ts
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
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 });
|
|
1031
1031
|
}
|
|
1032
|
+
return { keys };
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// src/runtime/index.ts
|
|
1036
|
+
function buildHttpImports(mem, http) {
|
|
1037
|
+
const decoder3 = new TextDecoder();
|
|
1032
1038
|
return {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
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
|
+
}
|
|
1038
1057
|
},
|
|
1039
|
-
|
|
1040
|
-
|
|
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);
|
|
1041
1063
|
},
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1064
|
+
end: () => {
|
|
1065
|
+
http.ended = true;
|
|
1066
|
+
if (http.streamWriter) {
|
|
1067
|
+
void http.streamWriter.close();
|
|
1068
|
+
http.streamWriter = null;
|
|
1069
|
+
}
|
|
1048
1070
|
}
|
|
1049
1071
|
};
|
|
1050
1072
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
1054
|
-
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));
|
|
1055
1075
|
return {
|
|
1056
1076
|
ws_upgrade: () => {
|
|
1057
1077
|
ws.upgraded = true;
|
|
@@ -1067,7 +1087,7 @@ function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
|
1067
1087
|
ws_close: (code, reason_ptr, reason_len) => {
|
|
1068
1088
|
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
1069
1089
|
},
|
|
1070
|
-
ws_recv:
|
|
1090
|
+
ws_recv: Suspending2 ? new Suspending2(async (buf_ptr, buf_max) => {
|
|
1071
1091
|
if (ws._resolveFirstSuspend) {
|
|
1072
1092
|
const fn = ws._resolveFirstSuspend;
|
|
1073
1093
|
ws._resolveFirstSuspend = void 0;
|
|
@@ -1080,23 +1100,23 @@ function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
|
1080
1100
|
return n;
|
|
1081
1101
|
};
|
|
1082
1102
|
if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
|
|
1083
|
-
return new Promise((
|
|
1084
|
-
ws.recvResolve = (bytes) =>
|
|
1103
|
+
return new Promise((resolve2) => {
|
|
1104
|
+
ws.recvResolve = (bytes) => resolve2(deliver(bytes));
|
|
1085
1105
|
});
|
|
1086
1106
|
}) : (_buf_ptr, _buf_max) => -1,
|
|
1087
1107
|
// Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
|
|
1088
1108
|
ws_subscribe: (ptr, len) => {
|
|
1089
|
-
ws.subscribe?.(
|
|
1109
|
+
ws.subscribe?.(readStr2(ptr, len));
|
|
1090
1110
|
},
|
|
1091
1111
|
ws_unsubscribe: (ptr, len) => {
|
|
1092
|
-
ws.unsubscribe?.(
|
|
1112
|
+
ws.unsubscribe?.(readStr2(ptr, len));
|
|
1093
1113
|
},
|
|
1094
1114
|
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
1095
|
-
const topic =
|
|
1115
|
+
const topic = readStr2(topic_ptr, topic_len);
|
|
1096
1116
|
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
1097
1117
|
return ws.publish?.(topic, data) ?? 0;
|
|
1098
1118
|
},
|
|
1099
|
-
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(
|
|
1119
|
+
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr2(ptr, len)) ? 1 : 0
|
|
1100
1120
|
};
|
|
1101
1121
|
}
|
|
1102
1122
|
function attachWebSocket(ws) {
|
|
@@ -1127,14 +1147,14 @@ function attachWebSocket(ws) {
|
|
|
1127
1147
|
});
|
|
1128
1148
|
return { client };
|
|
1129
1149
|
}
|
|
1130
|
-
function buildSysImports(
|
|
1150
|
+
function buildSysImports(jspi2, Suspending2) {
|
|
1131
1151
|
return {
|
|
1132
|
-
sleep_ms:
|
|
1152
|
+
sleep_ms: jspi2 ? new Suspending2(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
|
|
1133
1153
|
}
|
|
1134
1154
|
};
|
|
1135
1155
|
}
|
|
1136
|
-
function executeWasm(instance,
|
|
1137
|
-
if (!
|
|
1156
|
+
function executeWasm(instance, jspi2, Suspending2, wsState) {
|
|
1157
|
+
if (!jspi2) {
|
|
1138
1158
|
try {
|
|
1139
1159
|
instance.exports._start();
|
|
1140
1160
|
} catch (e) {
|
|
@@ -1154,25 +1174,6 @@ function executeWasm(instance, jspi, Suspending, wsState) {
|
|
|
1154
1174
|
}
|
|
1155
1175
|
});
|
|
1156
1176
|
}
|
|
1157
|
-
function parseZiexMeta(stderrText) {
|
|
1158
|
-
const meta = { status: 200, headers: new Headers(), streaming: false };
|
|
1159
|
-
const metaPrefix = "__ZIEX_META__:";
|
|
1160
|
-
const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
|
|
1161
|
-
if (metaLine) {
|
|
1162
|
-
try {
|
|
1163
|
-
const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
|
|
1164
|
-
if (parsed.status) meta.status = parsed.status;
|
|
1165
|
-
if (parsed.streaming === true) meta.streaming = true;
|
|
1166
|
-
if (Array.isArray(parsed.headers)) {
|
|
1167
|
-
for (const [name, value] of parsed.headers) {
|
|
1168
|
-
meta.headers.append(name, value);
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
} catch {
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
return meta;
|
|
1175
|
-
}
|
|
1176
1177
|
async function run({
|
|
1177
1178
|
request,
|
|
1178
1179
|
env,
|
|
@@ -1182,29 +1183,32 @@ async function run({
|
|
|
1182
1183
|
db: dbBindings,
|
|
1183
1184
|
imports,
|
|
1184
1185
|
wasi,
|
|
1185
|
-
|
|
1186
|
+
sticky
|
|
1186
1187
|
}) {
|
|
1187
|
-
if (
|
|
1188
|
-
const id =
|
|
1189
|
-
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);
|
|
1190
1191
|
}
|
|
1191
1192
|
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
|
|
1192
|
-
const
|
|
1193
|
-
|
|
1194
|
-
|
|
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({
|
|
1195
1203
|
request,
|
|
1196
|
-
stdinData
|
|
1197
|
-
onStdout: (chunk) => {
|
|
1198
|
-
if (streamWriter) void streamWriter.write(chunk);
|
|
1199
|
-
else stdoutChunks.push(chunk);
|
|
1200
|
-
}
|
|
1204
|
+
stdinData
|
|
1201
1205
|
});
|
|
1202
1206
|
let wasmMemory = null;
|
|
1203
1207
|
const mem = () => wasmMemory;
|
|
1204
1208
|
const bridgeRef = [null];
|
|
1205
1209
|
const allocRef = [null];
|
|
1206
|
-
const
|
|
1207
|
-
const
|
|
1210
|
+
const Suspending2 = WebAssembly.Suspending;
|
|
1211
|
+
const jspi2 = typeof Suspending2 === "function";
|
|
1208
1212
|
const wsState = {
|
|
1209
1213
|
upgraded: false,
|
|
1210
1214
|
server: null,
|
|
@@ -1214,15 +1218,16 @@ async function run({
|
|
|
1214
1218
|
};
|
|
1215
1219
|
const importObject = {
|
|
1216
1220
|
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
1217
|
-
__zx_sys: buildSysImports(
|
|
1218
|
-
__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),
|
|
1219
1224
|
__zx_net: createFetchImports(mem),
|
|
1220
1225
|
...imports ? imports(mem) : {},
|
|
1221
1226
|
...ZxWasiBridge.createImportObject(bridgeRef)
|
|
1222
1227
|
};
|
|
1223
1228
|
if (true) {
|
|
1224
1229
|
importObject.__zx_kv = createKVImports(
|
|
1225
|
-
kvBindings ?? { default:
|
|
1230
|
+
kvBindings ?? { default: { get: get2, put: put2, del: del2, list: list2 } },
|
|
1226
1231
|
mem,
|
|
1227
1232
|
allocRef
|
|
1228
1233
|
);
|
|
@@ -1239,34 +1244,37 @@ async function run({
|
|
|
1239
1244
|
setMemory(wasmMemory);
|
|
1240
1245
|
bridgeRef[0] = new ZxWasiBridge(instance.exports);
|
|
1241
1246
|
bindWasmAlloc(allocRef, instance.exports);
|
|
1242
|
-
const wasmPromise = executeWasm(instance,
|
|
1247
|
+
const wasmPromise = executeWasm(instance, jspi2, Suspending2, wsState);
|
|
1243
1248
|
if (wsState.upgraded) {
|
|
1244
1249
|
const server = attachWebSocket(wsState);
|
|
1245
1250
|
ctx?.waitUntil(wasmPromise);
|
|
1246
1251
|
return new Response(null, { status: 101, webSocket: server.client });
|
|
1247
1252
|
}
|
|
1248
|
-
|
|
1249
|
-
const earlyMeta = parseZiexMeta(earlyStderrText);
|
|
1250
|
-
if (earlyMeta.streaming) {
|
|
1253
|
+
if (httpState.committed && httpState.streaming) {
|
|
1251
1254
|
const { readable, writable } = new TransformStream();
|
|
1252
|
-
streamWriter = writable.getWriter();
|
|
1253
|
-
for (const chunk of
|
|
1254
|
-
|
|
1255
|
-
void wasmPromise.finally(() =>
|
|
1256
|
-
|
|
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 });
|
|
1257
1265
|
}
|
|
1258
1266
|
await wasmPromise;
|
|
1259
|
-
const
|
|
1260
|
-
const
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
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;
|
|
1264
1271
|
if (nullBody) {
|
|
1265
|
-
|
|
1266
|
-
return new Response(null, { status
|
|
1272
|
+
headers.delete("content-length");
|
|
1273
|
+
return new Response(null, { status, headers });
|
|
1267
1274
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
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 });
|
|
1270
1278
|
}
|
|
1271
1279
|
|
|
1272
1280
|
// src/app.ts
|
|
@@ -1303,7 +1311,7 @@ var Ziex = class {
|
|
|
1303
1311
|
*/
|
|
1304
1312
|
this.fetch = async (request, env, ctx) => {
|
|
1305
1313
|
const module = await this.getModule();
|
|
1306
|
-
const { wasi, imports,
|
|
1314
|
+
const { wasi, imports, sticky } = this.options;
|
|
1307
1315
|
return run({
|
|
1308
1316
|
request,
|
|
1309
1317
|
env,
|
|
@@ -1313,7 +1321,7 @@ var Ziex = class {
|
|
|
1313
1321
|
imports,
|
|
1314
1322
|
kv: this.resolveKV(env),
|
|
1315
1323
|
db: this.resolveDB(env),
|
|
1316
|
-
|
|
1324
|
+
sticky: sticky !== void 0 ? env[sticky] : void 0
|
|
1317
1325
|
});
|
|
1318
1326
|
};
|
|
1319
1327
|
this.options = options;
|
|
@@ -1322,6 +1330,27 @@ var Ziex = class {
|
|
|
1322
1330
|
if (!this.resolved) this.resolved = await resolveModule(this.options.module);
|
|
1323
1331
|
return this.resolved;
|
|
1324
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
|
+
}
|
|
1325
1354
|
resolveKV(env) {
|
|
1326
1355
|
const { kv } = this.options;
|
|
1327
1356
|
if (kv === void 0) return void 0;
|