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/index.js CHANGED
@@ -9,324 +9,108 @@ var __export = (target, all) => {
9
9
  });
10
10
  };
11
11
 
12
- // ../../vendor/jsz/js/src/zigjs.ts
13
- var NAN_PREFIX = 2146959360;
14
- var predefined = {
15
- nan: 0,
16
- null: 1,
17
- true: 2,
18
- false: 3,
19
- undefined: 4,
20
- globalThis: 5,
21
- runtime: 6
22
- };
23
- var PREDEFINED_ID_MAX = 6;
12
+ // src/runtime.ts
13
+ var exports_runtime = {};
14
+ __export(exports_runtime, {
15
+ run: () => run,
16
+ buildWsImports: () => buildWsImports,
17
+ attachWebSocket: () => attachWebSocket
18
+ });
19
+
20
+ // src/wasm/wasi.ts
21
+ var decoder = new TextDecoder;
24
22
  var encoder = new TextEncoder;
25
- var decoder = new TextDecoder("utf-8");
26
23
 
27
- class ZigJS {
28
- memory;
29
- values = [NaN, null, true, false, undefined, globalThis, this];
30
- idPool = [];
31
- importObject() {
32
- return {
33
- "zig-js": {
34
- valueGet: this.valueGet.bind(this),
35
- valueSet: this.valueSet.bind(this),
36
- valueDeinit: this.valueDeinit.bind(this),
37
- valueObjectCreate: this.valueObjectCreate.bind(this),
38
- valueStringCreate: this.valueStringCreate.bind(this),
39
- valueStringLen: this.valueStringLen.bind(this),
40
- valueStringCopy: this.valueStringCopy.bind(this),
41
- valueNew: this.valueNew.bind(this),
42
- funcApply: this.funcApply.bind(this)
43
- }
44
- };
45
- }
46
- valueGet(out, id, ptr, len) {
47
- const val = this.loadValue(id);
48
- const str = this.loadString(ptr, len);
49
- const result = Reflect.get(val, str);
50
- this.storeValue(out, result);
51
- }
52
- valueSet(id, ptr, len, refAddr) {
53
- const obj = this.loadValue(id);
54
- const str = this.loadString(ptr, len);
55
- const val = this.loadRef(refAddr);
56
- Reflect.set(obj, str, val);
57
- }
58
- valueDeinit(id) {
59
- if (id > PREDEFINED_ID_MAX) {
60
- this.values[id] = null;
61
- this.idPool.push(id);
62
- }
63
- }
64
- valueObjectCreate(out) {
65
- this.storeValue(out, new Object);
66
- }
67
- valueStringCreate(out, ptr, len) {
68
- const str = this.loadString(ptr, len);
69
- this.storeValue(out, str);
70
- }
71
- valueStringLen(id) {
72
- const val = this.loadValue(id);
73
- const buf = encoder.encode(val);
74
- return buf.byteLength;
75
- }
76
- valueStringCopy(id, ptr, max) {
77
- if (this.memory == null)
78
- return;
79
- const val = this.loadValue(id);
80
- const bytes = encoder.encode(val);
81
- if (bytes.byteLength > max)
82
- return;
83
- new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
84
- }
85
- valueNew(out, id, argsAddr, argsLen) {
86
- const fn = this.loadValue(id);
87
- const args = [];
88
- for (let i = 0;i < argsLen; i++) {
89
- args.push(this.loadRef(argsAddr + i * 8));
90
- }
91
- const result = Reflect.construct(fn, args);
92
- this.storeValue(out, result);
24
+ class ZxWasiBridge {
25
+ #alloc;
26
+ #fetchCompleteHandler;
27
+ #memory;
28
+ #cb;
29
+ #intervals = new Map;
30
+ #memView = null;
31
+ #memBuf = null;
32
+ constructor(exports) {
33
+ this.#memory = exports.memory;
34
+ this.#alloc = exports.__zx_alloc;
35
+ this.#fetchCompleteHandler = exports.__zx_fetch_complete;
36
+ this.#cb = exports.__zx_cb;
93
37
  }
94
- funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
95
- const fn = this.loadValue(id);
96
- const thisVal = this.loadRef(thisRefAddr);
97
- const args = [];
98
- for (let i = 0;i < argsLen; i++) {
99
- args.push(this.loadRef(argsAddr + i * 8));
38
+ #view() {
39
+ const buf = this.#memory.buffer;
40
+ if (buf !== this.#memBuf) {
41
+ this.#memBuf = buf;
42
+ this.#memView = new Uint8Array(buf);
100
43
  }
101
- const result = Reflect.apply(fn, thisVal, args);
102
- this.storeValue(out, result);
103
- }
104
- loadValue(id) {
105
- return this.values[id];
44
+ return this.#memView;
106
45
  }
107
- deleteValue(id) {
108
- const val = this.values[id];
109
- this.valueDeinit(id);
110
- return val;
111
- }
112
- loadRef(refAddr) {
113
- if (this.memory == null)
114
- return;
115
- const view = new DataView(this.memory.buffer);
116
- const floatVal = view.getFloat64(refAddr, true);
117
- if (!isNaN(floatVal))
118
- return floatVal;
119
- const id = this.loadRefId(refAddr);
120
- return this.values[id];
46
+ #readString(ptr, len) {
47
+ return decoder.decode(this.#view().subarray(ptr, ptr + len));
121
48
  }
122
- loadRefId(refAddr) {
123
- if (this.memory == null)
124
- return 0;
125
- return new DataView(this.memory.buffer).getUint32(refAddr, true);
49
+ #writeBytes(ptr, data) {
50
+ this.#view().set(data, ptr);
126
51
  }
127
- storeValue(out, val) {
128
- if (this.memory == null)
129
- return;
130
- const view = new DataView(this.memory.buffer);
131
- if (typeof val === "number") {
132
- if (isNaN(val)) {
133
- view.setUint32(out, predefined.nan, true);
134
- view.setUint32(out + 4, NAN_PREFIX, true);
135
- } else {
136
- view.setFloat64(out, val, true);
137
- }
138
- return;
139
- }
140
- if (val === null) {
141
- view.setUint32(out, predefined.null, true);
142
- view.setUint32(out + 4, NAN_PREFIX, true);
143
- return;
144
- }
145
- if (val === undefined) {
146
- view.setUint32(out, predefined.undefined, true);
147
- view.setUint32(out + 4, NAN_PREFIX, true);
148
- return;
149
- }
150
- let id = this.idPool.pop();
151
- if (id === undefined) {
152
- id = this.values.length;
153
- }
154
- this.values[id] = val;
155
- let typeId = 0;
156
- switch (typeof val) {
157
- case "object":
158
- typeId = 1;
52
+ log(level, ptr, len) {
53
+ const msg = decoder.decode(this.#view().subarray(ptr, ptr + len));
54
+ switch (level) {
55
+ case 0:
56
+ console.error(msg);
159
57
  break;
160
- case "string":
161
- typeId = 2;
58
+ case 1:
59
+ console.warn(msg);
162
60
  break;
163
- case "symbol":
164
- typeId = 3;
61
+ case 3:
62
+ console.debug(msg);
165
63
  break;
166
- case "function":
167
- typeId = 4;
64
+ default:
65
+ console.log(msg);
168
66
  break;
169
67
  }
170
- view.setUint32(out, Number(id), true);
171
- view.setUint32(out + 4, NAN_PREFIX | typeId, true);
172
- }
173
- loadString(ptr, len) {
174
- if (this.memory == null)
175
- return "";
176
- const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
177
- const data = arr.slice();
178
- return decoder.decode(data);
179
- }
180
- }
181
- // src/wasm/index.ts
182
- var CallbackType = {
183
- Event: 0,
184
- FetchSuccess: 1,
185
- FetchError: 2,
186
- Timeout: 3,
187
- Interval: 4,
188
- WebSocketOpen: 5,
189
- WebSocketMessage: 6,
190
- WebSocketError: 7,
191
- WebSocketClose: 8
192
- };
193
- var jsz = new ZigJS;
194
- var tempRefBuffer = new ArrayBuffer(8);
195
- var tempRefView = new DataView(tempRefBuffer);
196
- function storeValueGetRef(val) {
197
- const originalMemory = jsz.memory;
198
- jsz.memory = { buffer: tempRefBuffer };
199
- jsz.storeValue(0, val);
200
- jsz.memory = originalMemory;
201
- return tempRefView.getBigUint64(0, true);
202
- }
203
- var textDecoder = new TextDecoder;
204
- var textEncoder = new TextEncoder;
205
- var memoryView = null;
206
- var memoryBuffer = null;
207
- function getMemoryView() {
208
- const buf = jsz.memory.buffer;
209
- if (buf !== memoryBuffer) {
210
- memoryBuffer = buf;
211
- memoryView = new Uint8Array(buf);
212
- }
213
- return memoryView;
214
- }
215
- var stringCache = new Map;
216
- function stringCacheKey(ptr, len) {
217
- return ptr * 65536 + len;
218
- }
219
- function readString(ptr, len) {
220
- const key = stringCacheKey(ptr, len);
221
- const cached = stringCache.get(key);
222
- if (cached !== undefined)
223
- return cached;
224
- const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
225
- stringCache.set(key, str);
226
- return str;
227
- }
228
- function writeBytes(ptr, data) {
229
- getMemoryView().set(data, ptr);
230
- }
231
-
232
- class ZxBridge {
233
- #intervals = new Map;
234
- #websockets = new Map;
235
- #alloc;
236
- #handler;
237
- #fetchCompleteHandler;
238
- #wsOnOpenHandler;
239
- #wsOnMessageHandler;
240
- #wsOnErrorHandler;
241
- #wsOnCloseHandler;
242
- constructor(exports) {
243
- this.#alloc = exports.__zx_alloc;
244
- this.#handler = exports.__zx_cb;
245
- this.#fetchCompleteHandler = exports.__zx_fetch_complete;
246
- this.#wsOnOpenHandler = exports.__zx_ws_onopen;
247
- this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
248
- this.#wsOnErrorHandler = exports.__zx_ws_onerror;
249
- this.#wsOnCloseHandler = exports.__zx_ws_onclose;
250
- this.#eventbridge = exports.__zx_eventbridge;
251
- }
252
- #invoke(type, id, data) {
253
- const handler = this.#handler;
254
- if (!handler) {
255
- console.warn("__zx_cb not exported from WASM");
256
- return;
257
- }
258
- const dataRef = storeValueGetRef(data);
259
- handler(type, id, dataRef);
260
68
  }
261
69
  fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
262
- const url = readString(urlPtr, urlLen);
263
- const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
264
- const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
265
- const body = bodyLen > 0 ? readString(bodyPtr, bodyLen) : undefined;
70
+ const url = this.#readString(urlPtr, urlLen);
71
+ const method = methodLen > 0 ? this.#readString(methodPtr, methodLen) : "GET";
72
+ const headersJson = headersLen > 0 ? this.#readString(headersPtr, headersLen) : "{}";
73
+ const body = bodyLen > 0 ? this.#readString(bodyPtr, bodyLen) : undefined;
266
74
  let headers = {};
267
75
  try {
268
76
  headers = JSON.parse(headersJson);
269
77
  } catch {
270
78
  for (const line of headersJson.split(`
271
79
  `)) {
272
- const colonIdx = line.indexOf(":");
273
- if (colonIdx > 0) {
274
- headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
275
- }
80
+ const i = line.indexOf(":");
81
+ if (i > 0)
82
+ headers[line.slice(0, i)] = line.slice(i + 1);
276
83
  }
277
84
  }
278
85
  const controller = new AbortController;
279
86
  const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
280
- const fetchOptions = {
87
+ fetch(url, {
281
88
  method,
282
89
  headers: Object.keys(headers).length > 0 ? headers : undefined,
283
90
  body: method !== "GET" && method !== "HEAD" ? body : undefined,
284
91
  signal: controller.signal
285
- };
286
- fetch(url, fetchOptions).then(async (response) => {
92
+ }).then(async (res) => {
287
93
  if (timeout)
288
94
  clearTimeout(timeout);
289
- const text = await response.text();
290
- this.#notifyFetchComplete(fetchId, response.status, text, false);
291
- }).catch((error) => {
95
+ this.#notifyFetchComplete(fetchId, res.status, await res.text(), false);
96
+ }).catch((err) => {
292
97
  if (timeout)
293
98
  clearTimeout(timeout);
294
- const isAbort = error.name === "AbortError";
295
- const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
296
- this.#notifyFetchComplete(fetchId, 0, errorMsg, true);
99
+ const msg = err.name === "AbortError" ? "Request timeout" : err.message ?? "Fetch failed";
100
+ this.#notifyFetchComplete(fetchId, 0, msg, true);
297
101
  });
298
102
  }
299
- #notifyFetchComplete(fetchId, statusCode, body, isError) {
300
- const handler = this.#fetchCompleteHandler;
301
- const encoded = textEncoder.encode(body);
103
+ #notifyFetchComplete(fetchId, status, body, isError) {
104
+ const encoded = encoder.encode(body);
302
105
  const ptr = this.#alloc(encoded.length);
303
- writeBytes(ptr, encoded);
304
- handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
305
- }
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
- });
106
+ this.#writeBytes(ptr, encoded);
107
+ this.#fetchCompleteHandler(fetchId, status, ptr, encoded.length, isError ? 1 : 0);
320
108
  }
321
109
  setTimeout(callbackId, delayMs) {
322
- setTimeout(() => {
323
- this.#invoke(CallbackType.Timeout, callbackId, null);
324
- }, delayMs);
110
+ setTimeout(() => this.#cb?.(3, callbackId, 0n), delayMs);
325
111
  }
326
112
  setInterval(callbackId, intervalMs) {
327
- const handle = setInterval(() => {
328
- this.#invoke(CallbackType.Interval, callbackId, null);
329
- }, intervalMs);
113
+ const handle = setInterval(() => this.#cb?.(4, callbackId, 0n), intervalMs);
330
114
  this.#intervals.set(callbackId, handle);
331
115
  }
332
116
  clearInterval(callbackId) {
@@ -336,108 +120,12 @@ class ZxBridge {
336
120
  this.#intervals.delete(callbackId);
337
121
  }
338
122
  }
339
- wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
340
- const url = readString(urlPtr, urlLen);
341
- const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
342
- const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : undefined;
343
- try {
344
- const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
345
- ws.binaryType = "arraybuffer";
346
- ws.onopen = () => {
347
- const handler = this.#wsOnOpenHandler;
348
- if (!handler)
349
- return;
350
- const protocol = ws.protocol || "";
351
- const { ptr, len } = this.#writeStringToWasm(protocol);
352
- handler(wsId, ptr, len);
353
- };
354
- ws.onmessage = (event) => {
355
- const handler = this.#wsOnMessageHandler;
356
- if (!handler)
357
- return;
358
- const isBinary = event.data instanceof ArrayBuffer;
359
- let data;
360
- if (isBinary) {
361
- data = new Uint8Array(event.data);
362
- } else {
363
- data = textEncoder.encode(event.data);
364
- }
365
- const { ptr, len } = this.#writeBytesToWasm(data);
366
- handler(wsId, ptr, len, isBinary ? 1 : 0);
367
- };
368
- ws.onerror = (event) => {
369
- const handler = this.#wsOnErrorHandler;
370
- if (!handler)
371
- return;
372
- const msg = "WebSocket error";
373
- const { ptr, len } = this.#writeStringToWasm(msg);
374
- handler(wsId, ptr, len);
375
- };
376
- ws.onclose = (event) => {
377
- const handler = this.#wsOnCloseHandler;
378
- if (!handler)
379
- return;
380
- const reason = event.reason || "";
381
- const { ptr, len } = this.#writeStringToWasm(reason);
382
- handler(wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
383
- this.#websockets.delete(wsId);
384
- };
385
- this.#websockets.set(wsId, ws);
386
- } catch (error) {
387
- const handler = this.#wsOnErrorHandler;
388
- if (handler) {
389
- const msg = error instanceof Error ? error.message : "WebSocket connection failed";
390
- const { ptr, len } = this.#writeStringToWasm(msg);
391
- handler(wsId, ptr, len);
392
- }
393
- }
394
- }
395
- wsSend(wsId, dataPtr, dataLen, isBinary) {
396
- const ws = this.#websockets.get(wsId);
397
- if (!ws || ws.readyState !== WebSocket.OPEN)
398
- return;
399
- const memory = getMemoryView();
400
- if (isBinary) {
401
- ws.send(memory.slice(dataPtr, dataPtr + dataLen));
402
- } else {
403
- ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
404
- }
405
- }
406
- wsClose(wsId, code, reasonPtr, reasonLen) {
407
- const ws = this.#websockets.get(wsId);
408
- if (!ws)
409
- return;
410
- const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
411
- try {
412
- if (reason) {
413
- ws.close(code, reason);
414
- } else {
415
- ws.close(code);
416
- }
417
- } catch {
418
- ws.close();
419
- }
420
- }
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
- eventbridge(velementId, eventTypeId, event) {
432
- if (!this.#eventbridge)
433
- return;
434
- const eventRef = storeValueGetRef(event);
435
- this.#eventbridge(velementId, eventTypeId, eventRef);
436
- }
437
123
  static createImportObject(bridgeRef) {
438
124
  return {
439
- ...jsz.importObject(),
440
125
  __zx: {
126
+ _log: (level, ptr, len) => {
127
+ bridgeRef.current?.log(level, ptr, len);
128
+ },
441
129
  _fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
442
130
  bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
443
131
  },
@@ -449,409 +137,13 @@ class ZxBridge {
449
137
  },
450
138
  _clearInterval: (callbackId) => {
451
139
  bridgeRef.current?.clearInterval(callbackId);
452
- },
453
- _wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
454
- bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
455
- },
456
- _wsSend: (wsId, dataPtr, dataLen, isBinary) => {
457
- bridgeRef.current?.wsSend(wsId, dataPtr, dataLen, isBinary);
458
- },
459
- _wsClose: (wsId, code, reasonPtr, reasonLen) => {
460
- bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
461
- },
462
- _ce: (id, vnodeId) => {
463
- const tagName = TAG_NAMES[id];
464
- const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
465
- el.__zx_ref = Number(vnodeId);
466
- domNodes.set(vnodeId, el);
467
- return storeValueGetRef(el);
468
- },
469
- _ct: (ptr, len, vnodeId) => {
470
- const text = readString(ptr, len);
471
- const node = document.createTextNode(text);
472
- node.__zx_ref = Number(vnodeId);
473
- domNodes.set(vnodeId, node);
474
- return storeValueGetRef(node);
475
- },
476
- _sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
477
- domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
478
- },
479
- _ra: (vnodeId, namePtr, nameLen) => {
480
- domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
481
- },
482
- _snv: (vnodeId, ptr, len) => {
483
- const node = domNodes.get(vnodeId);
484
- if (node)
485
- node.nodeValue = readString(ptr, len);
486
- },
487
- _ac: (parentId, childId) => {
488
- const parent = domNodes.get(parentId);
489
- const child = domNodes.get(childId);
490
- if (parent && child)
491
- parent.appendChild(child);
492
- },
493
- _ib: (parentId, childId, refId) => {
494
- const parent = domNodes.get(parentId);
495
- const child = domNodes.get(childId);
496
- const ref = domNodes.get(refId) ?? null;
497
- if (parent && child)
498
- parent.insertBefore(child, ref);
499
- },
500
- _rc: (parentId, childId) => {
501
- const parent = domNodes.get(parentId);
502
- const child = domNodes.get(childId);
503
- if (parent && child) {
504
- parent.removeChild(child);
505
- cleanupDomNodes(child);
506
- }
507
- },
508
- _rpc: (parentId, newId, oldId) => {
509
- const parent = domNodes.get(parentId);
510
- const newChild = domNodes.get(newId);
511
- const oldChild = domNodes.get(oldId);
512
- if (parent && newChild && oldChild) {
513
- parent.replaceChild(newChild, oldChild);
514
- cleanupDomNodes(oldChild);
515
- }
516
- },
517
- _getLocationHref: (bufPtr, bufLen) => {
518
- const bytes = textEncoder.encode(window.location.href);
519
- const len = Math.min(bytes.length, bufLen);
520
- writeBytes(bufPtr, bytes.subarray(0, len));
521
- return len;
522
- },
523
- _getFormData: (vnodeId, bufPtr, bufLen) => {
524
- const form = domNodes.get(vnodeId);
525
- if (!form || !(form instanceof HTMLFormElement))
526
- return 0;
527
- const formData = new FormData(form);
528
- const urlEncoded = new URLSearchParams(formData).toString();
529
- const bytes = textEncoder.encode(urlEncoded);
530
- const len = Math.min(bytes.length, bufLen);
531
- writeBytes(bufPtr, bytes.subarray(0, len));
532
- return len;
533
- },
534
- _submitFormAction: (vnodeId) => {
535
- const form = domNodes.get(vnodeId);
536
- if (!form || !(form instanceof HTMLFormElement))
537
- return;
538
- const formData = new FormData(form);
539
- fetch(window.location.href, {
540
- method: "POST",
541
- headers: { "X-ZX-Action": "1" },
542
- body: formData
543
- }).catch(() => {});
544
- },
545
- _submitFormActionAsync: (vnodeId, statesPtr, statesLen, fetchId) => {
546
- const form = domNodes.get(vnodeId);
547
- if (!form || !(form instanceof HTMLFormElement))
548
- return;
549
- const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
550
- bridgeRef.current?.submitFormActionAsync(form, statesJson, fetchId);
551
140
  }
552
141
  }
553
142
  };
554
143
  }
555
144
  }
556
- var domNodes = new Map;
557
- function cleanupDomNodes(node) {
558
- const ref = node.__zx_ref;
559
- if (ref !== undefined)
560
- domNodes.delete(BigInt(ref));
561
- const children = node.childNodes;
562
- for (let i = 0;i < children.length; i++)
563
- cleanupDomNodes(children[i]);
564
- }
565
- var SVG_TAG_START_INDEX = 140;
566
- var TAG_NAMES = [
567
- "aside",
568
- "fragment",
569
- "iframe",
570
- "slot",
571
- "img",
572
- "html",
573
- "base",
574
- "head",
575
- "link",
576
- "meta",
577
- "script",
578
- "style",
579
- "title",
580
- "address",
581
- "article",
582
- "body",
583
- "h1",
584
- "h6",
585
- "footer",
586
- "header",
587
- "h2",
588
- "h3",
589
- "h4",
590
- "h5",
591
- "hgroup",
592
- "nav",
593
- "section",
594
- "dd",
595
- "dl",
596
- "dt",
597
- "div",
598
- "figcaption",
599
- "figure",
600
- "hr",
601
- "li",
602
- "ol",
603
- "ul",
604
- "menu",
605
- "main",
606
- "p",
607
- "picture",
608
- "pre",
609
- "a",
610
- "abbr",
611
- "b",
612
- "bdi",
613
- "bdo",
614
- "br",
615
- "cite",
616
- "code",
617
- "data",
618
- "time",
619
- "dfn",
620
- "em",
621
- "i",
622
- "kbd",
623
- "mark",
624
- "q",
625
- "blockquote",
626
- "rp",
627
- "ruby",
628
- "rt",
629
- "rtc",
630
- "rb",
631
- "s",
632
- "del",
633
- "ins",
634
- "samp",
635
- "small",
636
- "span",
637
- "strong",
638
- "sub",
639
- "sup",
640
- "u",
641
- "var",
642
- "wbr",
643
- "area",
644
- "map",
645
- "audio",
646
- "source",
647
- "track",
648
- "video",
649
- "embed",
650
- "object",
651
- "param",
652
- "canvas",
653
- "noscript",
654
- "caption",
655
- "table",
656
- "col",
657
- "colgroup",
658
- "tbody",
659
- "tr",
660
- "thead",
661
- "tfoot",
662
- "td",
663
- "th",
664
- "button",
665
- "datalist",
666
- "option",
667
- "fieldset",
668
- "label",
669
- "form",
670
- "input",
671
- "keygen",
672
- "legend",
673
- "meter",
674
- "optgroup",
675
- "select",
676
- "output",
677
- "progress",
678
- "textarea",
679
- "details",
680
- "dialog",
681
- "menuitem",
682
- "summary",
683
- "content",
684
- "element",
685
- "shadow",
686
- "template",
687
- "acronym",
688
- "applet",
689
- "basefont",
690
- "font",
691
- "big",
692
- "blink",
693
- "center",
694
- "command",
695
- "dir",
696
- "frame",
697
- "frameset",
698
- "isindex",
699
- "listing",
700
- "marquee",
701
- "noembed",
702
- "plaintext",
703
- "spacer",
704
- "strike",
705
- "tt",
706
- "xmp",
707
- "animate",
708
- "animateMotion",
709
- "animateTransform",
710
- "circle",
711
- "clipPath",
712
- "defs",
713
- "desc",
714
- "ellipse",
715
- "feBlend",
716
- "feColorMatrix",
717
- "feComponentTransfer",
718
- "feComposite",
719
- "feConvolveMatrix",
720
- "feDiffuseLighting",
721
- "feDisplacementMap",
722
- "feDistantLight",
723
- "feDropShadow",
724
- "feFlood",
725
- "feFuncA",
726
- "feFuncB",
727
- "feFuncG",
728
- "feFuncR",
729
- "feGaussianBlur",
730
- "feImage",
731
- "feMerge",
732
- "feMergeNode",
733
- "feMorphology",
734
- "feOffset",
735
- "fePointLight",
736
- "feSpecularLighting",
737
- "feSpotLight",
738
- "feTile",
739
- "feTurbulence",
740
- "filter",
741
- "foreignObject",
742
- "g",
743
- "image",
744
- "line",
745
- "linearGradient",
746
- "marker",
747
- "mask",
748
- "metadata",
749
- "mpath",
750
- "path",
751
- "pattern",
752
- "polygon",
753
- "polyline",
754
- "radialGradient",
755
- "rect",
756
- "set",
757
- "stop",
758
- "svg",
759
- "switch",
760
- "symbol",
761
- "text",
762
- "textPath",
763
- "tspan",
764
- "use",
765
- "view"
766
- ];
767
- var DELEGATED_EVENTS = [
768
- "click",
769
- "dblclick",
770
- "input",
771
- "change",
772
- "submit",
773
- "focus",
774
- "blur",
775
- "keydown",
776
- "keyup",
777
- "keypress",
778
- "mouseenter",
779
- "mouseleave",
780
- "mousedown",
781
- "mouseup",
782
- "mousemove",
783
- "touchstart",
784
- "touchend",
785
- "touchmove",
786
- "scroll"
787
- ];
788
- var EVENT_TYPE_MAP = {
789
- click: 0,
790
- dblclick: 1,
791
- input: 2,
792
- change: 3,
793
- submit: 4,
794
- focus: 5,
795
- blur: 6,
796
- keydown: 7,
797
- keyup: 8,
798
- keypress: 9,
799
- mouseenter: 10,
800
- mouseleave: 11,
801
- mousedown: 12,
802
- mouseup: 13,
803
- mousemove: 14,
804
- touchstart: 15,
805
- touchend: 16,
806
- touchmove: 17,
807
- scroll: 18
808
- };
809
- function initEventDelegation(bridge, rootSelector = "body") {
810
- const root = document.querySelector(rootSelector);
811
- if (!root)
812
- return;
813
- for (const eventType of DELEGATED_EVENTS) {
814
- root.addEventListener(eventType, (event) => {
815
- let target = event.target;
816
- while (target && target !== document.body) {
817
- const zxRef = target.__zx_ref;
818
- if (zxRef !== undefined) {
819
- bridge.eventbridge(BigInt(zxRef), EVENT_TYPE_MAP[eventType] ?? 0, event);
820
- if (event.cancelBubble)
821
- break;
822
- }
823
- target = target.parentElement;
824
- }
825
- }, { passive: eventType.startsWith("touch") || eventType === "scroll" });
826
- }
827
- }
828
- var DEFAULT_URL = "/assets/main.wasm";
829
- async function init(options = {}) {
830
- const url = options.url ?? DEFAULT_URL;
831
- const bridgeRef = { current: null };
832
- const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), options.importObject);
833
- const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
834
- const { instance } = source;
835
- jsz.memory = instance.exports.memory;
836
- const bridge = new ZxBridge(instance.exports);
837
- bridgeRef.current = bridge;
838
- initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
839
- const main = instance.exports.mainClient;
840
- if (typeof main === "function")
841
- main();
842
- return { source, bridge };
843
- }
844
-
845
- // src/cloudflare/worker.ts
846
- var exports_worker = {};
847
- __export(exports_worker, {
848
- run: () => run,
849
- respond: () => respond,
850
- prepare: () => prepare,
851
- createWebSocketDO: () => createWebSocketDO
852
- });
853
145
 
