ziex 0.1.0-dev.787 → 0.1.0-dev.805
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 -1
- package/app.d.ts +112 -0
- package/build.zig +5 -0
- package/build.zig.zon +7 -0
- package/cloudflare/app.d.ts +2 -95
- package/cloudflare/do.d.ts +48 -0
- package/cloudflare/index.d.ts +4 -4
- package/cloudflare/index.js +470 -276
- package/cloudflare/kv.d.ts +2 -27
- package/cloudflare/worker.d.ts +3 -148
- package/index.d.ts +2 -1
- package/index.js +257 -1028
- package/kv.d.ts +27 -0
- package/package.json +1 -5
- package/runtime.d.ts +70 -0
- package/wasi.d.ts +61 -0
- package/wasm/core.d.ts +78 -0
- package/wasm/index.d.ts +9 -35
- package/wasm/index.js +103 -59
- package/wasm/init.js +97 -59
- package/wasm/wasi.d.ts +28 -0
- package/hono/index.d.ts +0 -92
- package/hono/index.js +0 -1515
package/cloudflare/index.js
CHANGED
|
@@ -178,7 +178,7 @@ class ZigJS {
|
|
|
178
178
|
return decoder.decode(data);
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
|
-
// src/wasm/
|
|
181
|
+
// src/wasm/core.ts
|
|
182
182
|
var CallbackType = {
|
|
183
183
|
Event: 0,
|
|
184
184
|
FetchSuccess: 1,
|
|
@@ -229,25 +229,17 @@ function writeBytes(ptr, data) {
|
|
|
229
229
|
getMemoryView().set(data, ptr);
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
class
|
|
232
|
+
class ZxBridgeCore {
|
|
233
233
|
#intervals = new Map;
|
|
234
|
-
|
|
235
|
-
#alloc;
|
|
234
|
+
_alloc;
|
|
236
235
|
#handler;
|
|
237
236
|
#fetchCompleteHandler;
|
|
238
|
-
#wsOnOpenHandler;
|
|
239
|
-
#wsOnMessageHandler;
|
|
240
|
-
#wsOnErrorHandler;
|
|
241
|
-
#wsOnCloseHandler;
|
|
242
237
|
constructor(exports) {
|
|
243
|
-
this
|
|
238
|
+
this._alloc = exports.__zx_alloc;
|
|
244
239
|
this.#handler = exports.__zx_cb;
|
|
245
240
|
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
this.#wsOnErrorHandler = exports.__zx_ws_onerror;
|
|
249
|
-
this.#wsOnCloseHandler = exports.__zx_ws_onclose;
|
|
250
|
-
this.#eventbridge = exports.__zx_eventbridge;
|
|
241
|
+
if (exports.memory)
|
|
242
|
+
jsz.memory = exports.memory;
|
|
251
243
|
}
|
|
252
244
|
#invoke(type, id, data) {
|
|
253
245
|
const handler = this.#handler;
|
|
@@ -287,37 +279,22 @@ class ZxBridge {
|
|
|
287
279
|
if (timeout)
|
|
288
280
|
clearTimeout(timeout);
|
|
289
281
|
const text = await response.text();
|
|
290
|
-
this
|
|
282
|
+
this._notifyFetchComplete(fetchId, response.status, text, false);
|
|
291
283
|
}).catch((error) => {
|
|
292
284
|
if (timeout)
|
|
293
285
|
clearTimeout(timeout);
|
|
294
286
|
const isAbort = error.name === "AbortError";
|
|
295
287
|
const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
|
|
296
|
-
this
|
|
288
|
+
this._notifyFetchComplete(fetchId, 0, errorMsg, true);
|
|
297
289
|
});
|
|
298
290
|
}
|
|
299
|
-
|
|
291
|
+
_notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
300
292
|
const handler = this.#fetchCompleteHandler;
|
|
301
293
|
const encoded = textEncoder.encode(body);
|
|
302
|
-
const ptr = this
|
|
294
|
+
const ptr = this._alloc(encoded.length);
|
|
303
295
|
writeBytes(ptr, encoded);
|
|
304
296
|
handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
305
297
|
}
|
|
306
|
-
submitFormActionAsync(form, statesJson, fetchId) {
|
|
307
|
-
const formData = new FormData(form);
|
|
308
|
-
formData.append("__zx_states", statesJson);
|
|
309
|
-
fetch(window.location.href, {
|
|
310
|
-
method: "POST",
|
|
311
|
-
headers: { "X-ZX-Action": "1" },
|
|
312
|
-
body: formData
|
|
313
|
-
}).then(async (response) => {
|
|
314
|
-
const text = await response.text();
|
|
315
|
-
this.#notifyFetchComplete(fetchId, response.status, text, false);
|
|
316
|
-
}).catch((error) => {
|
|
317
|
-
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
318
|
-
this.#notifyFetchComplete(fetchId, 0, msg, true);
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
298
|
setTimeout(callbackId, delayMs) {
|
|
322
299
|
setTimeout(() => {
|
|
323
300
|
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
@@ -336,6 +313,83 @@ class ZxBridge {
|
|
|
336
313
|
this.#intervals.delete(callbackId);
|
|
337
314
|
}
|
|
338
315
|
}
|
|
316
|
+
_writeStringToWasm(str) {
|
|
317
|
+
return this._writeBytesToWasm(textEncoder.encode(str));
|
|
318
|
+
}
|
|
319
|
+
_writeBytesToWasm(data) {
|
|
320
|
+
const ptr = this._alloc(data.length);
|
|
321
|
+
writeBytes(ptr, data);
|
|
322
|
+
return { ptr, len: data.length };
|
|
323
|
+
}
|
|
324
|
+
static log(level, ptr, len) {
|
|
325
|
+
const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
326
|
+
switch (level) {
|
|
327
|
+
case 0:
|
|
328
|
+
console.error(msg);
|
|
329
|
+
break;
|
|
330
|
+
case 1:
|
|
331
|
+
console.warn(msg);
|
|
332
|
+
break;
|
|
333
|
+
case 3:
|
|
334
|
+
console.debug(msg);
|
|
335
|
+
break;
|
|
336
|
+
default:
|
|
337
|
+
console.log(msg);
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
static createImportObject(bridgeRef) {
|
|
342
|
+
return {
|
|
343
|
+
...jsz.importObject(),
|
|
344
|
+
__zx: {
|
|
345
|
+
_log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
|
|
346
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
347
|
+
bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
|
|
348
|
+
},
|
|
349
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
350
|
+
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
351
|
+
},
|
|
352
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
353
|
+
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
354
|
+
},
|
|
355
|
+
_clearInterval: (callbackId) => {
|
|
356
|
+
bridgeRef.current?.clearInterval(callbackId);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// src/wasm/index.ts
|
|
363
|
+
class ZxBridge extends ZxBridgeCore {
|
|
364
|
+
#websockets = new Map;
|
|
365
|
+
#wsOnOpenHandler;
|
|
366
|
+
#wsOnMessageHandler;
|
|
367
|
+
#wsOnErrorHandler;
|
|
368
|
+
#wsOnCloseHandler;
|
|
369
|
+
#eventbridge;
|
|
370
|
+
constructor(exports) {
|
|
371
|
+
super(exports);
|
|
372
|
+
this.#wsOnOpenHandler = exports.__zx_ws_onopen;
|
|
373
|
+
this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
|
|
374
|
+
this.#wsOnErrorHandler = exports.__zx_ws_onerror;
|
|
375
|
+
this.#wsOnCloseHandler = exports.__zx_ws_onclose;
|
|
376
|
+
this.#eventbridge = exports.__zx_eventbridge;
|
|
377
|
+
}
|
|
378
|
+
submitFormActionAsync(form, statesJson, fetchId) {
|
|
379
|
+
const formData = new FormData(form);
|
|
380
|
+
formData.append("__zx_states", statesJson);
|
|
381
|
+
fetch(window.location.href, {
|
|
382
|
+
method: "POST",
|
|
383
|
+
headers: { "X-ZX-Action": "1" },
|
|
384
|
+
body: formData
|
|
385
|
+
}).then(async (response) => {
|
|
386
|
+
const text = await response.text();
|
|
387
|
+
this._notifyFetchComplete(fetchId, response.status, text, false);
|
|
388
|
+
}).catch((error) => {
|
|
389
|
+
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
390
|
+
this._notifyFetchComplete(fetchId, 0, msg, true);
|
|
391
|
+
});
|
|
392
|
+
}
|
|
339
393
|
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
340
394
|
const url = readString(urlPtr, urlLen);
|
|
341
395
|
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
@@ -348,7 +402,7 @@ class ZxBridge {
|
|
|
348
402
|
if (!handler)
|
|
349
403
|
return;
|
|
350
404
|
const protocol = ws.protocol || "";
|
|
351
|
-
const { ptr, len } = this
|
|
405
|
+
const { ptr, len } = this._writeStringToWasm(protocol);
|
|
352
406
|
handler(wsId, ptr, len);
|
|
353
407
|
};
|
|
354
408
|
ws.onmessage = (event) => {
|
|
@@ -356,21 +410,15 @@ class ZxBridge {
|
|
|
356
410
|
if (!handler)
|
|
357
411
|
return;
|
|
358
412
|
const isBinary = event.data instanceof ArrayBuffer;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
data = new Uint8Array(event.data);
|
|
362
|
-
} else {
|
|
363
|
-
data = textEncoder.encode(event.data);
|
|
364
|
-
}
|
|
365
|
-
const { ptr, len } = this.#writeBytesToWasm(data);
|
|
413
|
+
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
414
|
+
const { ptr, len } = this._writeBytesToWasm(data);
|
|
366
415
|
handler(wsId, ptr, len, isBinary ? 1 : 0);
|
|
367
416
|
};
|
|
368
|
-
ws.onerror = (
|
|
417
|
+
ws.onerror = (_event) => {
|
|
369
418
|
const handler = this.#wsOnErrorHandler;
|
|
370
419
|
if (!handler)
|
|
371
420
|
return;
|
|
372
|
-
const
|
|
373
|
-
const { ptr, len } = this.#writeStringToWasm(msg);
|
|
421
|
+
const { ptr, len } = this._writeStringToWasm("WebSocket error");
|
|
374
422
|
handler(wsId, ptr, len);
|
|
375
423
|
};
|
|
376
424
|
ws.onclose = (event) => {
|
|
@@ -378,7 +426,7 @@ class ZxBridge {
|
|
|
378
426
|
if (!handler)
|
|
379
427
|
return;
|
|
380
428
|
const reason = event.reason || "";
|
|
381
|
-
const { ptr, len } = this
|
|
429
|
+
const { ptr, len } = this._writeStringToWasm(reason);
|
|
382
430
|
handler(wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
383
431
|
this.#websockets.delete(wsId);
|
|
384
432
|
};
|
|
@@ -387,7 +435,7 @@ class ZxBridge {
|
|
|
387
435
|
const handler = this.#wsOnErrorHandler;
|
|
388
436
|
if (handler) {
|
|
389
437
|
const msg = error instanceof Error ? error.message : "WebSocket connection failed";
|
|
390
|
-
const { ptr, len } = this
|
|
438
|
+
const { ptr, len } = this._writeStringToWasm(msg);
|
|
391
439
|
handler(wsId, ptr, len);
|
|
392
440
|
}
|
|
393
441
|
}
|
|
@@ -409,25 +457,14 @@ class ZxBridge {
|
|
|
409
457
|
return;
|
|
410
458
|
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
|
|
411
459
|
try {
|
|
412
|
-
if (reason)
|
|
460
|
+
if (reason)
|
|
413
461
|
ws.close(code, reason);
|
|
414
|
-
|
|
462
|
+
else
|
|
415
463
|
ws.close(code);
|
|
416
|
-
}
|
|
417
464
|
} catch {
|
|
418
465
|
ws.close();
|
|
419
466
|
}
|
|
420
467
|
}
|
|
421
|
-
#writeStringToWasm(str) {
|
|
422
|
-
const encoded = textEncoder.encode(str);
|
|
423
|
-
return this.#writeBytesToWasm(encoded);
|
|
424
|
-
}
|
|
425
|
-
#writeBytesToWasm(data) {
|
|
426
|
-
const ptr = this.#alloc(data.length);
|
|
427
|
-
writeBytes(ptr, data);
|
|
428
|
-
return { ptr, len: data.length };
|
|
429
|
-
}
|
|
430
|
-
#eventbridge;
|
|
431
468
|
eventbridge(velementId, eventTypeId, event) {
|
|
432
469
|
if (!this.#eventbridge)
|
|
433
470
|
return;
|
|
@@ -438,6 +475,7 @@ class ZxBridge {
|
|
|
438
475
|
return {
|
|
439
476
|
...jsz.importObject(),
|
|
440
477
|
__zx: {
|
|
478
|
+
_log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
|
|
441
479
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
442
480
|
bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
|
|
443
481
|
},
|
|
@@ -842,16 +880,141 @@ async function init(options = {}) {
|
|
|
842
880
|
return { source, bridge };
|
|
843
881
|
}
|
|
844
882
|
|
|
845
|
-
// src/
|
|
846
|
-
var
|
|
847
|
-
__export(
|
|
883
|
+
// src/runtime.ts
|
|
884
|
+
var exports_runtime = {};
|
|
885
|
+
__export(exports_runtime, {
|
|
848
886
|
run: () => run,
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
createWebSocketDO: () => createWebSocketDO
|
|
887
|
+
buildWsImports: () => buildWsImports,
|
|
888
|
+
attachWebSocket: () => attachWebSocket
|
|
852
889
|
});
|
|
853
890
|
|
|
854
|
-
// src/
|
|
891
|
+
// src/wasm/wasi.ts
|
|
892
|
+
var decoder2 = new TextDecoder;
|
|
893
|
+
var encoder2 = new TextEncoder;
|
|
894
|
+
|
|
895
|
+
class ZxWasiBridge {
|
|
896
|
+
#alloc;
|
|
897
|
+
#fetchCompleteHandler;
|
|
898
|
+
#memory;
|
|
899
|
+
#cb;
|
|
900
|
+
#intervals = new Map;
|
|
901
|
+
#memView = null;
|
|
902
|
+
#memBuf = null;
|
|
903
|
+
constructor(exports) {
|
|
904
|
+
this.#memory = exports.memory;
|
|
905
|
+
this.#alloc = exports.__zx_alloc;
|
|
906
|
+
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
907
|
+
this.#cb = exports.__zx_cb;
|
|
908
|
+
}
|
|
909
|
+
#view() {
|
|
910
|
+
const buf = this.#memory.buffer;
|
|
911
|
+
if (buf !== this.#memBuf) {
|
|
912
|
+
this.#memBuf = buf;
|
|
913
|
+
this.#memView = new Uint8Array(buf);
|
|
914
|
+
}
|
|
915
|
+
return this.#memView;
|
|
916
|
+
}
|
|
917
|
+
#readString(ptr, len) {
|
|
918
|
+
return decoder2.decode(this.#view().subarray(ptr, ptr + len));
|
|
919
|
+
}
|
|
920
|
+
#writeBytes(ptr, data) {
|
|
921
|
+
this.#view().set(data, ptr);
|
|
922
|
+
}
|
|
923
|
+
log(level, ptr, len) {
|
|
924
|
+
const msg = decoder2.decode(this.#view().subarray(ptr, ptr + len));
|
|
925
|
+
switch (level) {
|
|
926
|
+
case 0:
|
|
927
|
+
console.error(msg);
|
|
928
|
+
break;
|
|
929
|
+
case 1:
|
|
930
|
+
console.warn(msg);
|
|
931
|
+
break;
|
|
932
|
+
case 3:
|
|
933
|
+
console.debug(msg);
|
|
934
|
+
break;
|
|
935
|
+
default:
|
|
936
|
+
console.log(msg);
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
941
|
+
const url = this.#readString(urlPtr, urlLen);
|
|
942
|
+
const method = methodLen > 0 ? this.#readString(methodPtr, methodLen) : "GET";
|
|
943
|
+
const headersJson = headersLen > 0 ? this.#readString(headersPtr, headersLen) : "{}";
|
|
944
|
+
const body = bodyLen > 0 ? this.#readString(bodyPtr, bodyLen) : undefined;
|
|
945
|
+
let headers = {};
|
|
946
|
+
try {
|
|
947
|
+
headers = JSON.parse(headersJson);
|
|
948
|
+
} catch {
|
|
949
|
+
for (const line of headersJson.split(`
|
|
950
|
+
`)) {
|
|
951
|
+
const i = line.indexOf(":");
|
|
952
|
+
if (i > 0)
|
|
953
|
+
headers[line.slice(0, i)] = line.slice(i + 1);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
const controller = new AbortController;
|
|
957
|
+
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
958
|
+
fetch(url, {
|
|
959
|
+
method,
|
|
960
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
961
|
+
body: method !== "GET" && method !== "HEAD" ? body : undefined,
|
|
962
|
+
signal: controller.signal
|
|
963
|
+
}).then(async (res) => {
|
|
964
|
+
if (timeout)
|
|
965
|
+
clearTimeout(timeout);
|
|
966
|
+
this.#notifyFetchComplete(fetchId, res.status, await res.text(), false);
|
|
967
|
+
}).catch((err) => {
|
|
968
|
+
if (timeout)
|
|
969
|
+
clearTimeout(timeout);
|
|
970
|
+
const msg = err.name === "AbortError" ? "Request timeout" : err.message ?? "Fetch failed";
|
|
971
|
+
this.#notifyFetchComplete(fetchId, 0, msg, true);
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
#notifyFetchComplete(fetchId, status, body, isError) {
|
|
975
|
+
const encoded = encoder2.encode(body);
|
|
976
|
+
const ptr = this.#alloc(encoded.length);
|
|
977
|
+
this.#writeBytes(ptr, encoded);
|
|
978
|
+
this.#fetchCompleteHandler(fetchId, status, ptr, encoded.length, isError ? 1 : 0);
|
|
979
|
+
}
|
|
980
|
+
setTimeout(callbackId, delayMs) {
|
|
981
|
+
setTimeout(() => this.#cb?.(3, callbackId, 0n), delayMs);
|
|
982
|
+
}
|
|
983
|
+
setInterval(callbackId, intervalMs) {
|
|
984
|
+
const handle = setInterval(() => this.#cb?.(4, callbackId, 0n), intervalMs);
|
|
985
|
+
this.#intervals.set(callbackId, handle);
|
|
986
|
+
}
|
|
987
|
+
clearInterval(callbackId) {
|
|
988
|
+
const handle = this.#intervals.get(callbackId);
|
|
989
|
+
if (handle !== undefined) {
|
|
990
|
+
clearInterval(handle);
|
|
991
|
+
this.#intervals.delete(callbackId);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
static createImportObject(bridgeRef) {
|
|
995
|
+
return {
|
|
996
|
+
__zx: {
|
|
997
|
+
_log: (level, ptr, len) => {
|
|
998
|
+
bridgeRef.current?.log(level, ptr, len);
|
|
999
|
+
},
|
|
1000
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1001
|
+
bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
|
|
1002
|
+
},
|
|
1003
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
1004
|
+
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
1005
|
+
},
|
|
1006
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
1007
|
+
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
1008
|
+
},
|
|
1009
|
+
_clearInterval: (callbackId) => {
|
|
1010
|
+
bridgeRef.current?.clearInterval(callbackId);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// src/kv.ts
|
|
855
1018
|
var exports_kv = {};
|
|
856
1019
|
__export(exports_kv, {
|
|
857
1020
|
createMemoryKV: () => createMemoryKV,
|
|
@@ -876,10 +1039,10 @@ function createMemoryKV() {
|
|
|
876
1039
|
};
|
|
877
1040
|
}
|
|
878
1041
|
function createKVImports(bindings, getMemory) {
|
|
879
|
-
const
|
|
880
|
-
const
|
|
1042
|
+
const encoder3 = new TextEncoder;
|
|
1043
|
+
const decoder3 = new TextDecoder;
|
|
881
1044
|
function readStr(ptr, len) {
|
|
882
|
-
return
|
|
1045
|
+
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
883
1046
|
}
|
|
884
1047
|
function writeBytes2(buf_ptr, buf_max, data) {
|
|
885
1048
|
if (data.length > buf_max)
|
|
@@ -896,7 +1059,7 @@ function createKVImports(bindings, getMemory) {
|
|
|
896
1059
|
kv_get: (_ns, _nsLen, _key, _keyLen, _buf, _max) => -1,
|
|
897
1060
|
kv_put: (_ns, _nsLen, _key, _keyLen, _val, _valLen) => 0,
|
|
898
1061
|
kv_delete: (_ns, _nsLen, _key, _keyLen) => 0,
|
|
899
|
-
kv_list: (_ns, _nsLen, _pfx, _pfxLen, buf_ptr, buf_max) => writeBytes2(buf_ptr, buf_max,
|
|
1062
|
+
kv_list: (_ns, _nsLen, _pfx, _pfxLen, buf_ptr, buf_max) => writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"))
|
|
900
1063
|
};
|
|
901
1064
|
}
|
|
902
1065
|
return {
|
|
@@ -907,7 +1070,7 @@ function createKVImports(bindings, getMemory) {
|
|
|
907
1070
|
const value = await b.get(readStr(key_ptr, key_len));
|
|
908
1071
|
if (value === null)
|
|
909
1072
|
return -1;
|
|
910
|
-
return writeBytes2(buf_ptr, buf_max,
|
|
1073
|
+
return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
|
|
911
1074
|
}),
|
|
912
1075
|
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
|
|
913
1076
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
@@ -926,15 +1089,15 @@ function createKVImports(bindings, getMemory) {
|
|
|
926
1089
|
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
927
1090
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
928
1091
|
if (!b)
|
|
929
|
-
return writeBytes2(buf_ptr, buf_max,
|
|
1092
|
+
return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
|
|
930
1093
|
const prefix = readStr(prefix_ptr, prefix_len);
|
|
931
1094
|
const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
|
|
932
|
-
return writeBytes2(buf_ptr, buf_max,
|
|
1095
|
+
return writeBytes2(buf_ptr, buf_max, encoder3.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
933
1096
|
})
|
|
934
1097
|
};
|
|
935
1098
|
}
|
|
936
1099
|
|
|
937
|
-
// src/
|
|
1100
|
+
// src/wasi.ts
|
|
938
1101
|
class ProcExit extends Error {
|
|
939
1102
|
code;
|
|
940
1103
|
constructor(code) {
|
|
@@ -947,8 +1110,7 @@ function createWasiImports({
|
|
|
947
1110
|
stdinData,
|
|
948
1111
|
onStdout
|
|
949
1112
|
}) {
|
|
950
|
-
const
|
|
951
|
-
const decoder2 = new TextDecoder;
|
|
1113
|
+
const encoder3 = new TextEncoder;
|
|
952
1114
|
const url = new URL(request.url);
|
|
953
1115
|
const argStrings = [
|
|
954
1116
|
"wasm",
|
|
@@ -963,14 +1125,30 @@ function createWasiImports({
|
|
|
963
1125
|
if (value)
|
|
964
1126
|
argStrings.push("--header", `${name}:${value}`);
|
|
965
1127
|
});
|
|
966
|
-
const encodedArgs = argStrings.map((a) =>
|
|
1128
|
+
const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\x00"));
|
|
967
1129
|
const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
|
|
968
1130
|
let wasmMemory = null;
|
|
969
1131
|
const setMemory = (m2) => {
|
|
970
1132
|
wasmMemory = m2;
|
|
971
1133
|
};
|
|
972
1134
|
const stdoutChunks = [];
|
|
973
|
-
|
|
1135
|
+
let stderrMeta = "";
|
|
1136
|
+
let stderrPartial = "";
|
|
1137
|
+
const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
1138
|
+
function processStderrChunk(chunk) {
|
|
1139
|
+
const text = stderrDecoder.decode(chunk, { stream: true });
|
|
1140
|
+
const lines = (stderrPartial + text).split(`
|
|
1141
|
+
`);
|
|
1142
|
+
stderrPartial = lines.pop() ?? "";
|
|
1143
|
+
for (const line of lines) {
|
|
1144
|
+
if (line.startsWith("__EDGE_META__:")) {
|
|
1145
|
+
stderrMeta += line + `
|
|
1146
|
+
`;
|
|
1147
|
+
} else if (line.length > 0) {
|
|
1148
|
+
console.error("[ziex]", line);
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
974
1152
|
let stdinOffset = 0;
|
|
975
1153
|
function v() {
|
|
976
1154
|
return new DataView(wasmMemory.buffer);
|
|
@@ -1018,7 +1196,7 @@ function createWasiImports({
|
|
|
1018
1196
|
else
|
|
1019
1197
|
stdoutChunks.push(chunk);
|
|
1020
1198
|
} else if (fd === 2)
|
|
1021
|
-
|
|
1199
|
+
processStderrChunk(chunk);
|
|
1022
1200
|
written += buf_len;
|
|
1023
1201
|
}
|
|
1024
1202
|
dv.setUint32(nwritten_ptr, written, true);
|
|
@@ -1133,106 +1311,36 @@ function createWasiImports({
|
|
|
1133
1311
|
}
|
|
1134
1312
|
};
|
|
1135
1313
|
function collectOutput() {
|
|
1314
|
+
const remaining = stderrDecoder.decode(undefined, { stream: false });
|
|
1315
|
+
const tail = stderrPartial + remaining;
|
|
1316
|
+
if (tail.length > 0) {
|
|
1317
|
+
if (tail.startsWith("__EDGE_META__:"))
|
|
1318
|
+
stderrMeta += tail;
|
|
1319
|
+
else
|
|
1320
|
+
console.error("[ziex]", tail);
|
|
1321
|
+
stderrPartial = "";
|
|
1322
|
+
}
|
|
1136
1323
|
return {
|
|
1137
1324
|
stdout: mergeUint8Arrays(stdoutChunks),
|
|
1138
|
-
stderrText:
|
|
1325
|
+
stderrText: stderrMeta
|
|
1139
1326
|
};
|
|
1140
1327
|
}
|
|
1141
1328
|
return { wasiImport, setMemory, collectOutput };
|
|
1142
1329
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
wasi,
|
|
1151
|
-
websocket: doNamespace
|
|
1152
|
-
}) {
|
|
1153
|
-
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
1154
|
-
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
1155
|
-
return doNamespace.get(id).fetch(request);
|
|
1156
|
-
}
|
|
1157
|
-
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
|
|
1158
|
-
const { readable, writable } = new TransformStream;
|
|
1159
|
-
const stdoutWriter = writable.getWriter();
|
|
1160
|
-
const { wasiImport, setMemory, collectOutput } = createWasiImports({
|
|
1161
|
-
request,
|
|
1162
|
-
stdinData,
|
|
1163
|
-
onStdout: (chunk) => {
|
|
1164
|
-
stdoutWriter.write(chunk);
|
|
1165
|
-
}
|
|
1166
|
-
});
|
|
1167
|
-
let wasmMemory = null;
|
|
1168
|
-
const mem = () => wasmMemory;
|
|
1169
|
-
const bridgeRef = { current: null };
|
|
1170
|
-
const bridgeImports = ZxBridge.createImportObject(bridgeRef);
|
|
1171
|
-
const decoder2 = new TextDecoder;
|
|
1172
|
-
const Suspending = WebAssembly.Suspending;
|
|
1173
|
-
const jspi = typeof Suspending === "function";
|
|
1174
|
-
const sysImports = {
|
|
1175
|
-
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((resolve) => setTimeout(resolve, ms))) : (_ms) => {}
|
|
1176
|
-
};
|
|
1177
|
-
const wsState = {
|
|
1178
|
-
upgraded: false,
|
|
1179
|
-
server: null,
|
|
1180
|
-
pendingWrites: [],
|
|
1181
|
-
messageQueue: [],
|
|
1182
|
-
recvResolve: null
|
|
1183
|
-
};
|
|
1184
|
-
const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder2, wsState);
|
|
1185
|
-
const instance = new WebAssembly.Instance(module, {
|
|
1186
|
-
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
1187
|
-
__zx_sys: sysImports,
|
|
1188
|
-
__zx_ws: wsImports,
|
|
1189
|
-
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
1190
|
-
...imports ? imports(mem) : {},
|
|
1191
|
-
...bridgeImports
|
|
1192
|
-
});
|
|
1193
|
-
wasmMemory = instance.exports.memory;
|
|
1194
|
-
setMemory(wasmMemory);
|
|
1195
|
-
const bridge = new ZxBridge(instance.exports);
|
|
1196
|
-
bridgeRef.current = bridge;
|
|
1197
|
-
let wasmPromise;
|
|
1198
|
-
if (jspi) {
|
|
1199
|
-
const start = WebAssembly.promising(instance.exports._start);
|
|
1200
|
-
wasmPromise = start().catch((e) => {
|
|
1201
|
-
if (e instanceof Error && e.message.startsWith("proc_exit"))
|
|
1202
|
-
return;
|
|
1203
|
-
throw e;
|
|
1204
|
-
}).finally(() => {
|
|
1205
|
-
stdoutWriter.close();
|
|
1206
|
-
if (wsState.recvResolve) {
|
|
1207
|
-
const res = wsState.recvResolve;
|
|
1208
|
-
wsState.recvResolve = null;
|
|
1209
|
-
res(null);
|
|
1210
|
-
}
|
|
1211
|
-
});
|
|
1212
|
-
} else {
|
|
1213
|
-
try {
|
|
1214
|
-
instance.exports._start();
|
|
1215
|
-
} catch (e) {
|
|
1216
|
-
if (!(e instanceof ProcExit))
|
|
1217
|
-
throw e;
|
|
1218
|
-
}
|
|
1219
|
-
stdoutWriter.close();
|
|
1220
|
-
wasmPromise = Promise.resolve();
|
|
1221
|
-
}
|
|
1222
|
-
if (wsState.upgraded) {
|
|
1223
|
-
const server = attachWebSocket(wsState);
|
|
1224
|
-
ctx?.waitUntil(wasmPromise);
|
|
1225
|
-
return new Response(null, { status: 101, webSocket: server.client });
|
|
1330
|
+
function mergeUint8Arrays(arrays) {
|
|
1331
|
+
const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
1332
|
+
const result = new Uint8Array(totalLen);
|
|
1333
|
+
let offset = 0;
|
|
1334
|
+
for (const arr of arrays) {
|
|
1335
|
+
result.set(arr, offset);
|
|
1336
|
+
offset += arr.length;
|
|
1226
1337
|
}
|
|
1227
|
-
|
|
1228
|
-
const meta = parseEdgeMeta(stderrText);
|
|
1229
|
-
return new Response(readable, {
|
|
1230
|
-
status: meta.status,
|
|
1231
|
-
headers: meta.headers
|
|
1232
|
-
});
|
|
1338
|
+
return result;
|
|
1233
1339
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1340
|
+
|
|
1341
|
+
// src/runtime.ts
|
|
1342
|
+
function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
1343
|
+
const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
1236
1344
|
return {
|
|
1237
1345
|
ws_upgrade: () => {
|
|
1238
1346
|
ws.upgraded = true;
|
|
@@ -1246,7 +1354,7 @@ function buildWsImports(Suspending, mem, decoder2, ws) {
|
|
|
1246
1354
|
}
|
|
1247
1355
|
},
|
|
1248
1356
|
ws_close: (code, reason_ptr, reason_len) => {
|
|
1249
|
-
ws.server?.close(code,
|
|
1357
|
+
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
1250
1358
|
},
|
|
1251
1359
|
ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
|
|
1252
1360
|
if (ws._resolveFirstSuspend) {
|
|
@@ -1310,6 +1418,193 @@ function attachWebSocket(ws) {
|
|
|
1310
1418
|
});
|
|
1311
1419
|
return { client };
|
|
1312
1420
|
}
|
|
1421
|
+
function buildSysImports(jspi, Suspending) {
|
|
1422
|
+
return {
|
|
1423
|
+
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function executeWasm(instance, jspi, Suspending, wsState) {
|
|
1427
|
+
if (!jspi) {
|
|
1428
|
+
try {
|
|
1429
|
+
instance.exports._start();
|
|
1430
|
+
} catch (e) {
|
|
1431
|
+
if (!(e instanceof ProcExit))
|
|
1432
|
+
throw e;
|
|
1433
|
+
}
|
|
1434
|
+
return Promise.resolve();
|
|
1435
|
+
}
|
|
1436
|
+
const start = WebAssembly.promising(instance.exports._start);
|
|
1437
|
+
return start().catch((e) => {
|
|
1438
|
+
if (e instanceof Error && e.message.startsWith("proc_exit"))
|
|
1439
|
+
return;
|
|
1440
|
+
throw e;
|
|
1441
|
+
}).finally(() => {
|
|
1442
|
+
if (wsState.recvResolve) {
|
|
1443
|
+
const res = wsState.recvResolve;
|
|
1444
|
+
wsState.recvResolve = null;
|
|
1445
|
+
res(null);
|
|
1446
|
+
}
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
function parseEdgeMeta(stderrText) {
|
|
1450
|
+
const meta = { status: 200, headers: new Headers, streaming: false };
|
|
1451
|
+
const metaPrefix = "__EDGE_META__:";
|
|
1452
|
+
const metaLine = stderrText.split(`
|
|
1453
|
+
`).find((line) => line.startsWith(metaPrefix));
|
|
1454
|
+
if (metaLine) {
|
|
1455
|
+
try {
|
|
1456
|
+
const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
|
|
1457
|
+
if (parsed.status)
|
|
1458
|
+
meta.status = parsed.status;
|
|
1459
|
+
if (parsed.streaming === true)
|
|
1460
|
+
meta.streaming = true;
|
|
1461
|
+
if (Array.isArray(parsed.headers)) {
|
|
1462
|
+
for (const [name, value] of parsed.headers) {
|
|
1463
|
+
meta.headers.append(name, value);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
} catch {}
|
|
1467
|
+
}
|
|
1468
|
+
return meta;
|
|
1469
|
+
}
|
|
1470
|
+
async function run({
|
|
1471
|
+
request,
|
|
1472
|
+
env,
|
|
1473
|
+
ctx,
|
|
1474
|
+
module,
|
|
1475
|
+
kv: kvBindings,
|
|
1476
|
+
imports,
|
|
1477
|
+
wasi,
|
|
1478
|
+
websocket: doNamespace
|
|
1479
|
+
}) {
|
|
1480
|
+
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
1481
|
+
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
1482
|
+
return doNamespace.get(id).fetch(request);
|
|
1483
|
+
}
|
|
1484
|
+
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
|
|
1485
|
+
const stdoutChunks = [];
|
|
1486
|
+
let streamWriter = null;
|
|
1487
|
+
const { wasiImport, setMemory, collectOutput } = createWasiImports({
|
|
1488
|
+
request,
|
|
1489
|
+
stdinData,
|
|
1490
|
+
onStdout: (chunk) => {
|
|
1491
|
+
if (streamWriter)
|
|
1492
|
+
streamWriter.write(chunk);
|
|
1493
|
+
else
|
|
1494
|
+
stdoutChunks.push(chunk);
|
|
1495
|
+
}
|
|
1496
|
+
});
|
|
1497
|
+
let wasmMemory = null;
|
|
1498
|
+
const mem = () => wasmMemory;
|
|
1499
|
+
const bridgeRef = { current: null };
|
|
1500
|
+
const Suspending = WebAssembly.Suspending;
|
|
1501
|
+
const jspi = typeof Suspending === "function";
|
|
1502
|
+
const wsState = {
|
|
1503
|
+
upgraded: false,
|
|
1504
|
+
server: null,
|
|
1505
|
+
pendingWrites: [],
|
|
1506
|
+
messageQueue: [],
|
|
1507
|
+
recvResolve: null
|
|
1508
|
+
};
|
|
1509
|
+
const instance = new WebAssembly.Instance(module, {
|
|
1510
|
+
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
1511
|
+
__zx_sys: buildSysImports(jspi, Suspending),
|
|
1512
|
+
__zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder, wsState),
|
|
1513
|
+
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
1514
|
+
...imports ? imports(mem) : {},
|
|
1515
|
+
...ZxWasiBridge.createImportObject(bridgeRef)
|
|
1516
|
+
});
|
|
1517
|
+
wasmMemory = instance.exports.memory;
|
|
1518
|
+
setMemory(wasmMemory);
|
|
1519
|
+
bridgeRef.current = new ZxWasiBridge(instance.exports);
|
|
1520
|
+
const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
|
|
1521
|
+
if (wsState.upgraded) {
|
|
1522
|
+
const server = attachWebSocket(wsState);
|
|
1523
|
+
ctx?.waitUntil(wasmPromise);
|
|
1524
|
+
return new Response(null, { status: 101, webSocket: server.client });
|
|
1525
|
+
}
|
|
1526
|
+
const { stderrText } = collectOutput();
|
|
1527
|
+
const meta = parseEdgeMeta(stderrText);
|
|
1528
|
+
if (meta.streaming) {
|
|
1529
|
+
const { readable, writable } = new TransformStream;
|
|
1530
|
+
streamWriter = writable.getWriter();
|
|
1531
|
+
for (const chunk of stdoutChunks)
|
|
1532
|
+
streamWriter.write(chunk);
|
|
1533
|
+
stdoutChunks.length = 0;
|
|
1534
|
+
wasmPromise.finally(() => streamWriter?.close());
|
|
1535
|
+
return new Response(readable, { status: meta.status, headers: meta.headers });
|
|
1536
|
+
}
|
|
1537
|
+
await wasmPromise;
|
|
1538
|
+
const body = mergeUint8Arrays(stdoutChunks);
|
|
1539
|
+
meta.headers.delete("transfer-encoding");
|
|
1540
|
+
if (!meta.headers.has("content-length"))
|
|
1541
|
+
meta.headers.set("content-length", String(body.byteLength));
|
|
1542
|
+
return new Response(body.buffer, { status: meta.status, headers: meta.headers });
|
|
1543
|
+
}
|
|
1544
|
+
// src/app.ts
|
|
1545
|
+
async function resolveModule(input) {
|
|
1546
|
+
if (typeof input === "string") {
|
|
1547
|
+
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
1548
|
+
return WebAssembly.compileStreaming(fetch(input));
|
|
1549
|
+
}
|
|
1550
|
+
const url = input.startsWith("/") ? `file://${input}` : input;
|
|
1551
|
+
return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
|
|
1552
|
+
}
|
|
1553
|
+
if (input instanceof URL) {
|
|
1554
|
+
return WebAssembly.compileStreaming(fetch(input));
|
|
1555
|
+
}
|
|
1556
|
+
if (input instanceof Response) {
|
|
1557
|
+
return WebAssembly.compileStreaming(input);
|
|
1558
|
+
}
|
|
1559
|
+
if (input instanceof ArrayBuffer) {
|
|
1560
|
+
return WebAssembly.compile(input);
|
|
1561
|
+
}
|
|
1562
|
+
if (ArrayBuffer.isView(input)) {
|
|
1563
|
+
return WebAssembly.compile(input.buffer);
|
|
1564
|
+
}
|
|
1565
|
+
return input;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
class Ziex {
|
|
1569
|
+
options;
|
|
1570
|
+
resolved = null;
|
|
1571
|
+
constructor(options) {
|
|
1572
|
+
this.options = options;
|
|
1573
|
+
}
|
|
1574
|
+
async getModule() {
|
|
1575
|
+
if (!this.resolved)
|
|
1576
|
+
this.resolved = await resolveModule(this.options.module);
|
|
1577
|
+
return this.resolved;
|
|
1578
|
+
}
|
|
1579
|
+
resolveKV(env) {
|
|
1580
|
+
const { kv } = this.options;
|
|
1581
|
+
if (kv === undefined)
|
|
1582
|
+
return;
|
|
1583
|
+
if (typeof kv === "object" && kv !== null) {
|
|
1584
|
+
const result = {};
|
|
1585
|
+
for (const [name, key] of Object.entries(kv)) {
|
|
1586
|
+
result[name] = env[key];
|
|
1587
|
+
}
|
|
1588
|
+
return result;
|
|
1589
|
+
}
|
|
1590
|
+
return { default: env[kv] };
|
|
1591
|
+
}
|
|
1592
|
+
fetch = async (request, env, ctx) => {
|
|
1593
|
+
const module = await this.getModule();
|
|
1594
|
+
const { wasi, imports, websocket } = this.options;
|
|
1595
|
+
return run({
|
|
1596
|
+
request,
|
|
1597
|
+
env,
|
|
1598
|
+
ctx,
|
|
1599
|
+
module,
|
|
1600
|
+
wasi,
|
|
1601
|
+
imports,
|
|
1602
|
+
kv: this.resolveKV(env),
|
|
1603
|
+
websocket: websocket !== undefined ? env[websocket] : undefined
|
|
1604
|
+
});
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
// src/cloudflare/do.ts
|
|
1313
1608
|
function createWebSocketDO(module, options) {
|
|
1314
1609
|
return class ZxWebSocketDO {
|
|
1315
1610
|
doState;
|
|
@@ -1328,7 +1623,7 @@ function createWebSocketDO(module, options) {
|
|
|
1328
1623
|
const bridgeImports = ZxBridge.createImportObject(bridgeRef);
|
|
1329
1624
|
const Suspending = WebAssembly.Suspending;
|
|
1330
1625
|
const jspi = typeof Suspending === "function";
|
|
1331
|
-
const
|
|
1626
|
+
const decoder3 = new TextDecoder;
|
|
1332
1627
|
let _resolveFirstSuspend;
|
|
1333
1628
|
const firstSuspendPromise = new Promise((resolve) => {
|
|
1334
1629
|
_resolveFirstSuspend = resolve;
|
|
@@ -1365,7 +1660,7 @@ function createWebSocketDO(module, options) {
|
|
|
1365
1660
|
const sysImports = {
|
|
1366
1661
|
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
|
|
1367
1662
|
};
|
|
1368
|
-
const wsImports = buildWsImports(jspi ? Suspending : null, mem,
|
|
1663
|
+
const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder3, connState);
|
|
1369
1664
|
const kvBindings = options?.kv?.(this.env);
|
|
1370
1665
|
const instance = new WebAssembly.Instance(module, {
|
|
1371
1666
|
wasi_snapshot_preview1: wasiImport,
|
|
@@ -1404,109 +1699,8 @@ function createWebSocketDO(module, options) {
|
|
|
1404
1699
|
}
|
|
1405
1700
|
};
|
|
1406
1701
|
}
|
|
1407
|
-
function parseEdgeMeta(stderrText) {
|
|
1408
|
-
const meta = { status: 200, headers: new Headers };
|
|
1409
|
-
const metaPrefix = "__EDGE_META__:";
|
|
1410
|
-
const metaLine = stderrText.split(`
|
|
1411
|
-
`).find((line) => line.startsWith(metaPrefix));
|
|
1412
|
-
if (metaLine) {
|
|
1413
|
-
try {
|
|
1414
|
-
const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
|
|
1415
|
-
if (parsed.status)
|
|
1416
|
-
meta.status = parsed.status;
|
|
1417
|
-
if (Array.isArray(parsed.headers)) {
|
|
1418
|
-
for (const [name, value] of parsed.headers) {
|
|
1419
|
-
meta.headers.append(name, value);
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
} catch {}
|
|
1423
|
-
}
|
|
1424
|
-
return meta;
|
|
1425
|
-
}
|
|
1426
|
-
function mergeUint8Arrays(arrays) {
|
|
1427
|
-
const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
1428
|
-
const result = new Uint8Array(totalLen);
|
|
1429
|
-
let offset = 0;
|
|
1430
|
-
for (const arr of arrays) {
|
|
1431
|
-
result.set(arr, offset);
|
|
1432
|
-
offset += arr.length;
|
|
1433
|
-
}
|
|
1434
|
-
return result;
|
|
1435
|
-
}
|
|
1436
|
-
async function collectStream(readable, chunks) {
|
|
1437
|
-
const reader = readable.getReader();
|
|
1438
|
-
while (true) {
|
|
1439
|
-
const { done, value } = await reader.read();
|
|
1440
|
-
if (done)
|
|
1441
|
-
break;
|
|
1442
|
-
if (value)
|
|
1443
|
-
chunks.push(value);
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
function prepare({
|
|
1447
|
-
request,
|
|
1448
|
-
env,
|
|
1449
|
-
ctx
|
|
1450
|
-
}) {
|
|
1451
|
-
const stdout = new TransformStream;
|
|
1452
|
-
const stderr = new TransformStream;
|
|
1453
|
-
const url = new URL(request.url);
|
|
1454
|
-
const args = [
|
|
1455
|
-
"--pathname",
|
|
1456
|
-
url.pathname,
|
|
1457
|
-
"--method",
|
|
1458
|
-
request.method,
|
|
1459
|
-
"--search",
|
|
1460
|
-
url.search
|
|
1461
|
-
];
|
|
1462
|
-
request.headers.forEach((value, name) => {
|
|
1463
|
-
args.push("--header", `${name}:${value}`);
|
|
1464
|
-
});
|
|
1465
|
-
const stdin = request.body ?? undefined;
|
|
1466
|
-
return { args, stdout, stderr, stdin };
|
|
1467
|
-
}
|
|
1468
|
-
async function respond({
|
|
1469
|
-
exec,
|
|
1470
|
-
stdout,
|
|
1471
|
-
stderr
|
|
1472
|
-
}) {
|
|
1473
|
-
const stdoutChunks = [];
|
|
1474
|
-
const stderrChunks = [];
|
|
1475
|
-
const stderrReadable = stderr instanceof ReadableStream ? stderr : stderr.readable;
|
|
1476
|
-
await Promise.all([
|
|
1477
|
-
exec,
|
|
1478
|
-
collectStream(stdout.readable, stdoutChunks),
|
|
1479
|
-
collectStream(stderrReadable, stderrChunks)
|
|
1480
|
-
]);
|
|
1481
|
-
const stderrText = new TextDecoder().decode(mergeUint8Arrays(stderrChunks));
|
|
1482
|
-
const meta = parseEdgeMeta(stderrText);
|
|
1483
|
-
return new Response(mergeUint8Arrays(stdoutChunks).buffer, {
|
|
1484
|
-
status: meta.status,
|
|
1485
|
-
headers: meta.headers
|
|
1486
|
-
});
|
|
1487
|
-
}
|
|
1488
|
-
// src/cloudflare/app.ts
|
|
1489
|
-
class Ziex {
|
|
1490
|
-
options;
|
|
1491
|
-
constructor(options) {
|
|
1492
|
-
this.options = options;
|
|
1493
|
-
}
|
|
1494
|
-
fetch(request, env, ctx) {
|
|
1495
|
-
const { module, wasi, imports, kv, websocket } = this.options;
|
|
1496
|
-
return run({
|
|
1497
|
-
request,
|
|
1498
|
-
env,
|
|
1499
|
-
ctx,
|
|
1500
|
-
module,
|
|
1501
|
-
wasi,
|
|
1502
|
-
imports,
|
|
1503
|
-
kv: kv?.(env),
|
|
1504
|
-
websocket: websocket?.(env)
|
|
1505
|
-
});
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
1702
|
export {
|
|
1509
|
-
|
|
1703
|
+
exports_runtime as worker,
|
|
1510
1704
|
exports_kv as kv,
|
|
1511
1705
|
createWebSocketDO,
|
|
1512
1706
|
Ziex
|