ziex 0.1.0-dev.1360 → 0.1.0-dev.1377
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/aws-lambda/index.js +20 -29
- package/build.zig +118 -2
- package/build.zig.zon +13 -2
- package/cloudflare/index.js +1768 -1954
- package/index.js +190 -218
- package/{pkg/ziex/src/react → jsx}/dom.d.ts +5 -9
- package/{pkg/ziex/src/react → jsx}/index.d.ts +1 -1
- package/{react → jsx}/index.js +19 -25
- package/{pkg/ziex/src/react → jsx}/types.d.ts +14 -9
- package/package.json +6 -14
- package/vercel/index.js +0 -15
- package/wasm/index.js +259 -239
- package/wasm/init.dev.js +249 -191
- package/wasm/init.js +3 -3
- package/pkg/ziex/src/zx.d.ts +0 -1
- package/vendor/jsz/js/src/index.d.ts +0 -1
- package/vendor/jsz/js/src/zigjs.d.ts +0 -107
- /package/{pkg/ziex/src/app.d.ts → app.d.ts} +0 -0
- /package/{pkg/ziex/src/aws-lambda → aws-lambda}/index.d.ts +0 -0
- /package/{pkg/ziex/src/browser → browser}/kv.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/app.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/db.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/do.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/index.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/kv.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/worker.d.ts +0 -0
- /package/{pkg/ziex/src/db.d.ts → db.d.ts} +0 -0
- /package/{pkg/ziex/src/fetch.d.ts → fetch.d.ts} +0 -0
- /package/{pkg/ziex/src/index.d.ts → index.d.ts} +0 -0
- /package/{pkg/ziex/src/kv.d.ts → kv.d.ts} +0 -0
- /package/{pkg/ziex/src/runtime.d.ts → runtime.d.ts} +0 -0
- /package/{pkg/ziex/src/vercel → vercel}/index.d.ts +0 -0
- /package/{pkg/ziex/src/wasi.d.ts → wasi.d.ts} +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/core.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/dom.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/index.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/init.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/types.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/wasi.d.ts +0 -0
package/wasm/init.dev.js
CHANGED
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
// ../../vendor/jsz/js/src/zigjs.ts
|
|
2
2
|
var NAN_PREFIX = 2146959360;
|
|
3
3
|
var predefined = {
|
|
4
|
-
nan: 0,
|
|
5
|
-
null: 1,
|
|
6
|
-
true: 2,
|
|
7
|
-
false: 3,
|
|
8
|
-
undefined: 4,
|
|
9
|
-
globalThis: 5,
|
|
10
|
-
runtime: 6
|
|
4
|
+
"nan": 0,
|
|
5
|
+
"null": 1,
|
|
6
|
+
"true": 2,
|
|
7
|
+
"false": 3,
|
|
8
|
+
"undefined": 4,
|
|
9
|
+
"globalThis": 5,
|
|
10
|
+
"runtime": 6
|
|
11
11
|
};
|
|
12
12
|
var PREDEFINED_ID_MAX = 6;
|
|
13
|
-
var encoder = new TextEncoder;
|
|
13
|
+
var encoder = new TextEncoder();
|
|
14
14
|
var decoder = new TextDecoder("utf-8");
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
var ZigJS = class {
|
|
16
|
+
constructor() {
|
|
17
|
+
/**
|
|
18
|
+
* The values, indexed by ID (number). Duplicate values can be in this
|
|
19
|
+
* if they are loaded multiple times. That just acts as duplicate references.
|
|
20
|
+
* */
|
|
21
|
+
this.values = [NaN, null, true, false, void 0, globalThis, this];
|
|
22
|
+
/**
|
|
23
|
+
* When a value is removed from the values array, its ID is put
|
|
24
|
+
* in the pool so that we can use it next. This avoids fragmentation in
|
|
25
|
+
* our array keys.
|
|
26
|
+
* */
|
|
27
|
+
this.idPool = [];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns the import object that should be merged with your import
|
|
31
|
+
* object when instantiating your wasm instance. This injects the required
|
|
32
|
+
* functions into the wasm environment.
|
|
33
|
+
* */
|
|
20
34
|
importObject() {
|
|
21
35
|
return {
|
|
22
36
|
"zig-js": {
|
|
@@ -32,92 +46,121 @@ class ZigJS {
|
|
|
32
46
|
}
|
|
33
47
|
};
|
|
34
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Get a value from the JS environment.
|
|
51
|
+
* */
|
|
35
52
|
valueGet(out, id, ptr, len) {
|
|
36
53
|
const val = this.loadValue(id);
|
|
37
54
|
const str = this.loadString(ptr, len);
|
|
38
55
|
const result = Reflect.get(val, str);
|
|
39
56
|
this.storeValue(out, result);
|
|
40
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Set a value on an object.
|
|
60
|
+
* */
|
|
41
61
|
valueSet(id, ptr, len, refAddr) {
|
|
42
62
|
const obj = this.loadValue(id);
|
|
43
63
|
const str = this.loadString(ptr, len);
|
|
44
64
|
const val = this.loadRef(refAddr);
|
|
45
65
|
Reflect.set(obj, str, val);
|
|
46
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Dereference a value, allowing the JS environment to potentially GC it.
|
|
69
|
+
* */
|
|
47
70
|
valueDeinit(id) {
|
|
48
71
|
if (id > PREDEFINED_ID_MAX) {
|
|
49
72
|
this.values[id] = null;
|
|
50
73
|
this.idPool.push(id);
|
|
51
74
|
}
|
|
52
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Create an empty object.
|
|
78
|
+
* */
|
|
53
79
|
valueObjectCreate(out) {
|
|
54
|
-
this.storeValue(out, new Object);
|
|
80
|
+
this.storeValue(out, new Object());
|
|
55
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
|
|
84
|
+
* */
|
|
56
85
|
valueStringCreate(out, ptr, len) {
|
|
57
86
|
const str = this.loadString(ptr, len);
|
|
58
87
|
this.storeValue(out, str);
|
|
59
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Returns the length of the string given by id.
|
|
91
|
+
* */
|
|
60
92
|
valueStringLen(id) {
|
|
61
93
|
const val = this.loadValue(id);
|
|
62
94
|
const buf = encoder.encode(val);
|
|
63
95
|
return buf.byteLength;
|
|
64
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Copy the string at id "id" into the shared memory at ptr.
|
|
99
|
+
* */
|
|
65
100
|
valueStringCopy(id, ptr, max) {
|
|
66
|
-
if (this.memory == null)
|
|
67
|
-
return;
|
|
101
|
+
if (this.memory == null) return;
|
|
68
102
|
const val = this.loadValue(id);
|
|
69
103
|
const bytes = encoder.encode(val);
|
|
70
|
-
if (bytes.byteLength > max)
|
|
71
|
-
|
|
72
|
-
if (bytes.length === 0)
|
|
73
|
-
return;
|
|
104
|
+
if (bytes.byteLength > max) return;
|
|
105
|
+
if (bytes.length === 0) return;
|
|
74
106
|
new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
|
|
75
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Call a constructor given by id.
|
|
110
|
+
* */
|
|
76
111
|
valueNew(out, id, argsAddr, argsLen) {
|
|
77
112
|
const fn = this.loadValue(id);
|
|
78
113
|
const args = [];
|
|
79
|
-
for (let i = 0;i < argsLen; i++) {
|
|
114
|
+
for (let i = 0; i < argsLen; i++) {
|
|
80
115
|
args.push(this.loadRef(argsAddr + i * 8));
|
|
81
116
|
}
|
|
82
117
|
const result = Reflect.construct(fn, args);
|
|
83
118
|
this.storeValue(out, result);
|
|
84
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Call a function given by id.
|
|
122
|
+
* */
|
|
85
123
|
funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
|
|
86
124
|
const fn = this.loadValue(id);
|
|
87
125
|
const thisVal = this.loadRef(thisRefAddr);
|
|
88
126
|
const args = [];
|
|
89
|
-
for (let i = 0;i < argsLen; i++) {
|
|
127
|
+
for (let i = 0; i < argsLen; i++) {
|
|
90
128
|
args.push(this.loadRef(argsAddr + i * 8));
|
|
91
129
|
}
|
|
92
130
|
const result = Reflect.apply(fn, thisVal, args);
|
|
93
131
|
this.storeValue(out, result);
|
|
94
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* This can be used to load a value given by an ID. A WASM function
|
|
135
|
+
* might return a value as an ID. This can be used to retrieve it.
|
|
136
|
+
* */
|
|
95
137
|
loadValue(id) {
|
|
96
138
|
return this.values[id];
|
|
97
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* This removes the value from the values list and returns it. This
|
|
142
|
+
* will not remove predefined values but can still be used to retrieve
|
|
143
|
+
* them.
|
|
144
|
+
* */
|
|
98
145
|
deleteValue(id) {
|
|
99
146
|
const val = this.values[id];
|
|
100
147
|
this.valueDeinit(id);
|
|
101
148
|
return val;
|
|
102
149
|
}
|
|
103
150
|
loadRef(refAddr) {
|
|
104
|
-
if (this.memory == null)
|
|
105
|
-
return;
|
|
151
|
+
if (this.memory == null) return;
|
|
106
152
|
const view = new DataView(this.memory.buffer);
|
|
107
153
|
const floatVal = view.getFloat64(refAddr, true);
|
|
108
|
-
if (!isNaN(floatVal))
|
|
109
|
-
return floatVal;
|
|
154
|
+
if (!isNaN(floatVal)) return floatVal;
|
|
110
155
|
const id = this.loadRefId(refAddr);
|
|
111
156
|
return this.values[id];
|
|
112
157
|
}
|
|
113
158
|
loadRefId(refAddr) {
|
|
114
|
-
if (this.memory == null)
|
|
115
|
-
return 0;
|
|
159
|
+
if (this.memory == null) return 0;
|
|
116
160
|
return new DataView(this.memory.buffer).getUint32(refAddr, true);
|
|
117
161
|
}
|
|
118
162
|
storeValue(out, val) {
|
|
119
|
-
if (this.memory == null)
|
|
120
|
-
return;
|
|
163
|
+
if (this.memory == null) return;
|
|
121
164
|
const view = new DataView(this.memory.buffer);
|
|
122
165
|
if (typeof val === "number") {
|
|
123
166
|
if (isNaN(val)) {
|
|
@@ -133,7 +176,7 @@ class ZigJS {
|
|
|
133
176
|
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
134
177
|
return;
|
|
135
178
|
}
|
|
136
|
-
if (val ===
|
|
179
|
+
if (val === void 0) {
|
|
137
180
|
view.setUint32(out, predefined.undefined, true);
|
|
138
181
|
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
139
182
|
return;
|
|
@@ -148,7 +191,7 @@ class ZigJS {
|
|
|
148
191
|
return;
|
|
149
192
|
}
|
|
150
193
|
let id = this.idPool.pop();
|
|
151
|
-
if (id ===
|
|
194
|
+
if (id === void 0) {
|
|
152
195
|
id = this.values.length;
|
|
153
196
|
}
|
|
154
197
|
this.values[id] = val;
|
|
@@ -171,23 +214,22 @@ class ZigJS {
|
|
|
171
214
|
view.setUint32(out + 4, NAN_PREFIX | typeId, true);
|
|
172
215
|
}
|
|
173
216
|
loadString(ptr, len) {
|
|
174
|
-
if (this.memory == null)
|
|
175
|
-
return "";
|
|
217
|
+
if (this.memory == null) return "";
|
|
176
218
|
const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
|
|
177
219
|
const data = arr.slice();
|
|
178
220
|
return decoder.decode(data);
|
|
179
221
|
}
|
|
180
|
-
}
|
|
222
|
+
};
|
|
223
|
+
|
|
181
224
|
// src/fetch.ts
|
|
182
225
|
function createFetchImports(getMemory) {
|
|
183
|
-
const encoder2 = new TextEncoder;
|
|
184
|
-
const decoder2 = new TextDecoder;
|
|
226
|
+
const encoder2 = new TextEncoder();
|
|
227
|
+
const decoder2 = new TextDecoder();
|
|
185
228
|
function readStr(ptr, len) {
|
|
186
229
|
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
187
230
|
}
|
|
188
|
-
function
|
|
189
|
-
if (data.length > buf_max)
|
|
190
|
-
return -2;
|
|
231
|
+
function writeBytes2(buf_ptr, buf_max, data) {
|
|
232
|
+
if (data.length > buf_max) return -2;
|
|
191
233
|
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
192
234
|
return data.length;
|
|
193
235
|
}
|
|
@@ -199,8 +241,7 @@ function createFetchImports(getMemory) {
|
|
|
199
241
|
try {
|
|
200
242
|
headers = JSON.parse(headersJson);
|
|
201
243
|
} catch {
|
|
202
|
-
for (const line of headersJson.split(
|
|
203
|
-
`)) {
|
|
244
|
+
for (const line of headersJson.split("\n")) {
|
|
204
245
|
const colonIdx = line.indexOf(":");
|
|
205
246
|
if (colonIdx > 0) {
|
|
206
247
|
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
@@ -213,25 +254,23 @@ function createFetchImports(getMemory) {
|
|
|
213
254
|
const url = readStr(url_ptr, url_len);
|
|
214
255
|
const method = method_len > 0 ? readStr(method_ptr, method_len) : "GET";
|
|
215
256
|
const headersJson = headers_len > 0 ? readStr(headers_ptr, headers_len) : "{}";
|
|
216
|
-
const body = body_len > 0 ? readBytes(body_ptr, body_len) :
|
|
257
|
+
const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
|
|
217
258
|
const headers = parseHeaders(headersJson);
|
|
218
|
-
const controller = new AbortController;
|
|
259
|
+
const controller = new AbortController();
|
|
219
260
|
const timeout = timeout_ms > 0 ? setTimeout(() => controller.abort(), timeout_ms) : null;
|
|
220
261
|
try {
|
|
221
262
|
const response = await fetch(url, {
|
|
222
263
|
method,
|
|
223
|
-
headers: Object.keys(headers).length > 0 ? headers :
|
|
224
|
-
body: method !== "GET" && method !== "HEAD" ? body :
|
|
264
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
265
|
+
body: method !== "GET" && method !== "HEAD" ? body : void 0,
|
|
225
266
|
signal: controller.signal
|
|
226
267
|
});
|
|
227
|
-
if (timeout)
|
|
228
|
-
clearTimeout(timeout);
|
|
268
|
+
if (timeout) clearTimeout(timeout);
|
|
229
269
|
new DataView(getMemory().buffer).setUint16(status_out, response.status, true);
|
|
230
270
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
231
|
-
return
|
|
271
|
+
return writeBytes2(buf_ptr, buf_max, bytes);
|
|
232
272
|
} catch (err) {
|
|
233
|
-
if (timeout)
|
|
234
|
-
clearTimeout(timeout);
|
|
273
|
+
if (timeout) clearTimeout(timeout);
|
|
235
274
|
const msg = err instanceof Error ? err.message : String(err);
|
|
236
275
|
console.error(`wasm fetch failed: ${url} (${msg})`);
|
|
237
276
|
return -1;
|
|
@@ -260,7 +299,7 @@ var CallbackType = {
|
|
|
260
299
|
WebSocketError: 7,
|
|
261
300
|
WebSocketClose: 8
|
|
262
301
|
};
|
|
263
|
-
var jsz = new ZigJS;
|
|
302
|
+
var jsz = new ZigJS();
|
|
264
303
|
var tempRefBuffer = new ArrayBuffer(8);
|
|
265
304
|
var tempRefView = new DataView(tempRefBuffer);
|
|
266
305
|
function storeValueGetRef(val) {
|
|
@@ -270,8 +309,8 @@ function storeValueGetRef(val) {
|
|
|
270
309
|
jsz.memory = originalMemory;
|
|
271
310
|
return tempRefView.getBigUint64(0, true);
|
|
272
311
|
}
|
|
273
|
-
var textDecoder = new TextDecoder;
|
|
274
|
-
var textEncoder = new TextEncoder;
|
|
312
|
+
var textDecoder = new TextDecoder();
|
|
313
|
+
var textEncoder = new TextEncoder();
|
|
275
314
|
var memoryView = null;
|
|
276
315
|
var memoryBuffer = null;
|
|
277
316
|
function getMemoryView() {
|
|
@@ -282,15 +321,14 @@ function getMemoryView() {
|
|
|
282
321
|
}
|
|
283
322
|
return memoryView;
|
|
284
323
|
}
|
|
285
|
-
var stringCache = new Map;
|
|
324
|
+
var stringCache = /* @__PURE__ */ new Map();
|
|
286
325
|
function stringCacheKey(ptr, len) {
|
|
287
326
|
return ptr * 65536 + len;
|
|
288
327
|
}
|
|
289
328
|
function readString(ptr, len) {
|
|
290
329
|
const key = stringCacheKey(ptr, len);
|
|
291
330
|
const cached = stringCache.get(key);
|
|
292
|
-
if (cached !==
|
|
293
|
-
return cached;
|
|
331
|
+
if (cached !== void 0) return cached;
|
|
294
332
|
const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
295
333
|
stringCache.set(key, str);
|
|
296
334
|
return str;
|
|
@@ -299,27 +337,22 @@ function writeBytes(ptr, data) {
|
|
|
299
337
|
getMemoryView().set(data, ptr);
|
|
300
338
|
}
|
|
301
339
|
function wrapPromisingExport(fn) {
|
|
302
|
-
if (!fn)
|
|
303
|
-
return;
|
|
340
|
+
if (!fn) return void 0;
|
|
304
341
|
const promising = WebAssembly.promising;
|
|
305
|
-
if (typeof promising !== "function")
|
|
306
|
-
return fn;
|
|
342
|
+
if (typeof promising !== "function") return fn;
|
|
307
343
|
return promising(fn);
|
|
308
344
|
}
|
|
309
345
|
function invokeWasmExport(fn, ...args) {
|
|
310
|
-
if (!fn)
|
|
311
|
-
return;
|
|
346
|
+
if (!fn) return;
|
|
312
347
|
const result = fn(...args);
|
|
313
348
|
if (result && typeof result.then === "function") {
|
|
314
|
-
result.then(
|
|
349
|
+
void result.then(void 0, (error) => {
|
|
315
350
|
console.error(error);
|
|
316
351
|
});
|
|
317
352
|
}
|
|
318
353
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
#intervals = new Map;
|
|
322
|
-
_alloc;
|
|
354
|
+
var ZxBridgeCore = class _ZxBridgeCore {
|
|
355
|
+
#intervals = /* @__PURE__ */ new Map();
|
|
323
356
|
#handler;
|
|
324
357
|
#fetchCompleteHandler;
|
|
325
358
|
constructor(exports) {
|
|
@@ -330,9 +363,9 @@ class ZxBridgeCore {
|
|
|
330
363
|
throw new Error("__zx_fetch_complete not exported from WASM");
|
|
331
364
|
}
|
|
332
365
|
this.#fetchCompleteHandler = fetchCompleteHandler;
|
|
333
|
-
if (exports.memory)
|
|
334
|
-
jsz.memory = exports.memory;
|
|
366
|
+
if (exports.memory) jsz.memory = exports.memory;
|
|
335
367
|
}
|
|
368
|
+
/** Invoke the unified callback handler */
|
|
336
369
|
#invoke(type, id, data) {
|
|
337
370
|
const handler = this.#handler;
|
|
338
371
|
if (!handler) {
|
|
@@ -342,44 +375,46 @@ class ZxBridgeCore {
|
|
|
342
375
|
const dataRef = storeValueGetRef(data);
|
|
343
376
|
invokeWasmExport(handler, type, id, dataRef);
|
|
344
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Async fetch with full options support.
|
|
380
|
+
* Calls __zx_fetch_complete when done.
|
|
381
|
+
*/
|
|
345
382
|
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
346
383
|
const url = readString(urlPtr, urlLen);
|
|
347
384
|
const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
|
|
348
385
|
const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
|
|
349
|
-
const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) :
|
|
386
|
+
const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
|
|
350
387
|
let headers = {};
|
|
351
388
|
try {
|
|
352
389
|
headers = JSON.parse(headersJson);
|
|
353
390
|
} catch {
|
|
354
|
-
for (const line of headersJson.split(
|
|
355
|
-
`)) {
|
|
391
|
+
for (const line of headersJson.split("\n")) {
|
|
356
392
|
const colonIdx = line.indexOf(":");
|
|
357
393
|
if (colonIdx > 0) {
|
|
358
394
|
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
359
395
|
}
|
|
360
396
|
}
|
|
361
397
|
}
|
|
362
|
-
const controller = new AbortController;
|
|
398
|
+
const controller = new AbortController();
|
|
363
399
|
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
364
400
|
const fetchOptions = {
|
|
365
401
|
method,
|
|
366
|
-
headers: Object.keys(headers).length > 0 ? headers :
|
|
367
|
-
body: method !== "GET" && method !== "HEAD" ? body :
|
|
402
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
403
|
+
body: method !== "GET" && method !== "HEAD" ? body : void 0,
|
|
368
404
|
signal: controller.signal
|
|
369
405
|
};
|
|
370
406
|
fetch(url, fetchOptions).then(async (response) => {
|
|
371
|
-
if (timeout)
|
|
372
|
-
clearTimeout(timeout);
|
|
407
|
+
if (timeout) clearTimeout(timeout);
|
|
373
408
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
374
409
|
this._notifyFetchComplete(fetchId, response.status, bytes, false);
|
|
375
410
|
}).catch((error) => {
|
|
376
|
-
if (timeout)
|
|
377
|
-
clearTimeout(timeout);
|
|
411
|
+
if (timeout) clearTimeout(timeout);
|
|
378
412
|
const isAbort = error.name === "AbortError";
|
|
379
413
|
const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
|
|
380
414
|
this._notifyFetchComplete(fetchId, 0, errorMsg, true);
|
|
381
415
|
});
|
|
382
416
|
}
|
|
417
|
+
/** Notify WASM that a fetch completed. `body` is raw bytes on success, text on error. */
|
|
383
418
|
_notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
384
419
|
const handler = this.#fetchCompleteHandler;
|
|
385
420
|
const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
|
|
@@ -387,20 +422,23 @@ class ZxBridgeCore {
|
|
|
387
422
|
writeBytes(ptr, encoded);
|
|
388
423
|
invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
389
424
|
}
|
|
425
|
+
/** Set a timeout and callback when it fires */
|
|
390
426
|
setTimeout(callbackId, delayMs) {
|
|
391
427
|
setTimeout(() => {
|
|
392
428
|
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
393
429
|
}, delayMs);
|
|
394
430
|
}
|
|
431
|
+
/** Set an interval and callback each time it fires */
|
|
395
432
|
setInterval(callbackId, intervalMs) {
|
|
396
433
|
const handle = setInterval(() => {
|
|
397
434
|
this.#invoke(CallbackType.Interval, callbackId, null);
|
|
398
435
|
}, intervalMs);
|
|
399
436
|
this.#intervals.set(callbackId, handle);
|
|
400
437
|
}
|
|
438
|
+
/** Clear an interval */
|
|
401
439
|
clearInterval(callbackId) {
|
|
402
440
|
const handle = this.#intervals.get(callbackId);
|
|
403
|
-
if (handle !==
|
|
441
|
+
if (handle !== void 0) {
|
|
404
442
|
clearInterval(handle);
|
|
405
443
|
this.#intervals.delete(callbackId);
|
|
406
444
|
}
|
|
@@ -411,6 +449,7 @@ class ZxBridgeCore {
|
|
|
411
449
|
}
|
|
412
450
|
this.#intervals.clear();
|
|
413
451
|
}
|
|
452
|
+
/** Write a string to WASM memory, returning pointer and length */
|
|
414
453
|
_writeStringToWasm(str) {
|
|
415
454
|
return this._writeBytesToWasm(textEncoder.encode(str));
|
|
416
455
|
}
|
|
@@ -419,6 +458,7 @@ class ZxBridgeCore {
|
|
|
419
458
|
writeBytes(ptr, data);
|
|
420
459
|
return { ptr, len: data.length };
|
|
421
460
|
}
|
|
461
|
+
/** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
|
|
422
462
|
static log(level, ptr, len) {
|
|
423
463
|
const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
424
464
|
switch (level) {
|
|
@@ -436,18 +476,34 @@ class ZxBridgeCore {
|
|
|
436
476
|
break;
|
|
437
477
|
}
|
|
438
478
|
}
|
|
479
|
+
/**
|
|
480
|
+
* Create the core import object for WASM instantiation.
|
|
481
|
+
* Includes only environment-agnostic bindings: log, fetch, and timers.
|
|
482
|
+
* Use ZxBridge.createImportObject (from wasm/index.ts) in browser contexts
|
|
483
|
+
* to additionally include DOM and WebSocket bindings.
|
|
484
|
+
*/
|
|
439
485
|
static createImportObject(bridgeRef) {
|
|
440
486
|
return {
|
|
441
487
|
...jsz.importObject(),
|
|
442
488
|
__zx_net: createFetchImports(() => {
|
|
443
|
-
if (!jsz.memory)
|
|
444
|
-
throw new Error("WASM memory is not ready");
|
|
489
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
445
490
|
return jsz.memory;
|
|
446
491
|
}),
|
|
447
492
|
__zx: {
|
|
448
|
-
_log: (level, ptr, len) =>
|
|
493
|
+
_log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
|
|
449
494
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
450
|
-
bridgeRef.current?.fetchAsync(
|
|
495
|
+
bridgeRef.current?.fetchAsync(
|
|
496
|
+
urlPtr,
|
|
497
|
+
urlLen,
|
|
498
|
+
methodPtr,
|
|
499
|
+
methodLen,
|
|
500
|
+
headersPtr,
|
|
501
|
+
headersLen,
|
|
502
|
+
bodyPtr,
|
|
503
|
+
bodyLen,
|
|
504
|
+
timeoutMs,
|
|
505
|
+
fetchId
|
|
506
|
+
);
|
|
451
507
|
},
|
|
452
508
|
_setTimeout: (callbackId, delayMs) => {
|
|
453
509
|
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
@@ -461,21 +517,25 @@ class ZxBridgeCore {
|
|
|
461
517
|
}
|
|
462
518
|
};
|
|
463
519
|
}
|
|
464
|
-
}
|
|
520
|
+
};
|
|
521
|
+
|
|
465
522
|
// src/kv.ts
|
|
523
|
+
function putOptions(ttlSeconds) {
|
|
524
|
+
if (ttlSeconds < 60) return void 0;
|
|
525
|
+
return { expirationTtl: ttlSeconds };
|
|
526
|
+
}
|
|
466
527
|
function isSyncKVNamespace(binding) {
|
|
467
528
|
const candidate = binding;
|
|
468
529
|
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
469
530
|
}
|
|
470
531
|
function createKVImports(bindings, getMemory) {
|
|
471
|
-
const encoder2 = new TextEncoder;
|
|
472
|
-
const decoder2 = new TextDecoder;
|
|
532
|
+
const encoder2 = new TextEncoder();
|
|
533
|
+
const decoder2 = new TextDecoder();
|
|
473
534
|
function readStr(ptr, len) {
|
|
474
535
|
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
475
536
|
}
|
|
476
537
|
function writeBytes2(buf_ptr, buf_max, data) {
|
|
477
|
-
if (data.length > buf_max)
|
|
478
|
-
return -2;
|
|
538
|
+
if (data.length > buf_max) return -2;
|
|
479
539
|
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
480
540
|
return data.length;
|
|
481
541
|
}
|
|
@@ -484,40 +544,36 @@ function createKVImports(bindings, getMemory) {
|
|
|
484
544
|
}
|
|
485
545
|
const Suspending = WebAssembly.Suspending;
|
|
486
546
|
if (typeof Suspending !== "function") {
|
|
487
|
-
let
|
|
547
|
+
let syncBinding2 = function(ns) {
|
|
488
548
|
const candidate = binding(ns);
|
|
489
549
|
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
490
550
|
};
|
|
551
|
+
var syncBinding = syncBinding2;
|
|
491
552
|
return {
|
|
492
553
|
kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
493
|
-
const b =
|
|
494
|
-
if (!b)
|
|
495
|
-
return -1;
|
|
554
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
555
|
+
if (!b) return -1;
|
|
496
556
|
const value = b.getSync(readStr(key_ptr, key_len));
|
|
497
|
-
if (value === null)
|
|
498
|
-
return -1;
|
|
557
|
+
if (value === null) return -1;
|
|
499
558
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
500
559
|
},
|
|
501
|
-
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
|
|
502
|
-
const b =
|
|
503
|
-
if (!b)
|
|
504
|
-
|
|
505
|
-
b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len));
|
|
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));
|
|
506
564
|
return 0;
|
|
507
565
|
},
|
|
508
566
|
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
509
|
-
const b =
|
|
510
|
-
if (!b)
|
|
511
|
-
return 0;
|
|
567
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
568
|
+
if (!b) return 0;
|
|
512
569
|
b.deleteSync(readStr(key_ptr, key_len));
|
|
513
570
|
return 0;
|
|
514
571
|
},
|
|
515
572
|
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
|
|
516
|
-
const b =
|
|
517
|
-
if (!b)
|
|
518
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
573
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
574
|
+
if (!b) return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
519
575
|
const prefix = readStr(pfx_ptr, pfx_len);
|
|
520
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } :
|
|
576
|
+
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
521
577
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
522
578
|
}
|
|
523
579
|
};
|
|
@@ -525,33 +581,28 @@ function createKVImports(bindings, getMemory) {
|
|
|
525
581
|
return {
|
|
526
582
|
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
527
583
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
528
|
-
if (!b)
|
|
529
|
-
return -1;
|
|
584
|
+
if (!b) return -1;
|
|
530
585
|
const value = await b.get(readStr(key_ptr, key_len));
|
|
531
|
-
if (value === null)
|
|
532
|
-
return -1;
|
|
586
|
+
if (value === null) return -1;
|
|
533
587
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
534
588
|
}),
|
|
535
|
-
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
|
|
589
|
+
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
536
590
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
537
|
-
if (!b)
|
|
538
|
-
|
|
539
|
-
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len));
|
|
591
|
+
if (!b) return -1;
|
|
592
|
+
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
540
593
|
return 0;
|
|
541
594
|
}),
|
|
542
595
|
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
543
596
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
544
|
-
if (!b)
|
|
545
|
-
return -1;
|
|
597
|
+
if (!b) return -1;
|
|
546
598
|
await b.delete(readStr(key_ptr, key_len));
|
|
547
599
|
return 0;
|
|
548
600
|
}),
|
|
549
601
|
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
550
602
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
551
|
-
if (!b)
|
|
552
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
603
|
+
if (!b) return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
553
604
|
const prefix = readStr(prefix_ptr, prefix_len);
|
|
554
|
-
const result = await b.list(prefix.length > 0 ? { prefix } :
|
|
605
|
+
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
555
606
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
556
607
|
})
|
|
557
608
|
};
|
|
@@ -663,10 +714,9 @@ function createLocalStorageKV(options = {}) {
|
|
|
663
714
|
listSync(options2) {
|
|
664
715
|
const prefix = namespacePrefix + (options2?.prefix ?? "");
|
|
665
716
|
const keys = [];
|
|
666
|
-
for (let i = 0;i < storage.length; i += 1) {
|
|
717
|
+
for (let i = 0; i < storage.length; i += 1) {
|
|
667
718
|
const key = storage.key(i);
|
|
668
|
-
if (!key || !key.startsWith(prefix))
|
|
669
|
-
continue;
|
|
719
|
+
if (!key || !key.startsWith(prefix)) continue;
|
|
670
720
|
keys.push({ name: key.slice(namespacePrefix.length) });
|
|
671
721
|
}
|
|
672
722
|
return { keys };
|
|
@@ -687,8 +737,8 @@ function createBrowserKVBindings(options = {}) {
|
|
|
687
737
|
}
|
|
688
738
|
|
|
689
739
|
// src/wasm/index.ts
|
|
690
|
-
|
|
691
|
-
#websockets = new Map;
|
|
740
|
+
var ZxBridge = class extends ZxBridgeCore {
|
|
741
|
+
#websockets = /* @__PURE__ */ new Map();
|
|
692
742
|
#wsOnOpenHandler;
|
|
693
743
|
#wsOnMessageHandler;
|
|
694
744
|
#wsOnErrorHandler;
|
|
@@ -702,7 +752,9 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
702
752
|
this.#wsOnErrorHandler = wrapPromisingExport(exports.__zx_ws_onerror);
|
|
703
753
|
this.#wsOnCloseHandler = wrapPromisingExport(exports.__zx_ws_onclose);
|
|
704
754
|
this.#eventbridge = exports.__zx_eventbridge;
|
|
705
|
-
this.#eventbridgeAsync = wrapPromisingExport(
|
|
755
|
+
this.#eventbridgeAsync = wrapPromisingExport(
|
|
756
|
+
exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
|
|
757
|
+
);
|
|
706
758
|
}
|
|
707
759
|
eventMaySuspend(velementId, eventTypeId) {
|
|
708
760
|
return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
@@ -711,19 +763,19 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
711
763
|
const bit = 1 << eventTypeId;
|
|
712
764
|
const current = eventHandlerModes.get(velementId) ?? 0;
|
|
713
765
|
const next = maySuspend ? current | bit : current & ~bit;
|
|
714
|
-
if (next === 0)
|
|
715
|
-
|
|
716
|
-
else
|
|
717
|
-
eventHandlerModes.set(velementId, next);
|
|
766
|
+
if (next === 0) eventHandlerModes.delete(velementId);
|
|
767
|
+
else eventHandlerModes.set(velementId, next);
|
|
718
768
|
}
|
|
719
769
|
clearEventHandlerModes(velementId) {
|
|
720
770
|
eventHandlerModes.delete(velementId);
|
|
721
771
|
}
|
|
772
|
+
/** Submit a form action with bound-state round-trip. */
|
|
722
773
|
submitFormActionAsync(form, actionId, statesJson, fetchId) {
|
|
723
774
|
const formData = new FormData(form);
|
|
724
775
|
formData.append("__$states", statesJson);
|
|
725
776
|
fetch(window.location.href, {
|
|
726
777
|
method: "POST",
|
|
778
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
727
779
|
headers: { "x-action": String(actionId >>> 0) },
|
|
728
780
|
body: formData
|
|
729
781
|
}).then(async (response) => {
|
|
@@ -734,25 +786,27 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
734
786
|
this._notifyFetchComplete(fetchId, 0, msg, true);
|
|
735
787
|
});
|
|
736
788
|
}
|
|
789
|
+
/**
|
|
790
|
+
* Create and connect a WebSocket.
|
|
791
|
+
* Calls __zx_ws_onopen, __zx_ws_onmessage, __zx_ws_onerror, __zx_ws_onclose.
|
|
792
|
+
*/
|
|
737
793
|
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
738
794
|
const url = readString(urlPtr, urlLen);
|
|
739
795
|
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
740
|
-
const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) :
|
|
796
|
+
const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : void 0;
|
|
741
797
|
try {
|
|
742
798
|
const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
|
|
743
799
|
ws.binaryType = "arraybuffer";
|
|
744
800
|
ws.onopen = () => {
|
|
745
801
|
const handler = this.#wsOnOpenHandler;
|
|
746
|
-
if (!handler)
|
|
747
|
-
return;
|
|
802
|
+
if (!handler) return;
|
|
748
803
|
const protocol = ws.protocol || "";
|
|
749
804
|
const { ptr, len } = this._writeStringToWasm(protocol);
|
|
750
805
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
751
806
|
};
|
|
752
807
|
ws.onmessage = (event) => {
|
|
753
808
|
const handler = this.#wsOnMessageHandler;
|
|
754
|
-
if (!handler)
|
|
755
|
-
return;
|
|
809
|
+
if (!handler) return;
|
|
756
810
|
const isBinary = event.data instanceof ArrayBuffer;
|
|
757
811
|
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
758
812
|
const { ptr, len } = this._writeBytesToWasm(data);
|
|
@@ -760,15 +814,13 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
760
814
|
};
|
|
761
815
|
ws.onerror = (_event) => {
|
|
762
816
|
const handler = this.#wsOnErrorHandler;
|
|
763
|
-
if (!handler)
|
|
764
|
-
return;
|
|
817
|
+
if (!handler) return;
|
|
765
818
|
const { ptr, len } = this._writeStringToWasm("WebSocket error");
|
|
766
819
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
767
820
|
};
|
|
768
821
|
ws.onclose = (event) => {
|
|
769
822
|
const handler = this.#wsOnCloseHandler;
|
|
770
|
-
if (!handler)
|
|
771
|
-
return;
|
|
823
|
+
if (!handler) return;
|
|
772
824
|
const reason = event.reason || "";
|
|
773
825
|
const { ptr, len } = this._writeStringToWasm(reason);
|
|
774
826
|
invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
@@ -784,10 +836,10 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
784
836
|
}
|
|
785
837
|
}
|
|
786
838
|
}
|
|
839
|
+
/** Send data over WebSocket */
|
|
787
840
|
wsSend(wsId, dataPtr, dataLen, isBinary) {
|
|
788
841
|
const ws = this.#websockets.get(wsId);
|
|
789
|
-
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
790
|
-
return;
|
|
842
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
791
843
|
const memory = getMemoryView();
|
|
792
844
|
if (isBinary) {
|
|
793
845
|
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
@@ -795,16 +847,14 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
795
847
|
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
796
848
|
}
|
|
797
849
|
}
|
|
850
|
+
/** Close WebSocket connection */
|
|
798
851
|
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
799
852
|
const ws = this.#websockets.get(wsId);
|
|
800
|
-
if (!ws)
|
|
801
|
-
|
|
802
|
-
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
|
|
853
|
+
if (!ws) return;
|
|
854
|
+
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : void 0;
|
|
803
855
|
try {
|
|
804
|
-
if (reason)
|
|
805
|
-
|
|
806
|
-
else
|
|
807
|
-
ws.close(code);
|
|
856
|
+
if (reason) ws.close(code, reason);
|
|
857
|
+
else ws.close(code);
|
|
808
858
|
} catch {
|
|
809
859
|
ws.close();
|
|
810
860
|
}
|
|
@@ -815,10 +865,12 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
815
865
|
for (const ws of this.#websockets.values()) {
|
|
816
866
|
try {
|
|
817
867
|
ws.close();
|
|
818
|
-
} catch {
|
|
868
|
+
} catch {
|
|
869
|
+
}
|
|
819
870
|
}
|
|
820
871
|
this.#websockets.clear();
|
|
821
872
|
}
|
|
873
|
+
/** Handle a DOM event (called by event delegation) */
|
|
822
874
|
eventbridge(velementId, eventTypeId, event) {
|
|
823
875
|
const eventRef = storeValueGetRef(event);
|
|
824
876
|
if (this.eventMaySuspend(velementId, eventTypeId)) {
|
|
@@ -827,12 +879,12 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
827
879
|
}
|
|
828
880
|
invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
|
|
829
881
|
}
|
|
882
|
+
/** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
|
|
830
883
|
static createImportObject(bridgeRef) {
|
|
831
884
|
return {
|
|
832
885
|
...jsz.importObject(),
|
|
833
886
|
__zx_net: createFetchImports(() => {
|
|
834
|
-
if (!jsz.memory)
|
|
835
|
-
throw new Error("WASM memory is not ready");
|
|
887
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
836
888
|
return jsz.memory;
|
|
837
889
|
}),
|
|
838
890
|
__zx: {
|
|
@@ -844,7 +896,18 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
844
896
|
bridgeRef.current?.clearEventHandlerModes(vnodeId);
|
|
845
897
|
},
|
|
846
898
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
847
|
-
bridgeRef.current?.fetchAsync(
|
|
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
|
+
);
|
|
848
911
|
},
|
|
849
912
|
_setTimeout: (callbackId, delayMs) => {
|
|
850
913
|
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
@@ -855,6 +918,7 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
855
918
|
_clearInterval: (callbackId) => {
|
|
856
919
|
bridgeRef.current?.clearInterval(callbackId);
|
|
857
920
|
},
|
|
921
|
+
// WebSocket API
|
|
858
922
|
_wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
|
|
859
923
|
bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
|
|
860
924
|
},
|
|
@@ -898,26 +962,22 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
898
962
|
},
|
|
899
963
|
_snv: (vnodeId, ptr, len) => {
|
|
900
964
|
const node = domNodes.get(vnodeId);
|
|
901
|
-
if (node)
|
|
902
|
-
node.nodeValue = readString(ptr, len);
|
|
965
|
+
if (node) node.nodeValue = readString(ptr, len);
|
|
903
966
|
},
|
|
904
967
|
_srh: (vnodeId, ptr, len) => {
|
|
905
968
|
const el = domNodes.get(vnodeId);
|
|
906
|
-
if (el)
|
|
907
|
-
el.innerHTML = readString(ptr, len);
|
|
969
|
+
if (el) el.innerHTML = readString(ptr, len);
|
|
908
970
|
},
|
|
909
971
|
_ac: (parentId, childId) => {
|
|
910
972
|
const parent = domNodes.get(parentId);
|
|
911
973
|
const child = domNodes.get(childId);
|
|
912
|
-
if (parent && child)
|
|
913
|
-
parent.appendChild(child);
|
|
974
|
+
if (parent && child) parent.appendChild(child);
|
|
914
975
|
},
|
|
915
976
|
_ib: (parentId, childId, refId) => {
|
|
916
977
|
const parent = domNodes.get(parentId);
|
|
917
978
|
const child = domNodes.get(childId);
|
|
918
979
|
const ref = domNodes.get(refId) ?? null;
|
|
919
|
-
if (parent && child)
|
|
920
|
-
parent.insertBefore(child, ref);
|
|
980
|
+
if (parent && child) parent.insertBefore(child, ref);
|
|
921
981
|
},
|
|
922
982
|
_rc: (parentId, childId) => {
|
|
923
983
|
const parent = domNodes.get(parentId);
|
|
@@ -944,8 +1004,7 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
944
1004
|
},
|
|
945
1005
|
_getFormData: (vnodeId, bufPtr, bufLen) => {
|
|
946
1006
|
const form = domNodes.get(vnodeId);
|
|
947
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
948
|
-
return 0;
|
|
1007
|
+
if (!form || !(form instanceof HTMLFormElement)) return 0;
|
|
949
1008
|
const formData = new FormData(form);
|
|
950
1009
|
const urlEncoded = new URLSearchParams(formData).toString();
|
|
951
1010
|
const bytes = textEncoder.encode(urlEncoded);
|
|
@@ -955,34 +1014,32 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
955
1014
|
},
|
|
956
1015
|
_submitFormAction: (vnodeId, actionId) => {
|
|
957
1016
|
const form = domNodes.get(vnodeId);
|
|
958
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
959
|
-
return;
|
|
1017
|
+
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
960
1018
|
const formData = new FormData(form);
|
|
961
1019
|
fetch(window.location.href, {
|
|
962
1020
|
method: "POST",
|
|
1021
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
963
1022
|
headers: { "x-action": String(actionId >>> 0) },
|
|
964
1023
|
body: formData
|
|
965
|
-
}).catch(() => {
|
|
1024
|
+
}).catch(() => {
|
|
1025
|
+
});
|
|
966
1026
|
},
|
|
967
1027
|
_submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
|
|
968
1028
|
const form = domNodes.get(vnodeId);
|
|
969
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
970
|
-
return;
|
|
1029
|
+
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
971
1030
|
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
972
1031
|
bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
|
|
973
1032
|
}
|
|
974
1033
|
}
|
|
975
1034
|
};
|
|
976
1035
|
}
|
|
977
|
-
}
|
|
978
|
-
var domNodes = new Map;
|
|
1036
|
+
};
|
|
1037
|
+
var domNodes = /* @__PURE__ */ new Map();
|
|
979
1038
|
function cleanupDomNodes(node) {
|
|
980
1039
|
const ref = node.__zx_ref;
|
|
981
|
-
if (ref !==
|
|
982
|
-
domNodes.delete(BigInt(ref));
|
|
1040
|
+
if (ref !== void 0) domNodes.delete(BigInt(ref));
|
|
983
1041
|
const children = node.childNodes;
|
|
984
|
-
for (let i = 0;i < children.length; i++)
|
|
985
|
-
cleanupDomNodes(children[i]);
|
|
1042
|
+
for (let i = 0; i < children.length; i++) cleanupDomNodes(children[i]);
|
|
986
1043
|
}
|
|
987
1044
|
var SVG_TAG_START_INDEX = 140;
|
|
988
1045
|
var TAG_NAMES = [
|
|
@@ -1126,6 +1183,7 @@ var TAG_NAMES = [
|
|
|
1126
1183
|
"strike",
|
|
1127
1184
|
"tt",
|
|
1128
1185
|
"xmp",
|
|
1186
|
+
// SVG Tags
|
|
1129
1187
|
"animate",
|
|
1130
1188
|
"animateMotion",
|
|
1131
1189
|
"animateTransform",
|
|
@@ -1192,6 +1250,7 @@ var DELEGATED_EVENTS = [
|
|
|
1192
1250
|
{ domType: "input", eventTypeId: 2 },
|
|
1193
1251
|
{ domType: "change", eventTypeId: 3 },
|
|
1194
1252
|
{ domType: "submit", eventTypeId: 4 },
|
|
1253
|
+
// focus/blur do not bubble, so delegated handlers must listen to focusin/focusout.
|
|
1195
1254
|
{ domType: "focusin", eventTypeId: 5 },
|
|
1196
1255
|
{ domType: "focusout", eventTypeId: 6 },
|
|
1197
1256
|
{ domType: "keydown", eventTypeId: 7 },
|
|
@@ -1207,21 +1266,20 @@ var DELEGATED_EVENTS = [
|
|
|
1207
1266
|
{ domType: "touchmove", eventTypeId: 17 },
|
|
1208
1267
|
{ domType: "scroll", eventTypeId: 18 }
|
|
1209
1268
|
];
|
|
1210
|
-
var eventHandlerModes = new Map;
|
|
1269
|
+
var eventHandlerModes = /* @__PURE__ */ new Map();
|
|
1211
1270
|
function initEventDelegation(bridge, rootSelector = "body") {
|
|
1212
1271
|
const root = document.querySelector(rootSelector);
|
|
1213
|
-
if (!root)
|
|
1214
|
-
|
|
1272
|
+
if (!root) return () => {
|
|
1273
|
+
};
|
|
1215
1274
|
const removers = [];
|
|
1216
1275
|
for (const delegatedEvent of DELEGATED_EVENTS) {
|
|
1217
1276
|
const listener = (event) => {
|
|
1218
1277
|
let target = event.target;
|
|
1219
1278
|
while (target && target !== document.body) {
|
|
1220
1279
|
const zxRef = target.__zx_ref;
|
|
1221
|
-
if (zxRef !==
|
|
1280
|
+
if (zxRef !== void 0) {
|
|
1222
1281
|
bridge.eventbridge(BigInt(zxRef), delegatedEvent.eventTypeId, event);
|
|
1223
|
-
if (event.cancelBubble)
|
|
1224
|
-
break;
|
|
1282
|
+
if (event.cancelBubble) break;
|
|
1225
1283
|
}
|
|
1226
1284
|
target = target.parentElement;
|
|
1227
1285
|
}
|
|
@@ -1231,8 +1289,7 @@ function initEventDelegation(bridge, rootSelector = "body") {
|
|
|
1231
1289
|
removers.push(() => root.removeEventListener(delegatedEvent.domType, listener, options));
|
|
1232
1290
|
}
|
|
1233
1291
|
return () => {
|
|
1234
|
-
for (const remove of removers)
|
|
1235
|
-
remove();
|
|
1292
|
+
for (const remove of removers) remove();
|
|
1236
1293
|
};
|
|
1237
1294
|
}
|
|
1238
1295
|
var DEFAULT_URL = "/assets/_/main.wasm";
|
|
@@ -1254,8 +1311,7 @@ function normalizeOptions(options = {}) {
|
|
|
1254
1311
|
};
|
|
1255
1312
|
}
|
|
1256
1313
|
function registerDevReinit(options) {
|
|
1257
|
-
if (typeof window === "undefined")
|
|
1258
|
-
return;
|
|
1314
|
+
if (typeof window === "undefined") return;
|
|
1259
1315
|
const reinit = () => init(options);
|
|
1260
1316
|
window.__zx_dev_reinit = reinit;
|
|
1261
1317
|
window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
@@ -1275,14 +1331,17 @@ async function init(options = {}) {
|
|
|
1275
1331
|
const kvBindings = options.kv ?? createBrowserKVBindings();
|
|
1276
1332
|
const kvImportObject = {
|
|
1277
1333
|
__zx_kv: createKVImports(kvBindings, () => {
|
|
1278
|
-
if (wasmMemory)
|
|
1279
|
-
|
|
1280
|
-
if (jsz.memory)
|
|
1281
|
-
return jsz.memory;
|
|
1334
|
+
if (wasmMemory) return wasmMemory;
|
|
1335
|
+
if (jsz.memory) return jsz.memory;
|
|
1282
1336
|
throw new Error("WASM memory is not ready");
|
|
1283
1337
|
})
|
|
1284
1338
|
};
|
|
1285
|
-
const importObject = Object.assign(
|
|
1339
|
+
const importObject = Object.assign(
|
|
1340
|
+
{},
|
|
1341
|
+
ZxBridge.createImportObject(bridgeRef),
|
|
1342
|
+
kvImportObject,
|
|
1343
|
+
options.importObject
|
|
1344
|
+
);
|
|
1286
1345
|
const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
1287
1346
|
const { instance } = source;
|
|
1288
1347
|
wasmMemory = instance.exports.memory;
|
|
@@ -1301,8 +1360,7 @@ async function init(options = {}) {
|
|
|
1301
1360
|
domNodes.clear();
|
|
1302
1361
|
}
|
|
1303
1362
|
};
|
|
1304
|
-
if (true)
|
|
1305
|
-
registerDevReinit(normalizedOptions);
|
|
1363
|
+
if (true) registerDevReinit(normalizedOptions);
|
|
1306
1364
|
return { source, bridge };
|
|
1307
1365
|
}
|
|
1308
1366
|
|