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/index.js
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __returnValue = (v) => v;
|
|
3
|
-
function __exportSetter(name, newValue) {
|
|
4
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
5
|
-
}
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, {
|
|
9
|
-
get: all[name],
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
set: __exportSetter.bind(all, name)
|
|
13
|
-
});
|
|
14
|
-
};
|
|
15
|
-
|
|
16
1
|
// ../../vendor/jsz/js/src/zigjs.ts
|
|
17
2
|
var NAN_PREFIX = 2146959360;
|
|
18
3
|
var predefined = {
|
|
19
|
-
nan: 0,
|
|
20
|
-
null: 1,
|
|
21
|
-
true: 2,
|
|
22
|
-
false: 3,
|
|
23
|
-
undefined: 4,
|
|
24
|
-
globalThis: 5,
|
|
25
|
-
runtime: 6
|
|
4
|
+
"nan": 0,
|
|
5
|
+
"null": 1,
|
|
6
|
+
"true": 2,
|
|
7
|
+
"false": 3,
|
|
8
|
+
"undefined": 4,
|
|
9
|
+
"globalThis": 5,
|
|
10
|
+
"runtime": 6
|
|
26
11
|
};
|
|
27
12
|
var PREDEFINED_ID_MAX = 6;
|
|
28
|
-
var encoder = new TextEncoder;
|
|
13
|
+
var encoder = new TextEncoder();
|
|
29
14
|
var decoder = new TextDecoder("utf-8");
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
+
* */
|
|
35
34
|
importObject() {
|
|
36
35
|
return {
|
|
37
36
|
"zig-js": {
|
|
@@ -47,92 +46,121 @@ class ZigJS {
|
|
|
47
46
|
}
|
|
48
47
|
};
|
|
49
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Get a value from the JS environment.
|
|
51
|
+
* */
|
|
50
52
|
valueGet(out, id, ptr, len) {
|
|
51
53
|
const val = this.loadValue(id);
|
|
52
54
|
const str = this.loadString(ptr, len);
|
|
53
55
|
const result = Reflect.get(val, str);
|
|
54
56
|
this.storeValue(out, result);
|
|
55
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Set a value on an object.
|
|
60
|
+
* */
|
|
56
61
|
valueSet(id, ptr, len, refAddr) {
|
|
57
62
|
const obj = this.loadValue(id);
|
|
58
63
|
const str = this.loadString(ptr, len);
|
|
59
64
|
const val = this.loadRef(refAddr);
|
|
60
65
|
Reflect.set(obj, str, val);
|
|
61
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Dereference a value, allowing the JS environment to potentially GC it.
|
|
69
|
+
* */
|
|
62
70
|
valueDeinit(id) {
|
|
63
71
|
if (id > PREDEFINED_ID_MAX) {
|
|
64
72
|
this.values[id] = null;
|
|
65
73
|
this.idPool.push(id);
|
|
66
74
|
}
|
|
67
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Create an empty object.
|
|
78
|
+
* */
|
|
68
79
|
valueObjectCreate(out) {
|
|
69
|
-
this.storeValue(out, new Object);
|
|
80
|
+
this.storeValue(out, new Object());
|
|
70
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
|
|
84
|
+
* */
|
|
71
85
|
valueStringCreate(out, ptr, len) {
|
|
72
86
|
const str = this.loadString(ptr, len);
|
|
73
87
|
this.storeValue(out, str);
|
|
74
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Returns the length of the string given by id.
|
|
91
|
+
* */
|
|
75
92
|
valueStringLen(id) {
|
|
76
93
|
const val = this.loadValue(id);
|
|
77
94
|
const buf = encoder.encode(val);
|
|
78
95
|
return buf.byteLength;
|
|
79
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Copy the string at id "id" into the shared memory at ptr.
|
|
99
|
+
* */
|
|
80
100
|
valueStringCopy(id, ptr, max) {
|
|
81
|
-
if (this.memory == null)
|
|
82
|
-
return;
|
|
101
|
+
if (this.memory == null) return;
|
|
83
102
|
const val = this.loadValue(id);
|
|
84
103
|
const bytes = encoder.encode(val);
|
|
85
|
-
if (bytes.byteLength > max)
|
|
86
|
-
|
|
87
|
-
if (bytes.length === 0)
|
|
88
|
-
return;
|
|
104
|
+
if (bytes.byteLength > max) return;
|
|
105
|
+
if (bytes.length === 0) return;
|
|
89
106
|
new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
|
|
90
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Call a constructor given by id.
|
|
110
|
+
* */
|
|
91
111
|
valueNew(out, id, argsAddr, argsLen) {
|
|
92
112
|
const fn = this.loadValue(id);
|
|
93
113
|
const args = [];
|
|
94
|
-
for (let i = 0;i < argsLen; i++) {
|
|
114
|
+
for (let i = 0; i < argsLen; i++) {
|
|
95
115
|
args.push(this.loadRef(argsAddr + i * 8));
|
|
96
116
|
}
|
|
97
117
|
const result = Reflect.construct(fn, args);
|
|
98
118
|
this.storeValue(out, result);
|
|
99
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Call a function given by id.
|
|
122
|
+
* */
|
|
100
123
|
funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
|
|
101
124
|
const fn = this.loadValue(id);
|
|
102
125
|
const thisVal = this.loadRef(thisRefAddr);
|
|
103
126
|
const args = [];
|
|
104
|
-
for (let i = 0;i < argsLen; i++) {
|
|
127
|
+
for (let i = 0; i < argsLen; i++) {
|
|
105
128
|
args.push(this.loadRef(argsAddr + i * 8));
|
|
106
129
|
}
|
|
107
130
|
const result = Reflect.apply(fn, thisVal, args);
|
|
108
131
|
this.storeValue(out, result);
|
|
109
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
|
+
* */
|
|
110
137
|
loadValue(id) {
|
|
111
138
|
return this.values[id];
|
|
112
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
|
+
* */
|
|
113
145
|
deleteValue(id) {
|
|
114
146
|
const val = this.values[id];
|
|
115
147
|
this.valueDeinit(id);
|
|
116
148
|
return val;
|
|
117
149
|
}
|
|
118
150
|
loadRef(refAddr) {
|
|
119
|
-
if (this.memory == null)
|
|
120
|
-
return;
|
|
151
|
+
if (this.memory == null) return;
|
|
121
152
|
const view = new DataView(this.memory.buffer);
|
|
122
153
|
const floatVal = view.getFloat64(refAddr, true);
|
|
123
|
-
if (!isNaN(floatVal))
|
|
124
|
-
return floatVal;
|
|
154
|
+
if (!isNaN(floatVal)) return floatVal;
|
|
125
155
|
const id = this.loadRefId(refAddr);
|
|
126
156
|
return this.values[id];
|
|
127
157
|
}
|
|
128
158
|
loadRefId(refAddr) {
|
|
129
|
-
if (this.memory == null)
|
|
130
|
-
return 0;
|
|
159
|
+
if (this.memory == null) return 0;
|
|
131
160
|
return new DataView(this.memory.buffer).getUint32(refAddr, true);
|
|
132
161
|
}
|
|
133
162
|
storeValue(out, val) {
|
|
134
|
-
if (this.memory == null)
|
|
135
|
-
return;
|
|
163
|
+
if (this.memory == null) return;
|
|
136
164
|
const view = new DataView(this.memory.buffer);
|
|
137
165
|
if (typeof val === "number") {
|
|
138
166
|
if (isNaN(val)) {
|
|
@@ -148,7 +176,7 @@ class ZigJS {
|
|
|
148
176
|
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
149
177
|
return;
|
|
150
178
|
}
|
|
151
|
-
if (val ===
|
|
179
|
+
if (val === void 0) {
|
|
152
180
|
view.setUint32(out, predefined.undefined, true);
|
|
153
181
|
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
154
182
|
return;
|
|
@@ -163,7 +191,7 @@ class ZigJS {
|
|
|
163
191
|
return;
|
|
164
192
|
}
|
|
165
193
|
let id = this.idPool.pop();
|
|
166
|
-
if (id ===
|
|
194
|
+
if (id === void 0) {
|
|
167
195
|
id = this.values.length;
|
|
168
196
|
}
|
|
169
197
|
this.values[id] = val;
|
|
@@ -186,23 +214,22 @@ class ZigJS {
|
|
|
186
214
|
view.setUint32(out + 4, NAN_PREFIX | typeId, true);
|
|
187
215
|
}
|
|
188
216
|
loadString(ptr, len) {
|
|
189
|
-
if (this.memory == null)
|
|
190
|
-
return "";
|
|
217
|
+
if (this.memory == null) return "";
|
|
191
218
|
const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
|
|
192
219
|
const data = arr.slice();
|
|
193
220
|
return decoder.decode(data);
|
|
194
221
|
}
|
|
195
|
-
}
|
|
222
|
+
};
|
|
223
|
+
|
|
196
224
|
// src/fetch.ts
|
|
197
225
|
function createFetchImports(getMemory) {
|
|
198
|
-
const encoder2 = new TextEncoder;
|
|
199
|
-
const decoder2 = new TextDecoder;
|
|
226
|
+
const encoder2 = new TextEncoder();
|
|
227
|
+
const decoder2 = new TextDecoder();
|
|
200
228
|
function readStr(ptr, len) {
|
|
201
229
|
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
202
230
|
}
|
|
203
|
-
function
|
|
204
|
-
if (data.length > buf_max)
|
|
205
|
-
return -2;
|
|
231
|
+
function writeBytes2(buf_ptr, buf_max, data) {
|
|
232
|
+
if (data.length > buf_max) return -2;
|
|
206
233
|
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
207
234
|
return data.length;
|
|
208
235
|
}
|
|
@@ -214,8 +241,7 @@ function createFetchImports(getMemory) {
|
|
|
214
241
|
try {
|
|
215
242
|
headers = JSON.parse(headersJson);
|
|
216
243
|
} catch {
|
|
217
|
-
for (const line of headersJson.split(
|
|
218
|
-
`)) {
|
|
244
|
+
for (const line of headersJson.split("\n")) {
|
|
219
245
|
const colonIdx = line.indexOf(":");
|
|
220
246
|
if (colonIdx > 0) {
|
|
221
247
|
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
@@ -228,25 +254,23 @@ function createFetchImports(getMemory) {
|
|
|
228
254
|
const url = readStr(url_ptr, url_len);
|
|
229
255
|
const method = method_len > 0 ? readStr(method_ptr, method_len) : "GET";
|
|
230
256
|
const headersJson = headers_len > 0 ? readStr(headers_ptr, headers_len) : "{}";
|
|
231
|
-
const body = body_len > 0 ? readBytes(body_ptr, body_len) :
|
|
257
|
+
const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
|
|
232
258
|
const headers = parseHeaders(headersJson);
|
|
233
|
-
const controller = new AbortController;
|
|
259
|
+
const controller = new AbortController();
|
|
234
260
|
const timeout = timeout_ms > 0 ? setTimeout(() => controller.abort(), timeout_ms) : null;
|
|
235
261
|
try {
|
|
236
262
|
const response = await fetch(url, {
|
|
237
263
|
method,
|
|
238
|
-
headers: Object.keys(headers).length > 0 ? headers :
|
|
239
|
-
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,
|
|
240
266
|
signal: controller.signal
|
|
241
267
|
});
|
|
242
|
-
if (timeout)
|
|
243
|
-
clearTimeout(timeout);
|
|
268
|
+
if (timeout) clearTimeout(timeout);
|
|
244
269
|
new DataView(getMemory().buffer).setUint16(status_out, response.status, true);
|
|
245
270
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
246
|
-
return
|
|
271
|
+
return writeBytes2(buf_ptr, buf_max, bytes);
|
|
247
272
|
} catch (err) {
|
|
248
|
-
if (timeout)
|
|
249
|
-
clearTimeout(timeout);
|
|
273
|
+
if (timeout) clearTimeout(timeout);
|
|
250
274
|
const msg = err instanceof Error ? err.message : String(err);
|
|
251
275
|
console.error(`wasm fetch failed: ${url} (${msg})`);
|
|
252
276
|
return -1;
|
|
@@ -275,7 +299,7 @@ var CallbackType = {
|
|
|
275
299
|
WebSocketError: 7,
|
|
276
300
|
WebSocketClose: 8
|
|
277
301
|
};
|
|
278
|
-
var jsz = new ZigJS;
|
|
302
|
+
var jsz = new ZigJS();
|
|
279
303
|
var tempRefBuffer = new ArrayBuffer(8);
|
|
280
304
|
var tempRefView = new DataView(tempRefBuffer);
|
|
281
305
|
function storeValueGetRef(val) {
|
|
@@ -285,8 +309,8 @@ function storeValueGetRef(val) {
|
|
|
285
309
|
jsz.memory = originalMemory;
|
|
286
310
|
return tempRefView.getBigUint64(0, true);
|
|
287
311
|
}
|
|
288
|
-
var textDecoder = new TextDecoder;
|
|
289
|
-
var textEncoder = new TextEncoder;
|
|
312
|
+
var textDecoder = new TextDecoder();
|
|
313
|
+
var textEncoder = new TextEncoder();
|
|
290
314
|
var memoryView = null;
|
|
291
315
|
var memoryBuffer = null;
|
|
292
316
|
function getMemoryView() {
|
|
@@ -297,15 +321,14 @@ function getMemoryView() {
|
|
|
297
321
|
}
|
|
298
322
|
return memoryView;
|
|
299
323
|
}
|
|
300
|
-
var stringCache = new Map;
|
|
324
|
+
var stringCache = /* @__PURE__ */ new Map();
|
|
301
325
|
function stringCacheKey(ptr, len) {
|
|
302
326
|
return ptr * 65536 + len;
|
|
303
327
|
}
|
|
304
328
|
function readString(ptr, len) {
|
|
305
329
|
const key = stringCacheKey(ptr, len);
|
|
306
330
|
const cached = stringCache.get(key);
|
|
307
|
-
if (cached !==
|
|
308
|
-
return cached;
|
|
331
|
+
if (cached !== void 0) return cached;
|
|
309
332
|
const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
310
333
|
stringCache.set(key, str);
|
|
311
334
|
return str;
|
|
@@ -314,27 +337,22 @@ function writeBytes(ptr, data) {
|
|
|
314
337
|
getMemoryView().set(data, ptr);
|
|
315
338
|
}
|
|
316
339
|
function wrapPromisingExport(fn) {
|
|
317
|
-
if (!fn)
|
|
318
|
-
return;
|
|
340
|
+
if (!fn) return void 0;
|
|
319
341
|
const promising = WebAssembly.promising;
|
|
320
|
-
if (typeof promising !== "function")
|
|
321
|
-
return fn;
|
|
342
|
+
if (typeof promising !== "function") return fn;
|
|
322
343
|
return promising(fn);
|
|
323
344
|
}
|
|
324
345
|
function invokeWasmExport(fn, ...args) {
|
|
325
|
-
if (!fn)
|
|
326
|
-
return;
|
|
346
|
+
if (!fn) return;
|
|
327
347
|
const result = fn(...args);
|
|
328
348
|
if (result && typeof result.then === "function") {
|
|
329
|
-
result.then(
|
|
349
|
+
void result.then(void 0, (error) => {
|
|
330
350
|
console.error(error);
|
|
331
351
|
});
|
|
332
352
|
}
|
|
333
353
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
#intervals = new Map;
|
|
337
|
-
_alloc;
|
|
354
|
+
var ZxBridgeCore = class _ZxBridgeCore {
|
|
355
|
+
#intervals = /* @__PURE__ */ new Map();
|
|
338
356
|
#handler;
|
|
339
357
|
#fetchCompleteHandler;
|
|
340
358
|
constructor(exports) {
|
|
@@ -345,9 +363,9 @@ class ZxBridgeCore {
|
|
|
345
363
|
throw new Error("__zx_fetch_complete not exported from WASM");
|
|
346
364
|
}
|
|
347
365
|
this.#fetchCompleteHandler = fetchCompleteHandler;
|
|
348
|
-
if (exports.memory)
|
|
349
|
-
jsz.memory = exports.memory;
|
|
366
|
+
if (exports.memory) jsz.memory = exports.memory;
|
|
350
367
|
}
|
|
368
|
+
/** Invoke the unified callback handler */
|
|
351
369
|
#invoke(type, id, data) {
|
|
352
370
|
const handler = this.#handler;
|
|
353
371
|
if (!handler) {
|
|
@@ -357,44 +375,46 @@ class ZxBridgeCore {
|
|
|
357
375
|
const dataRef = storeValueGetRef(data);
|
|
358
376
|
invokeWasmExport(handler, type, id, dataRef);
|
|
359
377
|
}
|
|
378
|
+
/**
|
|
379
|
+
* Async fetch with full options support.
|
|
380
|
+
* Calls __zx_fetch_complete when done.
|
|
381
|
+
*/
|
|
360
382
|
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
361
383
|
const url = readString(urlPtr, urlLen);
|
|
362
384
|
const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
|
|
363
385
|
const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
|
|
364
|
-
const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) :
|
|
386
|
+
const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
|
|
365
387
|
let headers = {};
|
|
366
388
|
try {
|
|
367
389
|
headers = JSON.parse(headersJson);
|
|
368
390
|
} catch {
|
|
369
|
-
for (const line of headersJson.split(
|
|
370
|
-
`)) {
|
|
391
|
+
for (const line of headersJson.split("\n")) {
|
|
371
392
|
const colonIdx = line.indexOf(":");
|
|
372
393
|
if (colonIdx > 0) {
|
|
373
394
|
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
374
395
|
}
|
|
375
396
|
}
|
|
376
397
|
}
|
|
377
|
-
const controller = new AbortController;
|
|
398
|
+
const controller = new AbortController();
|
|
378
399
|
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
379
400
|
const fetchOptions = {
|
|
380
401
|
method,
|
|
381
|
-
headers: Object.keys(headers).length > 0 ? headers :
|
|
382
|
-
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,
|
|
383
404
|
signal: controller.signal
|
|
384
405
|
};
|
|
385
406
|
fetch(url, fetchOptions).then(async (response) => {
|
|
386
|
-
if (timeout)
|
|
387
|
-
clearTimeout(timeout);
|
|
407
|
+
if (timeout) clearTimeout(timeout);
|
|
388
408
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
389
409
|
this._notifyFetchComplete(fetchId, response.status, bytes, false);
|
|
390
410
|
}).catch((error) => {
|
|
391
|
-
if (timeout)
|
|
392
|
-
clearTimeout(timeout);
|
|
411
|
+
if (timeout) clearTimeout(timeout);
|
|
393
412
|
const isAbort = error.name === "AbortError";
|
|
394
413
|
const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
|
|
395
414
|
this._notifyFetchComplete(fetchId, 0, errorMsg, true);
|
|
396
415
|
});
|
|
397
416
|
}
|
|
417
|
+
/** Notify WASM that a fetch completed. `body` is raw bytes on success, text on error. */
|
|
398
418
|
_notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
399
419
|
const handler = this.#fetchCompleteHandler;
|
|
400
420
|
const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
|
|
@@ -402,20 +422,23 @@ class ZxBridgeCore {
|
|
|
402
422
|
writeBytes(ptr, encoded);
|
|
403
423
|
invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
404
424
|
}
|
|
425
|
+
/** Set a timeout and callback when it fires */
|
|
405
426
|
setTimeout(callbackId, delayMs) {
|
|
406
427
|
setTimeout(() => {
|
|
407
428
|
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
408
429
|
}, delayMs);
|
|
409
430
|
}
|
|
431
|
+
/** Set an interval and callback each time it fires */
|
|
410
432
|
setInterval(callbackId, intervalMs) {
|
|
411
433
|
const handle = setInterval(() => {
|
|
412
434
|
this.#invoke(CallbackType.Interval, callbackId, null);
|
|
413
435
|
}, intervalMs);
|
|
414
436
|
this.#intervals.set(callbackId, handle);
|
|
415
437
|
}
|
|
438
|
+
/** Clear an interval */
|
|
416
439
|
clearInterval(callbackId) {
|
|
417
440
|
const handle = this.#intervals.get(callbackId);
|
|
418
|
-
if (handle !==
|
|
441
|
+
if (handle !== void 0) {
|
|
419
442
|
clearInterval(handle);
|
|
420
443
|
this.#intervals.delete(callbackId);
|
|
421
444
|
}
|
|
@@ -426,6 +449,7 @@ class ZxBridgeCore {
|
|
|
426
449
|
}
|
|
427
450
|
this.#intervals.clear();
|
|
428
451
|
}
|
|
452
|
+
/** Write a string to WASM memory, returning pointer and length */
|
|
429
453
|
_writeStringToWasm(str) {
|
|
430
454
|
return this._writeBytesToWasm(textEncoder.encode(str));
|
|
431
455
|
}
|
|
@@ -434,6 +458,7 @@ class ZxBridgeCore {
|
|
|
434
458
|
writeBytes(ptr, data);
|
|
435
459
|
return { ptr, len: data.length };
|
|
436
460
|
}
|
|
461
|
+
/** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
|
|
437
462
|
static log(level, ptr, len) {
|
|
438
463
|
const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
439
464
|
switch (level) {
|
|
@@ -451,18 +476,34 @@ class ZxBridgeCore {
|
|
|
451
476
|
break;
|
|
452
477
|
}
|
|
453
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
|
+
*/
|
|
454
485
|
static createImportObject(bridgeRef) {
|
|
455
486
|
return {
|
|
456
487
|
...jsz.importObject(),
|
|
457
488
|
__zx_net: createFetchImports(() => {
|
|
458
|
-
if (!jsz.memory)
|
|
459
|
-
throw new Error("WASM memory is not ready");
|
|
489
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
460
490
|
return jsz.memory;
|
|
461
491
|
}),
|
|
462
492
|
__zx: {
|
|
463
|
-
_log: (level, ptr, len) =>
|
|
493
|
+
_log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
|
|
464
494
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
465
|
-
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
|
+
);
|
|
466
507
|
},
|
|
467
508
|
_setTimeout: (callbackId, delayMs) => {
|
|
468
509
|
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
@@ -476,44 +517,25 @@ class ZxBridgeCore {
|
|
|
476
517
|
}
|
|
477
518
|
};
|
|
478
519
|
}
|
|
479
|
-
}
|
|
520
|
+
};
|
|
521
|
+
|
|
480
522
|
// src/kv.ts
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
createKVImports: () => createKVImports
|
|
485
|
-
});
|
|
486
|
-
function createMemoryKV() {
|
|
487
|
-
const store = new Map;
|
|
488
|
-
return {
|
|
489
|
-
async get(key) {
|
|
490
|
-
return store.get(key) ?? null;
|
|
491
|
-
},
|
|
492
|
-
async put(key, value) {
|
|
493
|
-
store.set(key, value);
|
|
494
|
-
},
|
|
495
|
-
async delete(key) {
|
|
496
|
-
store.delete(key);
|
|
497
|
-
},
|
|
498
|
-
async list(options) {
|
|
499
|
-
const keys = [...store.keys()].filter((k) => !options?.prefix || k.startsWith(options.prefix)).map((name) => ({ name }));
|
|
500
|
-
return { keys };
|
|
501
|
-
}
|
|
502
|
-
};
|
|
523
|
+
function putOptions(ttlSeconds) {
|
|
524
|
+
if (ttlSeconds < 60) return void 0;
|
|
525
|
+
return { expirationTtl: ttlSeconds };
|
|
503
526
|
}
|
|
504
527
|
function isSyncKVNamespace(binding) {
|
|
505
528
|
const candidate = binding;
|
|
506
529
|
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
507
530
|
}
|
|
508
531
|
function createKVImports(bindings, getMemory) {
|
|
509
|
-
const encoder2 = new TextEncoder;
|
|
510
|
-
const decoder2 = new TextDecoder;
|
|
532
|
+
const encoder2 = new TextEncoder();
|
|
533
|
+
const decoder2 = new TextDecoder();
|
|
511
534
|
function readStr(ptr, len) {
|
|
512
535
|
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
513
536
|
}
|
|
514
537
|
function writeBytes2(buf_ptr, buf_max, data) {
|
|
515
|
-
if (data.length > buf_max)
|
|
516
|
-
return -2;
|
|
538
|
+
if (data.length > buf_max) return -2;
|
|
517
539
|
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
518
540
|
return data.length;
|
|
519
541
|
}
|
|
@@ -522,40 +544,36 @@ function createKVImports(bindings, getMemory) {
|
|
|
522
544
|
}
|
|
523
545
|
const Suspending = WebAssembly.Suspending;
|
|
524
546
|
if (typeof Suspending !== "function") {
|
|
525
|
-
let
|
|
547
|
+
let syncBinding2 = function(ns) {
|
|
526
548
|
const candidate = binding(ns);
|
|
527
549
|
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
528
550
|
};
|
|
551
|
+
var syncBinding = syncBinding2;
|
|
529
552
|
return {
|
|
530
553
|
kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
531
|
-
const b =
|
|
532
|
-
if (!b)
|
|
533
|
-
return -1;
|
|
554
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
555
|
+
if (!b) return -1;
|
|
534
556
|
const value = b.getSync(readStr(key_ptr, key_len));
|
|
535
|
-
if (value === null)
|
|
536
|
-
return -1;
|
|
557
|
+
if (value === null) return -1;
|
|
537
558
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
538
559
|
},
|
|
539
|
-
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
|
|
540
|
-
const b =
|
|
541
|
-
if (!b)
|
|
542
|
-
|
|
543
|
-
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));
|
|
544
564
|
return 0;
|
|
545
565
|
},
|
|
546
566
|
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
547
|
-
const b =
|
|
548
|
-
if (!b)
|
|
549
|
-
return 0;
|
|
567
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
568
|
+
if (!b) return 0;
|
|
550
569
|
b.deleteSync(readStr(key_ptr, key_len));
|
|
551
570
|
return 0;
|
|
552
571
|
},
|
|
553
572
|
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
|
|
554
|
-
const b =
|
|
555
|
-
if (!b)
|
|
556
|
-
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("[]"));
|
|
557
575
|
const prefix = readStr(pfx_ptr, pfx_len);
|
|
558
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } :
|
|
576
|
+
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
559
577
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
560
578
|
}
|
|
561
579
|
};
|
|
@@ -563,33 +581,28 @@ function createKVImports(bindings, getMemory) {
|
|
|
563
581
|
return {
|
|
564
582
|
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
565
583
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
566
|
-
if (!b)
|
|
567
|
-
return -1;
|
|
584
|
+
if (!b) return -1;
|
|
568
585
|
const value = await b.get(readStr(key_ptr, key_len));
|
|
569
|
-
if (value === null)
|
|
570
|
-
return -1;
|
|
586
|
+
if (value === null) return -1;
|
|
571
587
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
572
588
|
}),
|
|
573
|
-
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) => {
|
|
574
590
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
575
|
-
if (!b)
|
|
576
|
-
|
|
577
|
-
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));
|
|
578
593
|
return 0;
|
|
579
594
|
}),
|
|
580
595
|
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
581
596
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
582
|
-
if (!b)
|
|
583
|
-
return -1;
|
|
597
|
+
if (!b) return -1;
|
|
584
598
|
await b.delete(readStr(key_ptr, key_len));
|
|
585
599
|
return 0;
|
|
586
600
|
}),
|
|
587
601
|
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
588
602
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
589
|
-
if (!b)
|
|
590
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
603
|
+
if (!b) return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
591
604
|
const prefix = readStr(prefix_ptr, prefix_len);
|
|
592
|
-
const result = await b.list(prefix.length > 0 ? { prefix } :
|
|
605
|
+
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
593
606
|
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
594
607
|
})
|
|
595
608
|
};
|
|
@@ -701,10 +714,9 @@ function createLocalStorageKV(options = {}) {
|
|
|
701
714
|
listSync(options2) {
|
|
702
715
|
const prefix = namespacePrefix + (options2?.prefix ?? "");
|
|
703
716
|
const keys = [];
|
|
704
|
-
for (let i = 0;i < storage.length; i += 1) {
|
|
717
|
+
for (let i = 0; i < storage.length; i += 1) {
|
|
705
718
|
const key = storage.key(i);
|
|
706
|
-
if (!key || !key.startsWith(prefix))
|
|
707
|
-
continue;
|
|
719
|
+
if (!key || !key.startsWith(prefix)) continue;
|
|
708
720
|
keys.push({ name: key.slice(namespacePrefix.length) });
|
|
709
721
|
}
|
|
710
722
|
return { keys };
|
|
@@ -725,8 +737,8 @@ function createBrowserKVBindings(options = {}) {
|
|
|
725
737
|
}
|
|
726
738
|
|
|
727
739
|
// src/wasm/index.ts
|
|
728
|
-
|
|
729
|
-
#websockets = new Map;
|
|
740
|
+
var ZxBridge = class extends ZxBridgeCore {
|
|
741
|
+
#websockets = /* @__PURE__ */ new Map();
|
|
730
742
|
#wsOnOpenHandler;
|
|
731
743
|
#wsOnMessageHandler;
|
|
732
744
|
#wsOnErrorHandler;
|
|
@@ -740,7 +752,9 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
740
752
|
this.#wsOnErrorHandler = wrapPromisingExport(exports.__zx_ws_onerror);
|
|
741
753
|
this.#wsOnCloseHandler = wrapPromisingExport(exports.__zx_ws_onclose);
|
|
742
754
|
this.#eventbridge = exports.__zx_eventbridge;
|
|
743
|
-
this.#eventbridgeAsync = wrapPromisingExport(
|
|
755
|
+
this.#eventbridgeAsync = wrapPromisingExport(
|
|
756
|
+
exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
|
|
757
|
+
);
|
|
744
758
|
}
|
|
745
759
|
eventMaySuspend(velementId, eventTypeId) {
|
|
746
760
|
return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
@@ -749,19 +763,19 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
749
763
|
const bit = 1 << eventTypeId;
|
|
750
764
|
const current = eventHandlerModes.get(velementId) ?? 0;
|
|
751
765
|
const next = maySuspend ? current | bit : current & ~bit;
|
|
752
|
-
if (next === 0)
|
|
753
|
-
|
|
754
|
-
else
|
|
755
|
-
eventHandlerModes.set(velementId, next);
|
|
766
|
+
if (next === 0) eventHandlerModes.delete(velementId);
|
|
767
|
+
else eventHandlerModes.set(velementId, next);
|
|
756
768
|
}
|
|
757
769
|
clearEventHandlerModes(velementId) {
|
|
758
770
|
eventHandlerModes.delete(velementId);
|
|
759
771
|
}
|
|
772
|
+
/** Submit a form action with bound-state round-trip. */
|
|
760
773
|
submitFormActionAsync(form, actionId, statesJson, fetchId) {
|
|
761
774
|
const formData = new FormData(form);
|
|
762
775
|
formData.append("__$states", statesJson);
|
|
763
776
|
fetch(window.location.href, {
|
|
764
777
|
method: "POST",
|
|
778
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
765
779
|
headers: { "x-action": String(actionId >>> 0) },
|
|
766
780
|
body: formData
|
|
767
781
|
}).then(async (response) => {
|
|
@@ -772,25 +786,27 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
772
786
|
this._notifyFetchComplete(fetchId, 0, msg, true);
|
|
773
787
|
});
|
|
774
788
|
}
|
|
789
|
+
/**
|
|
790
|
+
* Create and connect a WebSocket.
|
|
791
|
+
* Calls __zx_ws_onopen, __zx_ws_onmessage, __zx_ws_onerror, __zx_ws_onclose.
|
|
792
|
+
*/
|
|
775
793
|
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
776
794
|
const url = readString(urlPtr, urlLen);
|
|
777
795
|
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
778
|
-
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;
|
|
779
797
|
try {
|
|
780
798
|
const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
|
|
781
799
|
ws.binaryType = "arraybuffer";
|
|
782
800
|
ws.onopen = () => {
|
|
783
801
|
const handler = this.#wsOnOpenHandler;
|
|
784
|
-
if (!handler)
|
|
785
|
-
return;
|
|
802
|
+
if (!handler) return;
|
|
786
803
|
const protocol = ws.protocol || "";
|
|
787
804
|
const { ptr, len } = this._writeStringToWasm(protocol);
|
|
788
805
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
789
806
|
};
|
|
790
807
|
ws.onmessage = (event) => {
|
|
791
808
|
const handler = this.#wsOnMessageHandler;
|
|
792
|
-
if (!handler)
|
|
793
|
-
return;
|
|
809
|
+
if (!handler) return;
|
|
794
810
|
const isBinary = event.data instanceof ArrayBuffer;
|
|
795
811
|
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
796
812
|
const { ptr, len } = this._writeBytesToWasm(data);
|
|
@@ -798,15 +814,13 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
798
814
|
};
|
|
799
815
|
ws.onerror = (_event) => {
|
|
800
816
|
const handler = this.#wsOnErrorHandler;
|
|
801
|
-
if (!handler)
|
|
802
|
-
return;
|
|
817
|
+
if (!handler) return;
|
|
803
818
|
const { ptr, len } = this._writeStringToWasm("WebSocket error");
|
|
804
819
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
805
820
|
};
|
|
806
821
|
ws.onclose = (event) => {
|
|
807
822
|
const handler = this.#wsOnCloseHandler;
|
|
808
|
-
if (!handler)
|
|
809
|
-
return;
|
|
823
|
+
if (!handler) return;
|
|
810
824
|
const reason = event.reason || "";
|
|
811
825
|
const { ptr, len } = this._writeStringToWasm(reason);
|
|
812
826
|
invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
@@ -822,10 +836,10 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
822
836
|
}
|
|
823
837
|
}
|
|
824
838
|
}
|
|
839
|
+
/** Send data over WebSocket */
|
|
825
840
|
wsSend(wsId, dataPtr, dataLen, isBinary) {
|
|
826
841
|
const ws = this.#websockets.get(wsId);
|
|
827
|
-
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
828
|
-
return;
|
|
842
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
829
843
|
const memory = getMemoryView();
|
|
830
844
|
if (isBinary) {
|
|
831
845
|
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
@@ -833,16 +847,14 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
833
847
|
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
834
848
|
}
|
|
835
849
|
}
|
|
850
|
+
/** Close WebSocket connection */
|
|
836
851
|
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
837
852
|
const ws = this.#websockets.get(wsId);
|
|
838
|
-
if (!ws)
|
|
839
|
-
|
|
840
|
-
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
|
|
853
|
+
if (!ws) return;
|
|
854
|
+
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : void 0;
|
|
841
855
|
try {
|
|
842
|
-
if (reason)
|
|
843
|
-
|
|
844
|
-
else
|
|
845
|
-
ws.close(code);
|
|
856
|
+
if (reason) ws.close(code, reason);
|
|
857
|
+
else ws.close(code);
|
|
846
858
|
} catch {
|
|
847
859
|
ws.close();
|
|
848
860
|
}
|
|
@@ -853,10 +865,12 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
853
865
|
for (const ws of this.#websockets.values()) {
|
|
854
866
|
try {
|
|
855
867
|
ws.close();
|
|
856
|
-
} catch {
|
|
868
|
+
} catch {
|
|
869
|
+
}
|
|
857
870
|
}
|
|
858
871
|
this.#websockets.clear();
|
|
859
872
|
}
|
|
873
|
+
/** Handle a DOM event (called by event delegation) */
|
|
860
874
|
eventbridge(velementId, eventTypeId, event) {
|
|
861
875
|
const eventRef = storeValueGetRef(event);
|
|
862
876
|
if (this.eventMaySuspend(velementId, eventTypeId)) {
|
|
@@ -865,12 +879,12 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
865
879
|
}
|
|
866
880
|
invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
|
|
867
881
|
}
|
|
882
|
+
/** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
|
|
868
883
|
static createImportObject(bridgeRef) {
|
|
869
884
|
return {
|
|
870
885
|
...jsz.importObject(),
|
|
871
886
|
__zx_net: createFetchImports(() => {
|
|
872
|
-
if (!jsz.memory)
|
|
873
|
-
throw new Error("WASM memory is not ready");
|
|
887
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
874
888
|
return jsz.memory;
|
|
875
889
|
}),
|
|
876
890
|
__zx: {
|
|
@@ -882,7 +896,18 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
882
896
|
bridgeRef.current?.clearEventHandlerModes(vnodeId);
|
|
883
897
|
},
|
|
884
898
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
885
|
-
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
|
+
);
|
|
886
911
|
},
|
|
887
912
|
_setTimeout: (callbackId, delayMs) => {
|
|
888
913
|
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
@@ -893,6 +918,7 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
893
918
|
_clearInterval: (callbackId) => {
|
|
894
919
|
bridgeRef.current?.clearInterval(callbackId);
|
|
895
920
|
},
|
|
921
|
+
// WebSocket API
|
|
896
922
|
_wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
|
|
897
923
|
bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
|
|
898
924
|
},
|
|
@@ -936,26 +962,22 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
936
962
|
},
|
|
937
963
|
_snv: (vnodeId, ptr, len) => {
|
|
938
964
|
const node = domNodes.get(vnodeId);
|
|
939
|
-
if (node)
|
|
940
|
-
node.nodeValue = readString(ptr, len);
|
|
965
|
+
if (node) node.nodeValue = readString(ptr, len);
|
|
941
966
|
},
|
|
942
967
|
_srh: (vnodeId, ptr, len) => {
|
|
943
968
|
const el = domNodes.get(vnodeId);
|
|
944
|
-
if (el)
|
|
945
|
-
el.innerHTML = readString(ptr, len);
|
|
969
|
+
if (el) el.innerHTML = readString(ptr, len);
|
|
946
970
|
},
|
|
947
971
|
_ac: (parentId, childId) => {
|
|
948
972
|
const parent = domNodes.get(parentId);
|
|
949
973
|
const child = domNodes.get(childId);
|
|
950
|
-
if (parent && child)
|
|
951
|
-
parent.appendChild(child);
|
|
974
|
+
if (parent && child) parent.appendChild(child);
|
|
952
975
|
},
|
|
953
976
|
_ib: (parentId, childId, refId) => {
|
|
954
977
|
const parent = domNodes.get(parentId);
|
|
955
978
|
const child = domNodes.get(childId);
|
|
956
979
|
const ref = domNodes.get(refId) ?? null;
|
|
957
|
-
if (parent && child)
|
|
958
|
-
parent.insertBefore(child, ref);
|
|
980
|
+
if (parent && child) parent.insertBefore(child, ref);
|
|
959
981
|
},
|
|
960
982
|
_rc: (parentId, childId) => {
|
|
961
983
|
const parent = domNodes.get(parentId);
|
|
@@ -982,8 +1004,7 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
982
1004
|
},
|
|
983
1005
|
_getFormData: (vnodeId, bufPtr, bufLen) => {
|
|
984
1006
|
const form = domNodes.get(vnodeId);
|
|
985
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
986
|
-
return 0;
|
|
1007
|
+
if (!form || !(form instanceof HTMLFormElement)) return 0;
|
|
987
1008
|
const formData = new FormData(form);
|
|
988
1009
|
const urlEncoded = new URLSearchParams(formData).toString();
|
|
989
1010
|
const bytes = textEncoder.encode(urlEncoded);
|
|
@@ -993,34 +1014,32 @@ class ZxBridge extends ZxBridgeCore {
|
|
|
993
1014
|
},
|
|
994
1015
|
_submitFormAction: (vnodeId, actionId) => {
|
|
995
1016
|
const form = domNodes.get(vnodeId);
|
|
996
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
997
|
-
return;
|
|
1017
|
+
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
998
1018
|
const formData = new FormData(form);
|
|
999
1019
|
fetch(window.location.href, {
|
|
1000
1020
|
method: "POST",
|
|
1021
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
1001
1022
|
headers: { "x-action": String(actionId >>> 0) },
|
|
1002
1023
|
body: formData
|
|
1003
|
-
}).catch(() => {
|
|
1024
|
+
}).catch(() => {
|
|
1025
|
+
});
|
|
1004
1026
|
},
|
|
1005
1027
|
_submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
|
|
1006
1028
|
const form = domNodes.get(vnodeId);
|
|
1007
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
1008
|
-
return;
|
|
1029
|
+
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1009
1030
|
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
1010
1031
|
bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
|
|
1011
1032
|
}
|
|
1012
1033
|
}
|
|
1013
1034
|
};
|
|
1014
1035
|
}
|
|
1015
|
-
}
|
|
1016
|
-
var domNodes = new Map;
|
|
1036
|
+
};
|
|
1037
|
+
var domNodes = /* @__PURE__ */ new Map();
|
|
1017
1038
|
function cleanupDomNodes(node) {
|
|
1018
1039
|
const ref = node.__zx_ref;
|
|
1019
|
-
if (ref !==
|
|
1020
|
-
domNodes.delete(BigInt(ref));
|
|
1040
|
+
if (ref !== void 0) domNodes.delete(BigInt(ref));
|
|
1021
1041
|
const children = node.childNodes;
|
|
1022
|
-
for (let i = 0;i < children.length; i++)
|
|
1023
|
-
cleanupDomNodes(children[i]);
|
|
1042
|
+
for (let i = 0; i < children.length; i++) cleanupDomNodes(children[i]);
|
|
1024
1043
|
}
|
|
1025
1044
|
var SVG_TAG_START_INDEX = 140;
|
|
1026
1045
|
var TAG_NAMES = [
|
|
@@ -1164,6 +1183,7 @@ var TAG_NAMES = [
|
|
|
1164
1183
|
"strike",
|
|
1165
1184
|
"tt",
|
|
1166
1185
|
"xmp",
|
|
1186
|
+
// SVG Tags
|
|
1167
1187
|
"animate",
|
|
1168
1188
|
"animateMotion",
|
|
1169
1189
|
"animateTransform",
|
|
@@ -1230,6 +1250,7 @@ var DELEGATED_EVENTS = [
|
|
|
1230
1250
|
{ domType: "input", eventTypeId: 2 },
|
|
1231
1251
|
{ domType: "change", eventTypeId: 3 },
|
|
1232
1252
|
{ domType: "submit", eventTypeId: 4 },
|
|
1253
|
+
// focus/blur do not bubble, so delegated handlers must listen to focusin/focusout.
|
|
1233
1254
|
{ domType: "focusin", eventTypeId: 5 },
|
|
1234
1255
|
{ domType: "focusout", eventTypeId: 6 },
|
|
1235
1256
|
{ domType: "keydown", eventTypeId: 7 },
|
|
@@ -1245,21 +1266,20 @@ var DELEGATED_EVENTS = [
|
|
|
1245
1266
|
{ domType: "touchmove", eventTypeId: 17 },
|
|
1246
1267
|
{ domType: "scroll", eventTypeId: 18 }
|
|
1247
1268
|
];
|
|
1248
|
-
var eventHandlerModes = new Map;
|
|
1269
|
+
var eventHandlerModes = /* @__PURE__ */ new Map();
|
|
1249
1270
|
function initEventDelegation(bridge, rootSelector = "body") {
|
|
1250
1271
|
const root = document.querySelector(rootSelector);
|
|
1251
|
-
if (!root)
|
|
1252
|
-
|
|
1272
|
+
if (!root) return () => {
|
|
1273
|
+
};
|
|
1253
1274
|
const removers = [];
|
|
1254
1275
|
for (const delegatedEvent of DELEGATED_EVENTS) {
|
|
1255
1276
|
const listener = (event) => {
|
|
1256
1277
|
let target = event.target;
|
|
1257
1278
|
while (target && target !== document.body) {
|
|
1258
1279
|
const zxRef = target.__zx_ref;
|
|
1259
|
-
if (zxRef !==
|
|
1280
|
+
if (zxRef !== void 0) {
|
|
1260
1281
|
bridge.eventbridge(BigInt(zxRef), delegatedEvent.eventTypeId, event);
|
|
1261
|
-
if (event.cancelBubble)
|
|
1262
|
-
break;
|
|
1282
|
+
if (event.cancelBubble) break;
|
|
1263
1283
|
}
|
|
1264
1284
|
target = target.parentElement;
|
|
1265
1285
|
}
|
|
@@ -1269,8 +1289,7 @@ function initEventDelegation(bridge, rootSelector = "body") {
|
|
|
1269
1289
|
removers.push(() => root.removeEventListener(delegatedEvent.domType, listener, options));
|
|
1270
1290
|
}
|
|
1271
1291
|
return () => {
|
|
1272
|
-
for (const remove of removers)
|
|
1273
|
-
remove();
|
|
1292
|
+
for (const remove of removers) remove();
|
|
1274
1293
|
};
|
|
1275
1294
|
}
|
|
1276
1295
|
var DEFAULT_URL = "/assets/_/main.wasm";
|
|
@@ -1292,8 +1311,7 @@ function normalizeOptions(options = {}) {
|
|
|
1292
1311
|
};
|
|
1293
1312
|
}
|
|
1294
1313
|
function registerDevReinit(options) {
|
|
1295
|
-
if (typeof window === "undefined")
|
|
1296
|
-
return;
|
|
1314
|
+
if (typeof window === "undefined") return;
|
|
1297
1315
|
const reinit = () => init(options);
|
|
1298
1316
|
window.__zx_dev_reinit = reinit;
|
|
1299
1317
|
window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
@@ -1313,14 +1331,17 @@ async function init(options = {}) {
|
|
|
1313
1331
|
const kvBindings = options.kv ?? createBrowserKVBindings();
|
|
1314
1332
|
const kvImportObject = {
|
|
1315
1333
|
__zx_kv: createKVImports(kvBindings, () => {
|
|
1316
|
-
if (wasmMemory)
|
|
1317
|
-
|
|
1318
|
-
if (jsz.memory)
|
|
1319
|
-
return jsz.memory;
|
|
1334
|
+
if (wasmMemory) return wasmMemory;
|
|
1335
|
+
if (jsz.memory) return jsz.memory;
|
|
1320
1336
|
throw new Error("WASM memory is not ready");
|
|
1321
1337
|
})
|
|
1322
1338
|
};
|
|
1323
|
-
const importObject = Object.assign(
|
|
1339
|
+
const importObject = Object.assign(
|
|
1340
|
+
{},
|
|
1341
|
+
ZxBridge.createImportObject(bridgeRef),
|
|
1342
|
+
kvImportObject,
|
|
1343
|
+
options.importObject
|
|
1344
|
+
);
|
|
1324
1345
|
const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
1325
1346
|
const { instance } = source;
|
|
1326
1347
|
wasmMemory = instance.exports.memory;
|
|
@@ -1339,21 +1360,20 @@ async function init(options = {}) {
|
|
|
1339
1360
|
domNodes.clear();
|
|
1340
1361
|
}
|
|
1341
1362
|
};
|
|
1342
|
-
if (true)
|
|
1343
|
-
registerDevReinit(normalizedOptions);
|
|
1363
|
+
if (true) registerDevReinit(normalizedOptions);
|
|
1344
1364
|
return { source, bridge };
|
|
1345
1365
|
}
|
|
1346
1366
|
export {
|
|
1347
|
-
|
|
1348
|
-
textEncoder,
|
|
1349
|
-
textDecoder,
|
|
1350
|
-
storeValueGetRef,
|
|
1351
|
-
readString,
|
|
1352
|
-
jsz,
|
|
1353
|
-
initEventDelegation,
|
|
1354
|
-
init,
|
|
1355
|
-
getMemoryView,
|
|
1356
|
-
ZxBridgeCore,
|
|
1367
|
+
CallbackType,
|
|
1357
1368
|
ZxBridge,
|
|
1358
|
-
|
|
1369
|
+
ZxBridgeCore,
|
|
1370
|
+
getMemoryView,
|
|
1371
|
+
init,
|
|
1372
|
+
initEventDelegation,
|
|
1373
|
+
jsz,
|
|
1374
|
+
readString,
|
|
1375
|
+
storeValueGetRef,
|
|
1376
|
+
textDecoder,
|
|
1377
|
+
textEncoder,
|
|
1378
|
+
writeBytes
|
|
1359
1379
|
};
|