ziex 0.1.0-dev.1389 → 0.1.0-dev.1466
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 +4 -1
- package/app.d.ts +6 -6
- package/build.zig.zon +1 -1
- package/index.js +490 -174
- package/package.json +7 -5
- package/{aws-lambda → platforms/aws-lambda}/index.js +1 -1
- package/platforms/cloudflare/app.d.ts +2 -0
- package/platforms/cloudflare/db.d.ts +6 -0
- package/{cloudflare → platforms/cloudflare}/do.d.ts +5 -5
- package/platforms/cloudflare/index.d.ts +4 -0
- package/{cloudflare → platforms/cloudflare}/index.js +1959 -1532
- package/platforms/cloudflare/kv.d.ts +5 -0
- package/platforms/cloudflare/worker.d.ts +3 -0
- package/{vercel → platforms/vercel}/index.js +1 -1
- package/runtime/db/extern.d.ts +38 -0
- package/runtime/db/sqlite.d.ts +7 -0
- package/runtime/db.d.ts +3 -0
- package/runtime/db.js +419 -0
- package/{fetch.d.ts → runtime/fetch.d.ts} +1 -1
- package/{runtime.d.ts → runtime/index.d.ts} +6 -15
- package/runtime/kv/extern.d.ts +11 -0
- package/runtime/kv/indexdb.d.ts +7 -0
- package/runtime/kv/localstorage.d.ts +6 -0
- package/runtime/kv/memory.d.ts +6 -0
- package/runtime/kv.d.ts +45 -0
- package/runtime/kv.js +543 -0
- package/wasm/constants.d.ts +33 -0
- package/wasm/core.d.ts +23 -33
- package/wasm/dom_cmd.d.ts +15 -0
- package/wasm/generated/event_bits.d.ts +2 -0
- package/wasm/generated/events.d.ts +1 -0
- package/wasm/generated/tag_indices.d.ts +2 -0
- package/wasm/generated/tags.d.ts +1 -0
- package/wasm/index.d.ts +15 -13
- package/wasm/index.js +911 -676
- package/wasm/init.dev.js +895 -674
- package/wasm/init.js +3 -3
- package/wasm/wasi.d.ts +1 -5
- package/browser/kv.d.ts +0 -13
- package/cloudflare/app.d.ts +0 -2
- package/cloudflare/db.d.ts +0 -2
- package/cloudflare/index.d.ts +0 -4
- package/cloudflare/kv.d.ts +0 -2
- package/cloudflare/worker.d.ts +0 -3
- package/db.d.ts +0 -22
- package/kv.d.ts +0 -42
- /package/{aws-lambda → platforms/aws-lambda}/index.d.ts +0 -0
- /package/{vercel → platforms/vercel}/index.d.ts +0 -0
- /package/{wasi.d.ts → runtime/wasi.d.ts} +0 -0
package/wasm/index.js
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
// src/wasm/constants.ts
|
|
2
|
+
var DOM_CMD_HEADER_SIZE = 8;
|
|
3
|
+
var DOM_CMD_RECORD_SIZE = 24;
|
|
4
|
+
var DomOp_CreateElement = 1;
|
|
5
|
+
var DomOp_CreateText = 2;
|
|
6
|
+
var DomOp_HydrateInsert = 3;
|
|
7
|
+
var DomOp_SetAttr = 4;
|
|
8
|
+
var DomOp_SetProp = 5;
|
|
9
|
+
var DomOp_RemoveAttr = 6;
|
|
10
|
+
var DomOp_SetNodeValue = 7;
|
|
11
|
+
var DomOp_SetInnerHtml = 8;
|
|
12
|
+
var DomOp_AppendChild = 9;
|
|
13
|
+
var DomOp_InsertBefore = 10;
|
|
14
|
+
var DomOp_RemoveChild = 11;
|
|
15
|
+
var DomOp_ReplaceChild = 12;
|
|
16
|
+
var CallbackType_Event = 0;
|
|
17
|
+
var CallbackType_FetchSuccess = 1;
|
|
18
|
+
var CallbackType_FetchError = 2;
|
|
19
|
+
var CallbackType_Timeout = 3;
|
|
20
|
+
var CallbackType_Interval = 4;
|
|
21
|
+
var CallbackType_WebSocketOpen = 5;
|
|
22
|
+
var CallbackType_WebSocketMessage = 6;
|
|
23
|
+
var CallbackType_WebSocketError = 7;
|
|
24
|
+
var CallbackType_WebSocketClose = 8;
|
|
25
|
+
|
|
1
26
|
// ../../vendor/jsz/js/src/zigjs.ts
|
|
2
27
|
var NAN_PREFIX = 2146959360;
|
|
3
28
|
var predefined = {
|
|
@@ -51,6 +76,10 @@ var ZigJS = class {
|
|
|
51
76
|
* */
|
|
52
77
|
valueGet(out, id, ptr, len) {
|
|
53
78
|
const val = this.loadValue(id);
|
|
79
|
+
if (val === null || val === void 0 || typeof val !== "object" && typeof val !== "function") {
|
|
80
|
+
this.storeValue(out, void 0);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
54
83
|
const str = this.loadString(ptr, len);
|
|
55
84
|
const result = Reflect.get(val, str);
|
|
56
85
|
this.storeValue(out, result);
|
|
@@ -99,11 +128,15 @@ var ZigJS = class {
|
|
|
99
128
|
* */
|
|
100
129
|
valueStringCopy(id, ptr, max) {
|
|
101
130
|
if (this.memory == null) return;
|
|
131
|
+
const dest = ptr >>> 0;
|
|
132
|
+
const cap = max >>> 0;
|
|
102
133
|
const val = this.loadValue(id);
|
|
134
|
+
if (typeof val !== "string") return;
|
|
103
135
|
const bytes = encoder.encode(val);
|
|
104
|
-
if (bytes.byteLength >
|
|
105
|
-
|
|
106
|
-
|
|
136
|
+
if (bytes.byteLength > cap || bytes.length === 0) return;
|
|
137
|
+
const buf = this.memory.buffer;
|
|
138
|
+
if (dest + bytes.length > buf.byteLength) return;
|
|
139
|
+
new Uint8Array(buf, dest, bytes.length).set(bytes);
|
|
107
140
|
}
|
|
108
141
|
/**
|
|
109
142
|
* Call a constructor given by id.
|
|
@@ -111,8 +144,10 @@ var ZigJS = class {
|
|
|
111
144
|
valueNew(out, id, argsAddr, argsLen) {
|
|
112
145
|
const fn = this.loadValue(id);
|
|
113
146
|
const args = [];
|
|
114
|
-
|
|
115
|
-
|
|
147
|
+
const base = argsAddr >>> 0;
|
|
148
|
+
const count = argsLen >>> 0;
|
|
149
|
+
for (let i = 0; i < count; i++) {
|
|
150
|
+
args.push(this.loadRef(base + i * 8));
|
|
116
151
|
}
|
|
117
152
|
const result = Reflect.construct(fn, args);
|
|
118
153
|
this.storeValue(out, result);
|
|
@@ -122,13 +157,23 @@ var ZigJS = class {
|
|
|
122
157
|
* */
|
|
123
158
|
funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
|
|
124
159
|
const fn = this.loadValue(id);
|
|
125
|
-
const thisVal = this.loadRef(thisRefAddr);
|
|
160
|
+
const thisVal = this.loadRef(thisRefAddr >>> 0);
|
|
126
161
|
const args = [];
|
|
127
|
-
|
|
128
|
-
|
|
162
|
+
const base = argsAddr >>> 0;
|
|
163
|
+
const count = argsLen >>> 0;
|
|
164
|
+
for (let i = 0; i < count; i++) {
|
|
165
|
+
args.push(this.loadRef(base + i * 8));
|
|
166
|
+
}
|
|
167
|
+
if (typeof fn !== "function") {
|
|
168
|
+
this.storeValue(out, void 0);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
try {
|
|
172
|
+
const result = Reflect.apply(fn, thisVal, args);
|
|
173
|
+
this.storeValue(out, result);
|
|
174
|
+
} catch {
|
|
175
|
+
this.storeValue(out, void 0);
|
|
129
176
|
}
|
|
130
|
-
const result = Reflect.apply(fn, thisVal, args);
|
|
131
|
-
this.storeValue(out, result);
|
|
132
177
|
}
|
|
133
178
|
/**
|
|
134
179
|
* This can be used to load a value given by an ID. A WASM function
|
|
@@ -149,19 +194,21 @@ var ZigJS = class {
|
|
|
149
194
|
}
|
|
150
195
|
loadRef(refAddr) {
|
|
151
196
|
if (this.memory == null) return;
|
|
197
|
+
const addr = refAddr >>> 0;
|
|
152
198
|
const view = new DataView(this.memory.buffer);
|
|
153
|
-
const floatVal = view.getFloat64(
|
|
199
|
+
const floatVal = view.getFloat64(addr, true);
|
|
154
200
|
if (!isNaN(floatVal)) return floatVal;
|
|
155
|
-
const id = this.loadRefId(
|
|
201
|
+
const id = this.loadRefId(addr);
|
|
156
202
|
return this.values[id];
|
|
157
203
|
}
|
|
158
204
|
loadRefId(refAddr) {
|
|
159
205
|
if (this.memory == null) return 0;
|
|
160
|
-
return new DataView(this.memory.buffer).getUint32(refAddr, true);
|
|
206
|
+
return new DataView(this.memory.buffer).getUint32(refAddr >>> 0, true);
|
|
161
207
|
}
|
|
162
208
|
storeValue(out, val) {
|
|
163
209
|
if (this.memory == null) return;
|
|
164
210
|
const view = new DataView(this.memory.buffer);
|
|
211
|
+
out = out >>> 0;
|
|
165
212
|
if (typeof val === "number") {
|
|
166
213
|
if (isNaN(val)) {
|
|
167
214
|
view.setUint32(out, predefined.nan, true);
|
|
@@ -215,13 +262,17 @@ var ZigJS = class {
|
|
|
215
262
|
}
|
|
216
263
|
loadString(ptr, len) {
|
|
217
264
|
if (this.memory == null) return "";
|
|
218
|
-
const
|
|
265
|
+
const start = ptr >>> 0;
|
|
266
|
+
const length = Number(len) >>> 0;
|
|
267
|
+
const buf = this.memory.buffer;
|
|
268
|
+
if (length === 0 || start + length > buf.byteLength) return "";
|
|
269
|
+
const arr = new Uint8ClampedArray(buf, start, length);
|
|
219
270
|
const data = arr.slice();
|
|
220
271
|
return decoder.decode(data);
|
|
221
272
|
}
|
|
222
273
|
};
|
|
223
274
|
|
|
224
|
-
// src/fetch.ts
|
|
275
|
+
// src/runtime/fetch.ts
|
|
225
276
|
function createFetchImports(getMemory) {
|
|
226
277
|
const encoder2 = new TextEncoder();
|
|
227
278
|
const decoder2 = new TextDecoder();
|
|
@@ -288,17 +339,6 @@ function createFetchImports(getMemory) {
|
|
|
288
339
|
}
|
|
289
340
|
|
|
290
341
|
// src/wasm/core.ts
|
|
291
|
-
var CallbackType = {
|
|
292
|
-
Event: 0,
|
|
293
|
-
FetchSuccess: 1,
|
|
294
|
-
FetchError: 2,
|
|
295
|
-
Timeout: 3,
|
|
296
|
-
Interval: 4,
|
|
297
|
-
WebSocketOpen: 5,
|
|
298
|
-
WebSocketMessage: 6,
|
|
299
|
-
WebSocketError: 7,
|
|
300
|
-
WebSocketClose: 8
|
|
301
|
-
};
|
|
302
342
|
var jsz = new ZigJS();
|
|
303
343
|
var tempRefBuffer = new ArrayBuffer(8);
|
|
304
344
|
var tempRefView = new DataView(tempRefBuffer);
|
|
@@ -309,6 +349,20 @@ function storeValueGetRef(val) {
|
|
|
309
349
|
jsz.memory = originalMemory;
|
|
310
350
|
return tempRefView.getBigUint64(0, true);
|
|
311
351
|
}
|
|
352
|
+
function loadValueFromRef(ref) {
|
|
353
|
+
tempRefView.setBigUint64(0, ref, true);
|
|
354
|
+
const originalMemory = jsz.memory;
|
|
355
|
+
jsz.memory = { buffer: tempRefBuffer };
|
|
356
|
+
const val = jsz.loadRef(0);
|
|
357
|
+
jsz.memory = originalMemory;
|
|
358
|
+
return val;
|
|
359
|
+
}
|
|
360
|
+
function releaseValueRef(ref) {
|
|
361
|
+
tempRefView.setBigUint64(0, ref, true);
|
|
362
|
+
if (!Number.isNaN(tempRefView.getFloat64(0, true))) return;
|
|
363
|
+
const id = tempRefView.getUint32(0, true);
|
|
364
|
+
if (id > 6) jsz.deleteValue(id);
|
|
365
|
+
}
|
|
312
366
|
var textDecoder = new TextDecoder();
|
|
313
367
|
var textEncoder = new TextEncoder();
|
|
314
368
|
var memoryView = null;
|
|
@@ -321,20 +375,19 @@ function getMemoryView() {
|
|
|
321
375
|
}
|
|
322
376
|
return memoryView;
|
|
323
377
|
}
|
|
324
|
-
var stringCache = /* @__PURE__ */ new Map();
|
|
325
|
-
function stringCacheKey(ptr, len) {
|
|
326
|
-
return ptr * 65536 + len;
|
|
327
|
-
}
|
|
328
378
|
function readString(ptr, len) {
|
|
329
|
-
const
|
|
330
|
-
const
|
|
331
|
-
if (
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
return
|
|
379
|
+
const start = ptr >>> 0;
|
|
380
|
+
const length = len >>> 0;
|
|
381
|
+
if (length === 0) return "";
|
|
382
|
+
const view = getMemoryView();
|
|
383
|
+
if (start + length > view.byteLength) return "";
|
|
384
|
+
return textDecoder.decode(view.subarray(start, start + length));
|
|
335
385
|
}
|
|
336
386
|
function writeBytes(ptr, data) {
|
|
337
|
-
|
|
387
|
+
const start = ptr >>> 0;
|
|
388
|
+
const view = getMemoryView();
|
|
389
|
+
if (start + data.length > view.byteLength) return;
|
|
390
|
+
view.set(data, start);
|
|
338
391
|
}
|
|
339
392
|
function wrapPromisingExport(fn) {
|
|
340
393
|
if (!fn) return void 0;
|
|
@@ -354,30 +407,26 @@ function invokeWasmExport(fn, ...args) {
|
|
|
354
407
|
var ZxBridgeCore = class _ZxBridgeCore {
|
|
355
408
|
#intervals = /* @__PURE__ */ new Map();
|
|
356
409
|
#handler;
|
|
357
|
-
#fetchCompleteHandler;
|
|
358
410
|
constructor(exports) {
|
|
359
411
|
this._alloc = exports.__zx_alloc;
|
|
360
412
|
this.#handler = wrapPromisingExport(exports.__zx_cb);
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
throw new Error("__zx_fetch_complete not exported from WASM");
|
|
413
|
+
if (!this.#handler) {
|
|
414
|
+
console.warn("__zx_cb not exported from WASM");
|
|
364
415
|
}
|
|
365
|
-
this.#fetchCompleteHandler = fetchCompleteHandler;
|
|
366
416
|
if (exports.memory) jsz.memory = exports.memory;
|
|
367
417
|
}
|
|
368
418
|
/** Invoke the unified callback handler */
|
|
369
|
-
|
|
419
|
+
_invoke(type, id, a = 0n, b = 0n, c = 0n) {
|
|
370
420
|
const handler = this.#handler;
|
|
371
421
|
if (!handler) {
|
|
372
422
|
console.warn("__zx_cb not exported from WASM");
|
|
373
423
|
return;
|
|
374
424
|
}
|
|
375
|
-
|
|
376
|
-
invokeWasmExport(handler, type, id, dataRef);
|
|
425
|
+
invokeWasmExport(handler, type, id, a, b, c);
|
|
377
426
|
}
|
|
378
427
|
/**
|
|
379
428
|
* Async fetch with full options support.
|
|
380
|
-
*
|
|
429
|
+
* Completes via `__zx_cb(fetch_success|fetch_error, ...)`.
|
|
381
430
|
*/
|
|
382
431
|
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
383
432
|
const url = readString(urlPtr, urlLen);
|
|
@@ -416,22 +465,23 @@ var ZxBridgeCore = class _ZxBridgeCore {
|
|
|
416
465
|
}
|
|
417
466
|
/** Notify WASM that a fetch completed. `body` is raw bytes on success, text on error. */
|
|
418
467
|
_notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
419
|
-
const handler = this.#fetchCompleteHandler;
|
|
420
468
|
const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
|
|
421
|
-
const ptr = this._alloc(encoded.length);
|
|
469
|
+
const ptr = this._alloc(encoded.length) >>> 0;
|
|
470
|
+
if (!ptr && encoded.length > 0) return;
|
|
422
471
|
writeBytes(ptr, encoded);
|
|
423
|
-
|
|
472
|
+
const type = isError ? CallbackType_FetchError : CallbackType_FetchSuccess;
|
|
473
|
+
this._invoke(type, fetchId, BigInt(statusCode), BigInt(ptr), BigInt(encoded.length));
|
|
424
474
|
}
|
|
425
475
|
/** Set a timeout and callback when it fires */
|
|
426
476
|
setTimeout(callbackId, delayMs) {
|
|
427
477
|
setTimeout(() => {
|
|
428
|
-
this
|
|
478
|
+
this._invoke(CallbackType_Timeout, callbackId);
|
|
429
479
|
}, delayMs);
|
|
430
480
|
}
|
|
431
481
|
/** Set an interval and callback each time it fires */
|
|
432
482
|
setInterval(callbackId, intervalMs) {
|
|
433
483
|
const handle = setInterval(() => {
|
|
434
|
-
this
|
|
484
|
+
this._invoke(CallbackType_Interval, callbackId);
|
|
435
485
|
}, intervalMs);
|
|
436
486
|
this.#intervals.set(callbackId, handle);
|
|
437
487
|
}
|
|
@@ -449,18 +499,24 @@ var ZxBridgeCore = class _ZxBridgeCore {
|
|
|
449
499
|
}
|
|
450
500
|
this.#intervals.clear();
|
|
451
501
|
}
|
|
452
|
-
/** Write a string to WASM memory, returning
|
|
502
|
+
/** Write a string to WASM memory, returning `[ptr, len]`. */
|
|
453
503
|
_writeStringToWasm(str) {
|
|
454
|
-
return this.
|
|
504
|
+
return this.writeBytesToWasm(textEncoder.encode(str));
|
|
455
505
|
}
|
|
456
|
-
|
|
457
|
-
|
|
506
|
+
writeBytesToWasm(data) {
|
|
507
|
+
if (data.length === 0) return [0, 0];
|
|
508
|
+
const ptr = this._alloc(data.length) >>> 0;
|
|
509
|
+
if (!ptr) return [0, 0];
|
|
458
510
|
writeBytes(ptr, data);
|
|
459
|
-
return
|
|
511
|
+
return [ptr, data.length];
|
|
460
512
|
}
|
|
461
513
|
/** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
|
|
462
514
|
static log(level, ptr, len) {
|
|
463
|
-
const
|
|
515
|
+
const start = ptr >>> 0;
|
|
516
|
+
const length = len >>> 0;
|
|
517
|
+
const view = getMemoryView();
|
|
518
|
+
if (start + length > view.byteLength) return;
|
|
519
|
+
const msg = textDecoder.decode(view.subarray(start, start + length));
|
|
464
520
|
switch (level) {
|
|
465
521
|
case 0:
|
|
466
522
|
console.error(msg);
|
|
@@ -492,7 +548,7 @@ var ZxBridgeCore = class _ZxBridgeCore {
|
|
|
492
548
|
__zx: {
|
|
493
549
|
_log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
|
|
494
550
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
495
|
-
bridgeRef
|
|
551
|
+
bridgeRef[0]?.fetchAsync(
|
|
496
552
|
urlPtr,
|
|
497
553
|
urlLen,
|
|
498
554
|
methodPtr,
|
|
@@ -506,542 +562,41 @@ var ZxBridgeCore = class _ZxBridgeCore {
|
|
|
506
562
|
);
|
|
507
563
|
},
|
|
508
564
|
_setTimeout: (callbackId, delayMs) => {
|
|
509
|
-
bridgeRef
|
|
565
|
+
bridgeRef[0]?.setTimeout(callbackId, delayMs);
|
|
510
566
|
},
|
|
511
567
|
_setInterval: (callbackId, intervalMs) => {
|
|
512
|
-
bridgeRef
|
|
568
|
+
bridgeRef[0]?.setInterval(callbackId, intervalMs);
|
|
513
569
|
},
|
|
514
570
|
_clearInterval: (callbackId) => {
|
|
515
|
-
bridgeRef
|
|
571
|
+
bridgeRef[0]?.clearInterval(callbackId);
|
|
516
572
|
}
|
|
517
573
|
}
|
|
518
574
|
};
|
|
519
575
|
}
|
|
520
576
|
};
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
return { expirationTtl: ttlSeconds };
|
|
526
|
-
}
|
|
527
|
-
function isSyncKVNamespace(binding) {
|
|
528
|
-
const candidate = binding;
|
|
529
|
-
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
530
|
-
}
|
|
531
|
-
function createKVImports(bindings, getMemory) {
|
|
532
|
-
const encoder2 = new TextEncoder();
|
|
533
|
-
const decoder2 = new TextDecoder();
|
|
534
|
-
function readStr(ptr, len) {
|
|
535
|
-
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
536
|
-
}
|
|
537
|
-
function writeBytes2(buf_ptr, buf_max, data) {
|
|
538
|
-
if (data.length > buf_max) return -2;
|
|
539
|
-
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
540
|
-
return data.length;
|
|
541
|
-
}
|
|
542
|
-
function binding(ns) {
|
|
543
|
-
return bindings[ns] ?? bindings["default"] ?? null;
|
|
544
|
-
}
|
|
545
|
-
const Suspending = WebAssembly.Suspending;
|
|
546
|
-
if (typeof Suspending !== "function") {
|
|
547
|
-
let syncBinding2 = function(ns) {
|
|
548
|
-
const candidate = binding(ns);
|
|
549
|
-
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
550
|
-
};
|
|
551
|
-
var syncBinding = syncBinding2;
|
|
552
|
-
return {
|
|
553
|
-
kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
554
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
555
|
-
if (!b) return -1;
|
|
556
|
-
const value = b.getSync(readStr(key_ptr, key_len));
|
|
557
|
-
if (value === null) return -1;
|
|
558
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
559
|
-
},
|
|
560
|
-
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
561
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
562
|
-
if (!b) return 0;
|
|
563
|
-
b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
564
|
-
return 0;
|
|
565
|
-
},
|
|
566
|
-
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
567
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
568
|
-
if (!b) return 0;
|
|
569
|
-
b.deleteSync(readStr(key_ptr, key_len));
|
|
570
|
-
return 0;
|
|
571
|
-
},
|
|
572
|
-
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
|
|
573
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
574
|
-
if (!b) return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
575
|
-
const prefix = readStr(pfx_ptr, pfx_len);
|
|
576
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
577
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
578
|
-
}
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
return {
|
|
582
|
-
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
583
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
584
|
-
if (!b) return -1;
|
|
585
|
-
const value = await b.get(readStr(key_ptr, key_len));
|
|
586
|
-
if (value === null) return -1;
|
|
587
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
588
|
-
}),
|
|
589
|
-
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
590
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
591
|
-
if (!b) return -1;
|
|
592
|
-
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
593
|
-
return 0;
|
|
594
|
-
}),
|
|
595
|
-
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
596
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
597
|
-
if (!b) return -1;
|
|
598
|
-
await b.delete(readStr(key_ptr, key_len));
|
|
599
|
-
return 0;
|
|
600
|
-
}),
|
|
601
|
-
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
602
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
603
|
-
if (!b) return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
604
|
-
const prefix = readStr(prefix_ptr, prefix_len);
|
|
605
|
-
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
606
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
607
|
-
})
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// src/browser/kv.ts
|
|
612
|
-
function getIndexedDb() {
|
|
613
|
-
if (typeof indexedDB === "undefined") {
|
|
614
|
-
throw new Error("IndexedDB is not available in this environment");
|
|
615
|
-
}
|
|
616
|
-
return indexedDB;
|
|
617
|
-
}
|
|
618
|
-
function requestToPromise(request) {
|
|
619
|
-
return new Promise((resolve, reject) => {
|
|
620
|
-
request.onsuccess = () => resolve(request.result);
|
|
621
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
function transactionToPromise(transaction) {
|
|
625
|
-
return new Promise((resolve, reject) => {
|
|
626
|
-
transaction.oncomplete = () => resolve();
|
|
627
|
-
transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
|
|
628
|
-
transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
|
|
629
|
-
});
|
|
630
|
-
}
|
|
631
|
-
function createIndexedDbKV(options = {}) {
|
|
632
|
-
const databaseName = options.databaseName ?? "ziex-kv";
|
|
633
|
-
const storeName = options.storeName ?? "kv";
|
|
634
|
-
const namespace = options.namespace ?? "default";
|
|
635
|
-
const dbPromise = new Promise((resolve, reject) => {
|
|
636
|
-
const request = getIndexedDb().open(databaseName, 1);
|
|
637
|
-
request.onupgradeneeded = () => {
|
|
638
|
-
const db = request.result;
|
|
639
|
-
if (!db.objectStoreNames.contains(storeName)) {
|
|
640
|
-
db.createObjectStore(storeName);
|
|
641
|
-
}
|
|
642
|
-
};
|
|
643
|
-
request.onsuccess = () => resolve(request.result);
|
|
644
|
-
request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
|
|
645
|
-
});
|
|
646
|
-
const scopedKey = (key) => `${namespace}:${key}`;
|
|
647
|
-
return {
|
|
648
|
-
async get(key) {
|
|
649
|
-
const db = await dbPromise;
|
|
650
|
-
const tx = db.transaction(storeName, "readonly");
|
|
651
|
-
const store = tx.objectStore(storeName);
|
|
652
|
-
const value = await requestToPromise(store.get(scopedKey(key)));
|
|
653
|
-
await transactionToPromise(tx);
|
|
654
|
-
console.debug(`KV GET - Key: ${key}, Value: ${value}`);
|
|
655
|
-
return typeof value === "string" ? value : null;
|
|
656
|
-
},
|
|
657
|
-
async put(key, value) {
|
|
658
|
-
const db = await dbPromise;
|
|
659
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
660
|
-
tx.objectStore(storeName).put(value, scopedKey(key));
|
|
661
|
-
await transactionToPromise(tx);
|
|
662
|
-
console.debug(`KV PUT - Key: ${key}, Value: ${value}`);
|
|
663
|
-
},
|
|
664
|
-
async delete(key) {
|
|
665
|
-
const db = await dbPromise;
|
|
666
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
667
|
-
tx.objectStore(storeName).delete(scopedKey(key));
|
|
668
|
-
await transactionToPromise(tx);
|
|
669
|
-
},
|
|
670
|
-
async list(options2) {
|
|
671
|
-
const db = await dbPromise;
|
|
672
|
-
const tx = db.transaction(storeName, "readonly");
|
|
673
|
-
const store = tx.objectStore(storeName);
|
|
674
|
-
const keys = await requestToPromise(store.getAllKeys());
|
|
675
|
-
await transactionToPromise(tx);
|
|
676
|
-
const prefix = scopedKey(options2?.prefix ?? "");
|
|
677
|
-
return {
|
|
678
|
-
keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
function getLocalStorage() {
|
|
684
|
-
if (typeof localStorage === "undefined") {
|
|
685
|
-
throw new Error("localStorage is not available in this environment");
|
|
577
|
+
function writeBytesOut(getMemory, allocRef, outPtrAddr, data) {
|
|
578
|
+
if (data.length === 0) {
|
|
579
|
+
new DataView(getMemory().buffer).setUint32(outPtrAddr, 0, true);
|
|
580
|
+
return 0;
|
|
686
581
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
return
|
|
696
|
-
getSync(key) {
|
|
697
|
-
return storage.getItem(scopedKey(key));
|
|
698
|
-
},
|
|
699
|
-
async get(key) {
|
|
700
|
-
return this.getSync(key);
|
|
701
|
-
},
|
|
702
|
-
putSync(key, value) {
|
|
703
|
-
storage.setItem(scopedKey(key), value);
|
|
704
|
-
},
|
|
705
|
-
async put(key, value) {
|
|
706
|
-
this.putSync(key, value);
|
|
707
|
-
},
|
|
708
|
-
deleteSync(key) {
|
|
709
|
-
storage.removeItem(scopedKey(key));
|
|
710
|
-
},
|
|
711
|
-
async delete(key) {
|
|
712
|
-
this.deleteSync(key);
|
|
713
|
-
},
|
|
714
|
-
listSync(options2) {
|
|
715
|
-
const prefix = namespacePrefix + (options2?.prefix ?? "");
|
|
716
|
-
const keys = [];
|
|
717
|
-
for (let i = 0; i < storage.length; i += 1) {
|
|
718
|
-
const key = storage.key(i);
|
|
719
|
-
if (!key || !key.startsWith(prefix)) continue;
|
|
720
|
-
keys.push({ name: key.slice(namespacePrefix.length) });
|
|
721
|
-
}
|
|
722
|
-
return { keys };
|
|
723
|
-
},
|
|
724
|
-
async list(options2) {
|
|
725
|
-
return this.listSync(options2);
|
|
726
|
-
}
|
|
727
|
-
};
|
|
582
|
+
const alloc = allocRef[0];
|
|
583
|
+
if (!alloc) return -1;
|
|
584
|
+
const ptr = alloc(data.length) >>> 0;
|
|
585
|
+
if (!ptr) return -1;
|
|
586
|
+
const buffer = getMemory().buffer;
|
|
587
|
+
if (ptr + data.length > buffer.byteLength) return -1;
|
|
588
|
+
new Uint8Array(buffer, ptr, data.length).set(data);
|
|
589
|
+
new DataView(buffer).setUint32(outPtrAddr >>> 0, ptr, true);
|
|
590
|
+
return data.length;
|
|
728
591
|
}
|
|
729
|
-
function
|
|
730
|
-
return
|
|
592
|
+
function writeJsonOut(getMemory, allocRef, outPtrAddr, value) {
|
|
593
|
+
return writeBytesOut(getMemory, allocRef, outPtrAddr, textEncoder.encode(JSON.stringify(value)));
|
|
731
594
|
}
|
|
732
|
-
function
|
|
733
|
-
|
|
734
|
-
return {
|
|
735
|
-
[namespace]: hasJSPI() ? createIndexedDbKV(options) : createLocalStorageKV(options)
|
|
736
|
-
};
|
|
595
|
+
function bindWasmAlloc(allocRef, exports) {
|
|
596
|
+
allocRef[0] = exports.__zx_alloc;
|
|
737
597
|
}
|
|
738
598
|
|
|
739
|
-
// src/wasm/
|
|
740
|
-
var ZxBridge = class extends ZxBridgeCore {
|
|
741
|
-
#websockets = /* @__PURE__ */ new Map();
|
|
742
|
-
#wsOnOpenHandler;
|
|
743
|
-
#wsOnMessageHandler;
|
|
744
|
-
#wsOnErrorHandler;
|
|
745
|
-
#wsOnCloseHandler;
|
|
746
|
-
#eventbridge;
|
|
747
|
-
#eventbridgeAsync;
|
|
748
|
-
constructor(exports) {
|
|
749
|
-
super(exports);
|
|
750
|
-
this.#wsOnOpenHandler = wrapPromisingExport(exports.__zx_ws_onopen);
|
|
751
|
-
this.#wsOnMessageHandler = wrapPromisingExport(exports.__zx_ws_onmessage);
|
|
752
|
-
this.#wsOnErrorHandler = wrapPromisingExport(exports.__zx_ws_onerror);
|
|
753
|
-
this.#wsOnCloseHandler = wrapPromisingExport(exports.__zx_ws_onclose);
|
|
754
|
-
this.#eventbridge = exports.__zx_eventbridge;
|
|
755
|
-
this.#eventbridgeAsync = wrapPromisingExport(
|
|
756
|
-
exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
|
|
757
|
-
);
|
|
758
|
-
}
|
|
759
|
-
eventMaySuspend(velementId, eventTypeId) {
|
|
760
|
-
return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
761
|
-
}
|
|
762
|
-
setEventHandlerMode(velementId, eventTypeId, maySuspend) {
|
|
763
|
-
const bit = 1 << eventTypeId;
|
|
764
|
-
const current = eventHandlerModes.get(velementId) ?? 0;
|
|
765
|
-
const next = maySuspend ? current | bit : current & ~bit;
|
|
766
|
-
if (next === 0) eventHandlerModes.delete(velementId);
|
|
767
|
-
else eventHandlerModes.set(velementId, next);
|
|
768
|
-
}
|
|
769
|
-
clearEventHandlerModes(velementId) {
|
|
770
|
-
eventHandlerModes.delete(velementId);
|
|
771
|
-
}
|
|
772
|
-
/** Submit a form action with bound-state round-trip. */
|
|
773
|
-
submitFormActionAsync(form, actionId, statesJson, fetchId) {
|
|
774
|
-
const formData = new FormData(form);
|
|
775
|
-
formData.append("__$states", statesJson);
|
|
776
|
-
fetch(window.location.href, {
|
|
777
|
-
method: "POST",
|
|
778
|
-
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
779
|
-
headers: { "x-action": String(actionId >>> 0) },
|
|
780
|
-
body: formData
|
|
781
|
-
}).then(async (response) => {
|
|
782
|
-
const text = await response.text();
|
|
783
|
-
this._notifyFetchComplete(fetchId, response.status, text, false);
|
|
784
|
-
}).catch((error) => {
|
|
785
|
-
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
786
|
-
this._notifyFetchComplete(fetchId, 0, msg, true);
|
|
787
|
-
});
|
|
788
|
-
}
|
|
789
|
-
/**
|
|
790
|
-
* Create and connect a WebSocket.
|
|
791
|
-
* Calls __zx_ws_onopen, __zx_ws_onmessage, __zx_ws_onerror, __zx_ws_onclose.
|
|
792
|
-
*/
|
|
793
|
-
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
794
|
-
const url = readString(urlPtr, urlLen);
|
|
795
|
-
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
796
|
-
const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : void 0;
|
|
797
|
-
try {
|
|
798
|
-
const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
|
|
799
|
-
ws.binaryType = "arraybuffer";
|
|
800
|
-
ws.onopen = () => {
|
|
801
|
-
const handler = this.#wsOnOpenHandler;
|
|
802
|
-
if (!handler) return;
|
|
803
|
-
const protocol = ws.protocol || "";
|
|
804
|
-
const { ptr, len } = this._writeStringToWasm(protocol);
|
|
805
|
-
invokeWasmExport(handler, wsId, ptr, len);
|
|
806
|
-
};
|
|
807
|
-
ws.onmessage = (event) => {
|
|
808
|
-
const handler = this.#wsOnMessageHandler;
|
|
809
|
-
if (!handler) return;
|
|
810
|
-
const isBinary = event.data instanceof ArrayBuffer;
|
|
811
|
-
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
812
|
-
const { ptr, len } = this._writeBytesToWasm(data);
|
|
813
|
-
invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
|
|
814
|
-
};
|
|
815
|
-
ws.onerror = (_event) => {
|
|
816
|
-
const handler = this.#wsOnErrorHandler;
|
|
817
|
-
if (!handler) return;
|
|
818
|
-
const { ptr, len } = this._writeStringToWasm("WebSocket error");
|
|
819
|
-
invokeWasmExport(handler, wsId, ptr, len);
|
|
820
|
-
};
|
|
821
|
-
ws.onclose = (event) => {
|
|
822
|
-
const handler = this.#wsOnCloseHandler;
|
|
823
|
-
if (!handler) return;
|
|
824
|
-
const reason = event.reason || "";
|
|
825
|
-
const { ptr, len } = this._writeStringToWasm(reason);
|
|
826
|
-
invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
827
|
-
this.#websockets.delete(wsId);
|
|
828
|
-
};
|
|
829
|
-
this.#websockets.set(wsId, ws);
|
|
830
|
-
} catch (error) {
|
|
831
|
-
const handler = this.#wsOnErrorHandler;
|
|
832
|
-
if (handler) {
|
|
833
|
-
const msg = error instanceof Error ? error.message : "WebSocket connection failed";
|
|
834
|
-
const { ptr, len } = this._writeStringToWasm(msg);
|
|
835
|
-
invokeWasmExport(handler, wsId, ptr, len);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
/** Send data over WebSocket */
|
|
840
|
-
wsSend(wsId, dataPtr, dataLen, isBinary) {
|
|
841
|
-
const ws = this.#websockets.get(wsId);
|
|
842
|
-
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
843
|
-
const memory = getMemoryView();
|
|
844
|
-
if (isBinary) {
|
|
845
|
-
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
846
|
-
} else {
|
|
847
|
-
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
848
|
-
}
|
|
849
|
-
}
|
|
850
|
-
/** Close WebSocket connection */
|
|
851
|
-
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
852
|
-
const ws = this.#websockets.get(wsId);
|
|
853
|
-
if (!ws) return;
|
|
854
|
-
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : void 0;
|
|
855
|
-
try {
|
|
856
|
-
if (reason) ws.close(code, reason);
|
|
857
|
-
else ws.close(code);
|
|
858
|
-
} catch {
|
|
859
|
-
ws.close();
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
dispose() {
|
|
863
|
-
super.dispose();
|
|
864
|
-
eventHandlerModes.clear();
|
|
865
|
-
for (const ws of this.#websockets.values()) {
|
|
866
|
-
try {
|
|
867
|
-
ws.close();
|
|
868
|
-
} catch {
|
|
869
|
-
}
|
|
870
|
-
}
|
|
871
|
-
this.#websockets.clear();
|
|
872
|
-
}
|
|
873
|
-
/** Handle a DOM event (called by event delegation) */
|
|
874
|
-
eventbridge(velementId, eventTypeId, event) {
|
|
875
|
-
const eventRef = storeValueGetRef(event);
|
|
876
|
-
if (this.eventMaySuspend(velementId, eventTypeId)) {
|
|
877
|
-
invokeWasmExport(this.#eventbridgeAsync, velementId, eventTypeId, eventRef);
|
|
878
|
-
return;
|
|
879
|
-
}
|
|
880
|
-
invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
|
|
881
|
-
}
|
|
882
|
-
/** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
|
|
883
|
-
static createImportObject(bridgeRef) {
|
|
884
|
-
return {
|
|
885
|
-
...jsz.importObject(),
|
|
886
|
-
__zx_net: createFetchImports(() => {
|
|
887
|
-
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
888
|
-
return jsz.memory;
|
|
889
|
-
}),
|
|
890
|
-
__zx: {
|
|
891
|
-
_log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
|
|
892
|
-
_setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
|
|
893
|
-
bridgeRef.current?.setEventHandlerMode(vnodeId, eventTypeId, maySuspend !== 0);
|
|
894
|
-
},
|
|
895
|
-
_clearEventHandlerModes: (vnodeId) => {
|
|
896
|
-
bridgeRef.current?.clearEventHandlerModes(vnodeId);
|
|
897
|
-
},
|
|
898
|
-
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
899
|
-
bridgeRef.current?.fetchAsync(
|
|
900
|
-
urlPtr,
|
|
901
|
-
urlLen,
|
|
902
|
-
methodPtr,
|
|
903
|
-
methodLen,
|
|
904
|
-
headersPtr,
|
|
905
|
-
headersLen,
|
|
906
|
-
bodyPtr,
|
|
907
|
-
bodyLen,
|
|
908
|
-
timeoutMs,
|
|
909
|
-
fetchId
|
|
910
|
-
);
|
|
911
|
-
},
|
|
912
|
-
_setTimeout: (callbackId, delayMs) => {
|
|
913
|
-
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
914
|
-
},
|
|
915
|
-
_setInterval: (callbackId, intervalMs) => {
|
|
916
|
-
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
917
|
-
},
|
|
918
|
-
_clearInterval: (callbackId) => {
|
|
919
|
-
bridgeRef.current?.clearInterval(callbackId);
|
|
920
|
-
},
|
|
921
|
-
// WebSocket API
|
|
922
|
-
_wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
|
|
923
|
-
bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
|
|
924
|
-
},
|
|
925
|
-
_wsSend: (wsId, dataPtr, dataLen, isBinary) => {
|
|
926
|
-
bridgeRef.current?.wsSend(wsId, dataPtr, dataLen, isBinary);
|
|
927
|
-
},
|
|
928
|
-
_wsClose: (wsId, code, reasonPtr, reasonLen) => {
|
|
929
|
-
bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
|
|
930
|
-
},
|
|
931
|
-
_ce: (id, vnodeId) => {
|
|
932
|
-
const tagName = TAG_NAMES[id];
|
|
933
|
-
const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
|
|
934
|
-
el.__zx_ref = Number(vnodeId);
|
|
935
|
-
domNodes.set(vnodeId, el);
|
|
936
|
-
return storeValueGetRef(el);
|
|
937
|
-
},
|
|
938
|
-
_ct: (ptr, len, vnodeId) => {
|
|
939
|
-
const text = readString(ptr, len);
|
|
940
|
-
const node = document.createTextNode(text);
|
|
941
|
-
node.__zx_ref = Number(vnodeId);
|
|
942
|
-
domNodes.set(vnodeId, node);
|
|
943
|
-
return storeValueGetRef(node);
|
|
944
|
-
},
|
|
945
|
-
_sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
|
|
946
|
-
domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
|
|
947
|
-
},
|
|
948
|
-
_sp: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
|
|
949
|
-
const el = domNodes.get(vnodeId);
|
|
950
|
-
if (el) {
|
|
951
|
-
const name = readString(namePtr, nameLen);
|
|
952
|
-
const val = readString(valPtr, valLen);
|
|
953
|
-
if (name === "checked" || name === "selected" || name === "muted") {
|
|
954
|
-
el[name] = val !== "false";
|
|
955
|
-
} else {
|
|
956
|
-
el[name] = val;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
},
|
|
960
|
-
_ra: (vnodeId, namePtr, nameLen) => {
|
|
961
|
-
domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
|
|
962
|
-
},
|
|
963
|
-
_snv: (vnodeId, ptr, len) => {
|
|
964
|
-
const node = domNodes.get(vnodeId);
|
|
965
|
-
if (node) node.nodeValue = readString(ptr, len);
|
|
966
|
-
},
|
|
967
|
-
_srh: (vnodeId, ptr, len) => {
|
|
968
|
-
const el = domNodes.get(vnodeId);
|
|
969
|
-
if (el) el.innerHTML = readString(ptr, len);
|
|
970
|
-
},
|
|
971
|
-
_ac: (parentId, childId) => {
|
|
972
|
-
const parent = domNodes.get(parentId);
|
|
973
|
-
const child = domNodes.get(childId);
|
|
974
|
-
if (parent && child) parent.appendChild(child);
|
|
975
|
-
},
|
|
976
|
-
_ib: (parentId, childId, refId) => {
|
|
977
|
-
const parent = domNodes.get(parentId);
|
|
978
|
-
const child = domNodes.get(childId);
|
|
979
|
-
const ref = domNodes.get(refId) ?? null;
|
|
980
|
-
if (parent && child) parent.insertBefore(child, ref);
|
|
981
|
-
},
|
|
982
|
-
_rc: (parentId, childId) => {
|
|
983
|
-
const parent = domNodes.get(parentId);
|
|
984
|
-
const child = domNodes.get(childId);
|
|
985
|
-
if (parent && child) {
|
|
986
|
-
parent.removeChild(child);
|
|
987
|
-
cleanupDomNodes(child);
|
|
988
|
-
}
|
|
989
|
-
},
|
|
990
|
-
_rpc: (parentId, newId, oldId) => {
|
|
991
|
-
const parent = domNodes.get(parentId);
|
|
992
|
-
const newChild = domNodes.get(newId);
|
|
993
|
-
const oldChild = domNodes.get(oldId);
|
|
994
|
-
if (parent && newChild && oldChild) {
|
|
995
|
-
parent.replaceChild(newChild, oldChild);
|
|
996
|
-
cleanupDomNodes(oldChild);
|
|
997
|
-
}
|
|
998
|
-
},
|
|
999
|
-
_getLocationHref: (bufPtr, bufLen) => {
|
|
1000
|
-
const bytes = textEncoder.encode(window.location.href);
|
|
1001
|
-
const len = Math.min(bytes.length, bufLen);
|
|
1002
|
-
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
1003
|
-
return len;
|
|
1004
|
-
},
|
|
1005
|
-
_getFormData: (vnodeId, bufPtr, bufLen) => {
|
|
1006
|
-
const form = domNodes.get(vnodeId);
|
|
1007
|
-
if (!form || !(form instanceof HTMLFormElement)) return 0;
|
|
1008
|
-
const formData = new FormData(form);
|
|
1009
|
-
const urlEncoded = new URLSearchParams(formData).toString();
|
|
1010
|
-
const bytes = textEncoder.encode(urlEncoded);
|
|
1011
|
-
const len = Math.min(bytes.length, bufLen);
|
|
1012
|
-
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
1013
|
-
return len;
|
|
1014
|
-
},
|
|
1015
|
-
_submitFormAction: (vnodeId, actionId) => {
|
|
1016
|
-
const form = domNodes.get(vnodeId);
|
|
1017
|
-
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1018
|
-
const formData = new FormData(form);
|
|
1019
|
-
fetch(window.location.href, {
|
|
1020
|
-
method: "POST",
|
|
1021
|
-
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
1022
|
-
headers: { "x-action": String(actionId >>> 0) },
|
|
1023
|
-
body: formData
|
|
1024
|
-
}).catch(() => {
|
|
1025
|
-
});
|
|
1026
|
-
},
|
|
1027
|
-
_submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
|
|
1028
|
-
const form = domNodes.get(vnodeId);
|
|
1029
|
-
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1030
|
-
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
1031
|
-
bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1036
|
-
};
|
|
1037
|
-
var domNodes = /* @__PURE__ */ new Map();
|
|
1038
|
-
function cleanupDomNodes(node) {
|
|
1039
|
-
const ref = node.__zx_ref;
|
|
1040
|
-
if (ref !== void 0) domNodes.delete(BigInt(ref));
|
|
1041
|
-
const children = node.childNodes;
|
|
1042
|
-
for (let i = 0; i < children.length; i++) cleanupDomNodes(children[i]);
|
|
1043
|
-
}
|
|
1044
|
-
var SVG_TAG_START_INDEX = 140;
|
|
599
|
+
// src/wasm/generated/tags.ts
|
|
1045
600
|
var TAG_NAMES = [
|
|
1046
601
|
"aside",
|
|
1047
602
|
"fragment",
|
|
@@ -1183,7 +738,6 @@ var TAG_NAMES = [
|
|
|
1183
738
|
"strike",
|
|
1184
739
|
"tt",
|
|
1185
740
|
"xmp",
|
|
1186
|
-
// SVG Tags
|
|
1187
741
|
"animate",
|
|
1188
742
|
"animateMotion",
|
|
1189
743
|
"animateTransform",
|
|
@@ -1242,112 +796,780 @@ var TAG_NAMES = [
|
|
|
1242
796
|
"textPath",
|
|
1243
797
|
"tspan",
|
|
1244
798
|
"use",
|
|
1245
|
-
"view"
|
|
1246
|
-
|
|
1247
|
-
var DELEGATED_EVENTS = [
|
|
1248
|
-
{ domType: "click", eventTypeId: 0 },
|
|
1249
|
-
{ domType: "dblclick", eventTypeId: 1 },
|
|
1250
|
-
{ domType: "input", eventTypeId: 2 },
|
|
1251
|
-
{ domType: "change", eventTypeId: 3 },
|
|
1252
|
-
{ domType: "submit", eventTypeId: 4 },
|
|
1253
|
-
// focus/blur do not bubble, so delegated handlers must listen to focusin/focusout.
|
|
1254
|
-
{ domType: "focusin", eventTypeId: 5 },
|
|
1255
|
-
{ domType: "focusout", eventTypeId: 6 },
|
|
1256
|
-
{ domType: "keydown", eventTypeId: 7 },
|
|
1257
|
-
{ domType: "keyup", eventTypeId: 8 },
|
|
1258
|
-
{ domType: "keypress", eventTypeId: 9 },
|
|
1259
|
-
{ domType: "mouseenter", eventTypeId: 10 },
|
|
1260
|
-
{ domType: "mouseleave", eventTypeId: 11 },
|
|
1261
|
-
{ domType: "mousedown", eventTypeId: 12 },
|
|
1262
|
-
{ domType: "mouseup", eventTypeId: 13 },
|
|
1263
|
-
{ domType: "mousemove", eventTypeId: 14 },
|
|
1264
|
-
{ domType: "touchstart", eventTypeId: 15 },
|
|
1265
|
-
{ domType: "touchend", eventTypeId: 16 },
|
|
1266
|
-
{ domType: "touchmove", eventTypeId: 17 },
|
|
1267
|
-
{ domType: "scroll", eventTypeId: 18 }
|
|
799
|
+
"view",
|
|
800
|
+
"custom"
|
|
1268
801
|
];
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
802
|
+
|
|
803
|
+
// src/wasm/generated/tag_indices.ts
|
|
804
|
+
var SVG_TAG_START_INDEX = 140;
|
|
805
|
+
var CUSTOM_TAG_INDEX = 199;
|
|
806
|
+
|
|
807
|
+
// src/wasm/dom_cmd.ts
|
|
808
|
+
function flushDomCmds(ptr, len, ctx) {
|
|
809
|
+
const start = ptr >>> 0;
|
|
810
|
+
const length = len >>> 0;
|
|
811
|
+
if (length < DOM_CMD_HEADER_SIZE) return;
|
|
812
|
+
const mem = getMemoryView();
|
|
813
|
+
if (start + length > mem.byteLength) return;
|
|
814
|
+
const view = new DataView(mem.buffer, mem.byteOffset + start, length);
|
|
815
|
+
const count = view.getUint32(0, true);
|
|
816
|
+
const recordsBytes = count * DOM_CMD_RECORD_SIZE;
|
|
817
|
+
if (DOM_CMD_HEADER_SIZE + recordsBytes > length) return;
|
|
818
|
+
const { domNodes: domNodes2, cleanupDomNodes: cleanupDomNodes2 } = ctx;
|
|
819
|
+
for (let i = 0; i < count; i++) {
|
|
820
|
+
const off = DOM_CMD_HEADER_SIZE + i * DOM_CMD_RECORD_SIZE;
|
|
821
|
+
const op = view.getUint8(off);
|
|
822
|
+
const p0 = view.getUint32(off + 4, true);
|
|
823
|
+
const p1 = view.getUint32(off + 8, true);
|
|
824
|
+
const p2 = view.getUint32(off + 12, true);
|
|
825
|
+
const p3 = view.getUint32(off + 16, true);
|
|
826
|
+
const p4 = view.getUint32(off + 20, true);
|
|
827
|
+
switch (op) {
|
|
828
|
+
case DomOp_CreateElement: {
|
|
829
|
+
const isCustom = p0 === CUSTOM_TAG_INDEX;
|
|
830
|
+
const tagName = isCustom ? readString(p2, p3) : TAG_NAMES[p0];
|
|
831
|
+
const el = !isCustom && p0 >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
|
|
832
|
+
el.__zx_ref = p1;
|
|
833
|
+
domNodes2.set(p1, el);
|
|
834
|
+
break;
|
|
835
|
+
}
|
|
836
|
+
case DomOp_CreateText: {
|
|
837
|
+
const node = document.createTextNode(readString(p0, p1));
|
|
838
|
+
node.__zx_ref = p2;
|
|
839
|
+
domNodes2.set(p2, node);
|
|
840
|
+
break;
|
|
841
|
+
}
|
|
842
|
+
case DomOp_HydrateInsert: {
|
|
843
|
+
const child = domNodes2.get(p0);
|
|
844
|
+
const ref = BigInt(p1) | BigInt(p2) << 32n;
|
|
845
|
+
const end = loadValueFromRef(ref);
|
|
846
|
+
if (!child || !end?.parentNode) break;
|
|
847
|
+
end.parentNode.insertBefore(child, end);
|
|
848
|
+
break;
|
|
849
|
+
}
|
|
850
|
+
case DomOp_SetAttr: {
|
|
851
|
+
domNodes2.get(p0)?.setAttribute(readString(p1, p2), readString(p3, p4));
|
|
852
|
+
break;
|
|
853
|
+
}
|
|
854
|
+
case DomOp_SetProp: {
|
|
855
|
+
const el = domNodes2.get(p0);
|
|
856
|
+
if (el) {
|
|
857
|
+
const name = readString(p1, p2);
|
|
858
|
+
const val = readString(p3, p4);
|
|
859
|
+
if (name === "checked" || name === "selected" || name === "muted") {
|
|
860
|
+
el[name] = val !== "false";
|
|
861
|
+
} else {
|
|
862
|
+
el[name] = val;
|
|
863
|
+
}
|
|
1283
864
|
}
|
|
1284
|
-
|
|
865
|
+
break;
|
|
1285
866
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
867
|
+
case DomOp_RemoveAttr: {
|
|
868
|
+
domNodes2.get(p0)?.removeAttribute(readString(p1, p2));
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
case DomOp_SetNodeValue: {
|
|
872
|
+
const node = domNodes2.get(p0);
|
|
873
|
+
if (node) node.nodeValue = readString(p1, p2);
|
|
874
|
+
break;
|
|
875
|
+
}
|
|
876
|
+
case DomOp_SetInnerHtml: {
|
|
877
|
+
const el = domNodes2.get(p0);
|
|
878
|
+
if (el) el.innerHTML = readString(p1, p2);
|
|
879
|
+
break;
|
|
880
|
+
}
|
|
881
|
+
case DomOp_AppendChild: {
|
|
882
|
+
const parent = domNodes2.get(p0);
|
|
883
|
+
const child = domNodes2.get(p1);
|
|
884
|
+
if (parent && child) parent.appendChild(child);
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
case DomOp_InsertBefore: {
|
|
888
|
+
const parent = domNodes2.get(p0);
|
|
889
|
+
const child = domNodes2.get(p1);
|
|
890
|
+
const refNode = domNodes2.get(p2) ?? null;
|
|
891
|
+
if (parent && child) parent.insertBefore(child, refNode);
|
|
892
|
+
break;
|
|
893
|
+
}
|
|
894
|
+
case DomOp_RemoveChild: {
|
|
895
|
+
const parent = domNodes2.get(p0);
|
|
896
|
+
const child = domNodes2.get(p1);
|
|
897
|
+
if (parent && child) {
|
|
898
|
+
parent.removeChild(child);
|
|
899
|
+
cleanupDomNodes2(child);
|
|
900
|
+
}
|
|
901
|
+
break;
|
|
902
|
+
}
|
|
903
|
+
case DomOp_ReplaceChild: {
|
|
904
|
+
const parent = domNodes2.get(p0);
|
|
905
|
+
const newChild = domNodes2.get(p1);
|
|
906
|
+
const oldChild = domNodes2.get(p2);
|
|
907
|
+
if (parent && newChild && oldChild) {
|
|
908
|
+
parent.replaceChild(newChild, oldChild);
|
|
909
|
+
cleanupDomNodes2(oldChild);
|
|
910
|
+
}
|
|
911
|
+
break;
|
|
912
|
+
}
|
|
913
|
+
default:
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
1290
916
|
}
|
|
1291
|
-
return () => {
|
|
1292
|
-
for (const remove of removers) remove();
|
|
1293
|
-
};
|
|
1294
|
-
}
|
|
1295
|
-
var DEFAULT_URL = "/assets/_/main.wasm";
|
|
1296
|
-
var activeRuntime = null;
|
|
1297
|
-
function buildDevtoolsLocation() {
|
|
1298
|
-
return {
|
|
1299
|
-
href: window.location.href,
|
|
1300
|
-
origin: window.location.origin,
|
|
1301
|
-
host: window.location.host,
|
|
1302
|
-
pathname: window.location.pathname
|
|
1303
|
-
};
|
|
1304
917
|
}
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
kv: options.kv
|
|
1311
|
-
};
|
|
918
|
+
|
|
919
|
+
// src/runtime/kv/extern.ts
|
|
920
|
+
function putOptions(ttlSeconds) {
|
|
921
|
+
if (ttlSeconds < 60) return void 0;
|
|
922
|
+
return { expirationTtl: ttlSeconds };
|
|
1312
923
|
}
|
|
1313
|
-
function
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
window.__zx_dev_reinit = reinit;
|
|
1317
|
-
window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
1318
|
-
location: buildDevtoolsLocation(),
|
|
1319
|
-
reinit
|
|
1320
|
-
};
|
|
924
|
+
function isSyncKVNamespace(binding) {
|
|
925
|
+
const candidate = binding;
|
|
926
|
+
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
1321
927
|
}
|
|
1322
|
-
|
|
1323
|
-
const
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
928
|
+
function createKVImports(bindings, getMemory, allocRef) {
|
|
929
|
+
const encoder2 = new TextEncoder();
|
|
930
|
+
const decoder2 = new TextDecoder();
|
|
931
|
+
function readStr(ptr, len) {
|
|
932
|
+
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
933
|
+
}
|
|
934
|
+
function binding(ns) {
|
|
935
|
+
return bindings[ns] ?? bindings["default"] ?? null;
|
|
936
|
+
}
|
|
937
|
+
const Suspending = WebAssembly.Suspending;
|
|
938
|
+
if (typeof Suspending !== "function") {
|
|
939
|
+
let syncBinding2 = function(ns) {
|
|
940
|
+
const candidate = binding(ns);
|
|
941
|
+
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
942
|
+
};
|
|
943
|
+
var syncBinding = syncBinding2;
|
|
944
|
+
return {
|
|
945
|
+
kv_get: (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
|
|
946
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
947
|
+
if (!b) return -1;
|
|
948
|
+
const value = b.getSync(readStr(key_ptr, key_len));
|
|
949
|
+
if (value === null) return -1;
|
|
950
|
+
return writeBytesOut(getMemory, allocRef, out_ptr, encoder2.encode(value));
|
|
951
|
+
},
|
|
952
|
+
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
953
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
954
|
+
if (!b) return 0;
|
|
955
|
+
b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
956
|
+
return 0;
|
|
957
|
+
},
|
|
958
|
+
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
959
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
960
|
+
if (!b) return 0;
|
|
961
|
+
b.deleteSync(readStr(key_ptr, key_len));
|
|
962
|
+
return 0;
|
|
963
|
+
},
|
|
964
|
+
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
|
|
965
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
966
|
+
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
967
|
+
const prefix = readStr(pfx_ptr, pfx_len);
|
|
968
|
+
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
969
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, result.keys.map((k) => k.name));
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
return {
|
|
974
|
+
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
|
|
975
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
976
|
+
if (!b) return -1;
|
|
977
|
+
const value = await b.get(readStr(key_ptr, key_len));
|
|
978
|
+
if (value === null) return -1;
|
|
979
|
+
return writeBytesOut(getMemory, allocRef, out_ptr, encoder2.encode(value));
|
|
980
|
+
}),
|
|
981
|
+
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
982
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
983
|
+
if (!b) return -1;
|
|
984
|
+
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
985
|
+
return 0;
|
|
986
|
+
}),
|
|
987
|
+
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
988
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
989
|
+
if (!b) return -1;
|
|
990
|
+
await b.delete(readStr(key_ptr, key_len));
|
|
991
|
+
return 0;
|
|
992
|
+
}),
|
|
993
|
+
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, out_ptr) => {
|
|
994
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
995
|
+
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
996
|
+
const prefix = readStr(prefix_ptr, prefix_len);
|
|
997
|
+
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
998
|
+
const names = result.keys.map((k) => k.name);
|
|
999
|
+
if (names.length === 0) {
|
|
1000
|
+
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
1001
|
+
return 0;
|
|
1002
|
+
}
|
|
1003
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, names);
|
|
1004
|
+
})
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// src/runtime/kv/localstorage.ts
|
|
1009
|
+
function getLocalStorage() {
|
|
1010
|
+
if (typeof localStorage === "undefined") {
|
|
1011
|
+
throw new Error("localStorage is not available in this environment");
|
|
1012
|
+
}
|
|
1013
|
+
return localStorage;
|
|
1014
|
+
}
|
|
1015
|
+
function createLocalStorageKV(options = {}) {
|
|
1016
|
+
const storage = getLocalStorage();
|
|
1017
|
+
const namespace = options.namespace ?? "default";
|
|
1018
|
+
const storagePrefix = options.storagePrefix ?? "ziex-kv";
|
|
1019
|
+
const scopedKey = (key) => `${storagePrefix}:${namespace}:${key}`;
|
|
1020
|
+
const namespacePrefix = scopedKey("");
|
|
1021
|
+
return {
|
|
1022
|
+
getSync(key) {
|
|
1023
|
+
return storage.getItem(scopedKey(key));
|
|
1024
|
+
},
|
|
1025
|
+
async get(key) {
|
|
1026
|
+
return this.getSync(key);
|
|
1027
|
+
},
|
|
1028
|
+
putSync(key, value) {
|
|
1029
|
+
storage.setItem(scopedKey(key), value);
|
|
1030
|
+
},
|
|
1031
|
+
async put(key, value) {
|
|
1032
|
+
this.putSync(key, value);
|
|
1033
|
+
},
|
|
1034
|
+
deleteSync(key) {
|
|
1035
|
+
storage.removeItem(scopedKey(key));
|
|
1036
|
+
},
|
|
1037
|
+
async delete(key) {
|
|
1038
|
+
this.deleteSync(key);
|
|
1039
|
+
},
|
|
1040
|
+
listSync(options2) {
|
|
1041
|
+
const prefix = namespacePrefix + (options2?.prefix ?? "");
|
|
1042
|
+
const keys = [];
|
|
1043
|
+
for (let i = 0; i < storage.length; i += 1) {
|
|
1044
|
+
const key = storage.key(i);
|
|
1045
|
+
if (!key || !key.startsWith(prefix)) continue;
|
|
1046
|
+
keys.push({ name: key.slice(namespacePrefix.length) });
|
|
1047
|
+
}
|
|
1048
|
+
return { keys };
|
|
1049
|
+
},
|
|
1050
|
+
async list(options2) {
|
|
1051
|
+
return this.listSync(options2);
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// src/runtime/kv/indexdb.ts
|
|
1057
|
+
function getIndexedDb() {
|
|
1058
|
+
if (typeof indexedDB === "undefined") {
|
|
1059
|
+
throw new Error("IndexedDB is not available in this environment");
|
|
1060
|
+
}
|
|
1061
|
+
return indexedDB;
|
|
1062
|
+
}
|
|
1063
|
+
function requestToPromise(request) {
|
|
1064
|
+
return new Promise((resolve, reject) => {
|
|
1065
|
+
request.onsuccess = () => resolve(request.result);
|
|
1066
|
+
request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
function transactionToPromise(transaction) {
|
|
1070
|
+
return new Promise((resolve, reject) => {
|
|
1071
|
+
transaction.oncomplete = () => resolve();
|
|
1072
|
+
transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
|
|
1073
|
+
transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
function createIndexedDbKV(options = {}) {
|
|
1077
|
+
const databaseName = options.databaseName ?? "ziex-kv";
|
|
1078
|
+
const storeName = options.storeName ?? "kv";
|
|
1079
|
+
const namespace = options.namespace ?? "default";
|
|
1080
|
+
const dbPromise = new Promise((resolve, reject) => {
|
|
1081
|
+
const request = getIndexedDb().open(databaseName, 1);
|
|
1082
|
+
request.onupgradeneeded = () => {
|
|
1083
|
+
const db = request.result;
|
|
1084
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
1085
|
+
db.createObjectStore(storeName);
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
request.onsuccess = () => resolve(request.result);
|
|
1089
|
+
request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
|
|
1090
|
+
});
|
|
1091
|
+
const scopedKey = (key) => `${namespace}:${key}`;
|
|
1092
|
+
return {
|
|
1093
|
+
async get(key) {
|
|
1094
|
+
const db = await dbPromise;
|
|
1095
|
+
const tx = db.transaction(storeName, "readonly");
|
|
1096
|
+
const store = tx.objectStore(storeName);
|
|
1097
|
+
const value = await requestToPromise(store.get(scopedKey(key)));
|
|
1098
|
+
await transactionToPromise(tx);
|
|
1099
|
+
return typeof value === "string" ? value : null;
|
|
1100
|
+
},
|
|
1101
|
+
async put(key, value) {
|
|
1102
|
+
const db = await dbPromise;
|
|
1103
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1104
|
+
tx.objectStore(storeName).put(value, scopedKey(key));
|
|
1105
|
+
await transactionToPromise(tx);
|
|
1106
|
+
},
|
|
1107
|
+
async delete(key) {
|
|
1108
|
+
const db = await dbPromise;
|
|
1109
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1110
|
+
tx.objectStore(storeName).delete(scopedKey(key));
|
|
1111
|
+
await transactionToPromise(tx);
|
|
1112
|
+
},
|
|
1113
|
+
async list(options2) {
|
|
1114
|
+
const db = await dbPromise;
|
|
1115
|
+
const tx = db.transaction(storeName, "readonly");
|
|
1116
|
+
const store = tx.objectStore(storeName);
|
|
1117
|
+
const keys = await requestToPromise(store.getAllKeys());
|
|
1118
|
+
await transactionToPromise(tx);
|
|
1119
|
+
const prefix = scopedKey(options2?.prefix ?? "");
|
|
1120
|
+
return {
|
|
1121
|
+
keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// src/runtime/kv.ts
|
|
1128
|
+
function hasJSPI() {
|
|
1129
|
+
return typeof WebAssembly.Suspending === "function" && typeof WebAssembly.promising === "function";
|
|
1130
|
+
}
|
|
1131
|
+
function createBrowserKVBindings(options = {}) {
|
|
1132
|
+
const namespace = options.namespace ?? "default";
|
|
1133
|
+
const isIndexedDb = hasJSPI() && !options.forceLocalStorage;
|
|
1134
|
+
return {
|
|
1135
|
+
[namespace]: isIndexedDb ? createIndexedDbKV(options) : createLocalStorageKV(options)
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// src/wasm/generated/events.ts
|
|
1140
|
+
var DELEGATED_EVENTS = [
|
|
1141
|
+
"click",
|
|
1142
|
+
"dblclick",
|
|
1143
|
+
"input",
|
|
1144
|
+
"change",
|
|
1145
|
+
"submit",
|
|
1146
|
+
"focusin",
|
|
1147
|
+
"focusout",
|
|
1148
|
+
"keydown",
|
|
1149
|
+
"keyup",
|
|
1150
|
+
"keypress",
|
|
1151
|
+
"mouseenter",
|
|
1152
|
+
"mouseleave",
|
|
1153
|
+
"mousedown",
|
|
1154
|
+
"mouseup",
|
|
1155
|
+
"mousemove",
|
|
1156
|
+
"touchstart",
|
|
1157
|
+
"touchend",
|
|
1158
|
+
"touchmove",
|
|
1159
|
+
"scroll",
|
|
1160
|
+
"wheel",
|
|
1161
|
+
"pointerdown",
|
|
1162
|
+
"pointermove",
|
|
1163
|
+
"pointerup",
|
|
1164
|
+
"pointercancel",
|
|
1165
|
+
"pointerenter",
|
|
1166
|
+
"pointerleave",
|
|
1167
|
+
"lostpointercapture"
|
|
1168
|
+
];
|
|
1169
|
+
|
|
1170
|
+
// src/wasm/generated/event_bits.ts
|
|
1171
|
+
var HIGH_FREQ_EVENT_BITS = 3031040;
|
|
1172
|
+
|
|
1173
|
+
// src/wasm/index.ts
|
|
1174
|
+
var ZxBridge = class extends ZxBridgeCore {
|
|
1175
|
+
#websockets = /* @__PURE__ */ new Map();
|
|
1176
|
+
#eventbridge;
|
|
1177
|
+
#eventbridgeAsync;
|
|
1178
|
+
constructor(exports) {
|
|
1179
|
+
super(exports);
|
|
1180
|
+
this.#eventbridge = exports.__zx_eventbridge;
|
|
1181
|
+
this.#eventbridgeAsync = wrapPromisingExport(
|
|
1182
|
+
exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
hasEventHandler(velementId, eventTypeId) {
|
|
1186
|
+
return !!((eventHandlersPresent.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
1187
|
+
}
|
|
1188
|
+
eventMaySuspend(velementId, eventTypeId) {
|
|
1189
|
+
return !!((eventHandlersSuspend.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
1190
|
+
}
|
|
1191
|
+
setEventHandlerMode(velementId, eventTypeId, maySuspend) {
|
|
1192
|
+
const bit = 1 << eventTypeId;
|
|
1193
|
+
const present = (eventHandlersPresent.get(velementId) ?? 0) | bit;
|
|
1194
|
+
eventHandlersPresent.set(velementId, present);
|
|
1195
|
+
const suspendBits = eventHandlersSuspend.get(velementId) ?? 0;
|
|
1196
|
+
const nextSuspend = maySuspend ? suspendBits | bit : suspendBits & ~bit;
|
|
1197
|
+
if (nextSuspend === 0) eventHandlersSuspend.delete(velementId);
|
|
1198
|
+
else eventHandlersSuspend.set(velementId, nextSuspend);
|
|
1199
|
+
ensureDelegatedListener(eventTypeId);
|
|
1200
|
+
}
|
|
1201
|
+
clearEventHandlerModes(velementId) {
|
|
1202
|
+
const present = eventHandlersPresent.get(velementId) ?? 0;
|
|
1203
|
+
eventHandlersPresent.delete(velementId);
|
|
1204
|
+
eventHandlersSuspend.delete(velementId);
|
|
1205
|
+
for (let bits = present & HIGH_FREQ_EVENT_BITS; bits !== 0; bits &= bits - 1) {
|
|
1206
|
+
maybeRemoveHighFreqListener(31 - Math.clz32(bits));
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
/** Submit a form action with bound-state round-trip. */
|
|
1210
|
+
submitFormActionAsync(form, actionId, statesJson, fetchId) {
|
|
1211
|
+
const formData = new FormData(form);
|
|
1212
|
+
formData.append("__$states", statesJson);
|
|
1213
|
+
fetch(window.location.href, {
|
|
1214
|
+
method: "POST",
|
|
1215
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
1216
|
+
headers: { "x-action": String(actionId >>> 0) },
|
|
1217
|
+
body: formData
|
|
1218
|
+
}).then(async (response) => {
|
|
1219
|
+
const text = await response.text();
|
|
1220
|
+
this._notifyFetchComplete(fetchId, response.status, text, false);
|
|
1221
|
+
}).catch((error) => {
|
|
1222
|
+
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
1223
|
+
this._notifyFetchComplete(fetchId, 0, msg, true);
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Create and connect a WebSocket.
|
|
1228
|
+
* Completes via `__zx_cb(ws_open|ws_message|ws_error|ws_close, ...)`.
|
|
1229
|
+
*/
|
|
1230
|
+
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
1231
|
+
const url = readString(urlPtr, urlLen);
|
|
1232
|
+
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
1233
|
+
const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : void 0;
|
|
1234
|
+
try {
|
|
1235
|
+
const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
|
|
1236
|
+
ws.binaryType = "arraybuffer";
|
|
1237
|
+
ws.onopen = () => {
|
|
1238
|
+
const protocol = ws.protocol || "";
|
|
1239
|
+
const [ptr, len] = this._writeStringToWasm(protocol);
|
|
1240
|
+
this._invoke(CallbackType_WebSocketOpen, wsId, BigInt(ptr), BigInt(len));
|
|
1241
|
+
};
|
|
1242
|
+
ws.onmessage = (event) => {
|
|
1243
|
+
const isBinary = event.data instanceof ArrayBuffer;
|
|
1244
|
+
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
1245
|
+
const [ptr, len] = this.writeBytesToWasm(data);
|
|
1246
|
+
this._invoke(CallbackType_WebSocketMessage, wsId, BigInt(ptr), BigInt(len), BigInt(isBinary ? 1 : 0));
|
|
1247
|
+
};
|
|
1248
|
+
ws.onerror = (_event) => {
|
|
1249
|
+
const [ptr, len] = this._writeStringToWasm("WebSocket error");
|
|
1250
|
+
this._invoke(CallbackType_WebSocketError, wsId, BigInt(ptr), BigInt(len));
|
|
1251
|
+
};
|
|
1252
|
+
ws.onclose = (event) => {
|
|
1253
|
+
const reason = event.reason || "";
|
|
1254
|
+
const [ptr, len] = this._writeStringToWasm(reason);
|
|
1255
|
+
const c = BigInt(len) | BigInt(event.wasClean ? 1 : 0) << 32n;
|
|
1256
|
+
this._invoke(CallbackType_WebSocketClose, wsId, BigInt(event.code), BigInt(ptr), c);
|
|
1257
|
+
this.#websockets.delete(wsId);
|
|
1258
|
+
};
|
|
1259
|
+
this.#websockets.set(wsId, ws);
|
|
1260
|
+
} catch (error) {
|
|
1261
|
+
const msg = error instanceof Error ? error.message : "WebSocket connection failed";
|
|
1262
|
+
const [ptr, len] = this._writeStringToWasm(msg);
|
|
1263
|
+
this._invoke(CallbackType_WebSocketError, wsId, BigInt(ptr), BigInt(len));
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
/** Send data over WebSocket */
|
|
1267
|
+
wsSend(wsId, dataPtr, dataLen, isBinary) {
|
|
1268
|
+
const ws = this.#websockets.get(wsId);
|
|
1269
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
1270
|
+
const memory = getMemoryView();
|
|
1271
|
+
const start = dataPtr >>> 0;
|
|
1272
|
+
const length = dataLen >>> 0;
|
|
1273
|
+
if (start + length > memory.byteLength) return;
|
|
1274
|
+
if (isBinary) {
|
|
1275
|
+
ws.send(memory.slice(start, start + length));
|
|
1276
|
+
} else {
|
|
1277
|
+
ws.send(textDecoder.decode(memory.subarray(start, start + length)));
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
/** Close WebSocket connection */
|
|
1281
|
+
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
1282
|
+
const ws = this.#websockets.get(wsId);
|
|
1283
|
+
if (!ws) return;
|
|
1284
|
+
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : void 0;
|
|
1285
|
+
try {
|
|
1286
|
+
if (reason) ws.close(code, reason);
|
|
1287
|
+
else ws.close(code);
|
|
1288
|
+
} catch {
|
|
1289
|
+
ws.close();
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
dispose() {
|
|
1293
|
+
super.dispose();
|
|
1294
|
+
eventHandlersPresent.clear();
|
|
1295
|
+
eventHandlersSuspend.clear();
|
|
1296
|
+
for (const ws of this.#websockets.values()) {
|
|
1297
|
+
try {
|
|
1298
|
+
ws.close();
|
|
1299
|
+
} catch {
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
this.#websockets.clear();
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Dispatch to WASM for one vnode. Caller owns `eventRef` lifetime
|
|
1306
|
+
* (store once per bubble, release after sync/async work completes).
|
|
1307
|
+
*/
|
|
1308
|
+
eventbridge(velementId, eventTypeId, eventRef) {
|
|
1309
|
+
const id = BigInt(velementId >>> 0);
|
|
1310
|
+
if (this.eventMaySuspend(velementId, eventTypeId)) {
|
|
1311
|
+
return invokeWasmExport(this.#eventbridgeAsync, id, eventTypeId, eventRef);
|
|
1312
|
+
}
|
|
1313
|
+
invokeWasmExport(this.#eventbridge, id, eventTypeId, eventRef);
|
|
1314
|
+
}
|
|
1315
|
+
/** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
|
|
1316
|
+
static createImportObject(bridgeRef) {
|
|
1317
|
+
return {
|
|
1318
|
+
...jsz.importObject(),
|
|
1319
|
+
__zx_net: createFetchImports(() => {
|
|
1320
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
1321
|
+
return jsz.memory;
|
|
1322
|
+
}),
|
|
1323
|
+
__zx: {
|
|
1324
|
+
_log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
|
|
1325
|
+
_setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
|
|
1326
|
+
bridgeRef[0]?.setEventHandlerMode(Number(vnodeId), eventTypeId, maySuspend !== 0);
|
|
1327
|
+
},
|
|
1328
|
+
_clearEventHandlerModes: (vnodeId) => {
|
|
1329
|
+
bridgeRef[0]?.clearEventHandlerModes(Number(vnodeId));
|
|
1330
|
+
},
|
|
1331
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1332
|
+
bridgeRef[0]?.fetchAsync(
|
|
1333
|
+
urlPtr,
|
|
1334
|
+
urlLen,
|
|
1335
|
+
methodPtr,
|
|
1336
|
+
methodLen,
|
|
1337
|
+
headersPtr,
|
|
1338
|
+
headersLen,
|
|
1339
|
+
bodyPtr,
|
|
1340
|
+
bodyLen,
|
|
1341
|
+
timeoutMs,
|
|
1342
|
+
fetchId
|
|
1343
|
+
);
|
|
1344
|
+
},
|
|
1345
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
1346
|
+
bridgeRef[0]?.setTimeout(callbackId, delayMs);
|
|
1347
|
+
},
|
|
1348
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
1349
|
+
bridgeRef[0]?.setInterval(callbackId, intervalMs);
|
|
1350
|
+
},
|
|
1351
|
+
_clearInterval: (callbackId) => {
|
|
1352
|
+
bridgeRef[0]?.clearInterval(callbackId);
|
|
1353
|
+
},
|
|
1354
|
+
// WebSocket API
|
|
1355
|
+
_wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
|
|
1356
|
+
bridgeRef[0]?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
|
|
1357
|
+
},
|
|
1358
|
+
_wsSend: (wsId, dataPtr, dataLen, isBinary) => {
|
|
1359
|
+
bridgeRef[0]?.wsSend(wsId, dataPtr, dataLen, isBinary);
|
|
1360
|
+
},
|
|
1361
|
+
_wsClose: (wsId, code, reasonPtr, reasonLen) => {
|
|
1362
|
+
bridgeRef[0]?.wsClose(wsId, code, reasonPtr, reasonLen);
|
|
1363
|
+
},
|
|
1364
|
+
_flush: (ptr, len) => {
|
|
1365
|
+
flushDomCmds(ptr, len, {
|
|
1366
|
+
domNodes,
|
|
1367
|
+
cleanupDomNodes
|
|
1368
|
+
});
|
|
1369
|
+
},
|
|
1370
|
+
_getLocationHref: (bufPtr, bufLen) => {
|
|
1371
|
+
const bytes = textEncoder.encode(window.location.href);
|
|
1372
|
+
const len = Math.min(bytes.length, bufLen);
|
|
1373
|
+
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
1374
|
+
return len;
|
|
1375
|
+
},
|
|
1376
|
+
_getFormData: (eventRef, outPtrAddr) => {
|
|
1377
|
+
const event = loadValueFromRef(eventRef);
|
|
1378
|
+
const el = event?.target;
|
|
1379
|
+
const form = el instanceof HTMLFormElement ? el : el?.closest?.("form") ?? null;
|
|
1380
|
+
if (!form) return 0;
|
|
1381
|
+
const entries = [];
|
|
1382
|
+
for (const [k, v] of new FormData(form).entries()) {
|
|
1383
|
+
entries.push(k, String(v));
|
|
1384
|
+
}
|
|
1385
|
+
const bytes = textEncoder.encode(JSON.stringify(entries));
|
|
1386
|
+
const [ptr, len] = bridgeRef[0].writeBytesToWasm(bytes);
|
|
1387
|
+
new DataView(jsz.memory.buffer).setUint32(outPtrAddr, ptr, true);
|
|
1388
|
+
return len;
|
|
1389
|
+
},
|
|
1390
|
+
_submitFormAction: (vnodeId, actionId) => {
|
|
1391
|
+
const form = domNodes.get(Number(vnodeId));
|
|
1392
|
+
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1393
|
+
const formData = new FormData(form);
|
|
1394
|
+
fetch(window.location.href, {
|
|
1395
|
+
method: "POST",
|
|
1396
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
1397
|
+
headers: { "x-action": String(actionId >>> 0) },
|
|
1398
|
+
body: formData
|
|
1399
|
+
}).catch(() => {
|
|
1400
|
+
});
|
|
1401
|
+
},
|
|
1402
|
+
_submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
|
|
1403
|
+
const form = domNodes.get(Number(vnodeId));
|
|
1404
|
+
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1405
|
+
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
1406
|
+
bridgeRef[0]?.submitFormActionAsync(form, actionId, statesJson, fetchId);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
var domNodes = /* @__PURE__ */ new Map();
|
|
1413
|
+
var eventHandlersPresent = /* @__PURE__ */ new Map();
|
|
1414
|
+
var eventHandlersSuspend = /* @__PURE__ */ new Map();
|
|
1415
|
+
function cleanupDomNodes(node) {
|
|
1416
|
+
const stack = [node];
|
|
1417
|
+
let highFreqBits = 0;
|
|
1418
|
+
while (stack.length > 0) {
|
|
1419
|
+
const n = stack.pop();
|
|
1420
|
+
const ref = n.__zx_ref;
|
|
1421
|
+
if (typeof ref === "number") {
|
|
1422
|
+
const present = eventHandlersPresent.get(ref);
|
|
1423
|
+
if (present !== void 0) {
|
|
1424
|
+
highFreqBits |= present;
|
|
1425
|
+
eventHandlersPresent.delete(ref);
|
|
1426
|
+
eventHandlersSuspend.delete(ref);
|
|
1427
|
+
}
|
|
1428
|
+
domNodes.delete(ref);
|
|
1429
|
+
}
|
|
1430
|
+
const children = n.childNodes;
|
|
1431
|
+
for (let i = 0; i < children.length; i++) stack.push(children[i]);
|
|
1432
|
+
}
|
|
1433
|
+
for (let bits = highFreqBits & HIGH_FREQ_EVENT_BITS; bits !== 0; bits &= bits - 1) {
|
|
1434
|
+
maybeRemoveHighFreqListener(31 - Math.clz32(bits));
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
var delegationState = null;
|
|
1438
|
+
function makeDelegatedListener(bridge, eventTypeId) {
|
|
1439
|
+
return (event) => {
|
|
1440
|
+
let eventRef;
|
|
1441
|
+
const pending = [];
|
|
1442
|
+
let target = event.target;
|
|
1443
|
+
while (target && target !== document.body) {
|
|
1444
|
+
const zxRef = target.__zx_ref;
|
|
1445
|
+
if (typeof zxRef === "number" && bridge.hasEventHandler(zxRef, eventTypeId)) {
|
|
1446
|
+
if (eventRef === void 0) eventRef = storeValueGetRef(event);
|
|
1447
|
+
const result = bridge.eventbridge(zxRef, eventTypeId, eventRef);
|
|
1448
|
+
if (result && typeof result.then === "function") {
|
|
1449
|
+
pending.push(result);
|
|
1450
|
+
}
|
|
1451
|
+
if (event.cancelBubble) break;
|
|
1452
|
+
}
|
|
1453
|
+
target = target.parentElement;
|
|
1454
|
+
}
|
|
1455
|
+
if (eventRef !== void 0) {
|
|
1456
|
+
const ref = eventRef;
|
|
1457
|
+
if (pending.length > 0) {
|
|
1458
|
+
Promise.all(pending).finally(() => releaseValueRef(ref));
|
|
1459
|
+
} else {
|
|
1460
|
+
releaseValueRef(ref);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
function ensureDelegatedListener(eventTypeId) {
|
|
1466
|
+
const state = delegationState;
|
|
1467
|
+
if (!state || state.attached.has(eventTypeId)) return;
|
|
1468
|
+
const domType = DELEGATED_EVENTS[eventTypeId];
|
|
1469
|
+
if (!domType) return;
|
|
1470
|
+
const passive = domType.startsWith("touch") || domType === "scroll";
|
|
1471
|
+
const options = { passive };
|
|
1472
|
+
const listener = makeDelegatedListener(state.bridge, eventTypeId);
|
|
1473
|
+
state.root.addEventListener(domType, listener, options);
|
|
1474
|
+
state.attached.set(eventTypeId, { listener, options });
|
|
1475
|
+
}
|
|
1476
|
+
function anyHandlerForType(eventTypeId) {
|
|
1477
|
+
const bit = 1 << eventTypeId;
|
|
1478
|
+
for (const mask of eventHandlersPresent.values()) {
|
|
1479
|
+
if (mask & bit) return true;
|
|
1480
|
+
}
|
|
1481
|
+
return false;
|
|
1482
|
+
}
|
|
1483
|
+
function maybeRemoveHighFreqListener(eventTypeId) {
|
|
1484
|
+
if ((HIGH_FREQ_EVENT_BITS & 1 << eventTypeId) === 0) return;
|
|
1485
|
+
if (anyHandlerForType(eventTypeId)) return;
|
|
1486
|
+
const state = delegationState;
|
|
1487
|
+
if (!state) return;
|
|
1488
|
+
const entry = state.attached.get(eventTypeId);
|
|
1489
|
+
if (!entry) return;
|
|
1490
|
+
const domType = DELEGATED_EVENTS[eventTypeId];
|
|
1491
|
+
state.root.removeEventListener(domType, entry.listener, entry.options);
|
|
1492
|
+
state.attached.delete(eventTypeId);
|
|
1493
|
+
}
|
|
1494
|
+
function initEventDelegation(bridge, rootSelector = "body") {
|
|
1495
|
+
const root = document.querySelector(rootSelector);
|
|
1496
|
+
if (!root) return () => {
|
|
1497
|
+
};
|
|
1498
|
+
delegationState = { root, bridge, attached: /* @__PURE__ */ new Map() };
|
|
1499
|
+
for (let eventTypeId = 0; eventTypeId < DELEGATED_EVENTS.length; eventTypeId++) {
|
|
1500
|
+
if ((HIGH_FREQ_EVENT_BITS & 1 << eventTypeId) !== 0) continue;
|
|
1501
|
+
ensureDelegatedListener(eventTypeId);
|
|
1502
|
+
}
|
|
1503
|
+
return () => {
|
|
1504
|
+
if (!delegationState) return;
|
|
1505
|
+
for (const [eventTypeId, entry] of delegationState.attached) {
|
|
1506
|
+
const domType = DELEGATED_EVENTS[eventTypeId];
|
|
1507
|
+
delegationState.root.removeEventListener(domType, entry.listener, entry.options);
|
|
1508
|
+
}
|
|
1509
|
+
delegationState.attached.clear();
|
|
1510
|
+
delegationState = null;
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
var activeRuntime = null;
|
|
1514
|
+
function buildDevtoolsLocation() {
|
|
1515
|
+
return {
|
|
1516
|
+
href: window.location.href,
|
|
1517
|
+
origin: window.location.origin,
|
|
1518
|
+
host: window.location.host,
|
|
1519
|
+
pathname: window.location.pathname
|
|
1520
|
+
};
|
|
1521
|
+
}
|
|
1522
|
+
function normalizeOptions(options = {}) {
|
|
1523
|
+
return {
|
|
1524
|
+
url: options.url,
|
|
1525
|
+
eventDelegationRoot: options.eventDelegationRoot,
|
|
1526
|
+
importObject: options.importObject,
|
|
1527
|
+
kv: options.kv
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
function registerDevReinit(options) {
|
|
1531
|
+
if (typeof window === "undefined") return;
|
|
1532
|
+
const reinit = () => init(options);
|
|
1533
|
+
window.__zx_dev_reinit = reinit;
|
|
1534
|
+
window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
1535
|
+
location: buildDevtoolsLocation(),
|
|
1536
|
+
reinit
|
|
1537
|
+
};
|
|
1538
|
+
}
|
|
1539
|
+
async function init(options = {}) {
|
|
1540
|
+
const normalizedOptions = normalizeOptions(options);
|
|
1541
|
+
if (activeRuntime) {
|
|
1542
|
+
activeRuntime.dispose();
|
|
1543
|
+
activeRuntime = null;
|
|
1544
|
+
}
|
|
1545
|
+
const url = options.url ?? document.getElementById("__$wasmlink")?.href;
|
|
1546
|
+
if (!url) throw new Error("WASM URL is not set");
|
|
1547
|
+
const bridgeRef = [null];
|
|
1548
|
+
let wasmMemory = null;
|
|
1549
|
+
const allocRef = [null];
|
|
1550
|
+
const getMemory = () => {
|
|
1551
|
+
if (wasmMemory) return wasmMemory;
|
|
1552
|
+
if (jsz.memory) return jsz.memory;
|
|
1553
|
+
throw new Error("WASM memory is not ready");
|
|
1554
|
+
};
|
|
1555
|
+
const importObject = {
|
|
1556
|
+
...ZxBridge.createImportObject(bridgeRef),
|
|
1557
|
+
...options.importObject
|
|
1558
|
+
};
|
|
1559
|
+
if (true) {
|
|
1560
|
+
importObject.__zx_kv = createKVImports(
|
|
1561
|
+
options.kv ?? createBrowserKVBindings(),
|
|
1562
|
+
getMemory,
|
|
1563
|
+
allocRef
|
|
1564
|
+
);
|
|
1327
1565
|
}
|
|
1328
|
-
const url = options.url ?? document.getElementById("__$wasmlink")?.href ?? DEFAULT_URL;
|
|
1329
|
-
const bridgeRef = { current: null };
|
|
1330
|
-
let wasmMemory = null;
|
|
1331
|
-
const kvBindings = options.kv ?? createBrowserKVBindings();
|
|
1332
|
-
const kvImportObject = {
|
|
1333
|
-
__zx_kv: createKVImports(kvBindings, () => {
|
|
1334
|
-
if (wasmMemory) return wasmMemory;
|
|
1335
|
-
if (jsz.memory) return jsz.memory;
|
|
1336
|
-
throw new Error("WASM memory is not ready");
|
|
1337
|
-
})
|
|
1338
|
-
};
|
|
1339
|
-
const importObject = Object.assign(
|
|
1340
|
-
{},
|
|
1341
|
-
ZxBridge.createImportObject(bridgeRef),
|
|
1342
|
-
kvImportObject,
|
|
1343
|
-
options.importObject
|
|
1344
|
-
);
|
|
1345
1566
|
const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
1346
1567
|
const { instance } = source;
|
|
1347
1568
|
wasmMemory = instance.exports.memory;
|
|
1348
1569
|
jsz.memory = wasmMemory;
|
|
1570
|
+
bindWasmAlloc(allocRef, instance.exports);
|
|
1349
1571
|
const bridge = new ZxBridge(instance.exports);
|
|
1350
|
-
bridgeRef
|
|
1572
|
+
bridgeRef[0] = bridge;
|
|
1351
1573
|
domNodes.clear();
|
|
1352
1574
|
const disposeDelegation = initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
|
|
1353
1575
|
const main = wrapPromisingExport(instance.exports.mainClient);
|
|
@@ -1364,16 +1586,29 @@ async function init(options = {}) {
|
|
|
1364
1586
|
return { source, bridge };
|
|
1365
1587
|
}
|
|
1366
1588
|
export {
|
|
1367
|
-
|
|
1589
|
+
CallbackType_Event,
|
|
1590
|
+
CallbackType_FetchError,
|
|
1591
|
+
CallbackType_FetchSuccess,
|
|
1592
|
+
CallbackType_Interval,
|
|
1593
|
+
CallbackType_Timeout,
|
|
1594
|
+
CallbackType_WebSocketClose,
|
|
1595
|
+
CallbackType_WebSocketError,
|
|
1596
|
+
CallbackType_WebSocketMessage,
|
|
1597
|
+
CallbackType_WebSocketOpen,
|
|
1368
1598
|
ZxBridge,
|
|
1369
1599
|
ZxBridgeCore,
|
|
1600
|
+
bindWasmAlloc,
|
|
1370
1601
|
getMemoryView,
|
|
1371
1602
|
init,
|
|
1372
1603
|
initEventDelegation,
|
|
1373
1604
|
jsz,
|
|
1605
|
+
loadValueFromRef,
|
|
1374
1606
|
readString,
|
|
1607
|
+
releaseValueRef,
|
|
1375
1608
|
storeValueGetRef,
|
|
1376
1609
|
textDecoder,
|
|
1377
1610
|
textEncoder,
|
|
1378
|
-
writeBytes
|
|
1611
|
+
writeBytes,
|
|
1612
|
+
writeBytesOut,
|
|
1613
|
+
writeJsonOut
|
|
1379
1614
|
};
|