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