854
- // src/cloudflare/kv.ts
146
+ // src/kv.ts
855
147
  var exports_kv = {};
856
148
  __export(exports_kv, {
857
149
  createMemoryKV: () => createMemoryKV,
@@ -881,7 +173,7 @@ function createKVImports(bindings, getMemory) {
881
173
  function readStr(ptr, len) {
882
174
  return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
883
175
  }
884
- function writeBytes2(buf_ptr, buf_max, data) {
176
+ function writeBytes(buf_ptr, buf_max, data) {
885
177
  if (data.length > buf_max)
886
178
  return -2;
887
179
  new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
@@ -896,7 +188,7 @@ function createKVImports(bindings, getMemory) {
896
188
  kv_get: (_ns, _nsLen, _key, _keyLen, _buf, _max) => -1,
897
189
  kv_put: (_ns, _nsLen, _key, _keyLen, _val, _valLen) => 0,
898
190
  kv_delete: (_ns, _nsLen, _key, _keyLen) => 0,
899
- kv_list: (_ns, _nsLen, _pfx, _pfxLen, buf_ptr, buf_max) => writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"))
191
+ kv_list: (_ns, _nsLen, _pfx, _pfxLen, buf_ptr, buf_max) => writeBytes(buf_ptr, buf_max, encoder2.encode("[]"))
900
192
  };
901
193
  }
902
194
  return {
@@ -907,7 +199,7 @@ function createKVImports(bindings, getMemory) {
907
199
  const value = await b.get(readStr(key_ptr, key_len));
908
200
  if (value === null)
909
201
  return -1;
910
- return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
202
+ return writeBytes(buf_ptr, buf_max, encoder2.encode(value));
911
203
  }),
912
204
  kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
913
205
  const b = binding(readStr(ns_ptr, ns_len));
@@ -926,15 +218,15 @@ function createKVImports(bindings, getMemory) {
926
218
  kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
927
219
  const b = binding(readStr(ns_ptr, ns_len));
928
220
  if (!b)
929
- return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
221
+ return writeBytes(buf_ptr, buf_max, encoder2.encode("[]"));
930
222
  const prefix = readStr(prefix_ptr, prefix_len);
931
223
  const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
932
- return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
224
+ return writeBytes(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
933
225
  })
934
226
  };
935
227
  }
936
228
 
937
- // src/cloudflare/worker.ts
229
+ // src/wasi.ts
938
230
  class ProcExit extends Error {
939
231
  code;
940
232
  constructor(code) {
@@ -948,7 +240,6 @@ function createWasiImports({
948
240
  onStdout
949
241
  }) {
950
242
  const encoder2 = new TextEncoder;
951
- const decoder2 = new TextDecoder;
952
243
  const url = new URL(request.url);
953
244
  const argStrings = [
954
245
  "wasm",
@@ -970,7 +261,23 @@ function createWasiImports({
970
261
  wasmMemory = m2;
971
262
  };
972
263
  const stdoutChunks = [];
973
- const stderrChunks = [];
264
+ let stderrMeta = "";
265
+ let stderrPartial = "";
266
+ const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
267
+ function processStderrChunk(chunk) {
268
+ const text = stderrDecoder.decode(chunk, { stream: true });
269
+ const lines = (stderrPartial + text).split(`
270
+ `);
271
+ stderrPartial = lines.pop() ?? "";
272
+ for (const line of lines) {
273
+ if (line.startsWith("__EDGE_META__:")) {
274
+ stderrMeta += line + `
275
+ `;
276
+ } else if (line.length > 0) {
277
+ console.error("[ziex]", line);
278
+ }
279
+ }
280
+ }
974
281
  let stdinOffset = 0;
975
282
  function v() {
976
283
  return new DataView(wasmMemory.buffer);
@@ -1018,7 +325,7 @@ function createWasiImports({
1018
325
  else
1019
326
  stdoutChunks.push(chunk);
1020
327
  } else if (fd === 2)
1021
- stderrChunks.push(chunk);
328
+ processStderrChunk(chunk);
1022
329
  written += buf_len;
1023
330
  }
1024
331
  dv.setUint32(nwritten_ptr, written, true);
@@ -1133,104 +440,34 @@ function createWasiImports({
1133
440
  }
1134
441
  };
1135
442
  function collectOutput() {
443
+ const remaining = stderrDecoder.decode(undefined, { stream: false });
444
+ const tail = stderrPartial + remaining;
445
+ if (tail.length > 0) {
446
+ if (tail.startsWith("__EDGE_META__:"))
447
+ stderrMeta += tail;
448
+ else
449
+ console.error("[ziex]", tail);
450
+ stderrPartial = "";
451
+ }
1136
452
  return {
1137
453
  stdout: mergeUint8Arrays(stdoutChunks),
1138
- stderrText: decoder2.decode(mergeUint8Arrays(stderrChunks))
454
+ stderrText: stderrMeta
1139
455
  };
1140
456
  }
1141
457
  return { wasiImport, setMemory, collectOutput };
1142
458
  }
1143
- async function run({
1144
- request,
1145
- env,
1146
- ctx,
1147
- module,
1148
- kv: kvBindings,
1149
- imports,
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 });
459
+ function mergeUint8Arrays(arrays) {
460
+ const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
461
+ const result = new Uint8Array(totalLen);
462
+ let offset = 0;
463
+ for (const arr of arrays) {
464
+ result.set(arr, offset);
465
+ offset += arr.length;
1226
466
  }
1227
- const { stderrText } = collectOutput();
1228
- const meta = parseEdgeMeta(stderrText);
1229
- return new Response(readable, {
1230
- status: meta.status,
1231
- headers: meta.headers
1232
- });
467
+ return result;
1233
468
  }
469
+
470
+ // src/runtime.ts
1234
471
  function buildWsImports(Suspending, mem, decoder2, ws) {
1235
472
  const readStr = (ptr, len) => decoder2.decode(new Uint8Array(mem().buffer, ptr, len));
1236
473
  return {
@@ -1310,102 +547,36 @@ function attachWebSocket(ws) {
1310
547
  });
1311
548
  return { client };
1312
549
  }
1313
- function createWebSocketDO(module, options) {
1314
- return class ZxWebSocketDO {
1315
- doState;
1316
- env;
1317
- connections = new Map;
1318
- constructor(state, env) {
1319
- this.doState = state;
1320
- this.env = env;
550
+ function buildSysImports(jspi, Suspending) {
551
+ return {
552
+ sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
553
+ };
554
+ }
555
+ function executeWasm(instance, jspi, Suspending, wsState) {
556
+ if (!jspi) {
557
+ try {
558
+ instance.exports._start();
559
+ } catch (e) {
560
+ if (!(e instanceof ProcExit))
561
+ throw e;
1321
562
  }
1322
- async fetch(request) {
1323
- const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
1324
- const { wasiImport, setMemory } = createWasiImports({ request, stdinData });
1325
- let wasmMemory = null;
1326
- const mem = () => wasmMemory;
1327
- const bridgeRef = { current: null };
1328
- const bridgeImports = ZxBridge.createImportObject(bridgeRef);
1329
- const Suspending = WebAssembly.Suspending;
1330
- const jspi = typeof Suspending === "function";
1331
- const decoder2 = new TextDecoder;
1332
- let _resolveFirstSuspend;
1333
- const firstSuspendPromise = new Promise((resolve) => {
1334
- _resolveFirstSuspend = resolve;
1335
- });
1336
- let wasmExited = false;
1337
- const connState = {
1338
- upgraded: false,
1339
- server: null,
1340
- pendingWrites: [],
1341
- messageQueue: [],
1342
- recvResolve: null,
1343
- _resolveFirstSuspend,
1344
- topics: new Set,
1345
- subscribe: (topic) => connState.topics.add(topic),
1346
- unsubscribe: (topic) => connState.topics.delete(topic),
1347
- publish: (topic, data) => {
1348
- let count = 0;
1349
- for (const [ws, conn] of this.connections) {
1350
- if (conn.topics.has(topic)) {
1351
- try {
1352
- ws.send(data);
1353
- count++;
1354
- } catch {}
1355
- }
1356
- }
1357
- if (!connState.server && connState.topics.has(topic)) {
1358
- connState.pendingWrites.push(data.slice());
1359
- count++;
1360
- }
1361
- return count;
1362
- },
1363
- isSubscribed: (topic) => connState.topics.has(topic)
1364
- };
1365
- const sysImports = {
1366
- sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
1367
- };
1368
- const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder2, connState);
1369
- const kvBindings = options?.kv?.(this.env);
1370
- const instance = new WebAssembly.Instance(module, {
1371
- wasi_snapshot_preview1: wasiImport,
1372
- __zx_sys: sysImports,
1373
- __zx_ws: wsImports,
1374
- __zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
1375
- ...options?.imports ? options.imports(mem) : {},
1376
- ...bridgeImports
1377
- });
1378
- wasmMemory = instance.exports.memory;
1379
- setMemory(wasmMemory);
1380
- bridgeRef.current = new ZxBridge(instance.exports);
1381
- const start = WebAssembly.promising(instance.exports._start);
1382
- const wasmPromise = start().catch((e) => {
1383
- wasmExited = true;
1384
- if (e instanceof Error && e.message.startsWith("proc_exit"))
1385
- return;
1386
- console.error("[ZxWebSocketDO] WASM error:", e);
1387
- }).finally(() => {
1388
- if (connState.server)
1389
- this.connections.delete(connState.server);
1390
- if (connState.recvResolve) {
1391
- const res = connState.recvResolve;
1392
- connState.recvResolve = null;
1393
- res(null);
1394
- }
1395
- });
1396
- await Promise.race([firstSuspendPromise, wasmPromise]);
1397
- if (!connState.upgraded || wasmExited) {
1398
- return new Response("WebSocket upgrade expected", { status: 426 });
1399
- }
1400
- const { client } = attachWebSocket(connState);
1401
- this.connections.set(connState.server, connState);
1402
- this.doState.waitUntil(wasmPromise);
1403
- return new Response(null, { status: 101, webSocket: client });
563
+ return Promise.resolve();
564
+ }
565
+ const start = WebAssembly.promising(instance.exports._start);
566
+ return start().catch((e) => {
567
+ if (e instanceof Error && e.message.startsWith("proc_exit"))
568
+ return;
569
+ throw e;
570
+ }).finally(() => {
571
+ if (wsState.recvResolve) {
572
+ const res = wsState.recvResolve;
573
+ wsState.recvResolve = null;
574
+ res(null);
1404
575
  }
1405
- };
576
+ });
1406
577
  }
1407
578
  function parseEdgeMeta(stderrText) {
1408
- const meta = { status: 200, headers: new Headers };
579
+ const meta = { status: 200, headers: new Headers, streaming: false };
1409
580
  const metaPrefix = "__EDGE_META__:";
1410
581
  const metaLine = stderrText.split(`
1411
582
  `).find((line) => line.startsWith(metaPrefix));
@@ -1414,6 +585,8 @@ function parseEdgeMeta(stderrText) {
1414
585
  const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
1415
586
  if (parsed.status)
1416
587
  meta.status = parsed.status;
588
+ if (parsed.streaming === true)
589
+ meta.streaming = true;
1417
590
  if (Array.isArray(parsed.headers)) {
1418
591
  for (const [name, value] of parsed.headers) {
1419
592
  meta.headers.append(name, value);
@@ -1423,76 +596,132 @@ function parseEdgeMeta(stderrText) {
1423
596
  }
1424
597
  return meta;
1425
598
  }
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({
599
+ async function run({
1447
600
  request,
1448
601
  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
602
+ ctx,
603
+ module,
604
+ kv: kvBindings,
605
+ imports,
606
+ wasi,
607
+ websocket: doNamespace
1472
608
  }) {
609
+ if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
610
+ const id = doNamespace.idFromName(new URL(request.url).pathname);
611
+ return doNamespace.get(id).fetch(request);
612
+ }
613
+ const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
1473
614
  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
615
+ let streamWriter = null;
616
+ const { wasiImport, setMemory, collectOutput } = createWasiImports({
617
+ request,
618
+ stdinData,
619
+ onStdout: (chunk) => {
620
+ if (streamWriter)
621
+ streamWriter.write(chunk);
622
+ else
623
+ stdoutChunks.push(chunk);
624
+ }
1486
625
  });
626
+ let wasmMemory = null;
627
+ const mem = () => wasmMemory;
628
+ const bridgeRef = { current: null };
629
+ const Suspending = WebAssembly.Suspending;
630
+ const jspi = typeof Suspending === "function";
631
+ const wsState = {
632
+ upgraded: false,
633
+ server: null,
634
+ pendingWrites: [],
635
+ messageQueue: [],
636
+ recvResolve: null
637
+ };
638
+ const instance = new WebAssembly.Instance(module, {
639
+ wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
640
+ __zx_sys: buildSysImports(jspi, Suspending),
641
+ __zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder, wsState),
642
+ __zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
643
+ ...imports ? imports(mem) : {},
644
+ ...ZxWasiBridge.createImportObject(bridgeRef)
645
+ });
646
+ wasmMemory = instance.exports.memory;
647
+ setMemory(wasmMemory);
648
+ bridgeRef.current = new ZxWasiBridge(instance.exports);
649
+ const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
650
+ if (wsState.upgraded) {
651
+ const server = attachWebSocket(wsState);
652
+ ctx?.waitUntil(wasmPromise);
653
+ return new Response(null, { status: 101, webSocket: server.client });
654
+ }
655
+ const { stderrText } = collectOutput();
656
+ const meta = parseEdgeMeta(stderrText);
657
+ if (meta.streaming) {
658
+ const { readable, writable } = new TransformStream;
659
+ streamWriter = writable.getWriter();
660
+ for (const chunk of stdoutChunks)
661
+ streamWriter.write(chunk);
662
+ stdoutChunks.length = 0;
663
+ wasmPromise.finally(() => streamWriter?.close());
664
+ return new Response(readable, { status: meta.status, headers: meta.headers });
665
+ }
666
+ await wasmPromise;
667
+ const body = mergeUint8Arrays(stdoutChunks);
668
+ meta.headers.delete("transfer-encoding");
669
+ if (!meta.headers.has("content-length"))
670
+ meta.headers.set("content-length", String(body.byteLength));
671
+ return new Response(body.buffer, { status: meta.status, headers: meta.headers });
672
+ }
673
+
674
+ // src/app.ts
675
+ async function resolveModule(input) {
676
+ if (typeof input === "string") {
677
+ if (input.startsWith("http://") || input.startsWith("https://")) {
678
+ return WebAssembly.compileStreaming(fetch(input));
679
+ }
680
+ const url = input.startsWith("/") ? `file://${input}` : input;
681
+ return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
682
+ }
683
+ if (input instanceof URL) {
684
+ return WebAssembly.compileStreaming(fetch(input));
685
+ }
686
+ if (input instanceof Response) {
687
+ return WebAssembly.compileStreaming(input);
688
+ }
689
+ if (input instanceof ArrayBuffer) {
690
+ return WebAssembly.compile(input);
691
+ }
692
+ if (ArrayBuffer.isView(input)) {
693
+ return WebAssembly.compile(input.buffer);
694
+ }
695
+ return input;
1487
696
  }
1488
- // src/cloudflare/app.ts
697
+
1489
698
  class Ziex {
1490
699
  options;
700
+ resolved = null;
1491
701
  constructor(options) {
1492
702
  this.options = options;
1493
703
  }
1494
- fetch(request, env, ctx) {
1495
- const { module, wasi, imports, kv, websocket } = this.options;
704
+ async getModule() {
705
+ if (!this.resolved)
706
+ this.resolved = await resolveModule(this.options.module);
707
+ return this.resolved;
708
+ }
709
+ resolveKV(env) {
710
+ const { kv } = this.options;
711
+ if (kv === undefined)
712
+ return;
713
+ if (typeof kv === "object" && kv !== null) {
714
+ const result = {};
715
+ for (const [name, key] of Object.entries(kv)) {
716
+ result[name] = env[key];
717
+ }
718
+ return result;
719
+ }
720
+ return { default: env[kv] };
721
+ }
722
+ fetch = async (request, env, ctx) => {
723
+ const module = await this.getModule();
724
+ const { wasi, imports, websocket } = this.options;
1496
725
  return run({
1497
726
  request,
1498
727
  env,
@@ -1500,10 +729,10 @@ class Ziex {
1500
729
  module,
1501
730
  wasi,
1502
731
  imports,
1503
- kv: kv?.(env),
1504
- websocket: websocket?.(env)
732
+ kv: this.resolveKV(env),
733
+ websocket: websocket !== undefined ? env[websocket] : undefined
1505
734
  });
1506
- }
735
+ };
1507
736
  }
1508
737
  export {
1509
738
  Ziex