ziex 0.1.0-dev.1387 → 0.1.0-dev.1458
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/app.d.ts +6 -6
- package/build.zig.zon +1 -1
- package/index.js +477 -169
- package/package.json +7 -5
- package/{aws-lambda → platforms/aws-lambda}/index.js +1 -1
- package/platforms/cloudflare/app.d.ts +2 -0
- package/platforms/cloudflare/db.d.ts +6 -0
- package/{cloudflare → platforms/cloudflare}/do.d.ts +5 -5
- package/platforms/cloudflare/index.d.ts +4 -0
- package/{cloudflare → platforms/cloudflare}/index.js +1666 -1293
- package/platforms/cloudflare/kv.d.ts +5 -0
- package/platforms/cloudflare/worker.d.ts +3 -0
- package/{vercel → platforms/vercel}/index.js +1 -1
- package/runtime/db/extern.d.ts +38 -0
- package/runtime/db/sqlite.d.ts +7 -0
- package/runtime/db.d.ts +3 -0
- package/runtime/db.js +419 -0
- package/{fetch.d.ts → runtime/fetch.d.ts} +1 -1
- package/{runtime.d.ts → runtime/index.d.ts} +6 -15
- package/runtime/kv/extern.d.ts +11 -0
- package/runtime/kv/indexdb.d.ts +7 -0
- package/runtime/kv/localstorage.d.ts +6 -0
- package/runtime/kv/memory.d.ts +6 -0
- package/runtime/kv.d.ts +44 -0
- package/runtime/kv.js +542 -0
- package/wasm/core.d.ts +29 -27
- package/wasm/index.d.ts +13 -12
- package/wasm/index.js +431 -240
- package/wasm/init.dev.js +407 -238
- package/wasm/init.js +3 -3
- package/wasm/wasi.d.ts +1 -5
- package/browser/kv.d.ts +0 -13
- package/cloudflare/app.d.ts +0 -2
- package/cloudflare/db.d.ts +0 -2
- package/cloudflare/index.d.ts +0 -4
- package/cloudflare/kv.d.ts +0 -2
- package/cloudflare/worker.d.ts +0 -3
- package/db.d.ts +0 -22
- package/kv.d.ts +0 -42
- /package/{aws-lambda → platforms/aws-lambda}/index.d.ts +0 -0
- /package/{vercel → platforms/vercel}/index.d.ts +0 -0
- /package/{wasi.d.ts → runtime/wasi.d.ts} +0 -0
|
@@ -4,7 +4,7 @@ var __export = (target, all) => {
|
|
|
4
4
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
// src/runtime.ts
|
|
7
|
+
// src/runtime/index.ts
|
|
8
8
|
var runtime_exports = {};
|
|
9
9
|
__export(runtime_exports, {
|
|
10
10
|
attachWebSocket: () => attachWebSocket,
|
|
@@ -39,10 +39,18 @@ var ZxWasiBridge = class {
|
|
|
39
39
|
return this.#memView;
|
|
40
40
|
}
|
|
41
41
|
#readString(ptr, len) {
|
|
42
|
-
|
|
42
|
+
const start = ptr >>> 0;
|
|
43
|
+
const length = len >>> 0;
|
|
44
|
+
if (length === 0) return "";
|
|
45
|
+
const view = this.#view();
|
|
46
|
+
if (start + length > view.byteLength) return "";
|
|
47
|
+
return decoder.decode(view.subarray(start, start + length));
|
|
43
48
|
}
|
|
44
49
|
#writeBytes(ptr, data) {
|
|
45
|
-
|
|
50
|
+
const start = ptr >>> 0;
|
|
51
|
+
const view = this.#view();
|
|
52
|
+
if (start + data.length > view.byteLength) return;
|
|
53
|
+
view.set(data, start);
|
|
46
54
|
}
|
|
47
55
|
log(level, ptr, len) {
|
|
48
56
|
const msg = decoder.decode(this.#view().subarray(ptr, ptr + len));
|
|
@@ -122,10 +130,10 @@ var ZxWasiBridge = class {
|
|
|
122
130
|
return {
|
|
123
131
|
__zx: {
|
|
124
132
|
_log: (level, ptr, len) => {
|
|
125
|
-
bridgeRef
|
|
133
|
+
bridgeRef[0]?.log(level, ptr, len);
|
|
126
134
|
},
|
|
127
135
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
128
|
-
bridgeRef
|
|
136
|
+
bridgeRef[0]?.fetchAsync(
|
|
129
137
|
urlPtr,
|
|
130
138
|
urlLen,
|
|
131
139
|
methodPtr,
|
|
@@ -139,153 +147,20 @@ var ZxWasiBridge = class {
|
|
|
139
147
|
);
|
|
140
148
|
},
|
|
141
149
|
_setTimeout: (callbackId, delayMs) => {
|
|
142
|
-
bridgeRef
|
|
150
|
+
bridgeRef[0]?.setTimeout(callbackId, delayMs);
|
|
143
151
|
},
|
|
144
152
|
_setInterval: (callbackId, intervalMs) => {
|
|
145
|
-
bridgeRef
|
|
153
|
+
bridgeRef[0]?.setInterval(callbackId, intervalMs);
|
|
146
154
|
},
|
|
147
155
|
_clearInterval: (callbackId) => {
|
|
148
|
-
bridgeRef
|
|
156
|
+
bridgeRef[0]?.clearInterval(callbackId);
|
|
149
157
|
}
|
|
150
158
|
}
|
|
151
159
|
};
|
|
152
160
|
}
|
|
153
161
|
};
|
|
154
162
|
|
|
155
|
-
// src/
|
|
156
|
-
var kv_exports = {};
|
|
157
|
-
__export(kv_exports, {
|
|
158
|
-
createKVImports: () => createKVImports,
|
|
159
|
-
createMemoryKV: () => createMemoryKV
|
|
160
|
-
});
|
|
161
|
-
function putOptions(ttlSeconds) {
|
|
162
|
-
if (ttlSeconds < 60) return void 0;
|
|
163
|
-
return { expirationTtl: ttlSeconds };
|
|
164
|
-
}
|
|
165
|
-
function createMemoryKV() {
|
|
166
|
-
const store = /* @__PURE__ */ new Map();
|
|
167
|
-
function read(key) {
|
|
168
|
-
const entry = store.get(key);
|
|
169
|
-
if (!entry) return null;
|
|
170
|
-
if (entry.expiresAt !== void 0 && Date.now() >= entry.expiresAt) {
|
|
171
|
-
store.delete(key);
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
return entry.value;
|
|
175
|
-
}
|
|
176
|
-
function write(key, value, options) {
|
|
177
|
-
let expiresAt;
|
|
178
|
-
if (options?.expiration !== void 0) {
|
|
179
|
-
expiresAt = options.expiration * 1e3;
|
|
180
|
-
} else if (options?.expirationTtl !== void 0) {
|
|
181
|
-
expiresAt = Date.now() + options.expirationTtl * 1e3;
|
|
182
|
-
}
|
|
183
|
-
store.set(key, { value, expiresAt });
|
|
184
|
-
}
|
|
185
|
-
return {
|
|
186
|
-
async get(key) {
|
|
187
|
-
return read(key);
|
|
188
|
-
},
|
|
189
|
-
async put(key, value, options) {
|
|
190
|
-
write(key, value, options);
|
|
191
|
-
},
|
|
192
|
-
async delete(key) {
|
|
193
|
-
store.delete(key);
|
|
194
|
-
},
|
|
195
|
-
async list(options) {
|
|
196
|
-
const keys = [...store.keys()].filter((k) => {
|
|
197
|
-
if (options?.prefix && !k.startsWith(options.prefix)) return false;
|
|
198
|
-
return read(k) !== null;
|
|
199
|
-
}).map((name) => ({ name }));
|
|
200
|
-
return { keys };
|
|
201
|
-
}
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
function isSyncKVNamespace(binding) {
|
|
205
|
-
const candidate = binding;
|
|
206
|
-
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
207
|
-
}
|
|
208
|
-
function createKVImports(bindings, getMemory) {
|
|
209
|
-
const encoder3 = new TextEncoder();
|
|
210
|
-
const decoder3 = new TextDecoder();
|
|
211
|
-
function readStr(ptr, len) {
|
|
212
|
-
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
213
|
-
}
|
|
214
|
-
function writeBytes2(buf_ptr, buf_max, data) {
|
|
215
|
-
if (data.length > buf_max) return -2;
|
|
216
|
-
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
217
|
-
return data.length;
|
|
218
|
-
}
|
|
219
|
-
function binding(ns) {
|
|
220
|
-
return bindings[ns] ?? bindings["default"] ?? null;
|
|
221
|
-
}
|
|
222
|
-
const Suspending = WebAssembly.Suspending;
|
|
223
|
-
if (typeof Suspending !== "function") {
|
|
224
|
-
let syncBinding2 = function(ns) {
|
|
225
|
-
const candidate = binding(ns);
|
|
226
|
-
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
227
|
-
};
|
|
228
|
-
var syncBinding = syncBinding2;
|
|
229
|
-
return {
|
|
230
|
-
kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
231
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
232
|
-
if (!b) return -1;
|
|
233
|
-
const value = b.getSync(readStr(key_ptr, key_len));
|
|
234
|
-
if (value === null) return -1;
|
|
235
|
-
return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
|
|
236
|
-
},
|
|
237
|
-
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
238
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
239
|
-
if (!b) return 0;
|
|
240
|
-
b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
241
|
-
return 0;
|
|
242
|
-
},
|
|
243
|
-
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
244
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
245
|
-
if (!b) return 0;
|
|
246
|
-
b.deleteSync(readStr(key_ptr, key_len));
|
|
247
|
-
return 0;
|
|
248
|
-
},
|
|
249
|
-
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
|
|
250
|
-
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
251
|
-
if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
|
|
252
|
-
const prefix = readStr(pfx_ptr, pfx_len);
|
|
253
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
254
|
-
return writeBytes2(buf_ptr, buf_max, encoder3.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
return {
|
|
259
|
-
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
260
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
261
|
-
if (!b) return -1;
|
|
262
|
-
const value = await b.get(readStr(key_ptr, key_len));
|
|
263
|
-
if (value === null) return -1;
|
|
264
|
-
return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
|
|
265
|
-
}),
|
|
266
|
-
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
267
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
268
|
-
if (!b) return -1;
|
|
269
|
-
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
270
|
-
return 0;
|
|
271
|
-
}),
|
|
272
|
-
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
273
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
274
|
-
if (!b) return -1;
|
|
275
|
-
await b.delete(readStr(key_ptr, key_len));
|
|
276
|
-
return 0;
|
|
277
|
-
}),
|
|
278
|
-
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
279
|
-
const b = binding(readStr(ns_ptr, ns_len));
|
|
280
|
-
if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
|
|
281
|
-
const prefix = readStr(prefix_ptr, prefix_len);
|
|
282
|
-
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
283
|
-
return writeBytes2(buf_ptr, buf_max, encoder3.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
284
|
-
})
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// src/fetch.ts
|
|
163
|
+
// src/runtime/fetch.ts
|
|
289
164
|
function createFetchImports(getMemory) {
|
|
290
165
|
const encoder3 = new TextEncoder();
|
|
291
166
|
const decoder3 = new TextDecoder();
|
|
@@ -351,1166 +226,1514 @@ function createFetchImports(getMemory) {
|
|
|
351
226
|
};
|
|
352
227
|
}
|
|
353
228
|
|
|
354
|
-
// src/
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
229
|
+
// ../../vendor/jsz/js/src/zigjs.ts
|
|
230
|
+
var NAN_PREFIX = 2146959360;
|
|
231
|
+
var predefined = {
|
|
232
|
+
"nan": 0,
|
|
233
|
+
"null": 1,
|
|
234
|
+
"true": 2,
|
|
235
|
+
"false": 3,
|
|
236
|
+
"undefined": 4,
|
|
237
|
+
"globalThis": 5,
|
|
238
|
+
"runtime": 6
|
|
239
|
+
};
|
|
240
|
+
var PREDEFINED_ID_MAX = 6;
|
|
241
|
+
var encoder2 = new TextEncoder();
|
|
242
|
+
var decoder2 = new TextDecoder("utf-8");
|
|
243
|
+
var ZigJS = class {
|
|
244
|
+
constructor() {
|
|
245
|
+
/**
|
|
246
|
+
* The values, indexed by ID (number). Duplicate values can be in this
|
|
247
|
+
* if they are loaded multiple times. That just acts as duplicate references.
|
|
248
|
+
* */
|
|
249
|
+
this.values = [NaN, null, true, false, void 0, globalThis, this];
|
|
250
|
+
/**
|
|
251
|
+
* When a value is removed from the values array, its ID is put
|
|
252
|
+
* in the pool so that we can use it next. This avoids fragmentation in
|
|
253
|
+
* our array keys.
|
|
254
|
+
* */
|
|
255
|
+
this.idPool = [];
|
|
375
256
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
257
|
+
/**
|
|
258
|
+
* Returns the import object that should be merged with your import
|
|
259
|
+
* object when instantiating your wasm instance. This injects the required
|
|
260
|
+
* functions into the wasm environment.
|
|
261
|
+
* */
|
|
262
|
+
importObject() {
|
|
263
|
+
return {
|
|
264
|
+
"zig-js": {
|
|
265
|
+
valueGet: this.valueGet.bind(this),
|
|
266
|
+
valueSet: this.valueSet.bind(this),
|
|
267
|
+
valueDeinit: this.valueDeinit.bind(this),
|
|
268
|
+
valueObjectCreate: this.valueObjectCreate.bind(this),
|
|
269
|
+
valueStringCreate: this.valueStringCreate.bind(this),
|
|
270
|
+
valueStringLen: this.valueStringLen.bind(this),
|
|
271
|
+
valueStringCopy: this.valueStringCopy.bind(this),
|
|
272
|
+
valueNew: this.valueNew.bind(this),
|
|
273
|
+
funcApply: this.funcApply.bind(this)
|
|
274
|
+
}
|
|
275
|
+
};
|
|
385
276
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
277
|
+
/**
|
|
278
|
+
* Get a value from the JS environment.
|
|
279
|
+
* */
|
|
280
|
+
valueGet(out, id, ptr, len) {
|
|
281
|
+
const val = this.loadValue(id);
|
|
282
|
+
if (val === null || val === void 0 || typeof val !== "object" && typeof val !== "function") {
|
|
283
|
+
this.storeValue(out, void 0);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const str = this.loadString(ptr, len);
|
|
287
|
+
const result = Reflect.get(val, str);
|
|
288
|
+
this.storeValue(out, result);
|
|
393
289
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
290
|
+
/**
|
|
291
|
+
* Set a value on an object.
|
|
292
|
+
* */
|
|
293
|
+
valueSet(id, ptr, len, refAddr) {
|
|
294
|
+
const obj = this.loadValue(id);
|
|
295
|
+
const str = this.loadString(ptr, len);
|
|
296
|
+
const val = this.loadRef(refAddr);
|
|
297
|
+
Reflect.set(obj, str, val);
|
|
399
298
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
299
|
+
/**
|
|
300
|
+
* Dereference a value, allowing the JS environment to potentially GC it.
|
|
301
|
+
* */
|
|
302
|
+
valueDeinit(id) {
|
|
303
|
+
if (id > PREDEFINED_ID_MAX) {
|
|
304
|
+
this.values[id] = null;
|
|
305
|
+
this.idPool.push(id);
|
|
306
|
+
}
|
|
405
307
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
name,
|
|
412
|
-
value: toWireValue(value)
|
|
413
|
-
}))
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
function valuesToWireRows(rows) {
|
|
417
|
-
return rows.map((row) => row.map((value) => toWireValue(value)));
|
|
418
|
-
}
|
|
419
|
-
function createD1Imports(bindings, getMemory) {
|
|
420
|
-
const encoder3 = new TextEncoder();
|
|
421
|
-
const decoder3 = new TextDecoder();
|
|
422
|
-
function readStr(ptr, len) {
|
|
423
|
-
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
308
|
+
/**
|
|
309
|
+
* Create an empty object.
|
|
310
|
+
* */
|
|
311
|
+
valueObjectCreate(out) {
|
|
312
|
+
this.storeValue(out, new Object());
|
|
424
313
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
|
|
316
|
+
* */
|
|
317
|
+
valueStringCreate(out, ptr, len) {
|
|
318
|
+
const str = this.loadString(ptr, len);
|
|
319
|
+
this.storeValue(out, str);
|
|
430
320
|
}
|
|
431
|
-
|
|
432
|
-
|
|
321
|
+
/**
|
|
322
|
+
* Returns the length of the string given by id.
|
|
323
|
+
* */
|
|
324
|
+
valueStringLen(id) {
|
|
325
|
+
const val = this.loadValue(id);
|
|
326
|
+
const buf = encoder2.encode(val);
|
|
327
|
+
return buf.byteLength;
|
|
433
328
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
329
|
+
/**
|
|
330
|
+
* Copy the string at id "id" into the shared memory at ptr.
|
|
331
|
+
* */
|
|
332
|
+
valueStringCopy(id, ptr, max) {
|
|
333
|
+
if (this.memory == null) return;
|
|
334
|
+
const dest = ptr >>> 0;
|
|
335
|
+
const cap = max >>> 0;
|
|
336
|
+
const val = this.loadValue(id);
|
|
337
|
+
if (typeof val !== "string") return;
|
|
338
|
+
const bytes = encoder2.encode(val);
|
|
339
|
+
if (bytes.byteLength > cap || bytes.length === 0) return;
|
|
340
|
+
const buf = this.memory.buffer;
|
|
341
|
+
if (dest + bytes.length > buf.byteLength) return;
|
|
342
|
+
new Uint8Array(buf, dest, bytes.length).set(bytes);
|
|
440
343
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Call a constructor given by id.
|
|
346
|
+
* */
|
|
347
|
+
valueNew(out, id, argsAddr, argsLen) {
|
|
348
|
+
const fn = this.loadValue(id);
|
|
349
|
+
const args = [];
|
|
350
|
+
const base = argsAddr >>> 0;
|
|
351
|
+
const count = argsLen >>> 0;
|
|
352
|
+
for (let i = 0; i < count; i++) {
|
|
353
|
+
args.push(this.loadRef(base + i * 8));
|
|
354
|
+
}
|
|
355
|
+
const result = Reflect.construct(fn, args);
|
|
356
|
+
this.storeValue(out, result);
|
|
450
357
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
return writeJson(buf_ptr, buf_max, (result.results ?? []).map(objectToWireRow));
|
|
474
|
-
}),
|
|
475
|
-
db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
476
|
-
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
477
|
-
if (!stmt) return -1;
|
|
478
|
-
const rows = await stmt.raw();
|
|
479
|
-
return writeJson(buf_ptr, buf_max, valuesToWireRows(rows));
|
|
480
|
-
})
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// src/wasi.ts
|
|
485
|
-
var ProcExit = class extends Error {
|
|
486
|
-
constructor(code) {
|
|
487
|
-
super(`proc_exit(${code})`);
|
|
488
|
-
this.code = code;
|
|
358
|
+
/**
|
|
359
|
+
* Call a function given by id.
|
|
360
|
+
* */
|
|
361
|
+
funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
|
|
362
|
+
const fn = this.loadValue(id);
|
|
363
|
+
const thisVal = this.loadRef(thisRefAddr >>> 0);
|
|
364
|
+
const args = [];
|
|
365
|
+
const base = argsAddr >>> 0;
|
|
366
|
+
const count = argsLen >>> 0;
|
|
367
|
+
for (let i = 0; i < count; i++) {
|
|
368
|
+
args.push(this.loadRef(base + i * 8));
|
|
369
|
+
}
|
|
370
|
+
if (typeof fn !== "function") {
|
|
371
|
+
this.storeValue(out, void 0);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
try {
|
|
375
|
+
const result = Reflect.apply(fn, thisVal, args);
|
|
376
|
+
this.storeValue(out, result);
|
|
377
|
+
} catch {
|
|
378
|
+
this.storeValue(out, void 0);
|
|
379
|
+
}
|
|
489
380
|
}
|
|
490
|
-
|
|
491
|
-
function
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
console.error("[ziex]", line);
|
|
381
|
+
/**
|
|
382
|
+
* This can be used to load a value given by an ID. A WASM function
|
|
383
|
+
* might return a value as an ID. This can be used to retrieve it.
|
|
384
|
+
* */
|
|
385
|
+
loadValue(id) {
|
|
386
|
+
return this.values[id];
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* This removes the value from the values list and returns it. This
|
|
390
|
+
* will not remove predefined values but can still be used to retrieve
|
|
391
|
+
* them.
|
|
392
|
+
* */
|
|
393
|
+
deleteValue(id) {
|
|
394
|
+
const val = this.values[id];
|
|
395
|
+
this.valueDeinit(id);
|
|
396
|
+
return val;
|
|
397
|
+
}
|
|
398
|
+
loadRef(refAddr) {
|
|
399
|
+
if (this.memory == null) return;
|
|
400
|
+
const addr = refAddr >>> 0;
|
|
401
|
+
const view = new DataView(this.memory.buffer);
|
|
402
|
+
const floatVal = view.getFloat64(addr, true);
|
|
403
|
+
if (!isNaN(floatVal)) return floatVal;
|
|
404
|
+
const id = this.loadRefId(addr);
|
|
405
|
+
return this.values[id];
|
|
406
|
+
}
|
|
407
|
+
loadRefId(refAddr) {
|
|
408
|
+
if (this.memory == null) return 0;
|
|
409
|
+
return new DataView(this.memory.buffer).getUint32(refAddr >>> 0, true);
|
|
410
|
+
}
|
|
411
|
+
storeValue(out, val) {
|
|
412
|
+
if (this.memory == null) return;
|
|
413
|
+
const view = new DataView(this.memory.buffer);
|
|
414
|
+
out = out >>> 0;
|
|
415
|
+
if (typeof val === "number") {
|
|
416
|
+
if (isNaN(val)) {
|
|
417
|
+
view.setUint32(out, predefined.nan, true);
|
|
418
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
419
|
+
} else {
|
|
420
|
+
view.setFloat64(out, val, true);
|
|
531
421
|
}
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (val === null) {
|
|
425
|
+
view.setUint32(out, predefined.null, true);
|
|
426
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
if (val === void 0) {
|
|
430
|
+
view.setUint32(out, predefined.undefined, true);
|
|
431
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
if (typeof val === "boolean") {
|
|
435
|
+
view.setUint32(out, val ? predefined.true : predefined.false, true);
|
|
436
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (typeof val === "bigint") {
|
|
440
|
+
view.setFloat64(out, Number(val), true);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
let id = this.idPool.pop();
|
|
444
|
+
if (id === void 0) {
|
|
445
|
+
id = this.values.length;
|
|
446
|
+
}
|
|
447
|
+
this.values[id] = val;
|
|
448
|
+
let typeId = 0;
|
|
449
|
+
switch (typeof val) {
|
|
450
|
+
case "object":
|
|
451
|
+
typeId = 1;
|
|
452
|
+
break;
|
|
453
|
+
case "string":
|
|
454
|
+
typeId = 2;
|
|
455
|
+
break;
|
|
456
|
+
case "symbol":
|
|
457
|
+
typeId = 3;
|
|
458
|
+
break;
|
|
459
|
+
case "function":
|
|
460
|
+
typeId = 4;
|
|
461
|
+
break;
|
|
532
462
|
}
|
|
463
|
+
view.setUint32(out, Number(id), true);
|
|
464
|
+
view.setUint32(out + 4, NAN_PREFIX | typeId, true);
|
|
533
465
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
466
|
+
loadString(ptr, len) {
|
|
467
|
+
if (this.memory == null) return "";
|
|
468
|
+
const start = ptr >>> 0;
|
|
469
|
+
const length = Number(len) >>> 0;
|
|
470
|
+
const buf = this.memory.buffer;
|
|
471
|
+
if (length === 0 || start + length > buf.byteLength) return "";
|
|
472
|
+
const arr = new Uint8ClampedArray(buf, start, length);
|
|
473
|
+
const data = arr.slice();
|
|
474
|
+
return decoder2.decode(data);
|
|
537
475
|
}
|
|
538
|
-
|
|
539
|
-
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/wasm/core.ts
|
|
479
|
+
var jsz = new ZigJS();
|
|
480
|
+
var tempRefBuffer = new ArrayBuffer(8);
|
|
481
|
+
var tempRefView = new DataView(tempRefBuffer);
|
|
482
|
+
function storeValueGetRef(val) {
|
|
483
|
+
const originalMemory = jsz.memory;
|
|
484
|
+
jsz.memory = { buffer: tempRefBuffer };
|
|
485
|
+
jsz.storeValue(0, val);
|
|
486
|
+
jsz.memory = originalMemory;
|
|
487
|
+
return tempRefView.getBigUint64(0, true);
|
|
488
|
+
}
|
|
489
|
+
function loadValueFromRef(ref) {
|
|
490
|
+
tempRefView.setBigUint64(0, ref, true);
|
|
491
|
+
const originalMemory = jsz.memory;
|
|
492
|
+
jsz.memory = { buffer: tempRefBuffer };
|
|
493
|
+
const val = jsz.loadRef(0);
|
|
494
|
+
jsz.memory = originalMemory;
|
|
495
|
+
return val;
|
|
496
|
+
}
|
|
497
|
+
function releaseValueRef(ref) {
|
|
498
|
+
tempRefView.setBigUint64(0, ref, true);
|
|
499
|
+
if (!Number.isNaN(tempRefView.getFloat64(0, true))) return;
|
|
500
|
+
const id = tempRefView.getUint32(0, true);
|
|
501
|
+
if (id > 6) jsz.deleteValue(id);
|
|
502
|
+
}
|
|
503
|
+
var textDecoder = new TextDecoder();
|
|
504
|
+
var textEncoder = new TextEncoder();
|
|
505
|
+
var memoryView = null;
|
|
506
|
+
var memoryBuffer = null;
|
|
507
|
+
function getMemoryView() {
|
|
508
|
+
const buf = jsz.memory.buffer;
|
|
509
|
+
if (buf !== memoryBuffer) {
|
|
510
|
+
memoryBuffer = buf;
|
|
511
|
+
memoryView = new Uint8Array(buf);
|
|
540
512
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
513
|
+
return memoryView;
|
|
514
|
+
}
|
|
515
|
+
function readString(ptr, len) {
|
|
516
|
+
const start = ptr >>> 0;
|
|
517
|
+
const length = len >>> 0;
|
|
518
|
+
if (length === 0) return "";
|
|
519
|
+
const view = getMemoryView();
|
|
520
|
+
if (start + length > view.byteLength) return "";
|
|
521
|
+
return textDecoder.decode(view.subarray(start, start + length));
|
|
522
|
+
}
|
|
523
|
+
function writeBytes(ptr, data) {
|
|
524
|
+
const start = ptr >>> 0;
|
|
525
|
+
const view = getMemoryView();
|
|
526
|
+
if (start + data.length > view.byteLength) return;
|
|
527
|
+
view.set(data, start);
|
|
528
|
+
}
|
|
529
|
+
function wrapPromisingExport(fn) {
|
|
530
|
+
if (!fn) return void 0;
|
|
531
|
+
const promising = WebAssembly.promising;
|
|
532
|
+
if (typeof promising !== "function") return fn;
|
|
533
|
+
return promising(fn);
|
|
534
|
+
}
|
|
535
|
+
function invokeWasmExport(fn, ...args) {
|
|
536
|
+
if (!fn) return;
|
|
537
|
+
const result = fn(...args);
|
|
538
|
+
if (result && typeof result.then === "function") {
|
|
539
|
+
void result.then(void 0, (error) => {
|
|
540
|
+
console.error(error);
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
var ZxBridgeCore = class _ZxBridgeCore {
|
|
545
|
+
#intervals = /* @__PURE__ */ new Map();
|
|
546
|
+
#handler;
|
|
547
|
+
#fetchCompleteHandler;
|
|
548
|
+
constructor(exports) {
|
|
549
|
+
this._alloc = exports.__zx_alloc;
|
|
550
|
+
this.#handler = wrapPromisingExport(exports.__zx_cb);
|
|
551
|
+
const fetchCompleteHandler = wrapPromisingExport(exports.__zx_fetch_complete);
|
|
552
|
+
if (!fetchCompleteHandler) {
|
|
553
|
+
throw new Error("__zx_fetch_complete not exported from WASM");
|
|
554
|
+
}
|
|
555
|
+
this.#fetchCompleteHandler = fetchCompleteHandler;
|
|
556
|
+
if (exports.memory) jsz.memory = exports.memory;
|
|
557
|
+
}
|
|
558
|
+
/** Invoke the unified callback handler */
|
|
559
|
+
#invoke(type, id, data) {
|
|
560
|
+
const handler = this.#handler;
|
|
561
|
+
if (!handler) {
|
|
562
|
+
console.warn("__zx_cb not exported from WASM");
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const dataRef = storeValueGetRef(data);
|
|
566
|
+
invokeWasmExport(handler, type, id, dataRef);
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Async fetch with full options support.
|
|
570
|
+
* Calls __zx_fetch_complete when done.
|
|
571
|
+
*/
|
|
572
|
+
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
573
|
+
const url = readString(urlPtr, urlLen);
|
|
574
|
+
const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
|
|
575
|
+
const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
|
|
576
|
+
const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
|
|
577
|
+
let headers = {};
|
|
578
|
+
try {
|
|
579
|
+
headers = JSON.parse(headersJson);
|
|
580
|
+
} catch {
|
|
581
|
+
for (const line of headersJson.split("\n")) {
|
|
582
|
+
const colonIdx = line.indexOf(":");
|
|
583
|
+
if (colonIdx > 0) {
|
|
584
|
+
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
597
585
|
}
|
|
598
586
|
}
|
|
599
|
-
dv.setUint32(nread_ptr, totalRead, true);
|
|
600
|
-
return 0;
|
|
601
|
-
},
|
|
602
|
-
fd_fdstat_get(_fd, fdstat_ptr) {
|
|
603
|
-
const dv = v();
|
|
604
|
-
dv.setUint8(fdstat_ptr, 2);
|
|
605
|
-
dv.setUint8(fdstat_ptr + 1, 0);
|
|
606
|
-
dv.setUint16(fdstat_ptr + 2, 0, true);
|
|
607
|
-
dv.setUint32(fdstat_ptr + 4, 0, true);
|
|
608
|
-
dv.setBigUint64(fdstat_ptr + 8, 0n, true);
|
|
609
|
-
dv.setBigUint64(fdstat_ptr + 16, 0n, true);
|
|
610
|
-
return 0;
|
|
611
|
-
},
|
|
612
|
-
fd_prestat_get(_fd, _bufptr) {
|
|
613
|
-
return 8;
|
|
614
|
-
},
|
|
615
|
-
fd_prestat_dir_name(_fd, _path, _path_len) {
|
|
616
|
-
return 8;
|
|
617
|
-
},
|
|
618
|
-
fd_close(_fd) {
|
|
619
|
-
return 0;
|
|
620
|
-
},
|
|
621
|
-
fd_pread(_fd, _iovs, _iovs_len, _offset, nread_ptr) {
|
|
622
|
-
v().setUint32(nread_ptr, 0, true);
|
|
623
|
-
return 0;
|
|
624
|
-
},
|
|
625
|
-
fd_pwrite(_fd, _iovs, _iovs_len, _offset, nwritten_ptr) {
|
|
626
|
-
v().setUint32(nwritten_ptr, 0, true);
|
|
627
|
-
return 0;
|
|
628
|
-
},
|
|
629
|
-
fd_filestat_get(_fd, filestat_ptr) {
|
|
630
|
-
const dv = v();
|
|
631
|
-
dv.setBigUint64(filestat_ptr, 0n, true);
|
|
632
|
-
dv.setBigUint64(filestat_ptr + 8, 0n, true);
|
|
633
|
-
dv.setUint8(filestat_ptr + 16, 2);
|
|
634
|
-
dv.setBigUint64(filestat_ptr + 24, 1n, true);
|
|
635
|
-
dv.setBigUint64(filestat_ptr + 32, 0n, true);
|
|
636
|
-
dv.setBigUint64(filestat_ptr + 40, 0n, true);
|
|
637
|
-
dv.setBigUint64(filestat_ptr + 48, 0n, true);
|
|
638
|
-
dv.setBigUint64(filestat_ptr + 56, 0n, true);
|
|
639
|
-
return 0;
|
|
640
|
-
},
|
|
641
|
-
fd_filestat_set_size(_fd, _size) {
|
|
642
|
-
return 76;
|
|
643
|
-
},
|
|
644
|
-
fd_filestat_set_times(_fd, _atim, _mtim, _fst_flags) {
|
|
645
|
-
return 76;
|
|
646
|
-
},
|
|
647
|
-
fd_fdstat_set_flags(_fd, _flags) {
|
|
648
|
-
return 0;
|
|
649
|
-
},
|
|
650
|
-
fd_fdstat_set_rights(_fd, _rights_base, _rights_inheriting) {
|
|
651
|
-
return 0;
|
|
652
|
-
},
|
|
653
|
-
fd_sync(_fd) {
|
|
654
|
-
return 0;
|
|
655
|
-
},
|
|
656
|
-
fd_datasync(_fd) {
|
|
657
|
-
return 0;
|
|
658
|
-
},
|
|
659
|
-
fd_advise(_fd, _offset, _len, _advice) {
|
|
660
|
-
return 0;
|
|
661
|
-
},
|
|
662
|
-
fd_allocate(_fd, _offset, _len) {
|
|
663
|
-
return 76;
|
|
664
|
-
},
|
|
665
|
-
fd_tell(_fd, offset_ptr) {
|
|
666
|
-
v().setBigUint64(offset_ptr, 0n, true);
|
|
667
|
-
return 0;
|
|
668
|
-
},
|
|
669
|
-
fd_renumber(_from, _to) {
|
|
670
|
-
return 0;
|
|
671
|
-
},
|
|
672
|
-
path_filestat_set_times(_fd, _flags, _path, _path_len, _atim, _mtim, _fst_flags) {
|
|
673
|
-
return 76;
|
|
674
|
-
},
|
|
675
|
-
path_link(_old_fd, _old_flags, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
|
|
676
|
-
return 76;
|
|
677
|
-
},
|
|
678
|
-
path_symlink(_old_path, _old_path_len, _fd, _new_path, _new_path_len) {
|
|
679
|
-
return 76;
|
|
680
|
-
},
|
|
681
|
-
proc_raise(_sig) {
|
|
682
|
-
return 0;
|
|
683
|
-
},
|
|
684
|
-
sock_recv(_fd, _ri_data, _ri_data_len, _ri_flags, ro_datalen_ptr, ro_flags_ptr) {
|
|
685
|
-
v().setUint32(ro_datalen_ptr, 0, true);
|
|
686
|
-
v().setUint32(ro_flags_ptr, 0, true);
|
|
687
|
-
return 76;
|
|
688
|
-
},
|
|
689
|
-
sock_send(_fd, _si_data, _si_data_len, _si_flags, so_datalen_ptr) {
|
|
690
|
-
v().setUint32(so_datalen_ptr, 0, true);
|
|
691
|
-
return 76;
|
|
692
|
-
},
|
|
693
|
-
sock_shutdown(_fd, _how) {
|
|
694
|
-
return 76;
|
|
695
|
-
},
|
|
696
|
-
fd_seek(_fd, _offset, _whence, newoffset_ptr) {
|
|
697
|
-
v().setBigInt64(newoffset_ptr, 0n, true);
|
|
698
|
-
return 0;
|
|
699
|
-
},
|
|
700
|
-
proc_exit(code) {
|
|
701
|
-
throw new ProcExit(code);
|
|
702
|
-
},
|
|
703
|
-
sched_yield() {
|
|
704
|
-
return 0;
|
|
705
|
-
},
|
|
706
|
-
clock_time_get(_id, _precision, time_ptr) {
|
|
707
|
-
v().setBigUint64(time_ptr, BigInt(Date.now()) * 1000000n, true);
|
|
708
|
-
return 0;
|
|
709
|
-
},
|
|
710
|
-
clock_res_get(_id, res_ptr) {
|
|
711
|
-
v().setBigUint64(res_ptr, 1000000n, true);
|
|
712
|
-
return 0;
|
|
713
|
-
},
|
|
714
|
-
random_get(buf_ptr, buf_len) {
|
|
715
|
-
crypto.getRandomValues(new Uint8Array(wasmMemory.buffer, buf_ptr, buf_len));
|
|
716
|
-
return 0;
|
|
717
|
-
},
|
|
718
|
-
path_open(_fd, _dirflags, _path, _path_len, _oflags, _rights_base, _rights_inheriting, _fdflags, opened_fd_ptr) {
|
|
719
|
-
v().setInt32(opened_fd_ptr, -1, true);
|
|
720
|
-
return 76;
|
|
721
|
-
},
|
|
722
|
-
path_create_directory(_fd, _path, _path_len) {
|
|
723
|
-
return 76;
|
|
724
|
-
},
|
|
725
|
-
path_unlink_file(_fd, _path, _path_len) {
|
|
726
|
-
return 76;
|
|
727
|
-
},
|
|
728
|
-
path_remove_directory(_fd, _path, _path_len) {
|
|
729
|
-
return 76;
|
|
730
|
-
},
|
|
731
|
-
path_rename(_fd, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
|
|
732
|
-
return 76;
|
|
733
|
-
},
|
|
734
|
-
path_filestat_get(_fd, _flags, _path, _path_len, filestat_ptr) {
|
|
735
|
-
new Uint8Array(wasmMemory.buffer, filestat_ptr, 64).fill(0);
|
|
736
|
-
return 76;
|
|
737
|
-
},
|
|
738
|
-
path_readlink(_fd, _path, _path_len, _buf, _buf_len, nread_ptr) {
|
|
739
|
-
v().setUint32(nread_ptr, 0, true);
|
|
740
|
-
return 76;
|
|
741
|
-
},
|
|
742
|
-
fd_readdir(_fd, _buf, _buf_len, _cookie, bufused_ptr) {
|
|
743
|
-
v().setUint32(bufused_ptr, 0, true);
|
|
744
|
-
return 76;
|
|
745
|
-
},
|
|
746
|
-
// Stub for poll_oneoff - no blocking I/O in edge runtimes.
|
|
747
|
-
poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
|
|
748
|
-
v().setUint32(nevents_ptr, 0, true);
|
|
749
|
-
return 0;
|
|
750
587
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
const
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
588
|
+
const controller = new AbortController();
|
|
589
|
+
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
590
|
+
const fetchOptions = {
|
|
591
|
+
method,
|
|
592
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
593
|
+
body: method !== "GET" && method !== "HEAD" ? body : void 0,
|
|
594
|
+
signal: controller.signal
|
|
595
|
+
};
|
|
596
|
+
fetch(url, fetchOptions).then(async (response) => {
|
|
597
|
+
if (timeout) clearTimeout(timeout);
|
|
598
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
599
|
+
this._notifyFetchComplete(fetchId, response.status, bytes, false);
|
|
600
|
+
}).catch((error) => {
|
|
601
|
+
if (timeout) clearTimeout(timeout);
|
|
602
|
+
const isAbort = error.name === "AbortError";
|
|
603
|
+
const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
|
|
604
|
+
this._notifyFetchComplete(fetchId, 0, errorMsg, true);
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
/** Notify WASM that a fetch completed. `body` is raw bytes on success, text on error. */
|
|
608
|
+
_notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
609
|
+
const handler = this.#fetchCompleteHandler;
|
|
610
|
+
const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
|
|
611
|
+
const ptr = this._alloc(encoded.length) >>> 0;
|
|
612
|
+
if (!ptr && encoded.length > 0) return;
|
|
613
|
+
writeBytes(ptr, encoded);
|
|
614
|
+
invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
615
|
+
}
|
|
616
|
+
/** Set a timeout and callback when it fires */
|
|
617
|
+
setTimeout(callbackId, delayMs) {
|
|
618
|
+
setTimeout(() => {
|
|
619
|
+
this.#invoke(3, callbackId, null);
|
|
620
|
+
}, delayMs);
|
|
621
|
+
}
|
|
622
|
+
/** Set an interval and callback each time it fires */
|
|
623
|
+
setInterval(callbackId, intervalMs) {
|
|
624
|
+
const handle = setInterval(() => {
|
|
625
|
+
this.#invoke(4, callbackId, null);
|
|
626
|
+
}, intervalMs);
|
|
627
|
+
this.#intervals.set(callbackId, handle);
|
|
628
|
+
}
|
|
629
|
+
/** Clear an interval */
|
|
630
|
+
clearInterval(callbackId) {
|
|
631
|
+
const handle = this.#intervals.get(callbackId);
|
|
632
|
+
if (handle !== void 0) {
|
|
633
|
+
clearInterval(handle);
|
|
634
|
+
this.#intervals.delete(callbackId);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
dispose() {
|
|
638
|
+
for (const handle of this.#intervals.values()) {
|
|
639
|
+
clearInterval(handle);
|
|
640
|
+
}
|
|
641
|
+
this.#intervals.clear();
|
|
642
|
+
}
|
|
643
|
+
/** Write a string to WASM memory, returning `[ptr, len]`. */
|
|
644
|
+
_writeStringToWasm(str) {
|
|
645
|
+
return this.writeBytesToWasm(textEncoder.encode(str));
|
|
646
|
+
}
|
|
647
|
+
writeBytesToWasm(data) {
|
|
648
|
+
if (data.length === 0) return [0, 0];
|
|
649
|
+
const ptr = this._alloc(data.length) >>> 0;
|
|
650
|
+
if (!ptr) return [0, 0];
|
|
651
|
+
writeBytes(ptr, data);
|
|
652
|
+
return [ptr, data.length];
|
|
653
|
+
}
|
|
654
|
+
/** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
|
|
655
|
+
static log(level, ptr, len) {
|
|
656
|
+
const start = ptr >>> 0;
|
|
657
|
+
const length = len >>> 0;
|
|
658
|
+
const view = getMemoryView();
|
|
659
|
+
if (start + length > view.byteLength) return;
|
|
660
|
+
const msg = textDecoder.decode(view.subarray(start, start + length));
|
|
661
|
+
switch (level) {
|
|
662
|
+
case 0:
|
|
663
|
+
console.error(msg);
|
|
664
|
+
break;
|
|
665
|
+
case 1:
|
|
666
|
+
console.warn(msg);
|
|
667
|
+
break;
|
|
668
|
+
case 3:
|
|
669
|
+
console.debug(msg);
|
|
670
|
+
break;
|
|
671
|
+
default:
|
|
672
|
+
console.log(msg);
|
|
673
|
+
break;
|
|
759
674
|
}
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Create the core import object for WASM instantiation.
|
|
678
|
+
* Includes only environment-agnostic bindings: log, fetch, and timers.
|
|
679
|
+
* Use ZxBridge.createImportObject (from wasm/index.ts) in browser contexts
|
|
680
|
+
* to additionally include DOM and WebSocket bindings.
|
|
681
|
+
*/
|
|
682
|
+
static createImportObject(bridgeRef) {
|
|
760
683
|
return {
|
|
761
|
-
|
|
762
|
-
|
|
684
|
+
...jsz.importObject(),
|
|
685
|
+
__zx_net: createFetchImports(() => {
|
|
686
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
687
|
+
return jsz.memory;
|
|
688
|
+
}),
|
|
689
|
+
__zx: {
|
|
690
|
+
_log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
|
|
691
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
692
|
+
bridgeRef[0]?.fetchAsync(
|
|
693
|
+
urlPtr,
|
|
694
|
+
urlLen,
|
|
695
|
+
methodPtr,
|
|
696
|
+
methodLen,
|
|
697
|
+
headersPtr,
|
|
698
|
+
headersLen,
|
|
699
|
+
bodyPtr,
|
|
700
|
+
bodyLen,
|
|
701
|
+
timeoutMs,
|
|
702
|
+
fetchId
|
|
703
|
+
);
|
|
704
|
+
},
|
|
705
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
706
|
+
bridgeRef[0]?.setTimeout(callbackId, delayMs);
|
|
707
|
+
},
|
|
708
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
709
|
+
bridgeRef[0]?.setInterval(callbackId, intervalMs);
|
|
710
|
+
},
|
|
711
|
+
_clearInterval: (callbackId) => {
|
|
712
|
+
bridgeRef[0]?.clearInterval(callbackId);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
763
715
|
};
|
|
764
716
|
}
|
|
765
|
-
|
|
717
|
+
};
|
|
718
|
+
function writeBytesOut(getMemory, allocRef, outPtrAddr, data) {
|
|
719
|
+
if (data.length === 0) {
|
|
720
|
+
new DataView(getMemory().buffer).setUint32(outPtrAddr, 0, true);
|
|
721
|
+
return 0;
|
|
722
|
+
}
|
|
723
|
+
const alloc = allocRef[0];
|
|
724
|
+
if (!alloc) return -1;
|
|
725
|
+
const ptr = alloc(data.length) >>> 0;
|
|
726
|
+
if (!ptr) return -1;
|
|
727
|
+
const buffer = getMemory().buffer;
|
|
728
|
+
if (ptr + data.length > buffer.byteLength) return -1;
|
|
729
|
+
new Uint8Array(buffer, ptr, data.length).set(data);
|
|
730
|
+
new DataView(buffer).setUint32(outPtrAddr >>> 0, ptr, true);
|
|
731
|
+
return data.length;
|
|
766
732
|
}
|
|
767
|
-
function
|
|
768
|
-
|
|
769
|
-
const result = new Uint8Array(totalLen);
|
|
770
|
-
let offset = 0;
|
|
771
|
-
for (const arr of arrays) {
|
|
772
|
-
result.set(arr, offset);
|
|
773
|
-
offset += arr.length;
|
|
774
|
-
}
|
|
775
|
-
return result;
|
|
733
|
+
function writeJsonOut(getMemory, allocRef, outPtrAddr, value) {
|
|
734
|
+
return writeBytesOut(getMemory, allocRef, outPtrAddr, textEncoder.encode(JSON.stringify(value)));
|
|
776
735
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
780
|
-
const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
781
|
-
return {
|
|
782
|
-
ws_upgrade: () => {
|
|
783
|
-
ws.upgraded = true;
|
|
784
|
-
},
|
|
785
|
-
ws_write: (ptr, len) => {
|
|
786
|
-
const data = new Uint8Array(mem().buffer, ptr, len).slice();
|
|
787
|
-
if (!ws.server) {
|
|
788
|
-
ws.pendingWrites.push(data);
|
|
789
|
-
} else {
|
|
790
|
-
ws.server.send(data);
|
|
791
|
-
}
|
|
792
|
-
},
|
|
793
|
-
ws_close: (code, reason_ptr, reason_len) => {
|
|
794
|
-
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
795
|
-
},
|
|
796
|
-
ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
|
|
797
|
-
if (ws._resolveFirstSuspend) {
|
|
798
|
-
const fn = ws._resolveFirstSuspend;
|
|
799
|
-
ws._resolveFirstSuspend = void 0;
|
|
800
|
-
fn();
|
|
801
|
-
}
|
|
802
|
-
const deliver = (bytes) => {
|
|
803
|
-
if (bytes === null) return -1;
|
|
804
|
-
const n = Math.min(bytes.length, buf_max);
|
|
805
|
-
new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
|
|
806
|
-
return n;
|
|
807
|
-
};
|
|
808
|
-
if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
|
|
809
|
-
return new Promise((resolve) => {
|
|
810
|
-
ws.recvResolve = (bytes) => resolve(deliver(bytes));
|
|
811
|
-
});
|
|
812
|
-
}) : (_buf_ptr, _buf_max) => -1,
|
|
813
|
-
// Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
|
|
814
|
-
ws_subscribe: (ptr, len) => {
|
|
815
|
-
ws.subscribe?.(readStr(ptr, len));
|
|
816
|
-
},
|
|
817
|
-
ws_unsubscribe: (ptr, len) => {
|
|
818
|
-
ws.unsubscribe?.(readStr(ptr, len));
|
|
819
|
-
},
|
|
820
|
-
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
821
|
-
const topic = readStr(topic_ptr, topic_len);
|
|
822
|
-
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
823
|
-
return ws.publish?.(topic, data) ?? 0;
|
|
824
|
-
},
|
|
825
|
-
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
|
|
826
|
-
};
|
|
736
|
+
function bindWasmAlloc(allocRef, exports) {
|
|
737
|
+
allocRef[0] = exports.__zx_alloc;
|
|
827
738
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
ws.server = server;
|
|
834
|
-
server.accept();
|
|
835
|
-
for (const data of ws.pendingWrites) server.send(data);
|
|
836
|
-
ws.pendingWrites = [];
|
|
837
|
-
server.addEventListener("message", (event) => {
|
|
838
|
-
const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
|
|
839
|
-
if (ws.recvResolve) {
|
|
840
|
-
const res = ws.recvResolve;
|
|
841
|
-
ws.recvResolve = null;
|
|
842
|
-
res(data);
|
|
843
|
-
} else {
|
|
844
|
-
ws.messageQueue.push(data);
|
|
845
|
-
}
|
|
846
|
-
});
|
|
847
|
-
server.addEventListener("close", () => {
|
|
848
|
-
if (ws.recvResolve) {
|
|
849
|
-
const res = ws.recvResolve;
|
|
850
|
-
ws.recvResolve = null;
|
|
851
|
-
res(null);
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
return { client };
|
|
739
|
+
|
|
740
|
+
// src/runtime/kv/extern.ts
|
|
741
|
+
function putOptions(ttlSeconds) {
|
|
742
|
+
if (ttlSeconds < 60) return void 0;
|
|
743
|
+
return { expirationTtl: ttlSeconds };
|
|
855
744
|
}
|
|
856
|
-
function
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}
|
|
860
|
-
};
|
|
745
|
+
function isSyncKVNamespace(binding) {
|
|
746
|
+
const candidate = binding;
|
|
747
|
+
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
861
748
|
}
|
|
862
|
-
function
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
if (!(e instanceof ProcExit)) throw e;
|
|
868
|
-
}
|
|
869
|
-
return Promise.resolve();
|
|
749
|
+
function createKVImports(bindings, getMemory, allocRef) {
|
|
750
|
+
const encoder3 = new TextEncoder();
|
|
751
|
+
const decoder3 = new TextDecoder();
|
|
752
|
+
function readStr(ptr, len) {
|
|
753
|
+
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
870
754
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
755
|
+
function binding(ns) {
|
|
756
|
+
return bindings[ns] ?? bindings["default"] ?? null;
|
|
757
|
+
}
|
|
758
|
+
const Suspending = WebAssembly.Suspending;
|
|
759
|
+
if (typeof Suspending !== "function") {
|
|
760
|
+
let syncBinding2 = function(ns) {
|
|
761
|
+
const candidate = binding(ns);
|
|
762
|
+
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
763
|
+
};
|
|
764
|
+
var syncBinding = syncBinding2;
|
|
765
|
+
return {
|
|
766
|
+
kv_get: (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
|
|
767
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
768
|
+
if (!b) return -1;
|
|
769
|
+
const value = b.getSync(readStr(key_ptr, key_len));
|
|
770
|
+
if (value === null) return -1;
|
|
771
|
+
return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
|
|
772
|
+
},
|
|
773
|
+
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
774
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
775
|
+
if (!b) return 0;
|
|
776
|
+
b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
777
|
+
return 0;
|
|
778
|
+
},
|
|
779
|
+
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
780
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
781
|
+
if (!b) return 0;
|
|
782
|
+
b.deleteSync(readStr(key_ptr, key_len));
|
|
783
|
+
return 0;
|
|
784
|
+
},
|
|
785
|
+
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, out_ptr) => {
|
|
786
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
787
|
+
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
788
|
+
const prefix = readStr(pfx_ptr, pfx_len);
|
|
789
|
+
const result = b.listSync(prefix.length > 0 ? { prefix } : void 0);
|
|
790
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, result.keys.map((k) => k.name));
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
}
|
|
794
|
+
return {
|
|
795
|
+
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, out_ptr) => {
|
|
796
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
797
|
+
if (!b) return -1;
|
|
798
|
+
const value = await b.get(readStr(key_ptr, key_len));
|
|
799
|
+
if (value === null) return -1;
|
|
800
|
+
return writeBytesOut(getMemory, allocRef, out_ptr, encoder3.encode(value));
|
|
801
|
+
}),
|
|
802
|
+
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
803
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
804
|
+
if (!b) return -1;
|
|
805
|
+
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
806
|
+
return 0;
|
|
807
|
+
}),
|
|
808
|
+
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
809
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
810
|
+
if (!b) return -1;
|
|
811
|
+
await b.delete(readStr(key_ptr, key_len));
|
|
812
|
+
return 0;
|
|
813
|
+
}),
|
|
814
|
+
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, out_ptr) => {
|
|
815
|
+
const b = binding(readStr(ns_ptr, ns_len));
|
|
816
|
+
if (!b) return writeJsonOut(getMemory, allocRef, out_ptr, []);
|
|
817
|
+
const prefix = readStr(prefix_ptr, prefix_len);
|
|
818
|
+
const result = await b.list(prefix.length > 0 ? { prefix } : void 0);
|
|
819
|
+
const names = result.keys.map((k) => k.name);
|
|
820
|
+
if (names.length === 0) {
|
|
821
|
+
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
822
|
+
return 0;
|
|
896
823
|
}
|
|
897
|
-
|
|
898
|
-
}
|
|
824
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, names);
|
|
825
|
+
})
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// src/runtime/db/extern.ts
|
|
830
|
+
function decodeBlob(base64) {
|
|
831
|
+
const binary = atob(base64);
|
|
832
|
+
const bytes = new Uint8Array(binary.length);
|
|
833
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
834
|
+
return bytes;
|
|
835
|
+
}
|
|
836
|
+
function toDbValue(value) {
|
|
837
|
+
switch (value.kind) {
|
|
838
|
+
case "null":
|
|
839
|
+
return null;
|
|
840
|
+
case "integer":
|
|
841
|
+
return value.integer;
|
|
842
|
+
case "float":
|
|
843
|
+
return value.float;
|
|
844
|
+
case "text":
|
|
845
|
+
return value.text;
|
|
846
|
+
case "blob":
|
|
847
|
+
return decodeBlob(value.blob);
|
|
848
|
+
case "boolean":
|
|
849
|
+
return value.boolean;
|
|
899
850
|
}
|
|
900
|
-
return meta;
|
|
901
851
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
wasi,
|
|
911
|
-
websocket: doNamespace
|
|
912
|
-
}) {
|
|
913
|
-
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
914
|
-
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
915
|
-
return doNamespace.get(id).fetch(request);
|
|
852
|
+
function toPositionalBindings(json) {
|
|
853
|
+
switch (json.kind) {
|
|
854
|
+
case "none":
|
|
855
|
+
return [];
|
|
856
|
+
case "positional":
|
|
857
|
+
return json.values.map(toDbValue);
|
|
858
|
+
case "named":
|
|
859
|
+
throw new Error("named SQL bindings are not supported yet");
|
|
916
860
|
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
if (streamWriter) void streamWriter.write(chunk);
|
|
925
|
-
else stdoutChunks.push(chunk);
|
|
926
|
-
}
|
|
927
|
-
});
|
|
928
|
-
let wasmMemory = null;
|
|
929
|
-
const mem = () => wasmMemory;
|
|
930
|
-
const bridgeRef = { current: null };
|
|
931
|
-
const Suspending = WebAssembly.Suspending;
|
|
932
|
-
const jspi = typeof Suspending === "function";
|
|
933
|
-
const wsState = {
|
|
934
|
-
upgraded: false,
|
|
935
|
-
server: null,
|
|
936
|
-
pendingWrites: [],
|
|
937
|
-
messageQueue: [],
|
|
938
|
-
recvResolve: null
|
|
939
|
-
};
|
|
940
|
-
const instance = new WebAssembly.Instance(module, {
|
|
941
|
-
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
942
|
-
__zx_sys: buildSysImports(jspi, Suspending),
|
|
943
|
-
__zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder(), wsState),
|
|
944
|
-
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
945
|
-
__zx_db: createD1Imports(dbBindings ?? {}, mem),
|
|
946
|
-
__zx_net: createFetchImports(mem),
|
|
947
|
-
...imports ? imports(mem) : {},
|
|
948
|
-
...ZxWasiBridge.createImportObject(bridgeRef)
|
|
949
|
-
});
|
|
950
|
-
wasmMemory = instance.exports.memory;
|
|
951
|
-
setMemory(wasmMemory);
|
|
952
|
-
bridgeRef.current = new ZxWasiBridge(instance.exports);
|
|
953
|
-
const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
|
|
954
|
-
if (wsState.upgraded) {
|
|
955
|
-
const server = attachWebSocket(wsState);
|
|
956
|
-
ctx?.waitUntil(wasmPromise);
|
|
957
|
-
return new Response(null, { status: 101, webSocket: server.client });
|
|
861
|
+
}
|
|
862
|
+
function toWireValue(value) {
|
|
863
|
+
if (value === null || value === void 0) return { kind: "null" };
|
|
864
|
+
if (typeof value === "string") return { kind: "text", text: value };
|
|
865
|
+
if (typeof value === "boolean") return { kind: "boolean", boolean: value };
|
|
866
|
+
if (typeof value === "number") {
|
|
867
|
+
return Number.isInteger(value) ? { kind: "integer", integer: value } : { kind: "float", float: value };
|
|
958
868
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
const
|
|
963
|
-
|
|
964
|
-
for (const chunk of stdoutChunks) void streamWriter.write(chunk);
|
|
965
|
-
stdoutChunks.length = 0;
|
|
966
|
-
void wasmPromise.finally(() => streamWriter?.close());
|
|
967
|
-
return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
|
|
869
|
+
if (value instanceof ArrayBuffer) {
|
|
870
|
+
const bytes = new Uint8Array(value);
|
|
871
|
+
let binary = "";
|
|
872
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
873
|
+
return { kind: "blob", blob: btoa(binary) };
|
|
968
874
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
|
|
975
|
-
if (nullBody) {
|
|
976
|
-
meta.headers.delete("content-length");
|
|
977
|
-
return new Response(null, { status: meta.status, headers: meta.headers });
|
|
875
|
+
if (ArrayBuffer.isView(value)) {
|
|
876
|
+
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
877
|
+
let binary = "";
|
|
878
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
879
|
+
return { kind: "blob", blob: btoa(binary) };
|
|
978
880
|
}
|
|
979
|
-
|
|
980
|
-
return new Response(body.buffer, { status: meta.status, headers: meta.headers });
|
|
881
|
+
return { kind: "text", text: String(value) };
|
|
981
882
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
883
|
+
function objectToWireRow(record) {
|
|
884
|
+
return {
|
|
885
|
+
fields: Object.entries(record).map(([name, value]) => ({
|
|
886
|
+
name,
|
|
887
|
+
value: toWireValue(value)
|
|
888
|
+
}))
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
function valuesToWireRows(rows) {
|
|
892
|
+
return rows.map((row) => row.map((value) => toWireValue(value)));
|
|
893
|
+
}
|
|
894
|
+
function createDbImports(bindings, getMemory, allocRef) {
|
|
895
|
+
const decoder3 = new TextDecoder();
|
|
896
|
+
function readStr(ptr, len) {
|
|
897
|
+
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
991
898
|
}
|
|
992
|
-
|
|
993
|
-
return
|
|
899
|
+
function binding(ns) {
|
|
900
|
+
return bindings[ns] ?? bindings["default"] ?? null;
|
|
994
901
|
}
|
|
995
|
-
|
|
996
|
-
|
|
902
|
+
async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
|
|
903
|
+
const database = binding(readStr(ns_ptr, ns_len));
|
|
904
|
+
if (!database) return null;
|
|
905
|
+
const sql = readStr(sql_ptr, sql_len);
|
|
906
|
+
const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
|
|
907
|
+
return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
|
|
997
908
|
}
|
|
998
|
-
|
|
999
|
-
|
|
909
|
+
const Suspending = WebAssembly.Suspending;
|
|
910
|
+
if (typeof Suspending !== "function") {
|
|
911
|
+
return {
|
|
912
|
+
db_open: (_ns, _ns_len) => -1,
|
|
913
|
+
db_run: (_a, _b, _c, _d, _e, _f, _g) => -1,
|
|
914
|
+
db_get: (_a, _b, _c, _d, _e, _f, _g) => -1,
|
|
915
|
+
db_all: (_a, _b, _c, _d, _e, _f, _g) => -1,
|
|
916
|
+
db_values: (_a, _b, _c, _d, _e, _f, _g) => -1
|
|
917
|
+
};
|
|
1000
918
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
919
|
+
return {
|
|
920
|
+
db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
|
|
921
|
+
db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
922
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
923
|
+
if (!stmt) return -1;
|
|
924
|
+
const result = await stmt.run();
|
|
925
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, {
|
|
926
|
+
last_insert_rowid: result.meta?.last_row_id ?? 0,
|
|
927
|
+
changes: result.meta?.changes ?? 0
|
|
928
|
+
});
|
|
929
|
+
}),
|
|
930
|
+
db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
931
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
932
|
+
if (!stmt) return -1;
|
|
933
|
+
const row = await stmt.first();
|
|
934
|
+
if (!row) {
|
|
935
|
+
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
936
|
+
return 0;
|
|
937
|
+
}
|
|
938
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, [objectToWireRow(row)]);
|
|
939
|
+
}),
|
|
940
|
+
db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
941
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
942
|
+
if (!stmt) return -1;
|
|
943
|
+
const result = await stmt.all();
|
|
944
|
+
const rows = (result.results ?? []).map(objectToWireRow);
|
|
945
|
+
if (rows.length === 0) {
|
|
946
|
+
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
947
|
+
return 0;
|
|
948
|
+
}
|
|
949
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, rows);
|
|
950
|
+
}),
|
|
951
|
+
db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, out_ptr) => {
|
|
952
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
953
|
+
if (!stmt) return -1;
|
|
954
|
+
const rows = await stmt.raw();
|
|
955
|
+
if (rows.length === 0) {
|
|
956
|
+
new DataView(getMemory().buffer).setUint32(out_ptr, 0, true);
|
|
957
|
+
return 0;
|
|
958
|
+
}
|
|
959
|
+
return writeJsonOut(getMemory, allocRef, out_ptr, valuesToWireRows(rows));
|
|
960
|
+
})
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// src/runtime/wasi.ts
|
|
965
|
+
var ProcExit = class extends Error {
|
|
966
|
+
constructor(code) {
|
|
967
|
+
super(`proc_exit(${code})`);
|
|
968
|
+
this.code = code;
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
function createWasiImports({
|
|
972
|
+
request,
|
|
973
|
+
stdinData,
|
|
974
|
+
onStdout
|
|
975
|
+
}) {
|
|
976
|
+
const encoder3 = new TextEncoder();
|
|
977
|
+
const url = new URL(request.url);
|
|
978
|
+
const argStrings = [
|
|
979
|
+
"wasm",
|
|
980
|
+
"--pathname",
|
|
981
|
+
url.pathname,
|
|
982
|
+
"--method",
|
|
983
|
+
request.method,
|
|
984
|
+
"--search",
|
|
985
|
+
url.search,
|
|
986
|
+
"--url",
|
|
987
|
+
url.href
|
|
988
|
+
];
|
|
989
|
+
request.headers.forEach((value, name) => {
|
|
990
|
+
if (value) argStrings.push("--header", `${name}:${value}`);
|
|
991
|
+
});
|
|
992
|
+
const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\0"));
|
|
993
|
+
const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
|
|
994
|
+
let wasmMemory = null;
|
|
995
|
+
const setMemory = (m2) => {
|
|
996
|
+
wasmMemory = m2;
|
|
997
|
+
};
|
|
998
|
+
const stdoutChunks = [];
|
|
999
|
+
let stderrMeta = "";
|
|
1000
|
+
let stderrPartial = "";
|
|
1001
|
+
const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
1002
|
+
function processStderrChunk(chunk) {
|
|
1003
|
+
const text = stderrDecoder.decode(chunk, { stream: true });
|
|
1004
|
+
const lines = (stderrPartial + text).split("\n");
|
|
1005
|
+
stderrPartial = lines.pop() ?? "";
|
|
1006
|
+
for (const line of lines) {
|
|
1007
|
+
if (line.startsWith("__ZIEX_META__:")) {
|
|
1008
|
+
stderrMeta += line + "\n";
|
|
1009
|
+
} else if (line.length > 0) {
|
|
1010
|
+
console.error("[ziex]", line);
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1003
1013
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
constructor(options) {
|
|
1008
|
-
this.resolved = null;
|
|
1009
|
-
/**
|
|
1010
|
-
* Fetch handler called by the runtime on every request.
|
|
1011
|
-
*
|
|
1012
|
-
* Arrow function so `this` is always the class instance, even when the
|
|
1013
|
-
* runtime extracts `fetch` from the exported object (e.g. Bun).
|
|
1014
|
-
*/
|
|
1015
|
-
this.fetch = async (request, env, ctx) => {
|
|
1016
|
-
const module = await this.getModule();
|
|
1017
|
-
const { wasi, imports, websocket } = this.options;
|
|
1018
|
-
return run({
|
|
1019
|
-
request,
|
|
1020
|
-
env,
|
|
1021
|
-
ctx,
|
|
1022
|
-
module,
|
|
1023
|
-
wasi,
|
|
1024
|
-
imports,
|
|
1025
|
-
kv: this.resolveKV(env),
|
|
1026
|
-
db: this.resolveDB(env),
|
|
1027
|
-
websocket: websocket !== void 0 ? env[websocket] : void 0
|
|
1028
|
-
});
|
|
1029
|
-
};
|
|
1030
|
-
this.options = options;
|
|
1014
|
+
let stdinOffset = 0;
|
|
1015
|
+
function v() {
|
|
1016
|
+
return new DataView(wasmMemory.buffer);
|
|
1031
1017
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
return this.resolved;
|
|
1018
|
+
function m() {
|
|
1019
|
+
return new Uint8Array(wasmMemory.buffer);
|
|
1035
1020
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1021
|
+
const wasiImport = {
|
|
1022
|
+
args_sizes_get(argc_ptr, argv_buf_size_ptr) {
|
|
1023
|
+
v().setUint32(argc_ptr, encodedArgs.length, true);
|
|
1024
|
+
v().setUint32(argv_buf_size_ptr, argBufSize, true);
|
|
1025
|
+
return 0;
|
|
1026
|
+
},
|
|
1027
|
+
args_get(argv_ptr, argv_buf_ptr) {
|
|
1028
|
+
const dv = v();
|
|
1029
|
+
const mem = m();
|
|
1030
|
+
let offset = argv_buf_ptr;
|
|
1031
|
+
for (const arg of encodedArgs) {
|
|
1032
|
+
dv.setUint32(argv_ptr, offset, true);
|
|
1033
|
+
mem.set(arg, offset);
|
|
1034
|
+
argv_ptr += 4;
|
|
1035
|
+
offset += arg.length;
|
|
1043
1036
|
}
|
|
1044
|
-
return
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1037
|
+
return 0;
|
|
1038
|
+
},
|
|
1039
|
+
environ_sizes_get(count_ptr, buf_size_ptr) {
|
|
1040
|
+
v().setUint32(count_ptr, 0, true);
|
|
1041
|
+
v().setUint32(buf_size_ptr, 0, true);
|
|
1042
|
+
return 0;
|
|
1043
|
+
},
|
|
1044
|
+
environ_get(_environ_ptr, _environ_buf_ptr) {
|
|
1045
|
+
return 0;
|
|
1046
|
+
},
|
|
1047
|
+
fd_write(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
|
1048
|
+
const dv = v();
|
|
1049
|
+
const mem = m();
|
|
1050
|
+
let written = 0;
|
|
1051
|
+
for (let i = 0; i < iovs_len; i++) {
|
|
1052
|
+
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
1053
|
+
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
1054
|
+
const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
|
|
1055
|
+
if (fd === 1) {
|
|
1056
|
+
if (onStdout) onStdout(chunk);
|
|
1057
|
+
else stdoutChunks.push(chunk);
|
|
1058
|
+
} else if (fd === 2) processStderrChunk(chunk);
|
|
1059
|
+
written += buf_len;
|
|
1055
1060
|
}
|
|
1056
|
-
|
|
1061
|
+
dv.setUint32(nwritten_ptr, written, true);
|
|
1062
|
+
return 0;
|
|
1063
|
+
},
|
|
1064
|
+
fd_read(fd, iovs_ptr, iovs_len, nread_ptr) {
|
|
1065
|
+
const dv = v();
|
|
1066
|
+
const mem = m();
|
|
1067
|
+
const stdin = stdinData ?? new Uint8Array(0);
|
|
1068
|
+
let totalRead = 0;
|
|
1069
|
+
for (let i = 0; i < iovs_len; i++) {
|
|
1070
|
+
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
1071
|
+
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
1072
|
+
if (fd === 0 && stdinOffset < stdin.length) {
|
|
1073
|
+
const toRead = Math.min(buf_len, stdin.length - stdinOffset);
|
|
1074
|
+
mem.set(stdin.subarray(stdinOffset, stdinOffset + toRead), buf_ptr);
|
|
1075
|
+
stdinOffset += toRead;
|
|
1076
|
+
totalRead += toRead;
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
dv.setUint32(nread_ptr, totalRead, true);
|
|
1080
|
+
return 0;
|
|
1081
|
+
},
|
|
1082
|
+
fd_fdstat_get(_fd, fdstat_ptr) {
|
|
1083
|
+
const dv = v();
|
|
1084
|
+
dv.setUint8(fdstat_ptr, 2);
|
|
1085
|
+
dv.setUint8(fdstat_ptr + 1, 0);
|
|
1086
|
+
dv.setUint16(fdstat_ptr + 2, 0, true);
|
|
1087
|
+
dv.setUint32(fdstat_ptr + 4, 0, true);
|
|
1088
|
+
dv.setBigUint64(fdstat_ptr + 8, 0n, true);
|
|
1089
|
+
dv.setBigUint64(fdstat_ptr + 16, 0n, true);
|
|
1090
|
+
return 0;
|
|
1091
|
+
},
|
|
1092
|
+
fd_prestat_get(_fd, _bufptr) {
|
|
1093
|
+
return 8;
|
|
1094
|
+
},
|
|
1095
|
+
fd_prestat_dir_name(_fd, _path, _path_len) {
|
|
1096
|
+
return 8;
|
|
1097
|
+
},
|
|
1098
|
+
fd_close(_fd) {
|
|
1099
|
+
return 0;
|
|
1100
|
+
},
|
|
1101
|
+
fd_pread(_fd, _iovs, _iovs_len, _offset, nread_ptr) {
|
|
1102
|
+
v().setUint32(nread_ptr, 0, true);
|
|
1103
|
+
return 0;
|
|
1104
|
+
},
|
|
1105
|
+
fd_pwrite(_fd, _iovs, _iovs_len, _offset, nwritten_ptr) {
|
|
1106
|
+
v().setUint32(nwritten_ptr, 0, true);
|
|
1107
|
+
return 0;
|
|
1108
|
+
},
|
|
1109
|
+
fd_filestat_get(_fd, filestat_ptr) {
|
|
1110
|
+
const dv = v();
|
|
1111
|
+
dv.setBigUint64(filestat_ptr, 0n, true);
|
|
1112
|
+
dv.setBigUint64(filestat_ptr + 8, 0n, true);
|
|
1113
|
+
dv.setUint8(filestat_ptr + 16, 2);
|
|
1114
|
+
dv.setBigUint64(filestat_ptr + 24, 1n, true);
|
|
1115
|
+
dv.setBigUint64(filestat_ptr + 32, 0n, true);
|
|
1116
|
+
dv.setBigUint64(filestat_ptr + 40, 0n, true);
|
|
1117
|
+
dv.setBigUint64(filestat_ptr + 48, 0n, true);
|
|
1118
|
+
dv.setBigUint64(filestat_ptr + 56, 0n, true);
|
|
1119
|
+
return 0;
|
|
1120
|
+
},
|
|
1121
|
+
fd_filestat_set_size(_fd, _size) {
|
|
1122
|
+
return 76;
|
|
1123
|
+
},
|
|
1124
|
+
fd_filestat_set_times(_fd, _atim, _mtim, _fst_flags) {
|
|
1125
|
+
return 76;
|
|
1126
|
+
},
|
|
1127
|
+
fd_fdstat_set_flags(_fd, _flags) {
|
|
1128
|
+
return 0;
|
|
1129
|
+
},
|
|
1130
|
+
fd_fdstat_set_rights(_fd, _rights_base, _rights_inheriting) {
|
|
1131
|
+
return 0;
|
|
1132
|
+
},
|
|
1133
|
+
fd_sync(_fd) {
|
|
1134
|
+
return 0;
|
|
1135
|
+
},
|
|
1136
|
+
fd_datasync(_fd) {
|
|
1137
|
+
return 0;
|
|
1138
|
+
},
|
|
1139
|
+
fd_advise(_fd, _offset, _len, _advice) {
|
|
1140
|
+
return 0;
|
|
1141
|
+
},
|
|
1142
|
+
fd_allocate(_fd, _offset, _len) {
|
|
1143
|
+
return 76;
|
|
1144
|
+
},
|
|
1145
|
+
fd_tell(_fd, offset_ptr) {
|
|
1146
|
+
v().setBigUint64(offset_ptr, 0n, true);
|
|
1147
|
+
return 0;
|
|
1148
|
+
},
|
|
1149
|
+
fd_renumber(_from, _to) {
|
|
1150
|
+
return 0;
|
|
1151
|
+
},
|
|
1152
|
+
path_filestat_set_times(_fd, _flags, _path, _path_len, _atim, _mtim, _fst_flags) {
|
|
1153
|
+
return 76;
|
|
1154
|
+
},
|
|
1155
|
+
path_link(_old_fd, _old_flags, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
|
|
1156
|
+
return 76;
|
|
1157
|
+
},
|
|
1158
|
+
path_symlink(_old_path, _old_path_len, _fd, _new_path, _new_path_len) {
|
|
1159
|
+
return 76;
|
|
1160
|
+
},
|
|
1161
|
+
proc_raise(_sig) {
|
|
1162
|
+
return 0;
|
|
1163
|
+
},
|
|
1164
|
+
sock_recv(_fd, _ri_data, _ri_data_len, _ri_flags, ro_datalen_ptr, ro_flags_ptr) {
|
|
1165
|
+
v().setUint32(ro_datalen_ptr, 0, true);
|
|
1166
|
+
v().setUint32(ro_flags_ptr, 0, true);
|
|
1167
|
+
return 76;
|
|
1168
|
+
},
|
|
1169
|
+
sock_send(_fd, _si_data, _si_data_len, _si_flags, so_datalen_ptr) {
|
|
1170
|
+
v().setUint32(so_datalen_ptr, 0, true);
|
|
1171
|
+
return 76;
|
|
1172
|
+
},
|
|
1173
|
+
sock_shutdown(_fd, _how) {
|
|
1174
|
+
return 76;
|
|
1175
|
+
},
|
|
1176
|
+
fd_seek(_fd, _offset, _whence, newoffset_ptr) {
|
|
1177
|
+
v().setBigInt64(newoffset_ptr, 0n, true);
|
|
1178
|
+
return 0;
|
|
1179
|
+
},
|
|
1180
|
+
proc_exit(code) {
|
|
1181
|
+
throw new ProcExit(code);
|
|
1182
|
+
},
|
|
1183
|
+
sched_yield() {
|
|
1184
|
+
return 0;
|
|
1185
|
+
},
|
|
1186
|
+
clock_time_get(_id, _precision, time_ptr) {
|
|
1187
|
+
v().setBigUint64(time_ptr, BigInt(Date.now()) * 1000000n, true);
|
|
1188
|
+
return 0;
|
|
1189
|
+
},
|
|
1190
|
+
clock_res_get(_id, res_ptr) {
|
|
1191
|
+
v().setBigUint64(res_ptr, 1000000n, true);
|
|
1192
|
+
return 0;
|
|
1193
|
+
},
|
|
1194
|
+
random_get(buf_ptr, buf_len) {
|
|
1195
|
+
crypto.getRandomValues(new Uint8Array(wasmMemory.buffer, buf_ptr, buf_len));
|
|
1196
|
+
return 0;
|
|
1197
|
+
},
|
|
1198
|
+
path_open(_fd, _dirflags, _path, _path_len, _oflags, _rights_base, _rights_inheriting, _fdflags, opened_fd_ptr) {
|
|
1199
|
+
v().setInt32(opened_fd_ptr, -1, true);
|
|
1200
|
+
return 76;
|
|
1201
|
+
},
|
|
1202
|
+
path_create_directory(_fd, _path, _path_len) {
|
|
1203
|
+
return 76;
|
|
1204
|
+
},
|
|
1205
|
+
path_unlink_file(_fd, _path, _path_len) {
|
|
1206
|
+
return 76;
|
|
1207
|
+
},
|
|
1208
|
+
path_remove_directory(_fd, _path, _path_len) {
|
|
1209
|
+
return 76;
|
|
1210
|
+
},
|
|
1211
|
+
path_rename(_fd, _old_path, _old_path_len, _new_fd, _new_path, _new_path_len) {
|
|
1212
|
+
return 76;
|
|
1213
|
+
},
|
|
1214
|
+
path_filestat_get(_fd, _flags, _path, _path_len, filestat_ptr) {
|
|
1215
|
+
new Uint8Array(wasmMemory.buffer, filestat_ptr, 64).fill(0);
|
|
1216
|
+
return 76;
|
|
1217
|
+
},
|
|
1218
|
+
path_readlink(_fd, _path, _path_len, _buf, _buf_len, nread_ptr) {
|
|
1219
|
+
v().setUint32(nread_ptr, 0, true);
|
|
1220
|
+
return 76;
|
|
1221
|
+
},
|
|
1222
|
+
fd_readdir(_fd, _buf, _buf_len, _cookie, bufused_ptr) {
|
|
1223
|
+
v().setUint32(bufused_ptr, 0, true);
|
|
1224
|
+
return 76;
|
|
1225
|
+
},
|
|
1226
|
+
// Stub for poll_oneoff - no blocking I/O in edge runtimes.
|
|
1227
|
+
poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
|
|
1228
|
+
v().setUint32(nevents_ptr, 0, true);
|
|
1229
|
+
return 0;
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
function collectOutput() {
|
|
1233
|
+
const remaining = stderrDecoder.decode(void 0, { stream: false });
|
|
1234
|
+
const tail = stderrPartial + remaining;
|
|
1235
|
+
if (tail.length > 0) {
|
|
1236
|
+
if (tail.startsWith("__ZIEX_META__:")) stderrMeta += tail;
|
|
1237
|
+
else console.error("[ziex]", tail);
|
|
1238
|
+
stderrPartial = "";
|
|
1057
1239
|
}
|
|
1058
|
-
return { default: env[db] };
|
|
1059
|
-
}
|
|
1060
|
-
};
|
|
1061
|
-
|
|
1062
|
-
// ../../vendor/jsz/js/src/zigjs.ts
|
|
1063
|
-
var NAN_PREFIX = 2146959360;
|
|
1064
|
-
var predefined = {
|
|
1065
|
-
"nan": 0,
|
|
1066
|
-
"null": 1,
|
|
1067
|
-
"true": 2,
|
|
1068
|
-
"false": 3,
|
|
1069
|
-
"undefined": 4,
|
|
1070
|
-
"globalThis": 5,
|
|
1071
|
-
"runtime": 6
|
|
1072
|
-
};
|
|
1073
|
-
var PREDEFINED_ID_MAX = 6;
|
|
1074
|
-
var encoder2 = new TextEncoder();
|
|
1075
|
-
var decoder2 = new TextDecoder("utf-8");
|
|
1076
|
-
var ZigJS = class {
|
|
1077
|
-
constructor() {
|
|
1078
|
-
/**
|
|
1079
|
-
* The values, indexed by ID (number). Duplicate values can be in this
|
|
1080
|
-
* if they are loaded multiple times. That just acts as duplicate references.
|
|
1081
|
-
* */
|
|
1082
|
-
this.values = [NaN, null, true, false, void 0, globalThis, this];
|
|
1083
|
-
/**
|
|
1084
|
-
* When a value is removed from the values array, its ID is put
|
|
1085
|
-
* in the pool so that we can use it next. This avoids fragmentation in
|
|
1086
|
-
* our array keys.
|
|
1087
|
-
* */
|
|
1088
|
-
this.idPool = [];
|
|
1089
|
-
}
|
|
1090
|
-
/**
|
|
1091
|
-
* Returns the import object that should be merged with your import
|
|
1092
|
-
* object when instantiating your wasm instance. This injects the required
|
|
1093
|
-
* functions into the wasm environment.
|
|
1094
|
-
* */
|
|
1095
|
-
importObject() {
|
|
1096
1240
|
return {
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
valueSet: this.valueSet.bind(this),
|
|
1100
|
-
valueDeinit: this.valueDeinit.bind(this),
|
|
1101
|
-
valueObjectCreate: this.valueObjectCreate.bind(this),
|
|
1102
|
-
valueStringCreate: this.valueStringCreate.bind(this),
|
|
1103
|
-
valueStringLen: this.valueStringLen.bind(this),
|
|
1104
|
-
valueStringCopy: this.valueStringCopy.bind(this),
|
|
1105
|
-
valueNew: this.valueNew.bind(this),
|
|
1106
|
-
funcApply: this.funcApply.bind(this)
|
|
1107
|
-
}
|
|
1241
|
+
stdout: mergeUint8Arrays(stdoutChunks),
|
|
1242
|
+
stderrText: stderrMeta
|
|
1108
1243
|
};
|
|
1109
1244
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
/**
|
|
1120
|
-
* Set a value on an object.
|
|
1121
|
-
* */
|
|
1122
|
-
valueSet(id, ptr, len, refAddr) {
|
|
1123
|
-
const obj = this.loadValue(id);
|
|
1124
|
-
const str = this.loadString(ptr, len);
|
|
1125
|
-
const val = this.loadRef(refAddr);
|
|
1126
|
-
Reflect.set(obj, str, val);
|
|
1127
|
-
}
|
|
1128
|
-
/**
|
|
1129
|
-
* Dereference a value, allowing the JS environment to potentially GC it.
|
|
1130
|
-
* */
|
|
1131
|
-
valueDeinit(id) {
|
|
1132
|
-
if (id > PREDEFINED_ID_MAX) {
|
|
1133
|
-
this.values[id] = null;
|
|
1134
|
-
this.idPool.push(id);
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
/**
|
|
1138
|
-
* Create an empty object.
|
|
1139
|
-
* */
|
|
1140
|
-
valueObjectCreate(out) {
|
|
1141
|
-
this.storeValue(out, new Object());
|
|
1142
|
-
}
|
|
1143
|
-
/**
|
|
1144
|
-
* Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
|
|
1145
|
-
* */
|
|
1146
|
-
valueStringCreate(out, ptr, len) {
|
|
1147
|
-
const str = this.loadString(ptr, len);
|
|
1148
|
-
this.storeValue(out, str);
|
|
1149
|
-
}
|
|
1150
|
-
/**
|
|
1151
|
-
* Returns the length of the string given by id.
|
|
1152
|
-
* */
|
|
1153
|
-
valueStringLen(id) {
|
|
1154
|
-
const val = this.loadValue(id);
|
|
1155
|
-
const buf = encoder2.encode(val);
|
|
1156
|
-
return buf.byteLength;
|
|
1157
|
-
}
|
|
1158
|
-
/**
|
|
1159
|
-
* Copy the string at id "id" into the shared memory at ptr.
|
|
1160
|
-
* */
|
|
1161
|
-
valueStringCopy(id, ptr, max) {
|
|
1162
|
-
if (this.memory == null) return;
|
|
1163
|
-
const val = this.loadValue(id);
|
|
1164
|
-
const bytes = encoder2.encode(val);
|
|
1165
|
-
if (bytes.byteLength > max) return;
|
|
1166
|
-
if (bytes.length === 0) return;
|
|
1167
|
-
new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
|
|
1245
|
+
return { wasiImport, setMemory, collectOutput };
|
|
1246
|
+
}
|
|
1247
|
+
function mergeUint8Arrays(arrays) {
|
|
1248
|
+
const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
1249
|
+
const result = new Uint8Array(totalLen);
|
|
1250
|
+
let offset = 0;
|
|
1251
|
+
for (const arr of arrays) {
|
|
1252
|
+
result.set(arr, offset);
|
|
1253
|
+
offset += arr.length;
|
|
1168
1254
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1255
|
+
return result;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// src/runtime/kv.ts
|
|
1259
|
+
var kv_exports = {};
|
|
1260
|
+
__export(kv_exports, {
|
|
1261
|
+
createBrowserKVBindings: () => createBrowserKVBindings,
|
|
1262
|
+
createIndexedDbKV: () => createIndexedDbKV,
|
|
1263
|
+
createKVImports: () => createKVImports,
|
|
1264
|
+
createLocalStorageKV: () => createLocalStorageKV,
|
|
1265
|
+
createMemoryKV: () => createMemoryKV,
|
|
1266
|
+
hasJSPI: () => hasJSPI
|
|
1267
|
+
});
|
|
1268
|
+
|
|
1269
|
+
// src/runtime/kv/memory.ts
|
|
1270
|
+
function createMemoryKV() {
|
|
1271
|
+
const store = /* @__PURE__ */ new Map();
|
|
1272
|
+
function read(key) {
|
|
1273
|
+
const entry = store.get(key);
|
|
1274
|
+
if (!entry) return null;
|
|
1275
|
+
const expiresAt = entry[1];
|
|
1276
|
+
if (expiresAt !== void 0 && Date.now() >= expiresAt) {
|
|
1277
|
+
store.delete(key);
|
|
1278
|
+
return null;
|
|
1177
1279
|
}
|
|
1178
|
-
|
|
1179
|
-
this.storeValue(out, result);
|
|
1280
|
+
return entry[0];
|
|
1180
1281
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
const args = [];
|
|
1188
|
-
for (let i = 0; i < argsLen; i++) {
|
|
1189
|
-
args.push(this.loadRef(argsAddr + i * 8));
|
|
1282
|
+
function write(key, value, options) {
|
|
1283
|
+
let expiresAt;
|
|
1284
|
+
if (options?.expiration !== void 0) {
|
|
1285
|
+
expiresAt = options.expiration * 1e3;
|
|
1286
|
+
} else if (options?.expirationTtl !== void 0) {
|
|
1287
|
+
expiresAt = Date.now() + options.expirationTtl * 1e3;
|
|
1190
1288
|
}
|
|
1191
|
-
|
|
1192
|
-
this.storeValue(out, result);
|
|
1193
|
-
}
|
|
1194
|
-
/**
|
|
1195
|
-
* This can be used to load a value given by an ID. A WASM function
|
|
1196
|
-
* might return a value as an ID. This can be used to retrieve it.
|
|
1197
|
-
* */
|
|
1198
|
-
loadValue(id) {
|
|
1199
|
-
return this.values[id];
|
|
1200
|
-
}
|
|
1201
|
-
/**
|
|
1202
|
-
* This removes the value from the values list and returns it. This
|
|
1203
|
-
* will not remove predefined values but can still be used to retrieve
|
|
1204
|
-
* them.
|
|
1205
|
-
* */
|
|
1206
|
-
deleteValue(id) {
|
|
1207
|
-
const val = this.values[id];
|
|
1208
|
-
this.valueDeinit(id);
|
|
1209
|
-
return val;
|
|
1210
|
-
}
|
|
1211
|
-
loadRef(refAddr) {
|
|
1212
|
-
if (this.memory == null) return;
|
|
1213
|
-
const view = new DataView(this.memory.buffer);
|
|
1214
|
-
const floatVal = view.getFloat64(refAddr, true);
|
|
1215
|
-
if (!isNaN(floatVal)) return floatVal;
|
|
1216
|
-
const id = this.loadRefId(refAddr);
|
|
1217
|
-
return this.values[id];
|
|
1289
|
+
store.set(key, [value, expiresAt]);
|
|
1218
1290
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
if (val === null) {
|
|
1236
|
-
view.setUint32(out, predefined.null, true);
|
|
1237
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1238
|
-
return;
|
|
1239
|
-
}
|
|
1240
|
-
if (val === void 0) {
|
|
1241
|
-
view.setUint32(out, predefined.undefined, true);
|
|
1242
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1243
|
-
return;
|
|
1244
|
-
}
|
|
1245
|
-
if (typeof val === "boolean") {
|
|
1246
|
-
view.setUint32(out, val ? predefined.true : predefined.false, true);
|
|
1247
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1248
|
-
return;
|
|
1249
|
-
}
|
|
1250
|
-
if (typeof val === "bigint") {
|
|
1251
|
-
view.setFloat64(out, Number(val), true);
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
let id = this.idPool.pop();
|
|
1255
|
-
if (id === void 0) {
|
|
1256
|
-
id = this.values.length;
|
|
1257
|
-
}
|
|
1258
|
-
this.values[id] = val;
|
|
1259
|
-
let typeId = 0;
|
|
1260
|
-
switch (typeof val) {
|
|
1261
|
-
case "object":
|
|
1262
|
-
typeId = 1;
|
|
1263
|
-
break;
|
|
1264
|
-
case "string":
|
|
1265
|
-
typeId = 2;
|
|
1266
|
-
break;
|
|
1267
|
-
case "symbol":
|
|
1268
|
-
typeId = 3;
|
|
1269
|
-
break;
|
|
1270
|
-
case "function":
|
|
1271
|
-
typeId = 4;
|
|
1272
|
-
break;
|
|
1291
|
+
return {
|
|
1292
|
+
async get(key) {
|
|
1293
|
+
return read(key);
|
|
1294
|
+
},
|
|
1295
|
+
async put(key, value, options) {
|
|
1296
|
+
write(key, value, options);
|
|
1297
|
+
},
|
|
1298
|
+
async delete(key) {
|
|
1299
|
+
store.delete(key);
|
|
1300
|
+
},
|
|
1301
|
+
async list(options) {
|
|
1302
|
+
const keys = [...store.keys()].filter((k) => {
|
|
1303
|
+
if (options?.prefix && !k.startsWith(options.prefix)) return false;
|
|
1304
|
+
return read(k) !== null;
|
|
1305
|
+
}).map((name) => ({ name }));
|
|
1306
|
+
return { keys };
|
|
1273
1307
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
loadString(ptr, len) {
|
|
1278
|
-
if (this.memory == null) return "";
|
|
1279
|
-
const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
|
|
1280
|
-
const data = arr.slice();
|
|
1281
|
-
return decoder2.decode(data);
|
|
1282
|
-
}
|
|
1283
|
-
};
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1284
1310
|
|
|
1285
|
-
// src/
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
Interval: 4,
|
|
1292
|
-
WebSocketOpen: 5,
|
|
1293
|
-
WebSocketMessage: 6,
|
|
1294
|
-
WebSocketError: 7,
|
|
1295
|
-
WebSocketClose: 8
|
|
1296
|
-
};
|
|
1297
|
-
var jsz = new ZigJS();
|
|
1298
|
-
var tempRefBuffer = new ArrayBuffer(8);
|
|
1299
|
-
var tempRefView = new DataView(tempRefBuffer);
|
|
1300
|
-
function storeValueGetRef(val) {
|
|
1301
|
-
const originalMemory = jsz.memory;
|
|
1302
|
-
jsz.memory = { buffer: tempRefBuffer };
|
|
1303
|
-
jsz.storeValue(0, val);
|
|
1304
|
-
jsz.memory = originalMemory;
|
|
1305
|
-
return tempRefView.getBigUint64(0, true);
|
|
1311
|
+
// src/runtime/kv/localstorage.ts
|
|
1312
|
+
function getLocalStorage() {
|
|
1313
|
+
if (typeof localStorage === "undefined") {
|
|
1314
|
+
throw new Error("localStorage is not available in this environment");
|
|
1315
|
+
}
|
|
1316
|
+
return localStorage;
|
|
1306
1317
|
}
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
const
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1318
|
+
function createLocalStorageKV(options = {}) {
|
|
1319
|
+
const storage = getLocalStorage();
|
|
1320
|
+
const namespace = options.namespace ?? "default";
|
|
1321
|
+
const storagePrefix = options.storagePrefix ?? "ziex-kv";
|
|
1322
|
+
const scopedKey = (key) => `${storagePrefix}:${namespace}:${key}`;
|
|
1323
|
+
const namespacePrefix = scopedKey("");
|
|
1324
|
+
return {
|
|
1325
|
+
getSync(key) {
|
|
1326
|
+
return storage.getItem(scopedKey(key));
|
|
1327
|
+
},
|
|
1328
|
+
async get(key) {
|
|
1329
|
+
return this.getSync(key);
|
|
1330
|
+
},
|
|
1331
|
+
putSync(key, value) {
|
|
1332
|
+
storage.setItem(scopedKey(key), value);
|
|
1333
|
+
},
|
|
1334
|
+
async put(key, value) {
|
|
1335
|
+
this.putSync(key, value);
|
|
1336
|
+
},
|
|
1337
|
+
deleteSync(key) {
|
|
1338
|
+
storage.removeItem(scopedKey(key));
|
|
1339
|
+
},
|
|
1340
|
+
async delete(key) {
|
|
1341
|
+
this.deleteSync(key);
|
|
1342
|
+
},
|
|
1343
|
+
listSync(options2) {
|
|
1344
|
+
const prefix = namespacePrefix + (options2?.prefix ?? "");
|
|
1345
|
+
const keys = [];
|
|
1346
|
+
for (let i = 0; i < storage.length; i += 1) {
|
|
1347
|
+
const key = storage.key(i);
|
|
1348
|
+
if (!key || !key.startsWith(prefix)) continue;
|
|
1349
|
+
keys.push({ name: key.slice(namespacePrefix.length) });
|
|
1350
|
+
}
|
|
1351
|
+
return { keys };
|
|
1352
|
+
},
|
|
1353
|
+
async list(options2) {
|
|
1354
|
+
return this.listSync(options2);
|
|
1355
|
+
}
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
// src/runtime/kv/indexdb.ts
|
|
1360
|
+
function getIndexedDb() {
|
|
1361
|
+
if (typeof indexedDB === "undefined") {
|
|
1362
|
+
throw new Error("IndexedDB is not available in this environment");
|
|
1316
1363
|
}
|
|
1317
|
-
return
|
|
1364
|
+
return indexedDB;
|
|
1318
1365
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1366
|
+
function requestToPromise(request) {
|
|
1367
|
+
return new Promise((resolve, reject) => {
|
|
1368
|
+
request.onsuccess = () => resolve(request.result);
|
|
1369
|
+
request.onerror = () => reject(request.error ?? new Error("IndexedDB request failed"));
|
|
1370
|
+
});
|
|
1322
1371
|
}
|
|
1323
|
-
function
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
return str;
|
|
1372
|
+
function transactionToPromise(transaction) {
|
|
1373
|
+
return new Promise((resolve, reject) => {
|
|
1374
|
+
transaction.oncomplete = () => resolve();
|
|
1375
|
+
transaction.onabort = () => reject(transaction.error ?? new Error("IndexedDB transaction aborted"));
|
|
1376
|
+
transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB transaction failed"));
|
|
1377
|
+
});
|
|
1330
1378
|
}
|
|
1331
|
-
function
|
|
1332
|
-
|
|
1379
|
+
function createIndexedDbKV(options = {}) {
|
|
1380
|
+
const databaseName = options.databaseName ?? "ziex-kv";
|
|
1381
|
+
const storeName = options.storeName ?? "kv";
|
|
1382
|
+
const namespace = options.namespace ?? "default";
|
|
1383
|
+
const dbPromise = new Promise((resolve, reject) => {
|
|
1384
|
+
const request = getIndexedDb().open(databaseName, 1);
|
|
1385
|
+
request.onupgradeneeded = () => {
|
|
1386
|
+
const db = request.result;
|
|
1387
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
1388
|
+
db.createObjectStore(storeName);
|
|
1389
|
+
}
|
|
1390
|
+
};
|
|
1391
|
+
request.onsuccess = () => resolve(request.result);
|
|
1392
|
+
request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
|
|
1393
|
+
});
|
|
1394
|
+
const scopedKey = (key) => `${namespace}:${key}`;
|
|
1395
|
+
return {
|
|
1396
|
+
async get(key) {
|
|
1397
|
+
const db = await dbPromise;
|
|
1398
|
+
const tx = db.transaction(storeName, "readonly");
|
|
1399
|
+
const store = tx.objectStore(storeName);
|
|
1400
|
+
const value = await requestToPromise(store.get(scopedKey(key)));
|
|
1401
|
+
await transactionToPromise(tx);
|
|
1402
|
+
return typeof value === "string" ? value : null;
|
|
1403
|
+
},
|
|
1404
|
+
async put(key, value) {
|
|
1405
|
+
const db = await dbPromise;
|
|
1406
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1407
|
+
tx.objectStore(storeName).put(value, scopedKey(key));
|
|
1408
|
+
await transactionToPromise(tx);
|
|
1409
|
+
},
|
|
1410
|
+
async delete(key) {
|
|
1411
|
+
const db = await dbPromise;
|
|
1412
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
1413
|
+
tx.objectStore(storeName).delete(scopedKey(key));
|
|
1414
|
+
await transactionToPromise(tx);
|
|
1415
|
+
},
|
|
1416
|
+
async list(options2) {
|
|
1417
|
+
const db = await dbPromise;
|
|
1418
|
+
const tx = db.transaction(storeName, "readonly");
|
|
1419
|
+
const store = tx.objectStore(storeName);
|
|
1420
|
+
const keys = await requestToPromise(store.getAllKeys());
|
|
1421
|
+
await transactionToPromise(tx);
|
|
1422
|
+
const prefix = scopedKey(options2?.prefix ?? "");
|
|
1423
|
+
return {
|
|
1424
|
+
keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
|
|
1425
|
+
};
|
|
1426
|
+
}
|
|
1427
|
+
};
|
|
1333
1428
|
}
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
return promising(fn);
|
|
1429
|
+
|
|
1430
|
+
// src/runtime/kv.ts
|
|
1431
|
+
function hasJSPI() {
|
|
1432
|
+
return typeof WebAssembly.Suspending === "function" && typeof WebAssembly.promising === "function";
|
|
1339
1433
|
}
|
|
1340
|
-
function
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
console.error(error);
|
|
1346
|
-
});
|
|
1347
|
-
}
|
|
1434
|
+
function createBrowserKVBindings(options = {}) {
|
|
1435
|
+
const namespace = options.namespace ?? "default";
|
|
1436
|
+
return {
|
|
1437
|
+
[namespace]: hasJSPI() ? createIndexedDbKV(options) : createLocalStorageKV(options)
|
|
1438
|
+
};
|
|
1348
1439
|
}
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1440
|
+
|
|
1441
|
+
// src/runtime/index.ts
|
|
1442
|
+
function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
1443
|
+
const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
1444
|
+
return {
|
|
1445
|
+
ws_upgrade: () => {
|
|
1446
|
+
ws.upgraded = true;
|
|
1447
|
+
},
|
|
1448
|
+
ws_write: (ptr, len) => {
|
|
1449
|
+
const data = new Uint8Array(mem().buffer, ptr, len).slice();
|
|
1450
|
+
if (!ws.server) {
|
|
1451
|
+
ws.pendingWrites.push(data);
|
|
1452
|
+
} else {
|
|
1453
|
+
ws.server.send(data);
|
|
1454
|
+
}
|
|
1455
|
+
},
|
|
1456
|
+
ws_close: (code, reason_ptr, reason_len) => {
|
|
1457
|
+
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
1458
|
+
},
|
|
1459
|
+
ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
|
|
1460
|
+
if (ws._resolveFirstSuspend) {
|
|
1461
|
+
const fn = ws._resolveFirstSuspend;
|
|
1462
|
+
ws._resolveFirstSuspend = void 0;
|
|
1463
|
+
fn();
|
|
1464
|
+
}
|
|
1465
|
+
const deliver = (bytes) => {
|
|
1466
|
+
if (bytes === null) return -1;
|
|
1467
|
+
const n = Math.min(bytes.length, buf_max);
|
|
1468
|
+
new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
|
|
1469
|
+
return n;
|
|
1470
|
+
};
|
|
1471
|
+
if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
|
|
1472
|
+
return new Promise((resolve) => {
|
|
1473
|
+
ws.recvResolve = (bytes) => resolve(deliver(bytes));
|
|
1474
|
+
});
|
|
1475
|
+
}) : (_buf_ptr, _buf_max) => -1,
|
|
1476
|
+
// Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
|
|
1477
|
+
ws_subscribe: (ptr, len) => {
|
|
1478
|
+
ws.subscribe?.(readStr(ptr, len));
|
|
1479
|
+
},
|
|
1480
|
+
ws_unsubscribe: (ptr, len) => {
|
|
1481
|
+
ws.unsubscribe?.(readStr(ptr, len));
|
|
1482
|
+
},
|
|
1483
|
+
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
1484
|
+
const topic = readStr(topic_ptr, topic_len);
|
|
1485
|
+
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
1486
|
+
return ws.publish?.(topic, data) ?? 0;
|
|
1487
|
+
},
|
|
1488
|
+
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
function attachWebSocket(ws) {
|
|
1492
|
+
const WebSocketPairCtor = globalThis.WebSocketPair;
|
|
1493
|
+
const pair = new WebSocketPairCtor();
|
|
1494
|
+
const client = pair[0];
|
|
1495
|
+
const server = pair[1];
|
|
1496
|
+
ws.server = server;
|
|
1497
|
+
server.accept();
|
|
1498
|
+
for (const data of ws.pendingWrites) server.send(data);
|
|
1499
|
+
ws.pendingWrites = [];
|
|
1500
|
+
server.addEventListener("message", (event) => {
|
|
1501
|
+
const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
|
|
1502
|
+
if (ws.recvResolve) {
|
|
1503
|
+
const res = ws.recvResolve;
|
|
1504
|
+
ws.recvResolve = null;
|
|
1505
|
+
res(data);
|
|
1506
|
+
} else {
|
|
1507
|
+
ws.messageQueue.push(data);
|
|
1359
1508
|
}
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
if (!handler) {
|
|
1367
|
-
console.warn("__zx_cb not exported from WASM");
|
|
1368
|
-
return;
|
|
1509
|
+
});
|
|
1510
|
+
server.addEventListener("close", () => {
|
|
1511
|
+
if (ws.recvResolve) {
|
|
1512
|
+
const res = ws.recvResolve;
|
|
1513
|
+
ws.recvResolve = null;
|
|
1514
|
+
res(null);
|
|
1369
1515
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1516
|
+
});
|
|
1517
|
+
return { client };
|
|
1518
|
+
}
|
|
1519
|
+
function buildSysImports(jspi, Suspending) {
|
|
1520
|
+
return {
|
|
1521
|
+
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
|
|
1522
|
+
}
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
function executeWasm(instance, jspi, Suspending, wsState) {
|
|
1526
|
+
if (!jspi) {
|
|
1527
|
+
try {
|
|
1528
|
+
instance.exports._start();
|
|
1529
|
+
} catch (e) {
|
|
1530
|
+
if (!(e instanceof ProcExit)) throw e;
|
|
1531
|
+
}
|
|
1532
|
+
return Promise.resolve();
|
|
1372
1533
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1534
|
+
const start = WebAssembly.promising(instance.exports._start);
|
|
1535
|
+
return start().catch((e) => {
|
|
1536
|
+
if (e instanceof Error && e.message.startsWith("proc_exit")) return;
|
|
1537
|
+
throw e;
|
|
1538
|
+
}).finally(() => {
|
|
1539
|
+
if (wsState.recvResolve) {
|
|
1540
|
+
const res = wsState.recvResolve;
|
|
1541
|
+
wsState.recvResolve = null;
|
|
1542
|
+
res(null);
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
function parseZiexMeta(stderrText) {
|
|
1547
|
+
const meta = { status: 200, headers: new Headers(), streaming: false };
|
|
1548
|
+
const metaPrefix = "__ZIEX_META__:";
|
|
1549
|
+
const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
|
|
1550
|
+
if (metaLine) {
|
|
1383
1551
|
try {
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
headers
|
|
1552
|
+
const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
|
|
1553
|
+
if (parsed.status) meta.status = parsed.status;
|
|
1554
|
+
if (parsed.streaming === true) meta.streaming = true;
|
|
1555
|
+
if (Array.isArray(parsed.headers)) {
|
|
1556
|
+
for (const [name, value] of parsed.headers) {
|
|
1557
|
+
meta.headers.append(name, value);
|
|
1390
1558
|
}
|
|
1391
1559
|
}
|
|
1560
|
+
} catch {
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return meta;
|
|
1564
|
+
}
|
|
1565
|
+
async function run({
|
|
1566
|
+
request,
|
|
1567
|
+
env,
|
|
1568
|
+
ctx,
|
|
1569
|
+
module,
|
|
1570
|
+
kv: kvBindings,
|
|
1571
|
+
db: dbBindings,
|
|
1572
|
+
imports,
|
|
1573
|
+
wasi,
|
|
1574
|
+
websocket: doNamespace
|
|
1575
|
+
}) {
|
|
1576
|
+
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
1577
|
+
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
1578
|
+
return doNamespace.get(id).fetch(request);
|
|
1579
|
+
}
|
|
1580
|
+
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
|
|
1581
|
+
const stdoutChunks = [];
|
|
1582
|
+
let streamWriter = null;
|
|
1583
|
+
const { wasiImport, setMemory, collectOutput } = createWasiImports({
|
|
1584
|
+
request,
|
|
1585
|
+
stdinData,
|
|
1586
|
+
onStdout: (chunk) => {
|
|
1587
|
+
if (streamWriter) void streamWriter.write(chunk);
|
|
1588
|
+
else stdoutChunks.push(chunk);
|
|
1392
1589
|
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1590
|
+
});
|
|
1591
|
+
let wasmMemory = null;
|
|
1592
|
+
const mem = () => wasmMemory;
|
|
1593
|
+
const bridgeRef = [null];
|
|
1594
|
+
const allocRef = [null];
|
|
1595
|
+
const Suspending = WebAssembly.Suspending;
|
|
1596
|
+
const jspi = typeof Suspending === "function";
|
|
1597
|
+
const wsState = {
|
|
1598
|
+
upgraded: false,
|
|
1599
|
+
server: null,
|
|
1600
|
+
pendingWrites: [],
|
|
1601
|
+
messageQueue: [],
|
|
1602
|
+
recvResolve: null
|
|
1603
|
+
};
|
|
1604
|
+
const importObject = {
|
|
1605
|
+
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
1606
|
+
__zx_sys: buildSysImports(jspi, Suspending),
|
|
1607
|
+
__zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder(), wsState),
|
|
1608
|
+
__zx_net: createFetchImports(mem),
|
|
1609
|
+
...imports ? imports(mem) : {},
|
|
1610
|
+
...ZxWasiBridge.createImportObject(bridgeRef)
|
|
1611
|
+
};
|
|
1612
|
+
if (true) {
|
|
1613
|
+
importObject.__zx_kv = createKVImports(
|
|
1614
|
+
kvBindings ?? { default: createMemoryKV() },
|
|
1615
|
+
mem,
|
|
1616
|
+
allocRef
|
|
1617
|
+
);
|
|
1411
1618
|
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
1619
|
+
if (true) {
|
|
1620
|
+
importObject.__zx_db = createDbImports(
|
|
1621
|
+
dbBindings ?? {},
|
|
1622
|
+
mem,
|
|
1623
|
+
allocRef
|
|
1624
|
+
);
|
|
1419
1625
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1626
|
+
const instance = new WebAssembly.Instance(module, importObject);
|
|
1627
|
+
wasmMemory = instance.exports.memory;
|
|
1628
|
+
setMemory(wasmMemory);
|
|
1629
|
+
bridgeRef[0] = new ZxWasiBridge(instance.exports);
|
|
1630
|
+
bindWasmAlloc(allocRef, instance.exports);
|
|
1631
|
+
const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
|
|
1632
|
+
if (wsState.upgraded) {
|
|
1633
|
+
const server = attachWebSocket(wsState);
|
|
1634
|
+
ctx?.waitUntil(wasmPromise);
|
|
1635
|
+
return new Response(null, { status: 101, webSocket: server.client });
|
|
1425
1636
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1637
|
+
const { stderrText: earlyStderrText } = collectOutput();
|
|
1638
|
+
const earlyMeta = parseZiexMeta(earlyStderrText);
|
|
1639
|
+
if (earlyMeta.streaming) {
|
|
1640
|
+
const { readable, writable } = new TransformStream();
|
|
1641
|
+
streamWriter = writable.getWriter();
|
|
1642
|
+
for (const chunk of stdoutChunks) void streamWriter.write(chunk);
|
|
1643
|
+
stdoutChunks.length = 0;
|
|
1644
|
+
void wasmPromise.finally(() => streamWriter?.close());
|
|
1645
|
+
return new Response(readable, { status: earlyMeta.status, headers: earlyMeta.headers });
|
|
1432
1646
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1647
|
+
await wasmPromise;
|
|
1648
|
+
const { stderrText } = collectOutput();
|
|
1649
|
+
const meta = parseZiexMeta(stderrText);
|
|
1650
|
+
const body = mergeUint8Arrays(stdoutChunks);
|
|
1651
|
+
meta.headers.delete("transfer-encoding");
|
|
1652
|
+
const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
|
|
1653
|
+
if (nullBody) {
|
|
1654
|
+
meta.headers.delete("content-length");
|
|
1655
|
+
return new Response(null, { status: meta.status, headers: meta.headers });
|
|
1440
1656
|
}
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1657
|
+
if (!meta.headers.has("content-length")) meta.headers.set("content-length", String(body.byteLength));
|
|
1658
|
+
return new Response(body.buffer, { status: meta.status, headers: meta.headers });
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
// src/app.ts
|
|
1662
|
+
async function resolveModule(input) {
|
|
1663
|
+
if (typeof input === "string") {
|
|
1664
|
+
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
1665
|
+
return WebAssembly.compileStreaming(fetch(input));
|
|
1444
1666
|
}
|
|
1445
|
-
|
|
1667
|
+
const url = input.startsWith("/") ? `file://${input}` : input;
|
|
1668
|
+
return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
|
|
1446
1669
|
}
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
return this._writeBytesToWasm(textEncoder.encode(str));
|
|
1670
|
+
if (input instanceof URL) {
|
|
1671
|
+
return WebAssembly.compileStreaming(fetch(input));
|
|
1450
1672
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
writeBytes(ptr, data);
|
|
1454
|
-
return { ptr, len: data.length };
|
|
1673
|
+
if (input instanceof Response) {
|
|
1674
|
+
return WebAssembly.compileStreaming(input);
|
|
1455
1675
|
}
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1676
|
+
if (input instanceof ArrayBuffer) {
|
|
1677
|
+
return WebAssembly.compile(input);
|
|
1678
|
+
}
|
|
1679
|
+
if (ArrayBuffer.isView(input)) {
|
|
1680
|
+
return WebAssembly.compile(input.buffer);
|
|
1681
|
+
}
|
|
1682
|
+
return input;
|
|
1683
|
+
}
|
|
1684
|
+
var Ziex = class {
|
|
1685
|
+
constructor(options) {
|
|
1686
|
+
this.resolved = null;
|
|
1687
|
+
/**
|
|
1688
|
+
* Fetch handler called by the runtime on every request.
|
|
1689
|
+
*
|
|
1690
|
+
* Arrow function so `this` is always the class instance, even when the
|
|
1691
|
+
* runtime extracts `fetch` from the exported object (e.g. Bun).
|
|
1692
|
+
*/
|
|
1693
|
+
this.fetch = async (request, env, ctx) => {
|
|
1694
|
+
const module = await this.getModule();
|
|
1695
|
+
const { wasi, imports, websocket } = this.options;
|
|
1696
|
+
return run({
|
|
1697
|
+
request,
|
|
1698
|
+
env,
|
|
1699
|
+
ctx,
|
|
1700
|
+
module,
|
|
1701
|
+
wasi,
|
|
1702
|
+
imports,
|
|
1703
|
+
kv: this.resolveKV(env),
|
|
1704
|
+
db: this.resolveDB(env),
|
|
1705
|
+
websocket: websocket !== void 0 ? env[websocket] : void 0
|
|
1706
|
+
});
|
|
1707
|
+
};
|
|
1708
|
+
this.options = options;
|
|
1709
|
+
}
|
|
1710
|
+
async getModule() {
|
|
1711
|
+
if (!this.resolved) this.resolved = await resolveModule(this.options.module);
|
|
1712
|
+
return this.resolved;
|
|
1713
|
+
}
|
|
1714
|
+
resolveKV(env) {
|
|
1715
|
+
const { kv } = this.options;
|
|
1716
|
+
if (kv === void 0) return void 0;
|
|
1717
|
+
if (typeof kv === "object" && kv !== null) {
|
|
1718
|
+
const result = {};
|
|
1719
|
+
for (const [name, key] of Object.entries(kv)) {
|
|
1720
|
+
result[name] = env[key];
|
|
1721
|
+
}
|
|
1722
|
+
return result;
|
|
1472
1723
|
}
|
|
1724
|
+
return { default: env[kv] };
|
|
1473
1725
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
return {
|
|
1482
|
-
...jsz.importObject(),
|
|
1483
|
-
__zx_net: createFetchImports(() => {
|
|
1484
|
-
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
1485
|
-
return jsz.memory;
|
|
1486
|
-
}),
|
|
1487
|
-
__zx: {
|
|
1488
|
-
_log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
|
|
1489
|
-
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1490
|
-
bridgeRef.current?.fetchAsync(
|
|
1491
|
-
urlPtr,
|
|
1492
|
-
urlLen,
|
|
1493
|
-
methodPtr,
|
|
1494
|
-
methodLen,
|
|
1495
|
-
headersPtr,
|
|
1496
|
-
headersLen,
|
|
1497
|
-
bodyPtr,
|
|
1498
|
-
bodyLen,
|
|
1499
|
-
timeoutMs,
|
|
1500
|
-
fetchId
|
|
1501
|
-
);
|
|
1502
|
-
},
|
|
1503
|
-
_setTimeout: (callbackId, delayMs) => {
|
|
1504
|
-
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
1505
|
-
},
|
|
1506
|
-
_setInterval: (callbackId, intervalMs) => {
|
|
1507
|
-
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
1508
|
-
},
|
|
1509
|
-
_clearInterval: (callbackId) => {
|
|
1510
|
-
bridgeRef.current?.clearInterval(callbackId);
|
|
1511
|
-
}
|
|
1726
|
+
resolveDB(env) {
|
|
1727
|
+
const { db } = this.options;
|
|
1728
|
+
if (db === void 0) return void 0;
|
|
1729
|
+
if (typeof db === "object" && db !== null) {
|
|
1730
|
+
const result = {};
|
|
1731
|
+
for (const [name, key] of Object.entries(db)) {
|
|
1732
|
+
result[name] = env[key];
|
|
1512
1733
|
}
|
|
1513
|
-
|
|
1734
|
+
return result;
|
|
1735
|
+
}
|
|
1736
|
+
return { default: env[db] };
|
|
1514
1737
|
}
|
|
1515
1738
|
};
|
|
1516
1739
|
|
|
@@ -1534,18 +1757,29 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1534
1757
|
exports.__zx_eventbridge_async ?? exports.__zx_eventbridge
|
|
1535
1758
|
);
|
|
1536
1759
|
}
|
|
1760
|
+
hasEventHandler(velementId, eventTypeId) {
|
|
1761
|
+
return !!((eventHandlersPresent.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
1762
|
+
}
|
|
1537
1763
|
eventMaySuspend(velementId, eventTypeId) {
|
|
1538
|
-
return !!((
|
|
1764
|
+
return !!((eventHandlersSuspend.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
1539
1765
|
}
|
|
1540
1766
|
setEventHandlerMode(velementId, eventTypeId, maySuspend) {
|
|
1541
1767
|
const bit = 1 << eventTypeId;
|
|
1542
|
-
const
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1768
|
+
const present = (eventHandlersPresent.get(velementId) ?? 0) | bit;
|
|
1769
|
+
eventHandlersPresent.set(velementId, present);
|
|
1770
|
+
const suspendBits = eventHandlersSuspend.get(velementId) ?? 0;
|
|
1771
|
+
const nextSuspend = maySuspend ? suspendBits | bit : suspendBits & ~bit;
|
|
1772
|
+
if (nextSuspend === 0) eventHandlersSuspend.delete(velementId);
|
|
1773
|
+
else eventHandlersSuspend.set(velementId, nextSuspend);
|
|
1774
|
+
ensureDelegatedListener(eventTypeId);
|
|
1546
1775
|
}
|
|
1547
1776
|
clearEventHandlerModes(velementId) {
|
|
1548
|
-
|
|
1777
|
+
const present = eventHandlersPresent.get(velementId) ?? 0;
|
|
1778
|
+
eventHandlersPresent.delete(velementId);
|
|
1779
|
+
eventHandlersSuspend.delete(velementId);
|
|
1780
|
+
for (const eventTypeId of HIGH_FREQ_EVENT_IDS) {
|
|
1781
|
+
if (present & 1 << eventTypeId) maybeRemoveHighFreqListener(eventTypeId);
|
|
1782
|
+
}
|
|
1549
1783
|
}
|
|
1550
1784
|
/** Submit a form action with bound-state round-trip. */
|
|
1551
1785
|
submitFormActionAsync(form, actionId, statesJson, fetchId) {
|
|
@@ -1579,7 +1813,7 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1579
1813
|
const handler = this.#wsOnOpenHandler;
|
|
1580
1814
|
if (!handler) return;
|
|
1581
1815
|
const protocol = ws.protocol || "";
|
|
1582
|
-
const
|
|
1816
|
+
const [ptr, len] = this._writeStringToWasm(protocol);
|
|
1583
1817
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
1584
1818
|
};
|
|
1585
1819
|
ws.onmessage = (event) => {
|
|
@@ -1587,20 +1821,20 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1587
1821
|
if (!handler) return;
|
|
1588
1822
|
const isBinary = event.data instanceof ArrayBuffer;
|
|
1589
1823
|
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
1590
|
-
const
|
|
1824
|
+
const [ptr, len] = this.writeBytesToWasm(data);
|
|
1591
1825
|
invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
|
|
1592
1826
|
};
|
|
1593
1827
|
ws.onerror = (_event) => {
|
|
1594
1828
|
const handler = this.#wsOnErrorHandler;
|
|
1595
1829
|
if (!handler) return;
|
|
1596
|
-
const
|
|
1830
|
+
const [ptr, len] = this._writeStringToWasm("WebSocket error");
|
|
1597
1831
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
1598
1832
|
};
|
|
1599
1833
|
ws.onclose = (event) => {
|
|
1600
1834
|
const handler = this.#wsOnCloseHandler;
|
|
1601
1835
|
if (!handler) return;
|
|
1602
1836
|
const reason = event.reason || "";
|
|
1603
|
-
const
|
|
1837
|
+
const [ptr, len] = this._writeStringToWasm(reason);
|
|
1604
1838
|
invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
1605
1839
|
this.#websockets.delete(wsId);
|
|
1606
1840
|
};
|
|
@@ -1609,7 +1843,7 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1609
1843
|
const handler = this.#wsOnErrorHandler;
|
|
1610
1844
|
if (handler) {
|
|
1611
1845
|
const msg = error instanceof Error ? error.message : "WebSocket connection failed";
|
|
1612
|
-
const
|
|
1846
|
+
const [ptr, len] = this._writeStringToWasm(msg);
|
|
1613
1847
|
invokeWasmExport(handler, wsId, ptr, len);
|
|
1614
1848
|
}
|
|
1615
1849
|
}
|
|
@@ -1619,10 +1853,13 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1619
1853
|
const ws = this.#websockets.get(wsId);
|
|
1620
1854
|
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
1621
1855
|
const memory = getMemoryView();
|
|
1856
|
+
const start = dataPtr >>> 0;
|
|
1857
|
+
const length = dataLen >>> 0;
|
|
1858
|
+
if (start + length > memory.byteLength) return;
|
|
1622
1859
|
if (isBinary) {
|
|
1623
|
-
ws.send(memory.slice(
|
|
1860
|
+
ws.send(memory.slice(start, start + length));
|
|
1624
1861
|
} else {
|
|
1625
|
-
ws.send(textDecoder.decode(memory.subarray(
|
|
1862
|
+
ws.send(textDecoder.decode(memory.subarray(start, start + length)));
|
|
1626
1863
|
}
|
|
1627
1864
|
}
|
|
1628
1865
|
/** Close WebSocket connection */
|
|
@@ -1639,7 +1876,8 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1639
1876
|
}
|
|
1640
1877
|
dispose() {
|
|
1641
1878
|
super.dispose();
|
|
1642
|
-
|
|
1879
|
+
eventHandlersPresent.clear();
|
|
1880
|
+
eventHandlersSuspend.clear();
|
|
1643
1881
|
for (const ws of this.#websockets.values()) {
|
|
1644
1882
|
try {
|
|
1645
1883
|
ws.close();
|
|
@@ -1648,14 +1886,16 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1648
1886
|
}
|
|
1649
1887
|
this.#websockets.clear();
|
|
1650
1888
|
}
|
|
1651
|
-
/**
|
|
1652
|
-
|
|
1653
|
-
|
|
1889
|
+
/**
|
|
1890
|
+
* Dispatch to WASM for one vnode. Caller owns `eventRef` lifetime
|
|
1891
|
+
* (store once per bubble, release after sync/async work completes).
|
|
1892
|
+
*/
|
|
1893
|
+
eventbridge(velementId, eventTypeId, eventRef) {
|
|
1894
|
+
const id = BigInt(velementId >>> 0);
|
|
1654
1895
|
if (this.eventMaySuspend(velementId, eventTypeId)) {
|
|
1655
|
-
invokeWasmExport(this.#eventbridgeAsync,
|
|
1656
|
-
return;
|
|
1896
|
+
return invokeWasmExport(this.#eventbridgeAsync, id, eventTypeId, eventRef);
|
|
1657
1897
|
}
|
|
1658
|
-
invokeWasmExport(this.#eventbridge,
|
|
1898
|
+
invokeWasmExport(this.#eventbridge, id, eventTypeId, eventRef);
|
|
1659
1899
|
}
|
|
1660
1900
|
/** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
|
|
1661
1901
|
static createImportObject(bridgeRef) {
|
|
@@ -1668,13 +1908,13 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1668
1908
|
__zx: {
|
|
1669
1909
|
_log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
|
|
1670
1910
|
_setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
|
|
1671
|
-
bridgeRef
|
|
1911
|
+
bridgeRef[0]?.setEventHandlerMode(Number(vnodeId), eventTypeId, maySuspend !== 0);
|
|
1672
1912
|
},
|
|
1673
1913
|
_clearEventHandlerModes: (vnodeId) => {
|
|
1674
|
-
bridgeRef
|
|
1914
|
+
bridgeRef[0]?.clearEventHandlerModes(Number(vnodeId));
|
|
1675
1915
|
},
|
|
1676
1916
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1677
|
-
bridgeRef
|
|
1917
|
+
bridgeRef[0]?.fetchAsync(
|
|
1678
1918
|
urlPtr,
|
|
1679
1919
|
urlLen,
|
|
1680
1920
|
methodPtr,
|
|
@@ -1688,43 +1928,49 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1688
1928
|
);
|
|
1689
1929
|
},
|
|
1690
1930
|
_setTimeout: (callbackId, delayMs) => {
|
|
1691
|
-
bridgeRef
|
|
1931
|
+
bridgeRef[0]?.setTimeout(callbackId, delayMs);
|
|
1692
1932
|
},
|
|
1693
1933
|
_setInterval: (callbackId, intervalMs) => {
|
|
1694
|
-
bridgeRef
|
|
1934
|
+
bridgeRef[0]?.setInterval(callbackId, intervalMs);
|
|
1695
1935
|
},
|
|
1696
1936
|
_clearInterval: (callbackId) => {
|
|
1697
|
-
bridgeRef
|
|
1937
|
+
bridgeRef[0]?.clearInterval(callbackId);
|
|
1698
1938
|
},
|
|
1699
1939
|
// WebSocket API
|
|
1700
1940
|
_wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
|
|
1701
|
-
bridgeRef
|
|
1941
|
+
bridgeRef[0]?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
|
|
1702
1942
|
},
|
|
1703
1943
|
_wsSend: (wsId, dataPtr, dataLen, isBinary) => {
|
|
1704
|
-
bridgeRef
|
|
1944
|
+
bridgeRef[0]?.wsSend(wsId, dataPtr, dataLen, isBinary);
|
|
1705
1945
|
},
|
|
1706
1946
|
_wsClose: (wsId, code, reasonPtr, reasonLen) => {
|
|
1707
|
-
bridgeRef
|
|
1947
|
+
bridgeRef[0]?.wsClose(wsId, code, reasonPtr, reasonLen);
|
|
1708
1948
|
},
|
|
1709
1949
|
_ce: (id, vnodeId) => {
|
|
1950
|
+
const nid = Number(vnodeId);
|
|
1710
1951
|
const tagName = TAG_NAMES[id];
|
|
1711
1952
|
const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
|
|
1712
|
-
el.__zx_ref =
|
|
1713
|
-
domNodes.set(
|
|
1714
|
-
return storeValueGetRef(el);
|
|
1953
|
+
el.__zx_ref = nid;
|
|
1954
|
+
domNodes.set(nid, el);
|
|
1715
1955
|
},
|
|
1716
1956
|
_ct: (ptr, len, vnodeId) => {
|
|
1717
|
-
const
|
|
1718
|
-
const node = document.createTextNode(
|
|
1719
|
-
node.__zx_ref =
|
|
1720
|
-
domNodes.set(
|
|
1721
|
-
|
|
1957
|
+
const nid = Number(vnodeId);
|
|
1958
|
+
const node = document.createTextNode(readString(ptr, len));
|
|
1959
|
+
node.__zx_ref = nid;
|
|
1960
|
+
domNodes.set(nid, node);
|
|
1961
|
+
},
|
|
1962
|
+
/** Insert vnode before a jsz-held end comment (hydration). */
|
|
1963
|
+
_ih: (vnodeId, endCommentRef) => {
|
|
1964
|
+
const child = domNodes.get(Number(vnodeId));
|
|
1965
|
+
const end = loadValueFromRef(endCommentRef);
|
|
1966
|
+
if (!child || !end?.parentNode) return;
|
|
1967
|
+
end.parentNode.insertBefore(child, end);
|
|
1722
1968
|
},
|
|
1723
1969
|
_sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
|
|
1724
|
-
domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
|
|
1970
|
+
domNodes.get(Number(vnodeId))?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
|
|
1725
1971
|
},
|
|
1726
1972
|
_sp: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
|
|
1727
|
-
const el = domNodes.get(vnodeId);
|
|
1973
|
+
const el = domNodes.get(Number(vnodeId));
|
|
1728
1974
|
if (el) {
|
|
1729
1975
|
const name = readString(namePtr, nameLen);
|
|
1730
1976
|
const val = readString(valPtr, valLen);
|
|
@@ -1736,39 +1982,39 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1736
1982
|
}
|
|
1737
1983
|
},
|
|
1738
1984
|
_ra: (vnodeId, namePtr, nameLen) => {
|
|
1739
|
-
domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
|
|
1985
|
+
domNodes.get(Number(vnodeId))?.removeAttribute(readString(namePtr, nameLen));
|
|
1740
1986
|
},
|
|
1741
1987
|
_snv: (vnodeId, ptr, len) => {
|
|
1742
|
-
const node = domNodes.get(vnodeId);
|
|
1988
|
+
const node = domNodes.get(Number(vnodeId));
|
|
1743
1989
|
if (node) node.nodeValue = readString(ptr, len);
|
|
1744
1990
|
},
|
|
1745
1991
|
_srh: (vnodeId, ptr, len) => {
|
|
1746
|
-
const el = domNodes.get(vnodeId);
|
|
1992
|
+
const el = domNodes.get(Number(vnodeId));
|
|
1747
1993
|
if (el) el.innerHTML = readString(ptr, len);
|
|
1748
1994
|
},
|
|
1749
1995
|
_ac: (parentId, childId) => {
|
|
1750
|
-
const parent = domNodes.get(parentId);
|
|
1751
|
-
const child = domNodes.get(childId);
|
|
1996
|
+
const parent = domNodes.get(Number(parentId));
|
|
1997
|
+
const child = domNodes.get(Number(childId));
|
|
1752
1998
|
if (parent && child) parent.appendChild(child);
|
|
1753
1999
|
},
|
|
1754
2000
|
_ib: (parentId, childId, refId) => {
|
|
1755
|
-
const parent = domNodes.get(parentId);
|
|
1756
|
-
const child = domNodes.get(childId);
|
|
1757
|
-
const ref = domNodes.get(refId) ?? null;
|
|
2001
|
+
const parent = domNodes.get(Number(parentId));
|
|
2002
|
+
const child = domNodes.get(Number(childId));
|
|
2003
|
+
const ref = domNodes.get(Number(refId)) ?? null;
|
|
1758
2004
|
if (parent && child) parent.insertBefore(child, ref);
|
|
1759
2005
|
},
|
|
1760
2006
|
_rc: (parentId, childId) => {
|
|
1761
|
-
const parent = domNodes.get(parentId);
|
|
1762
|
-
const child = domNodes.get(childId);
|
|
2007
|
+
const parent = domNodes.get(Number(parentId));
|
|
2008
|
+
const child = domNodes.get(Number(childId));
|
|
1763
2009
|
if (parent && child) {
|
|
1764
2010
|
parent.removeChild(child);
|
|
1765
2011
|
cleanupDomNodes(child);
|
|
1766
2012
|
}
|
|
1767
2013
|
},
|
|
1768
2014
|
_rpc: (parentId, newId, oldId) => {
|
|
1769
|
-
const parent = domNodes.get(parentId);
|
|
1770
|
-
const newChild = domNodes.get(newId);
|
|
1771
|
-
const oldChild = domNodes.get(oldId);
|
|
2015
|
+
const parent = domNodes.get(Number(parentId));
|
|
2016
|
+
const newChild = domNodes.get(Number(newId));
|
|
2017
|
+
const oldChild = domNodes.get(Number(oldId));
|
|
1772
2018
|
if (parent && newChild && oldChild) {
|
|
1773
2019
|
parent.replaceChild(newChild, oldChild);
|
|
1774
2020
|
cleanupDomNodes(oldChild);
|
|
@@ -1780,18 +2026,22 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1780
2026
|
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
1781
2027
|
return len;
|
|
1782
2028
|
},
|
|
1783
|
-
_getFormData: (
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1786
|
-
const
|
|
1787
|
-
|
|
1788
|
-
const
|
|
1789
|
-
const
|
|
1790
|
-
|
|
2029
|
+
_getFormData: (eventRef, outPtrAddr) => {
|
|
2030
|
+
const event = loadValueFromRef(eventRef);
|
|
2031
|
+
const el = event?.target;
|
|
2032
|
+
const form = el instanceof HTMLFormElement ? el : el?.closest?.("form") ?? null;
|
|
2033
|
+
if (!form) return 0;
|
|
2034
|
+
const entries = [];
|
|
2035
|
+
for (const [k, v] of new FormData(form).entries()) {
|
|
2036
|
+
entries.push(k, String(v));
|
|
2037
|
+
}
|
|
2038
|
+
const bytes = textEncoder.encode(JSON.stringify(entries));
|
|
2039
|
+
const [ptr, len] = bridgeRef[0].writeBytesToWasm(bytes);
|
|
2040
|
+
new DataView(jsz.memory.buffer).setUint32(outPtrAddr, ptr, true);
|
|
1791
2041
|
return len;
|
|
1792
2042
|
},
|
|
1793
2043
|
_submitFormAction: (vnodeId, actionId) => {
|
|
1794
|
-
const form = domNodes.get(vnodeId);
|
|
2044
|
+
const form = domNodes.get(Number(vnodeId));
|
|
1795
2045
|
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1796
2046
|
const formData = new FormData(form);
|
|
1797
2047
|
fetch(window.location.href, {
|
|
@@ -1803,21 +2053,39 @@ var ZxBridge = class extends ZxBridgeCore {
|
|
|
1803
2053
|
});
|
|
1804
2054
|
},
|
|
1805
2055
|
_submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
|
|
1806
|
-
const form = domNodes.get(vnodeId);
|
|
2056
|
+
const form = domNodes.get(Number(vnodeId));
|
|
1807
2057
|
if (!form || !(form instanceof HTMLFormElement)) return;
|
|
1808
2058
|
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
1809
|
-
bridgeRef
|
|
2059
|
+
bridgeRef[0]?.submitFormActionAsync(form, actionId, statesJson, fetchId);
|
|
1810
2060
|
}
|
|
1811
2061
|
}
|
|
1812
2062
|
};
|
|
1813
2063
|
}
|
|
1814
2064
|
};
|
|
1815
2065
|
var domNodes = /* @__PURE__ */ new Map();
|
|
2066
|
+
var eventHandlersPresent = /* @__PURE__ */ new Map();
|
|
2067
|
+
var eventHandlersSuspend = /* @__PURE__ */ new Map();
|
|
1816
2068
|
function cleanupDomNodes(node) {
|
|
1817
|
-
const
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
2069
|
+
const stack = [node];
|
|
2070
|
+
let highFreqBits = 0;
|
|
2071
|
+
while (stack.length > 0) {
|
|
2072
|
+
const n = stack.pop();
|
|
2073
|
+
const ref = n.__zx_ref;
|
|
2074
|
+
if (typeof ref === "number") {
|
|
2075
|
+
const present = eventHandlersPresent.get(ref);
|
|
2076
|
+
if (present !== void 0) {
|
|
2077
|
+
highFreqBits |= present;
|
|
2078
|
+
eventHandlersPresent.delete(ref);
|
|
2079
|
+
eventHandlersSuspend.delete(ref);
|
|
2080
|
+
}
|
|
2081
|
+
domNodes.delete(ref);
|
|
2082
|
+
}
|
|
2083
|
+
const children = n.childNodes;
|
|
2084
|
+
for (let i = 0; i < children.length; i++) stack.push(children[i]);
|
|
2085
|
+
}
|
|
2086
|
+
for (const eventTypeId of HIGH_FREQ_EVENT_IDS) {
|
|
2087
|
+
if (highFreqBits & 1 << eventTypeId) maybeRemoveHighFreqListener(eventTypeId);
|
|
2088
|
+
}
|
|
1821
2089
|
}
|
|
1822
2090
|
var SVG_TAG_START_INDEX = 140;
|
|
1823
2091
|
var TAG_NAMES = [
|
|
@@ -2022,9 +2290,99 @@ var TAG_NAMES = [
|
|
|
2022
2290
|
"use",
|
|
2023
2291
|
"view"
|
|
2024
2292
|
];
|
|
2025
|
-
var
|
|
2293
|
+
var DELEGATED_EVENTS = [
|
|
2294
|
+
"click",
|
|
2295
|
+
"dblclick",
|
|
2296
|
+
"input",
|
|
2297
|
+
"change",
|
|
2298
|
+
"submit",
|
|
2299
|
+
// focus/blur do not bubble - listen to focusin/focusout instead.
|
|
2300
|
+
"focusin",
|
|
2301
|
+
"focusout",
|
|
2302
|
+
"keydown",
|
|
2303
|
+
"keyup",
|
|
2304
|
+
"keypress",
|
|
2305
|
+
"mouseenter",
|
|
2306
|
+
"mouseleave",
|
|
2307
|
+
"mousedown",
|
|
2308
|
+
"mouseup",
|
|
2309
|
+
"mousemove",
|
|
2310
|
+
"touchstart",
|
|
2311
|
+
"touchend",
|
|
2312
|
+
"touchmove",
|
|
2313
|
+
"scroll",
|
|
2314
|
+
"wheel",
|
|
2315
|
+
"pointerdown",
|
|
2316
|
+
"pointermove",
|
|
2317
|
+
"pointerup",
|
|
2318
|
+
"pointercancel"
|
|
2319
|
+
];
|
|
2320
|
+
var HIGH_FREQ_EVENT_IDS = new Set([
|
|
2321
|
+
DELEGATED_EVENTS.indexOf("mousemove"),
|
|
2322
|
+
DELEGATED_EVENTS.indexOf("pointermove"),
|
|
2323
|
+
DELEGATED_EVENTS.indexOf("wheel"),
|
|
2324
|
+
DELEGATED_EVENTS.indexOf("scroll"),
|
|
2325
|
+
DELEGATED_EVENTS.indexOf("touchmove")
|
|
2326
|
+
].filter((id) => id >= 0));
|
|
2327
|
+
var delegationState = null;
|
|
2328
|
+
function makeDelegatedListener(bridge, eventTypeId) {
|
|
2329
|
+
return (event) => {
|
|
2330
|
+
let eventRef;
|
|
2331
|
+
const pending = [];
|
|
2332
|
+
let target = event.target;
|
|
2333
|
+
while (target && target !== document.body) {
|
|
2334
|
+
const zxRef = target.__zx_ref;
|
|
2335
|
+
if (typeof zxRef === "number" && bridge.hasEventHandler(zxRef, eventTypeId)) {
|
|
2336
|
+
if (eventRef === void 0) eventRef = storeValueGetRef(event);
|
|
2337
|
+
const result = bridge.eventbridge(zxRef, eventTypeId, eventRef);
|
|
2338
|
+
if (result && typeof result.then === "function") {
|
|
2339
|
+
pending.push(result);
|
|
2340
|
+
}
|
|
2341
|
+
if (event.cancelBubble) break;
|
|
2342
|
+
}
|
|
2343
|
+
target = target.parentElement;
|
|
2344
|
+
}
|
|
2345
|
+
if (eventRef !== void 0) {
|
|
2346
|
+
const ref = eventRef;
|
|
2347
|
+
if (pending.length > 0) {
|
|
2348
|
+
Promise.all(pending).finally(() => releaseValueRef(ref));
|
|
2349
|
+
} else {
|
|
2350
|
+
releaseValueRef(ref);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2355
|
+
function ensureDelegatedListener(eventTypeId) {
|
|
2356
|
+
const state = delegationState;
|
|
2357
|
+
if (!state || state.attached.has(eventTypeId)) return;
|
|
2358
|
+
const domType = DELEGATED_EVENTS[eventTypeId];
|
|
2359
|
+
if (!domType) return;
|
|
2360
|
+
const passive = domType.startsWith("touch") || domType === "scroll";
|
|
2361
|
+
const options = { passive };
|
|
2362
|
+
const listener = makeDelegatedListener(state.bridge, eventTypeId);
|
|
2363
|
+
state.root.addEventListener(domType, listener, options);
|
|
2364
|
+
state.attached.set(eventTypeId, { listener, options });
|
|
2365
|
+
}
|
|
2366
|
+
function anyHandlerForType(eventTypeId) {
|
|
2367
|
+
const bit = 1 << eventTypeId;
|
|
2368
|
+
for (const mask of eventHandlersPresent.values()) {
|
|
2369
|
+
if (mask & bit) return true;
|
|
2370
|
+
}
|
|
2371
|
+
return false;
|
|
2372
|
+
}
|
|
2373
|
+
function maybeRemoveHighFreqListener(eventTypeId) {
|
|
2374
|
+
if (!HIGH_FREQ_EVENT_IDS.has(eventTypeId)) return;
|
|
2375
|
+
if (anyHandlerForType(eventTypeId)) return;
|
|
2376
|
+
const state = delegationState;
|
|
2377
|
+
if (!state) return;
|
|
2378
|
+
const entry = state.attached.get(eventTypeId);
|
|
2379
|
+
if (!entry) return;
|
|
2380
|
+
const domType = DELEGATED_EVENTS[eventTypeId];
|
|
2381
|
+
state.root.removeEventListener(domType, entry.listener, entry.options);
|
|
2382
|
+
state.attached.delete(eventTypeId);
|
|
2383
|
+
}
|
|
2026
2384
|
|
|
2027
|
-
// src/cloudflare/do.ts
|
|
2385
|
+
// src/platforms/cloudflare/do.ts
|
|
2028
2386
|
function createWebSocketDO(module, options) {
|
|
2029
2387
|
return class ZxWebSocketDO {
|
|
2030
2388
|
constructor(state, env) {
|
|
@@ -2038,7 +2396,7 @@ function createWebSocketDO(module, options) {
|
|
|
2038
2396
|
const { wasiImport, setMemory } = createWasiImports({ request, stdinData });
|
|
2039
2397
|
let wasmMemory = null;
|
|
2040
2398
|
const mem = () => wasmMemory;
|
|
2041
|
-
const bridgeRef =
|
|
2399
|
+
const bridgeRef = [null];
|
|
2042
2400
|
const bridgeImports = ZxBridge.createImportObject(bridgeRef);
|
|
2043
2401
|
const Suspending = WebAssembly.Suspending;
|
|
2044
2402
|
const jspi = typeof Suspending === "function";
|
|
@@ -2084,19 +2442,34 @@ function createWebSocketDO(module, options) {
|
|
|
2084
2442
|
const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder3, connState);
|
|
2085
2443
|
const kvBindings = options?.kv?.(this.env);
|
|
2086
2444
|
const dbBindings = options?.db?.(this.env);
|
|
2087
|
-
const
|
|
2445
|
+
const allocRef = [null];
|
|
2446
|
+
const importObject = {
|
|
2088
2447
|
wasi_snapshot_preview1: wasiImport,
|
|
2089
2448
|
__zx_sys: sysImports,
|
|
2090
2449
|
__zx_ws: wsImports,
|
|
2091
|
-
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
2092
|
-
__zx_db: createD1Imports(dbBindings ?? {}, mem),
|
|
2093
2450
|
__zx_net: createFetchImports(mem),
|
|
2094
2451
|
...options?.imports ? options.imports(mem) : {},
|
|
2095
2452
|
...bridgeImports
|
|
2096
|
-
}
|
|
2453
|
+
};
|
|
2454
|
+
if (true) {
|
|
2455
|
+
importObject.__zx_kv = createKVImports(
|
|
2456
|
+
kvBindings ?? { default: createMemoryKV() },
|
|
2457
|
+
mem,
|
|
2458
|
+
allocRef
|
|
2459
|
+
);
|
|
2460
|
+
}
|
|
2461
|
+
if (true) {
|
|
2462
|
+
importObject.__zx_db = createDbImports(
|
|
2463
|
+
dbBindings ?? {},
|
|
2464
|
+
mem,
|
|
2465
|
+
allocRef
|
|
2466
|
+
);
|
|
2467
|
+
}
|
|
2468
|
+
const instance = new WebAssembly.Instance(module, importObject);
|
|
2097
2469
|
wasmMemory = instance.exports.memory;
|
|
2098
2470
|
setMemory(wasmMemory);
|
|
2099
|
-
bridgeRef
|
|
2471
|
+
bridgeRef[0] = new ZxBridge(instance.exports);
|
|
2472
|
+
bindWasmAlloc(allocRef, instance.exports);
|
|
2100
2473
|
const start = WebAssembly.promising(instance.exports._start);
|
|
2101
2474
|
const wasmPromise = start().catch((e) => {
|
|
2102
2475
|
wasmExited = true;
|