ziex 0.1.0-dev.785 → 0.1.0-dev.787
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/aws-lambda/index.d.ts +96 -0
- package/aws-lambda/index.js +126 -0
- package/cloudflare/app.d.ts +95 -0
- package/cloudflare/index.d.ts +2 -0
- package/cloudflare/index.js +1160 -58
- package/cloudflare/kv.d.ts +8 -0
- package/cloudflare/worker.d.ts +111 -2
- package/hono/index.d.ts +92 -0
- package/hono/index.js +1515 -0
- package/index.d.ts +1 -9
- package/index.js +1496 -46
- package/package.json +16 -2
- package/vercel/index.d.ts +26 -0
- package/vercel/index.js +18 -0
- package/wasm/index.d.ts +4 -5
- package/wasm/index.js +161 -55
- package/wasm/init.js +161 -39
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ziex",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.787",
|
|
4
4
|
"description": "ZX is a framework for building web applications with Zig.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
"./react": "./react/index.js",
|
|
10
10
|
"./wasm": "./wasm/index.js",
|
|
11
11
|
"./wasm/init": "./wasm/init.js",
|
|
12
|
-
"./cloudflare": "./cloudflare/index.js"
|
|
12
|
+
"./cloudflare": "./cloudflare/index.js",
|
|
13
|
+
"./hono": "./hono/index.js",
|
|
14
|
+
"./aws-lambda": "./aws-lambda/index.js",
|
|
15
|
+
"./vercel": "./vercel/index.js"
|
|
13
16
|
},
|
|
14
17
|
"homepage": "https://ziex.dev",
|
|
15
18
|
"repository": {
|
|
@@ -30,6 +33,17 @@
|
|
|
30
33
|
],
|
|
31
34
|
"author": "Nurul Huda (Apon) <me@nurulhudaapon.com>",
|
|
32
35
|
"license": "MIT",
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"react": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"react-dom": {
|
|
41
|
+
"optional": true
|
|
42
|
+
},
|
|
43
|
+
"hono": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
33
47
|
"module": "index.js",
|
|
34
48
|
"types": "index.d.ts"
|
|
35
49
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ziex adapter for Vercel Edge Functions.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* import { Ziex } from "ziex/cloudflare";
|
|
7
|
+
* import { handle } from "ziex/vercel";
|
|
8
|
+
* import module from "./app.wasm"; // or fetch at runtime
|
|
9
|
+
*
|
|
10
|
+
* const app = new Ziex({ module });
|
|
11
|
+
*
|
|
12
|
+
* export const config = { runtime: "edge" };
|
|
13
|
+
* export default handle(app);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
type FetchApp = {
|
|
17
|
+
fetch(req: Request, env?: unknown, ctx?: unknown): Promise<Response>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Wrap a Ziex app as a Vercel Edge Function handler.
|
|
21
|
+
*
|
|
22
|
+
* Returns a standard `(req: Request) => Promise<Response>` function.
|
|
23
|
+
* Vercel's edge runtime calls it directly — just export it as default.
|
|
24
|
+
*/
|
|
25
|
+
export declare function handle(app: FetchApp): (req: Request) => Promise<Response>;
|
|
26
|
+
export {};
|
package/vercel/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/vercel/index.ts
|
|
13
|
+
function handle(app) {
|
|
14
|
+
return (req) => app.fetch(req);
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
handle
|
|
18
|
+
};
|
package/wasm/index.d.ts
CHANGED
|
@@ -27,6 +27,10 @@ export declare class ZxBridge {
|
|
|
27
27
|
* Calls __zx_fetch_complete when done.
|
|
28
28
|
*/
|
|
29
29
|
fetchAsync(urlPtr: number, urlLen: number, methodPtr: number, methodLen: number, headersPtr: number, headersLen: number, bodyPtr: number, bodyLen: number, timeoutMs: number, fetchId: bigint): void;
|
|
30
|
+
/** Submit a form action with bound-state round-trip.
|
|
31
|
+
* Sends the form as multipart/form-data + __zx_states field,
|
|
32
|
+
* then calls __zx_fetch_complete so WASM can apply state updates. */
|
|
33
|
+
submitFormActionAsync(form: HTMLFormElement, statesJson: string, fetchId: bigint): void;
|
|
30
34
|
/** Set a timeout and callback when it fires */
|
|
31
35
|
setTimeout(callbackId: bigint, delayMs: number): void;
|
|
32
36
|
/** Set an interval and callback each time it fires */
|
|
@@ -61,11 +65,6 @@ export declare function init(options?: InitOptions): Promise<{
|
|
|
61
65
|
source: WebAssembly.WebAssemblyInstantiatedSource;
|
|
62
66
|
bridge: ZxBridge;
|
|
63
67
|
}>;
|
|
64
|
-
/** Initialize WASM with the ZX Bridge */
|
|
65
|
-
export declare function edge(options?: InitOptions): Promise<{
|
|
66
|
-
source: WebAssembly.WebAssemblyInstantiatedSource;
|
|
67
|
-
bridge: ZxBridge;
|
|
68
|
-
}>;
|
|
69
68
|
declare global {
|
|
70
69
|
interface HTMLElement {
|
|
71
70
|
__zx_ref?: number;
|
package/wasm/index.js
CHANGED
|
@@ -200,42 +200,54 @@ function storeValueGetRef(val) {
|
|
|
200
200
|
jsz.memory = originalMemory;
|
|
201
201
|
return tempRefView.getBigUint64(0, true);
|
|
202
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
|
+
}
|
|
203
219
|
function readString(ptr, len) {
|
|
204
|
-
const
|
|
205
|
-
|
|
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;
|
|
206
227
|
}
|
|
207
228
|
function writeBytes(ptr, data) {
|
|
208
|
-
|
|
209
|
-
memory.set(data, ptr);
|
|
229
|
+
getMemoryView().set(data, ptr);
|
|
210
230
|
}
|
|
211
231
|
|
|
212
232
|
class ZxBridge {
|
|
213
|
-
#exports;
|
|
214
233
|
#intervals = new Map;
|
|
215
234
|
#websockets = new Map;
|
|
235
|
+
#alloc;
|
|
236
|
+
#handler;
|
|
237
|
+
#fetchCompleteHandler;
|
|
238
|
+
#wsOnOpenHandler;
|
|
239
|
+
#wsOnMessageHandler;
|
|
240
|
+
#wsOnErrorHandler;
|
|
241
|
+
#wsOnCloseHandler;
|
|
216
242
|
constructor(exports) {
|
|
217
|
-
this.#
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
get #fetchCompleteHandler() {
|
|
226
|
-
return this.#exports.__zx_fetch_complete;
|
|
227
|
-
}
|
|
228
|
-
get #wsOnOpenHandler() {
|
|
229
|
-
return this.#exports.__zx_ws_onopen;
|
|
230
|
-
}
|
|
231
|
-
get #wsOnMessageHandler() {
|
|
232
|
-
return this.#exports.__zx_ws_onmessage;
|
|
233
|
-
}
|
|
234
|
-
get #wsOnErrorHandler() {
|
|
235
|
-
return this.#exports.__zx_ws_onerror;
|
|
236
|
-
}
|
|
237
|
-
get #wsOnCloseHandler() {
|
|
238
|
-
return this.#exports.__zx_ws_onclose;
|
|
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;
|
|
239
251
|
}
|
|
240
252
|
#invoke(type, id, data) {
|
|
241
253
|
const handler = this.#handler;
|
|
@@ -286,11 +298,26 @@ class ZxBridge {
|
|
|
286
298
|
}
|
|
287
299
|
#notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
288
300
|
const handler = this.#fetchCompleteHandler;
|
|
289
|
-
const encoded =
|
|
301
|
+
const encoded = textEncoder.encode(body);
|
|
290
302
|
const ptr = this.#alloc(encoded.length);
|
|
291
303
|
writeBytes(ptr, encoded);
|
|
292
304
|
handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
293
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
|
+
});
|
|
320
|
+
}
|
|
294
321
|
setTimeout(callbackId, delayMs) {
|
|
295
322
|
setTimeout(() => {
|
|
296
323
|
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
@@ -333,7 +360,7 @@ class ZxBridge {
|
|
|
333
360
|
if (isBinary) {
|
|
334
361
|
data = new Uint8Array(event.data);
|
|
335
362
|
} else {
|
|
336
|
-
data =
|
|
363
|
+
data = textEncoder.encode(event.data);
|
|
337
364
|
}
|
|
338
365
|
const { ptr, len } = this.#writeBytesToWasm(data);
|
|
339
366
|
handler(wsId, ptr, len, isBinary ? 1 : 0);
|
|
@@ -369,12 +396,11 @@ class ZxBridge {
|
|
|
369
396
|
const ws = this.#websockets.get(wsId);
|
|
370
397
|
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
371
398
|
return;
|
|
372
|
-
const memory =
|
|
373
|
-
const data = memory.slice(dataPtr, dataPtr + dataLen);
|
|
399
|
+
const memory = getMemoryView();
|
|
374
400
|
if (isBinary) {
|
|
375
|
-
ws.send(
|
|
401
|
+
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
376
402
|
} else {
|
|
377
|
-
ws.send(
|
|
403
|
+
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
378
404
|
}
|
|
379
405
|
}
|
|
380
406
|
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
@@ -393,7 +419,7 @@ class ZxBridge {
|
|
|
393
419
|
}
|
|
394
420
|
}
|
|
395
421
|
#writeStringToWasm(str) {
|
|
396
|
-
const encoded =
|
|
422
|
+
const encoded = textEncoder.encode(str);
|
|
397
423
|
return this.#writeBytesToWasm(encoded);
|
|
398
424
|
}
|
|
399
425
|
#writeBytesToWasm(data) {
|
|
@@ -401,11 +427,12 @@ class ZxBridge {
|
|
|
401
427
|
writeBytes(ptr, data);
|
|
402
428
|
return { ptr, len: data.length };
|
|
403
429
|
}
|
|
430
|
+
#eventbridge;
|
|
404
431
|
eventbridge(velementId, eventTypeId, event) {
|
|
432
|
+
if (!this.#eventbridge)
|
|
433
|
+
return;
|
|
405
434
|
const eventRef = storeValueGetRef(event);
|
|
406
|
-
|
|
407
|
-
if (eventbridge)
|
|
408
|
-
eventbridge(velementId, eventTypeId, eventRef);
|
|
435
|
+
this.#eventbridge(velementId, eventTypeId, eventRef);
|
|
409
436
|
}
|
|
410
437
|
static createImportObject(bridgeRef) {
|
|
411
438
|
return {
|
|
@@ -432,15 +459,109 @@ class ZxBridge {
|
|
|
432
459
|
_wsClose: (wsId, code, reasonPtr, reasonLen) => {
|
|
433
460
|
bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
|
|
434
461
|
},
|
|
435
|
-
_ce: (id) => {
|
|
462
|
+
_ce: (id, vnodeId) => {
|
|
436
463
|
const tagName = TAG_NAMES[id];
|
|
437
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);
|
|
438
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);
|
|
439
551
|
}
|
|
440
552
|
}
|
|
441
553
|
};
|
|
442
554
|
}
|
|
443
555
|
}
|
|
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
|
+
}
|
|
444
565
|
var SVG_TAG_START_INDEX = 140;
|
|
445
566
|
var TAG_NAMES = [
|
|
446
567
|
"aside",
|
|
@@ -696,7 +817,8 @@ function initEventDelegation(bridge, rootSelector = "body") {
|
|
|
696
817
|
const zxRef = target.__zx_ref;
|
|
697
818
|
if (zxRef !== undefined) {
|
|
698
819
|
bridge.eventbridge(BigInt(zxRef), EVENT_TYPE_MAP[eventType] ?? 0, event);
|
|
699
|
-
|
|
820
|
+
if (event.cancelBubble)
|
|
821
|
+
break;
|
|
700
822
|
}
|
|
701
823
|
target = target.parentElement;
|
|
702
824
|
}
|
|
@@ -719,27 +841,11 @@ async function init(options = {}) {
|
|
|
719
841
|
main();
|
|
720
842
|
return { source, bridge };
|
|
721
843
|
}
|
|
722
|
-
async function edge(options = {}) {
|
|
723
|
-
const url = options.url ?? DEFAULT_URL;
|
|
724
|
-
const bridgeRef = { current: null };
|
|
725
|
-
const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), options.importObject);
|
|
726
|
-
const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
727
|
-
const { instance } = source;
|
|
728
|
-
jsz.memory = instance.exports.memory;
|
|
729
|
-
const bridge = new ZxBridge(instance.exports);
|
|
730
|
-
bridgeRef.current = bridge;
|
|
731
|
-
initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
|
|
732
|
-
const main = instance.exports.main;
|
|
733
|
-
if (typeof main === "function")
|
|
734
|
-
main();
|
|
735
|
-
return { source, bridge };
|
|
736
|
-
}
|
|
737
844
|
export {
|
|
738
845
|
storeValueGetRef,
|
|
739
846
|
jsz,
|
|
740
847
|
initEventDelegation,
|
|
741
848
|
init,
|
|
742
|
-
edge,
|
|
743
849
|
ZxBridge,
|
|
744
850
|
CallbackType
|
|
745
851
|
};
|
package/wasm/init.js
CHANGED
|
@@ -189,42 +189,54 @@ function storeValueGetRef(val) {
|
|
|
189
189
|
jsz.memory = originalMemory;
|
|
190
190
|
return tempRefView.getBigUint64(0, true);
|
|
191
191
|
}
|
|
192
|
+
var textDecoder = new TextDecoder;
|
|
193
|
+
var textEncoder = new TextEncoder;
|
|
194
|
+
var memoryView = null;
|
|
195
|
+
var memoryBuffer = null;
|
|
196
|
+
function getMemoryView() {
|
|
197
|
+
const buf = jsz.memory.buffer;
|
|
198
|
+
if (buf !== memoryBuffer) {
|
|
199
|
+
memoryBuffer = buf;
|
|
200
|
+
memoryView = new Uint8Array(buf);
|
|
201
|
+
}
|
|
202
|
+
return memoryView;
|
|
203
|
+
}
|
|
204
|
+
var stringCache = new Map;
|
|
205
|
+
function stringCacheKey(ptr, len) {
|
|
206
|
+
return ptr * 65536 + len;
|
|
207
|
+
}
|
|
192
208
|
function readString(ptr, len) {
|
|
193
|
-
const
|
|
194
|
-
|
|
209
|
+
const key = stringCacheKey(ptr, len);
|
|
210
|
+
const cached = stringCache.get(key);
|
|
211
|
+
if (cached !== undefined)
|
|
212
|
+
return cached;
|
|
213
|
+
const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
214
|
+
stringCache.set(key, str);
|
|
215
|
+
return str;
|
|
195
216
|
}
|
|
196
217
|
function writeBytes(ptr, data) {
|
|
197
|
-
|
|
198
|
-
memory.set(data, ptr);
|
|
218
|
+
getMemoryView().set(data, ptr);
|
|
199
219
|
}
|
|
200
220
|
|
|
201
221
|
class ZxBridge {
|
|
202
|
-
#exports;
|
|
203
222
|
#intervals = new Map;
|
|
204
223
|
#websockets = new Map;
|
|
224
|
+
#alloc;
|
|
225
|
+
#handler;
|
|
226
|
+
#fetchCompleteHandler;
|
|
227
|
+
#wsOnOpenHandler;
|
|
228
|
+
#wsOnMessageHandler;
|
|
229
|
+
#wsOnErrorHandler;
|
|
230
|
+
#wsOnCloseHandler;
|
|
205
231
|
constructor(exports) {
|
|
206
|
-
this.#
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
get #fetchCompleteHandler() {
|
|
215
|
-
return this.#exports.__zx_fetch_complete;
|
|
216
|
-
}
|
|
217
|
-
get #wsOnOpenHandler() {
|
|
218
|
-
return this.#exports.__zx_ws_onopen;
|
|
219
|
-
}
|
|
220
|
-
get #wsOnMessageHandler() {
|
|
221
|
-
return this.#exports.__zx_ws_onmessage;
|
|
222
|
-
}
|
|
223
|
-
get #wsOnErrorHandler() {
|
|
224
|
-
return this.#exports.__zx_ws_onerror;
|
|
225
|
-
}
|
|
226
|
-
get #wsOnCloseHandler() {
|
|
227
|
-
return this.#exports.__zx_ws_onclose;
|
|
232
|
+
this.#alloc = exports.__zx_alloc;
|
|
233
|
+
this.#handler = exports.__zx_cb;
|
|
234
|
+
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
235
|
+
this.#wsOnOpenHandler = exports.__zx_ws_onopen;
|
|
236
|
+
this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
|
|
237
|
+
this.#wsOnErrorHandler = exports.__zx_ws_onerror;
|
|
238
|
+
this.#wsOnCloseHandler = exports.__zx_ws_onclose;
|
|
239
|
+
this.#eventbridge = exports.__zx_eventbridge;
|
|
228
240
|
}
|
|
229
241
|
#invoke(type, id, data) {
|
|
230
242
|
const handler = this.#handler;
|
|
@@ -275,11 +287,26 @@ class ZxBridge {
|
|
|
275
287
|
}
|
|
276
288
|
#notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
277
289
|
const handler = this.#fetchCompleteHandler;
|
|
278
|
-
const encoded =
|
|
290
|
+
const encoded = textEncoder.encode(body);
|
|
279
291
|
const ptr = this.#alloc(encoded.length);
|
|
280
292
|
writeBytes(ptr, encoded);
|
|
281
293
|
handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
282
294
|
}
|
|
295
|
+
submitFormActionAsync(form, statesJson, fetchId) {
|
|
296
|
+
const formData = new FormData(form);
|
|
297
|
+
formData.append("__zx_states", statesJson);
|
|
298
|
+
fetch(window.location.href, {
|
|
299
|
+
method: "POST",
|
|
300
|
+
headers: { "X-ZX-Action": "1" },
|
|
301
|
+
body: formData
|
|
302
|
+
}).then(async (response) => {
|
|
303
|
+
const text = await response.text();
|
|
304
|
+
this.#notifyFetchComplete(fetchId, response.status, text, false);
|
|
305
|
+
}).catch((error) => {
|
|
306
|
+
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
307
|
+
this.#notifyFetchComplete(fetchId, 0, msg, true);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
283
310
|
setTimeout(callbackId, delayMs) {
|
|
284
311
|
setTimeout(() => {
|
|
285
312
|
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
@@ -322,7 +349,7 @@ class ZxBridge {
|
|
|
322
349
|
if (isBinary) {
|
|
323
350
|
data = new Uint8Array(event.data);
|
|
324
351
|
} else {
|
|
325
|
-
data =
|
|
352
|
+
data = textEncoder.encode(event.data);
|
|
326
353
|
}
|
|
327
354
|
const { ptr, len } = this.#writeBytesToWasm(data);
|
|
328
355
|
handler(wsId, ptr, len, isBinary ? 1 : 0);
|
|
@@ -358,12 +385,11 @@ class ZxBridge {
|
|
|
358
385
|
const ws = this.#websockets.get(wsId);
|
|
359
386
|
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
360
387
|
return;
|
|
361
|
-
const memory =
|
|
362
|
-
const data = memory.slice(dataPtr, dataPtr + dataLen);
|
|
388
|
+
const memory = getMemoryView();
|
|
363
389
|
if (isBinary) {
|
|
364
|
-
ws.send(
|
|
390
|
+
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
365
391
|
} else {
|
|
366
|
-
ws.send(
|
|
392
|
+
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
367
393
|
}
|
|
368
394
|
}
|
|
369
395
|
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
@@ -382,7 +408,7 @@ class ZxBridge {
|
|
|
382
408
|
}
|
|
383
409
|
}
|
|
384
410
|
#writeStringToWasm(str) {
|
|
385
|
-
const encoded =
|
|
411
|
+
const encoded = textEncoder.encode(str);
|
|
386
412
|
return this.#writeBytesToWasm(encoded);
|
|
387
413
|
}
|
|
388
414
|
#writeBytesToWasm(data) {
|
|
@@ -390,11 +416,12 @@ class ZxBridge {
|
|
|
390
416
|
writeBytes(ptr, data);
|
|
391
417
|
return { ptr, len: data.length };
|
|
392
418
|
}
|
|
419
|
+
#eventbridge;
|
|
393
420
|
eventbridge(velementId, eventTypeId, event) {
|
|
421
|
+
if (!this.#eventbridge)
|
|
422
|
+
return;
|
|
394
423
|
const eventRef = storeValueGetRef(event);
|
|
395
|
-
|
|
396
|
-
if (eventbridge)
|
|
397
|
-
eventbridge(velementId, eventTypeId, eventRef);
|
|
424
|
+
this.#eventbridge(velementId, eventTypeId, eventRef);
|
|
398
425
|
}
|
|
399
426
|
static createImportObject(bridgeRef) {
|
|
400
427
|
return {
|
|
@@ -421,15 +448,109 @@ class ZxBridge {
|
|
|
421
448
|
_wsClose: (wsId, code, reasonPtr, reasonLen) => {
|
|
422
449
|
bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
|
|
423
450
|
},
|
|
424
|
-
_ce: (id) => {
|
|
451
|
+
_ce: (id, vnodeId) => {
|
|
425
452
|
const tagName = TAG_NAMES[id];
|
|
426
453
|
const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
|
|
454
|
+
el.__zx_ref = Number(vnodeId);
|
|
455
|
+
domNodes.set(vnodeId, el);
|
|
427
456
|
return storeValueGetRef(el);
|
|
457
|
+
},
|
|
458
|
+
_ct: (ptr, len, vnodeId) => {
|
|
459
|
+
const text = readString(ptr, len);
|
|
460
|
+
const node = document.createTextNode(text);
|
|
461
|
+
node.__zx_ref = Number(vnodeId);
|
|
462
|
+
domNodes.set(vnodeId, node);
|
|
463
|
+
return storeValueGetRef(node);
|
|
464
|
+
},
|
|
465
|
+
_sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
|
|
466
|
+
domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
|
|
467
|
+
},
|
|
468
|
+
_ra: (vnodeId, namePtr, nameLen) => {
|
|
469
|
+
domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
|
|
470
|
+
},
|
|
471
|
+
_snv: (vnodeId, ptr, len) => {
|
|
472
|
+
const node = domNodes.get(vnodeId);
|
|
473
|
+
if (node)
|
|
474
|
+
node.nodeValue = readString(ptr, len);
|
|
475
|
+
},
|
|
476
|
+
_ac: (parentId, childId) => {
|
|
477
|
+
const parent = domNodes.get(parentId);
|
|
478
|
+
const child = domNodes.get(childId);
|
|
479
|
+
if (parent && child)
|
|
480
|
+
parent.appendChild(child);
|
|
481
|
+
},
|
|
482
|
+
_ib: (parentId, childId, refId) => {
|
|
483
|
+
const parent = domNodes.get(parentId);
|
|
484
|
+
const child = domNodes.get(childId);
|
|
485
|
+
const ref = domNodes.get(refId) ?? null;
|
|
486
|
+
if (parent && child)
|
|
487
|
+
parent.insertBefore(child, ref);
|
|
488
|
+
},
|
|
489
|
+
_rc: (parentId, childId) => {
|
|
490
|
+
const parent = domNodes.get(parentId);
|
|
491
|
+
const child = domNodes.get(childId);
|
|
492
|
+
if (parent && child) {
|
|
493
|
+
parent.removeChild(child);
|
|
494
|
+
cleanupDomNodes(child);
|
|
495
|
+
}
|
|
496
|
+
},
|
|
497
|
+
_rpc: (parentId, newId, oldId) => {
|
|
498
|
+
const parent = domNodes.get(parentId);
|
|
499
|
+
const newChild = domNodes.get(newId);
|
|
500
|
+
const oldChild = domNodes.get(oldId);
|
|
501
|
+
if (parent && newChild && oldChild) {
|
|
502
|
+
parent.replaceChild(newChild, oldChild);
|
|
503
|
+
cleanupDomNodes(oldChild);
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
_getLocationHref: (bufPtr, bufLen) => {
|
|
507
|
+
const bytes = textEncoder.encode(window.location.href);
|
|
508
|
+
const len = Math.min(bytes.length, bufLen);
|
|
509
|
+
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
510
|
+
return len;
|
|
511
|
+
},
|
|
512
|
+
_getFormData: (vnodeId, bufPtr, bufLen) => {
|
|
513
|
+
const form = domNodes.get(vnodeId);
|
|
514
|
+
if (!form || !(form instanceof HTMLFormElement))
|
|
515
|
+
return 0;
|
|
516
|
+
const formData = new FormData(form);
|
|
517
|
+
const urlEncoded = new URLSearchParams(formData).toString();
|
|
518
|
+
const bytes = textEncoder.encode(urlEncoded);
|
|
519
|
+
const len = Math.min(bytes.length, bufLen);
|
|
520
|
+
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
521
|
+
return len;
|
|
522
|
+
},
|
|
523
|
+
_submitFormAction: (vnodeId) => {
|
|
524
|
+
const form = domNodes.get(vnodeId);
|
|
525
|
+
if (!form || !(form instanceof HTMLFormElement))
|
|
526
|
+
return;
|
|
527
|
+
const formData = new FormData(form);
|
|
528
|
+
fetch(window.location.href, {
|
|
529
|
+
method: "POST",
|
|
530
|
+
headers: { "X-ZX-Action": "1" },
|
|
531
|
+
body: formData
|
|
532
|
+
}).catch(() => {});
|
|
533
|
+
},
|
|
534
|
+
_submitFormActionAsync: (vnodeId, statesPtr, statesLen, fetchId) => {
|
|
535
|
+
const form = domNodes.get(vnodeId);
|
|
536
|
+
if (!form || !(form instanceof HTMLFormElement))
|
|
537
|
+
return;
|
|
538
|
+
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
539
|
+
bridgeRef.current?.submitFormActionAsync(form, statesJson, fetchId);
|
|
428
540
|
}
|
|
429
541
|
}
|
|
430
542
|
};
|
|
431
543
|
}
|
|
432
544
|
}
|
|
545
|
+
var domNodes = new Map;
|
|
546
|
+
function cleanupDomNodes(node) {
|
|
547
|
+
const ref = node.__zx_ref;
|
|
548
|
+
if (ref !== undefined)
|
|
549
|
+
domNodes.delete(BigInt(ref));
|
|
550
|
+
const children = node.childNodes;
|
|
551
|
+
for (let i = 0;i < children.length; i++)
|
|
552
|
+
cleanupDomNodes(children[i]);
|
|
553
|
+
}
|
|
433
554
|
var SVG_TAG_START_INDEX = 140;
|
|
434
555
|
var TAG_NAMES = [
|
|
435
556
|
"aside",
|
|
@@ -685,7 +806,8 @@ function initEventDelegation(bridge, rootSelector = "body") {
|
|
|
685
806
|
const zxRef = target.__zx_ref;
|
|
686
807
|
if (zxRef !== undefined) {
|
|
687
808
|
bridge.eventbridge(BigInt(zxRef), EVENT_TYPE_MAP[eventType] ?? 0, event);
|
|
688
|
-
|
|
809
|
+
if (event.cancelBubble)
|
|
810
|
+
break;
|
|
689
811
|
}
|
|
690
812
|
target = target.parentElement;
|
|
691
813
|
}
|