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