ziex 0.1.0-dev.1367 → 0.1.0-dev.1377
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/aws-lambda/index.js +20 -29
- package/build.zig +118 -2
- package/build.zig.zon +13 -2
- package/cloudflare/index.js +1635 -1854
- package/index.js +155 -216
- package/{pkg/ziex/src/react → jsx}/dom.d.ts +5 -9
- package/{pkg/ziex/src/react → jsx}/index.d.ts +1 -1
- package/{react → jsx}/index.js +19 -25
- package/{pkg/ziex/src/react → jsx}/types.d.ts +14 -9
- package/package.json +6 -14
- package/vercel/index.js +0 -15
- package/wasm/index.js +253 -261
- package/wasm/init.dev.js +242 -189
- package/wasm/init.js +3 -3
- package/pkg/ziex/src/zx.d.ts +0 -1
- package/vendor/jsz/js/src/index.d.ts +0 -1
- package/vendor/jsz/js/src/zigjs.d.ts +0 -107
- /package/{pkg/ziex/src/app.d.ts → app.d.ts} +0 -0
- /package/{pkg/ziex/src/aws-lambda → aws-lambda}/index.d.ts +0 -0
- /package/{pkg/ziex/src/browser → browser}/kv.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/app.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/db.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/do.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/index.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/kv.d.ts +0 -0
- /package/{pkg/ziex/src/cloudflare → cloudflare}/worker.d.ts +0 -0
- /package/{pkg/ziex/src/db.d.ts → db.d.ts} +0 -0
- /package/{pkg/ziex/src/fetch.d.ts → fetch.d.ts} +0 -0
- /package/{pkg/ziex/src/index.d.ts → index.d.ts} +0 -0
- /package/{pkg/ziex/src/kv.d.ts → kv.d.ts} +0 -0
- /package/{pkg/ziex/src/runtime.d.ts → runtime.d.ts} +0 -0
- /package/{pkg/ziex/src/vercel → vercel}/index.d.ts +0 -0
- /package/{pkg/ziex/src/wasi.d.ts → wasi.d.ts} +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/core.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/dom.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/index.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/init.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/types.d.ts +0 -0
- /package/{pkg/ziex/src/wasm → wasm}/wasi.d.ts +0 -0
package/cloudflare/index.js
CHANGED
|
@@ -1,468 +1,142 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
-
var __returnValue = (v) => v;
|
|
3
|
-
function __exportSetter(name, newValue) {
|
|
4
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
5
|
-
}
|
|
6
2
|
var __export = (target, all) => {
|
|
7
3
|
for (var name in all)
|
|
8
|
-
__defProp(target, name, {
|
|
9
|
-
get: all[name],
|
|
10
|
-
enumerable: true,
|
|
11
|
-
configurable: true,
|
|
12
|
-
set: __exportSetter.bind(all, name)
|
|
13
|
-
});
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
5
|
};
|
|
15
6
|
|
|
16
|
-
//
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
undefined: 4,
|
|
24
|
-
globalThis: 5,
|
|
25
|
-
runtime: 6
|
|
26
|
-
};
|
|
27
|
-
var PREDEFINED_ID_MAX = 6;
|
|
28
|
-
var encoder = new TextEncoder;
|
|
29
|
-
var decoder = new TextDecoder("utf-8");
|
|
7
|
+
// src/runtime.ts
|
|
8
|
+
var runtime_exports = {};
|
|
9
|
+
__export(runtime_exports, {
|
|
10
|
+
attachWebSocket: () => attachWebSocket,
|
|
11
|
+
buildWsImports: () => buildWsImports,
|
|
12
|
+
run: () => run
|
|
13
|
+
});
|
|
30
14
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
valueGet(out, id, ptr, len) {
|
|
51
|
-
const val = this.loadValue(id);
|
|
52
|
-
const str = this.loadString(ptr, len);
|
|
53
|
-
const result = Reflect.get(val, str);
|
|
54
|
-
this.storeValue(out, result);
|
|
55
|
-
}
|
|
56
|
-
valueSet(id, ptr, len, refAddr) {
|
|
57
|
-
const obj = this.loadValue(id);
|
|
58
|
-
const str = this.loadString(ptr, len);
|
|
59
|
-
const val = this.loadRef(refAddr);
|
|
60
|
-
Reflect.set(obj, str, val);
|
|
61
|
-
}
|
|
62
|
-
valueDeinit(id) {
|
|
63
|
-
if (id > PREDEFINED_ID_MAX) {
|
|
64
|
-
this.values[id] = null;
|
|
65
|
-
this.idPool.push(id);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
valueObjectCreate(out) {
|
|
69
|
-
this.storeValue(out, new Object);
|
|
70
|
-
}
|
|
71
|
-
valueStringCreate(out, ptr, len) {
|
|
72
|
-
const str = this.loadString(ptr, len);
|
|
73
|
-
this.storeValue(out, str);
|
|
74
|
-
}
|
|
75
|
-
valueStringLen(id) {
|
|
76
|
-
const val = this.loadValue(id);
|
|
77
|
-
const buf = encoder.encode(val);
|
|
78
|
-
return buf.byteLength;
|
|
79
|
-
}
|
|
80
|
-
valueStringCopy(id, ptr, max) {
|
|
81
|
-
if (this.memory == null)
|
|
82
|
-
return;
|
|
83
|
-
const val = this.loadValue(id);
|
|
84
|
-
const bytes = encoder.encode(val);
|
|
85
|
-
if (bytes.byteLength > max)
|
|
86
|
-
return;
|
|
87
|
-
if (bytes.length === 0)
|
|
88
|
-
return;
|
|
89
|
-
new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
|
|
90
|
-
}
|
|
91
|
-
valueNew(out, id, argsAddr, argsLen) {
|
|
92
|
-
const fn = this.loadValue(id);
|
|
93
|
-
const args = [];
|
|
94
|
-
for (let i = 0;i < argsLen; i++) {
|
|
95
|
-
args.push(this.loadRef(argsAddr + i * 8));
|
|
96
|
-
}
|
|
97
|
-
const result = Reflect.construct(fn, args);
|
|
98
|
-
this.storeValue(out, result);
|
|
15
|
+
// src/wasm/wasi.ts
|
|
16
|
+
var decoder = new TextDecoder();
|
|
17
|
+
var encoder = new TextEncoder();
|
|
18
|
+
var ZxWasiBridge = class {
|
|
19
|
+
#alloc;
|
|
20
|
+
#fetchCompleteHandler;
|
|
21
|
+
#memory;
|
|
22
|
+
#cb;
|
|
23
|
+
#intervals = /* @__PURE__ */ new Map();
|
|
24
|
+
// Cached memory view - invalidated when the WASM buffer grows.
|
|
25
|
+
#memView = null;
|
|
26
|
+
#memBuf = null;
|
|
27
|
+
constructor(exports) {
|
|
28
|
+
this.#memory = exports.memory;
|
|
29
|
+
this.#alloc = exports.__zx_alloc;
|
|
30
|
+
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
31
|
+
this.#cb = exports.__zx_cb;
|
|
99
32
|
}
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
args.push(this.loadRef(argsAddr + i * 8));
|
|
33
|
+
#view() {
|
|
34
|
+
const buf = this.#memory.buffer;
|
|
35
|
+
if (buf !== this.#memBuf) {
|
|
36
|
+
this.#memBuf = buf;
|
|
37
|
+
this.#memView = new Uint8Array(buf);
|
|
106
38
|
}
|
|
107
|
-
|
|
108
|
-
this.storeValue(out, result);
|
|
109
|
-
}
|
|
110
|
-
loadValue(id) {
|
|
111
|
-
return this.values[id];
|
|
112
|
-
}
|
|
113
|
-
deleteValue(id) {
|
|
114
|
-
const val = this.values[id];
|
|
115
|
-
this.valueDeinit(id);
|
|
116
|
-
return val;
|
|
39
|
+
return this.#memView;
|
|
117
40
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return;
|
|
121
|
-
const view = new DataView(this.memory.buffer);
|
|
122
|
-
const floatVal = view.getFloat64(refAddr, true);
|
|
123
|
-
if (!isNaN(floatVal))
|
|
124
|
-
return floatVal;
|
|
125
|
-
const id = this.loadRefId(refAddr);
|
|
126
|
-
return this.values[id];
|
|
41
|
+
#readString(ptr, len) {
|
|
42
|
+
return decoder.decode(this.#view().subarray(ptr, ptr + len));
|
|
127
43
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return 0;
|
|
131
|
-
return new DataView(this.memory.buffer).getUint32(refAddr, true);
|
|
44
|
+
#writeBytes(ptr, data) {
|
|
45
|
+
this.#view().set(data, ptr);
|
|
132
46
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (isNaN(val)) {
|
|
139
|
-
view.setUint32(out, predefined.nan, true);
|
|
140
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
141
|
-
} else {
|
|
142
|
-
view.setFloat64(out, val, true);
|
|
143
|
-
}
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
if (val === null) {
|
|
147
|
-
view.setUint32(out, predefined.null, true);
|
|
148
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (val === undefined) {
|
|
152
|
-
view.setUint32(out, predefined.undefined, true);
|
|
153
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
if (typeof val === "boolean") {
|
|
157
|
-
view.setUint32(out, val ? predefined.true : predefined.false, true);
|
|
158
|
-
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
if (typeof val === "bigint") {
|
|
162
|
-
view.setFloat64(out, Number(val), true);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
let id = this.idPool.pop();
|
|
166
|
-
if (id === undefined) {
|
|
167
|
-
id = this.values.length;
|
|
168
|
-
}
|
|
169
|
-
this.values[id] = val;
|
|
170
|
-
let typeId = 0;
|
|
171
|
-
switch (typeof val) {
|
|
172
|
-
case "object":
|
|
173
|
-
typeId = 1;
|
|
47
|
+
log(level, ptr, len) {
|
|
48
|
+
const msg = decoder.decode(this.#view().subarray(ptr, ptr + len));
|
|
49
|
+
switch (level) {
|
|
50
|
+
case 0:
|
|
51
|
+
console.error(msg);
|
|
174
52
|
break;
|
|
175
|
-
case
|
|
176
|
-
|
|
53
|
+
case 1:
|
|
54
|
+
console.warn(msg);
|
|
177
55
|
break;
|
|
178
|
-
case
|
|
179
|
-
|
|
56
|
+
case 3:
|
|
57
|
+
console.debug(msg);
|
|
180
58
|
break;
|
|
181
|
-
|
|
182
|
-
|
|
59
|
+
default:
|
|
60
|
+
console.log(msg);
|
|
183
61
|
break;
|
|
184
62
|
}
|
|
185
|
-
view.setUint32(out, Number(id), true);
|
|
186
|
-
view.setUint32(out + 4, NAN_PREFIX | typeId, true);
|
|
187
|
-
}
|
|
188
|
-
loadString(ptr, len) {
|
|
189
|
-
if (this.memory == null)
|
|
190
|
-
return "";
|
|
191
|
-
const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
|
|
192
|
-
const data = arr.slice();
|
|
193
|
-
return decoder.decode(data);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
// src/fetch.ts
|
|
197
|
-
function createFetchImports(getMemory) {
|
|
198
|
-
const encoder2 = new TextEncoder;
|
|
199
|
-
const decoder2 = new TextDecoder;
|
|
200
|
-
function readStr(ptr, len) {
|
|
201
|
-
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
202
|
-
}
|
|
203
|
-
function writeBytes(buf_ptr, buf_max, data) {
|
|
204
|
-
if (data.length > buf_max)
|
|
205
|
-
return -2;
|
|
206
|
-
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
207
|
-
return data.length;
|
|
208
63
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
64
|
+
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
65
|
+
const url = this.#readString(urlPtr, urlLen);
|
|
66
|
+
const method = methodLen > 0 ? this.#readString(methodPtr, methodLen) : "GET";
|
|
67
|
+
const headersJson = headersLen > 0 ? this.#readString(headersPtr, headersLen) : "{}";
|
|
68
|
+
const body = bodyLen > 0 ? this.#view().subarray(bodyPtr, bodyPtr + bodyLen) : void 0;
|
|
213
69
|
let headers = {};
|
|
214
70
|
try {
|
|
215
71
|
headers = JSON.parse(headersJson);
|
|
216
72
|
} catch {
|
|
217
|
-
for (const line of headersJson.split(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (colonIdx > 0) {
|
|
221
|
-
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
222
|
-
}
|
|
73
|
+
for (const line of headersJson.split("\n")) {
|
|
74
|
+
const i = line.indexOf(":");
|
|
75
|
+
if (i > 0) headers[line.slice(0, i)] = line.slice(i + 1);
|
|
223
76
|
}
|
|
224
77
|
}
|
|
225
|
-
|
|
78
|
+
const controller = new AbortController();
|
|
79
|
+
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
80
|
+
fetch(url, {
|
|
81
|
+
method,
|
|
82
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
83
|
+
body: method !== "GET" && method !== "HEAD" ? body : void 0,
|
|
84
|
+
signal: controller.signal
|
|
85
|
+
}).then(async (res) => {
|
|
86
|
+
if (timeout) clearTimeout(timeout);
|
|
87
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
88
|
+
this.#notifyFetchComplete(fetchId, res.status, bytes, false);
|
|
89
|
+
}).catch((err) => {
|
|
90
|
+
if (timeout) clearTimeout(timeout);
|
|
91
|
+
const msg = err.name === "AbortError" ? "Request timeout" : err.message ?? "Fetch failed";
|
|
92
|
+
this.#notifyFetchComplete(fetchId, 0, msg, true);
|
|
93
|
+
});
|
|
226
94
|
}
|
|
227
|
-
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
246
|
-
return writeBytes(buf_ptr, buf_max, bytes);
|
|
247
|
-
} catch (err) {
|
|
248
|
-
if (timeout)
|
|
249
|
-
clearTimeout(timeout);
|
|
250
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
251
|
-
console.error(`wasm fetch failed: ${url} (${msg})`);
|
|
252
|
-
return -1;
|
|
95
|
+
#notifyFetchComplete(fetchId, status, body, isError) {
|
|
96
|
+
const encoded = typeof body === "string" ? encoder.encode(body) : body;
|
|
97
|
+
const ptr = this.#alloc(encoded.length);
|
|
98
|
+
this.#writeBytes(ptr, encoded);
|
|
99
|
+
this.#fetchCompleteHandler(fetchId, status, ptr, encoded.length, isError ? 1 : 0);
|
|
100
|
+
}
|
|
101
|
+
setTimeout(callbackId, delayMs) {
|
|
102
|
+
setTimeout(() => this.#cb?.(3, callbackId, 0n), delayMs);
|
|
103
|
+
}
|
|
104
|
+
setInterval(callbackId, intervalMs) {
|
|
105
|
+
const handle = setInterval(() => this.#cb?.(4, callbackId, 0n), intervalMs);
|
|
106
|
+
this.#intervals.set(callbackId, handle);
|
|
107
|
+
}
|
|
108
|
+
clearInterval(callbackId) {
|
|
109
|
+
const handle = this.#intervals.get(callbackId);
|
|
110
|
+
if (handle !== void 0) {
|
|
111
|
+
clearInterval(handle);
|
|
112
|
+
this.#intervals.delete(callbackId);
|
|
253
113
|
}
|
|
254
114
|
}
|
|
255
|
-
|
|
256
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Create the WASI import object for WASM instantiation.
|
|
117
|
+
*
|
|
118
|
+
* Returns only the `__zx` namespace (log, fetch, timers).
|
|
119
|
+
* Does NOT include jsz.importObject() - the server binary does not use jsz.
|
|
120
|
+
*/
|
|
121
|
+
static createImportObject(bridgeRef) {
|
|
257
122
|
return {
|
|
258
|
-
fetch: (_url_ptr, _url_len, _method_ptr, _method_len, _headers_ptr, _headers_len, _body_ptr, _body_len, _timeout_ms, _status_out, _buf_ptr, _buf_max) => -1
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
return {
|
|
262
|
-
fetch: new Suspending(doFetch)
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// src/wasm/core.ts
|
|
267
|
-
var CallbackType = {
|
|
268
|
-
Event: 0,
|
|
269
|
-
FetchSuccess: 1,
|
|
270
|
-
FetchError: 2,
|
|
271
|
-
Timeout: 3,
|
|
272
|
-
Interval: 4,
|
|
273
|
-
WebSocketOpen: 5,
|
|
274
|
-
WebSocketMessage: 6,
|
|
275
|
-
WebSocketError: 7,
|
|
276
|
-
WebSocketClose: 8
|
|
277
|
-
};
|
|
278
|
-
var jsz = new ZigJS;
|
|
279
|
-
var tempRefBuffer = new ArrayBuffer(8);
|
|
280
|
-
var tempRefView = new DataView(tempRefBuffer);
|
|
281
|
-
function storeValueGetRef(val) {
|
|
282
|
-
const originalMemory = jsz.memory;
|
|
283
|
-
jsz.memory = { buffer: tempRefBuffer };
|
|
284
|
-
jsz.storeValue(0, val);
|
|
285
|
-
jsz.memory = originalMemory;
|
|
286
|
-
return tempRefView.getBigUint64(0, true);
|
|
287
|
-
}
|
|
288
|
-
var textDecoder = new TextDecoder;
|
|
289
|
-
var textEncoder = new TextEncoder;
|
|
290
|
-
var memoryView = null;
|
|
291
|
-
var memoryBuffer = null;
|
|
292
|
-
function getMemoryView() {
|
|
293
|
-
const buf = jsz.memory.buffer;
|
|
294
|
-
if (buf !== memoryBuffer) {
|
|
295
|
-
memoryBuffer = buf;
|
|
296
|
-
memoryView = new Uint8Array(buf);
|
|
297
|
-
}
|
|
298
|
-
return memoryView;
|
|
299
|
-
}
|
|
300
|
-
var stringCache = new Map;
|
|
301
|
-
function stringCacheKey(ptr, len) {
|
|
302
|
-
return ptr * 65536 + len;
|
|
303
|
-
}
|
|
304
|
-
function readString(ptr, len) {
|
|
305
|
-
const key = stringCacheKey(ptr, len);
|
|
306
|
-
const cached = stringCache.get(key);
|
|
307
|
-
if (cached !== undefined)
|
|
308
|
-
return cached;
|
|
309
|
-
const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
310
|
-
stringCache.set(key, str);
|
|
311
|
-
return str;
|
|
312
|
-
}
|
|
313
|
-
function writeBytes(ptr, data) {
|
|
314
|
-
getMemoryView().set(data, ptr);
|
|
315
|
-
}
|
|
316
|
-
function wrapPromisingExport(fn) {
|
|
317
|
-
if (!fn)
|
|
318
|
-
return;
|
|
319
|
-
const promising = WebAssembly.promising;
|
|
320
|
-
if (typeof promising !== "function")
|
|
321
|
-
return fn;
|
|
322
|
-
return promising(fn);
|
|
323
|
-
}
|
|
324
|
-
function invokeWasmExport(fn, ...args) {
|
|
325
|
-
if (!fn)
|
|
326
|
-
return;
|
|
327
|
-
const result = fn(...args);
|
|
328
|
-
if (result && typeof result.then === "function") {
|
|
329
|
-
result.then(undefined, (error) => {
|
|
330
|
-
console.error(error);
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
class ZxBridgeCore {
|
|
336
|
-
#intervals = new Map;
|
|
337
|
-
_alloc;
|
|
338
|
-
#handler;
|
|
339
|
-
#fetchCompleteHandler;
|
|
340
|
-
constructor(exports) {
|
|
341
|
-
this._alloc = exports.__zx_alloc;
|
|
342
|
-
this.#handler = wrapPromisingExport(exports.__zx_cb);
|
|
343
|
-
const fetchCompleteHandler = wrapPromisingExport(exports.__zx_fetch_complete);
|
|
344
|
-
if (!fetchCompleteHandler) {
|
|
345
|
-
throw new Error("__zx_fetch_complete not exported from WASM");
|
|
346
|
-
}
|
|
347
|
-
this.#fetchCompleteHandler = fetchCompleteHandler;
|
|
348
|
-
if (exports.memory)
|
|
349
|
-
jsz.memory = exports.memory;
|
|
350
|
-
}
|
|
351
|
-
#invoke(type, id, data) {
|
|
352
|
-
const handler = this.#handler;
|
|
353
|
-
if (!handler) {
|
|
354
|
-
console.warn("__zx_cb not exported from WASM");
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
const dataRef = storeValueGetRef(data);
|
|
358
|
-
invokeWasmExport(handler, type, id, dataRef);
|
|
359
|
-
}
|
|
360
|
-
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
361
|
-
const url = readString(urlPtr, urlLen);
|
|
362
|
-
const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
|
|
363
|
-
const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
|
|
364
|
-
const body = bodyLen > 0 ? getMemoryView().subarray(bodyPtr, bodyPtr + bodyLen) : undefined;
|
|
365
|
-
let headers = {};
|
|
366
|
-
try {
|
|
367
|
-
headers = JSON.parse(headersJson);
|
|
368
|
-
} catch {
|
|
369
|
-
for (const line of headersJson.split(`
|
|
370
|
-
`)) {
|
|
371
|
-
const colonIdx = line.indexOf(":");
|
|
372
|
-
if (colonIdx > 0) {
|
|
373
|
-
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
const controller = new AbortController;
|
|
378
|
-
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
379
|
-
const fetchOptions = {
|
|
380
|
-
method,
|
|
381
|
-
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
382
|
-
body: method !== "GET" && method !== "HEAD" ? body : undefined,
|
|
383
|
-
signal: controller.signal
|
|
384
|
-
};
|
|
385
|
-
fetch(url, fetchOptions).then(async (response) => {
|
|
386
|
-
if (timeout)
|
|
387
|
-
clearTimeout(timeout);
|
|
388
|
-
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
389
|
-
this._notifyFetchComplete(fetchId, response.status, bytes, false);
|
|
390
|
-
}).catch((error) => {
|
|
391
|
-
if (timeout)
|
|
392
|
-
clearTimeout(timeout);
|
|
393
|
-
const isAbort = error.name === "AbortError";
|
|
394
|
-
const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
|
|
395
|
-
this._notifyFetchComplete(fetchId, 0, errorMsg, true);
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
_notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
399
|
-
const handler = this.#fetchCompleteHandler;
|
|
400
|
-
const encoded = typeof body === "string" ? textEncoder.encode(body) : body;
|
|
401
|
-
const ptr = this._alloc(encoded.length);
|
|
402
|
-
writeBytes(ptr, encoded);
|
|
403
|
-
invokeWasmExport(handler, fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
404
|
-
}
|
|
405
|
-
setTimeout(callbackId, delayMs) {
|
|
406
|
-
setTimeout(() => {
|
|
407
|
-
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
408
|
-
}, delayMs);
|
|
409
|
-
}
|
|
410
|
-
setInterval(callbackId, intervalMs) {
|
|
411
|
-
const handle = setInterval(() => {
|
|
412
|
-
this.#invoke(CallbackType.Interval, callbackId, null);
|
|
413
|
-
}, intervalMs);
|
|
414
|
-
this.#intervals.set(callbackId, handle);
|
|
415
|
-
}
|
|
416
|
-
clearInterval(callbackId) {
|
|
417
|
-
const handle = this.#intervals.get(callbackId);
|
|
418
|
-
if (handle !== undefined) {
|
|
419
|
-
clearInterval(handle);
|
|
420
|
-
this.#intervals.delete(callbackId);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
dispose() {
|
|
424
|
-
for (const handle of this.#intervals.values()) {
|
|
425
|
-
clearInterval(handle);
|
|
426
|
-
}
|
|
427
|
-
this.#intervals.clear();
|
|
428
|
-
}
|
|
429
|
-
_writeStringToWasm(str) {
|
|
430
|
-
return this._writeBytesToWasm(textEncoder.encode(str));
|
|
431
|
-
}
|
|
432
|
-
_writeBytesToWasm(data) {
|
|
433
|
-
const ptr = this._alloc(data.length);
|
|
434
|
-
writeBytes(ptr, data);
|
|
435
|
-
return { ptr, len: data.length };
|
|
436
|
-
}
|
|
437
|
-
static log(level, ptr, len) {
|
|
438
|
-
const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
439
|
-
switch (level) {
|
|
440
|
-
case 0:
|
|
441
|
-
console.error(msg);
|
|
442
|
-
break;
|
|
443
|
-
case 1:
|
|
444
|
-
console.warn(msg);
|
|
445
|
-
break;
|
|
446
|
-
case 3:
|
|
447
|
-
console.debug(msg);
|
|
448
|
-
break;
|
|
449
|
-
default:
|
|
450
|
-
console.log(msg);
|
|
451
|
-
break;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
static createImportObject(bridgeRef) {
|
|
455
|
-
return {
|
|
456
|
-
...jsz.importObject(),
|
|
457
|
-
__zx_net: createFetchImports(() => {
|
|
458
|
-
if (!jsz.memory)
|
|
459
|
-
throw new Error("WASM memory is not ready");
|
|
460
|
-
return jsz.memory;
|
|
461
|
-
}),
|
|
462
123
|
__zx: {
|
|
463
|
-
_log: (level, ptr, len) =>
|
|
124
|
+
_log: (level, ptr, len) => {
|
|
125
|
+
bridgeRef.current?.log(level, ptr, len);
|
|
126
|
+
},
|
|
464
127
|
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
465
|
-
bridgeRef.current?.fetchAsync(
|
|
128
|
+
bridgeRef.current?.fetchAsync(
|
|
129
|
+
urlPtr,
|
|
130
|
+
urlLen,
|
|
131
|
+
methodPtr,
|
|
132
|
+
methodLen,
|
|
133
|
+
headersPtr,
|
|
134
|
+
headersLen,
|
|
135
|
+
bodyPtr,
|
|
136
|
+
bodyLen,
|
|
137
|
+
timeoutMs,
|
|
138
|
+
fetchId
|
|
139
|
+
);
|
|
466
140
|
},
|
|
467
141
|
_setTimeout: (callbackId, delayMs) => {
|
|
468
142
|
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
@@ -476,25 +150,24 @@ class ZxBridgeCore {
|
|
|
476
150
|
}
|
|
477
151
|
};
|
|
478
152
|
}
|
|
479
|
-
}
|
|
153
|
+
};
|
|
154
|
+
|
|
480
155
|
// src/kv.ts
|
|
481
|
-
var
|
|
482
|
-
__export(
|
|
483
|
-
|
|
484
|
-
|
|
156
|
+
var kv_exports = {};
|
|
157
|
+
__export(kv_exports, {
|
|
158
|
+
createKVImports: () => createKVImports,
|
|
159
|
+
createMemoryKV: () => createMemoryKV
|
|
485
160
|
});
|
|
486
161
|
function putOptions(ttlSeconds) {
|
|
487
|
-
if (ttlSeconds < 60)
|
|
488
|
-
return;
|
|
162
|
+
if (ttlSeconds < 60) return void 0;
|
|
489
163
|
return { expirationTtl: ttlSeconds };
|
|
490
164
|
}
|
|
491
165
|
function createMemoryKV() {
|
|
492
|
-
const store = new Map;
|
|
166
|
+
const store = /* @__PURE__ */ new Map();
|
|
493
167
|
function read(key) {
|
|
494
168
|
const entry = store.get(key);
|
|
495
|
-
if (!entry)
|
|
496
|
-
|
|
497
|
-
if (entry.expiresAt !== undefined && Date.now() >= entry.expiresAt) {
|
|
169
|
+
if (!entry) return null;
|
|
170
|
+
if (entry.expiresAt !== void 0 && Date.now() >= entry.expiresAt) {
|
|
498
171
|
store.delete(key);
|
|
499
172
|
return null;
|
|
500
173
|
}
|
|
@@ -502,10 +175,10 @@ function createMemoryKV() {
|
|
|
502
175
|
}
|
|
503
176
|
function write(key, value, options) {
|
|
504
177
|
let expiresAt;
|
|
505
|
-
if (options?.expiration !==
|
|
506
|
-
expiresAt = options.expiration *
|
|
507
|
-
} else if (options?.expirationTtl !==
|
|
508
|
-
expiresAt = Date.now() + options.expirationTtl *
|
|
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;
|
|
509
182
|
}
|
|
510
183
|
store.set(key, { value, expiresAt });
|
|
511
184
|
}
|
|
@@ -521,8 +194,7 @@ function createMemoryKV() {
|
|
|
521
194
|
},
|
|
522
195
|
async list(options) {
|
|
523
196
|
const keys = [...store.keys()].filter((k) => {
|
|
524
|
-
if (options?.prefix && !k.startsWith(options.prefix))
|
|
525
|
-
return false;
|
|
197
|
+
if (options?.prefix && !k.startsWith(options.prefix)) return false;
|
|
526
198
|
return read(k) !== null;
|
|
527
199
|
}).map((name) => ({ name }));
|
|
528
200
|
return { keys };
|
|
@@ -534,14 +206,13 @@ function isSyncKVNamespace(binding) {
|
|
|
534
206
|
return typeof candidate.getSync === "function" && typeof candidate.putSync === "function" && typeof candidate.deleteSync === "function" && typeof candidate.listSync === "function";
|
|
535
207
|
}
|
|
536
208
|
function createKVImports(bindings, getMemory) {
|
|
537
|
-
const
|
|
538
|
-
const
|
|
209
|
+
const encoder3 = new TextEncoder();
|
|
210
|
+
const decoder3 = new TextDecoder();
|
|
539
211
|
function readStr(ptr, len) {
|
|
540
|
-
return
|
|
212
|
+
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
541
213
|
}
|
|
542
214
|
function writeBytes2(buf_ptr, buf_max, data) {
|
|
543
|
-
if (data.length > buf_max)
|
|
544
|
-
return -2;
|
|
215
|
+
if (data.length > buf_max) return -2;
|
|
545
216
|
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
546
217
|
return data.length;
|
|
547
218
|
}
|
|
@@ -550,1158 +221,314 @@ function createKVImports(bindings, getMemory) {
|
|
|
550
221
|
}
|
|
551
222
|
const Suspending = WebAssembly.Suspending;
|
|
552
223
|
if (typeof Suspending !== "function") {
|
|
553
|
-
let
|
|
224
|
+
let syncBinding2 = function(ns) {
|
|
554
225
|
const candidate = binding(ns);
|
|
555
226
|
return candidate && isSyncKVNamespace(candidate) ? candidate : null;
|
|
556
227
|
};
|
|
228
|
+
var syncBinding = syncBinding2;
|
|
557
229
|
return {
|
|
558
230
|
kv_get: (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
559
|
-
const b =
|
|
560
|
-
if (!b)
|
|
561
|
-
return -1;
|
|
231
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
232
|
+
if (!b) return -1;
|
|
562
233
|
const value = b.getSync(readStr(key_ptr, key_len));
|
|
563
|
-
if (value === null)
|
|
564
|
-
|
|
565
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
234
|
+
if (value === null) return -1;
|
|
235
|
+
return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
|
|
566
236
|
},
|
|
567
237
|
kv_put: (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
568
|
-
const b =
|
|
569
|
-
if (!b)
|
|
570
|
-
return 0;
|
|
238
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
239
|
+
if (!b) return 0;
|
|
571
240
|
b.putSync(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
572
241
|
return 0;
|
|
573
242
|
},
|
|
574
243
|
kv_delete: (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
575
|
-
const b =
|
|
576
|
-
if (!b)
|
|
577
|
-
return 0;
|
|
244
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
245
|
+
if (!b) return 0;
|
|
578
246
|
b.deleteSync(readStr(key_ptr, key_len));
|
|
579
247
|
return 0;
|
|
580
248
|
},
|
|
581
249
|
kv_list: (ns_ptr, ns_len, pfx_ptr, pfx_len, buf_ptr, buf_max) => {
|
|
582
|
-
const b =
|
|
583
|
-
if (!b)
|
|
584
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
250
|
+
const b = syncBinding2(readStr(ns_ptr, ns_len));
|
|
251
|
+
if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
|
|
585
252
|
const prefix = readStr(pfx_ptr, pfx_len);
|
|
586
|
-
const result = b.listSync(prefix.length > 0 ? { prefix } :
|
|
587
|
-
return writeBytes2(buf_ptr, buf_max,
|
|
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))));
|
|
588
255
|
}
|
|
589
256
|
};
|
|
590
257
|
}
|
|
591
258
|
return {
|
|
592
259
|
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
593
260
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
594
|
-
if (!b)
|
|
595
|
-
return -1;
|
|
261
|
+
if (!b) return -1;
|
|
596
262
|
const value = await b.get(readStr(key_ptr, key_len));
|
|
597
|
-
if (value === null)
|
|
598
|
-
|
|
599
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
263
|
+
if (value === null) return -1;
|
|
264
|
+
return writeBytes2(buf_ptr, buf_max, encoder3.encode(value));
|
|
600
265
|
}),
|
|
601
266
|
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len, ttl_seconds) => {
|
|
602
267
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
603
|
-
if (!b)
|
|
604
|
-
return -1;
|
|
268
|
+
if (!b) return -1;
|
|
605
269
|
await b.put(readStr(key_ptr, key_len), readStr(val_ptr, val_len), putOptions(ttl_seconds));
|
|
606
270
|
return 0;
|
|
607
271
|
}),
|
|
608
272
|
kv_delete: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len) => {
|
|
609
273
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
610
|
-
if (!b)
|
|
611
|
-
return -1;
|
|
274
|
+
if (!b) return -1;
|
|
612
275
|
await b.delete(readStr(key_ptr, key_len));
|
|
613
276
|
return 0;
|
|
614
277
|
}),
|
|
615
278
|
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
616
279
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
617
|
-
if (!b)
|
|
618
|
-
return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
280
|
+
if (!b) return writeBytes2(buf_ptr, buf_max, encoder3.encode("[]"));
|
|
619
281
|
const prefix = readStr(prefix_ptr, prefix_len);
|
|
620
|
-
const result = await b.list(prefix.length > 0 ? { prefix } :
|
|
621
|
-
return writeBytes2(buf_ptr, buf_max,
|
|
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))));
|
|
622
284
|
})
|
|
623
285
|
};
|
|
624
286
|
}
|
|
625
287
|
|
|
626
|
-
// src/
|
|
627
|
-
function
|
|
628
|
-
|
|
629
|
-
|
|
288
|
+
// src/fetch.ts
|
|
289
|
+
function createFetchImports(getMemory) {
|
|
290
|
+
const encoder3 = new TextEncoder();
|
|
291
|
+
const decoder3 = new TextDecoder();
|
|
292
|
+
function readStr(ptr, len) {
|
|
293
|
+
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
630
294
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
639
|
-
function
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const namespace = options.namespace ?? "default";
|
|
650
|
-
const dbPromise = new Promise((resolve, reject) => {
|
|
651
|
-
const request = getIndexedDb().open(databaseName, 1);
|
|
652
|
-
request.onupgradeneeded = () => {
|
|
653
|
-
const db = request.result;
|
|
654
|
-
if (!db.objectStoreNames.contains(storeName)) {
|
|
655
|
-
db.createObjectStore(storeName);
|
|
295
|
+
function writeBytes2(buf_ptr, buf_max, data) {
|
|
296
|
+
if (data.length > buf_max) return -2;
|
|
297
|
+
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
298
|
+
return data.length;
|
|
299
|
+
}
|
|
300
|
+
function readBytes(ptr, len) {
|
|
301
|
+
return new Uint8Array(getMemory().buffer, ptr, len);
|
|
302
|
+
}
|
|
303
|
+
function parseHeaders(headersJson) {
|
|
304
|
+
let headers = {};
|
|
305
|
+
try {
|
|
306
|
+
headers = JSON.parse(headersJson);
|
|
307
|
+
} catch {
|
|
308
|
+
for (const line of headersJson.split("\n")) {
|
|
309
|
+
const colonIdx = line.indexOf(":");
|
|
310
|
+
if (colonIdx > 0) {
|
|
311
|
+
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
312
|
+
}
|
|
656
313
|
}
|
|
657
|
-
};
|
|
658
|
-
request.onsuccess = () => resolve(request.result);
|
|
659
|
-
request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB"));
|
|
660
|
-
});
|
|
661
|
-
const scopedKey = (key) => `${namespace}:${key}`;
|
|
662
|
-
return {
|
|
663
|
-
async get(key) {
|
|
664
|
-
const db = await dbPromise;
|
|
665
|
-
const tx = db.transaction(storeName, "readonly");
|
|
666
|
-
const store = tx.objectStore(storeName);
|
|
667
|
-
const value = await requestToPromise(store.get(scopedKey(key)));
|
|
668
|
-
await transactionToPromise(tx);
|
|
669
|
-
console.debug(`KV GET - Key: ${key}, Value: ${value}`);
|
|
670
|
-
return typeof value === "string" ? value : null;
|
|
671
|
-
},
|
|
672
|
-
async put(key, value) {
|
|
673
|
-
const db = await dbPromise;
|
|
674
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
675
|
-
tx.objectStore(storeName).put(value, scopedKey(key));
|
|
676
|
-
await transactionToPromise(tx);
|
|
677
|
-
console.debug(`KV PUT - Key: ${key}, Value: ${value}`);
|
|
678
|
-
},
|
|
679
|
-
async delete(key) {
|
|
680
|
-
const db = await dbPromise;
|
|
681
|
-
const tx = db.transaction(storeName, "readwrite");
|
|
682
|
-
tx.objectStore(storeName).delete(scopedKey(key));
|
|
683
|
-
await transactionToPromise(tx);
|
|
684
|
-
},
|
|
685
|
-
async list(options2) {
|
|
686
|
-
const db = await dbPromise;
|
|
687
|
-
const tx = db.transaction(storeName, "readonly");
|
|
688
|
-
const store = tx.objectStore(storeName);
|
|
689
|
-
const keys = await requestToPromise(store.getAllKeys());
|
|
690
|
-
await transactionToPromise(tx);
|
|
691
|
-
const prefix = scopedKey(options2?.prefix ?? "");
|
|
692
|
-
return {
|
|
693
|
-
keys: keys.filter((key) => typeof key === "string" && key.startsWith(prefix)).map((key) => ({ name: key.slice(namespace.length + 1) }))
|
|
694
|
-
};
|
|
695
314
|
}
|
|
696
|
-
|
|
697
|
-
}
|
|
698
|
-
function getLocalStorage() {
|
|
699
|
-
if (typeof localStorage === "undefined") {
|
|
700
|
-
throw new Error("localStorage is not available in this environment");
|
|
315
|
+
return headers;
|
|
701
316
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
async delete(key) {
|
|
727
|
-
this.deleteSync(key);
|
|
728
|
-
},
|
|
729
|
-
listSync(options2) {
|
|
730
|
-
const prefix = namespacePrefix + (options2?.prefix ?? "");
|
|
731
|
-
const keys = [];
|
|
732
|
-
for (let i = 0;i < storage.length; i += 1) {
|
|
733
|
-
const key = storage.key(i);
|
|
734
|
-
if (!key || !key.startsWith(prefix))
|
|
735
|
-
continue;
|
|
736
|
-
keys.push({ name: key.slice(namespacePrefix.length) });
|
|
737
|
-
}
|
|
738
|
-
return { keys };
|
|
739
|
-
},
|
|
740
|
-
async list(options2) {
|
|
741
|
-
return this.listSync(options2);
|
|
317
|
+
async function doFetch(url_ptr, url_len, method_ptr, method_len, headers_ptr, headers_len, body_ptr, body_len, timeout_ms, status_out, buf_ptr, buf_max) {
|
|
318
|
+
const url = readStr(url_ptr, url_len);
|
|
319
|
+
const method = method_len > 0 ? readStr(method_ptr, method_len) : "GET";
|
|
320
|
+
const headersJson = headers_len > 0 ? readStr(headers_ptr, headers_len) : "{}";
|
|
321
|
+
const body = body_len > 0 ? readBytes(body_ptr, body_len) : void 0;
|
|
322
|
+
const headers = parseHeaders(headersJson);
|
|
323
|
+
const controller = new AbortController();
|
|
324
|
+
const timeout = timeout_ms > 0 ? setTimeout(() => controller.abort(), timeout_ms) : null;
|
|
325
|
+
try {
|
|
326
|
+
const response = await fetch(url, {
|
|
327
|
+
method,
|
|
328
|
+
headers: Object.keys(headers).length > 0 ? headers : void 0,
|
|
329
|
+
body: method !== "GET" && method !== "HEAD" ? body : void 0,
|
|
330
|
+
signal: controller.signal
|
|
331
|
+
});
|
|
332
|
+
if (timeout) clearTimeout(timeout);
|
|
333
|
+
new DataView(getMemory().buffer).setUint16(status_out, response.status, true);
|
|
334
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
335
|
+
return writeBytes2(buf_ptr, buf_max, bytes);
|
|
336
|
+
} catch (err) {
|
|
337
|
+
if (timeout) clearTimeout(timeout);
|
|
338
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
339
|
+
console.error(`wasm fetch failed: ${url} (${msg})`);
|
|
340
|
+
return -1;
|
|
742
341
|
}
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
342
|
+
}
|
|
343
|
+
const Suspending = WebAssembly.Suspending;
|
|
344
|
+
if (typeof Suspending !== "function") {
|
|
345
|
+
return {
|
|
346
|
+
fetch: (_url_ptr, _url_len, _method_ptr, _method_len, _headers_ptr, _headers_len, _body_ptr, _body_len, _timeout_ms, _status_out, _buf_ptr, _buf_max) => -1
|
|
347
|
+
};
|
|
348
|
+
}
|
|
750
349
|
return {
|
|
751
|
-
|
|
350
|
+
fetch: new Suspending(doFetch)
|
|
752
351
|
};
|
|
753
352
|
}
|
|
754
353
|
|
|
755
|
-
// src/
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
354
|
+
// src/db.ts
|
|
355
|
+
function decodeBlob(base64) {
|
|
356
|
+
const binary = atob(base64);
|
|
357
|
+
const bytes = new Uint8Array(binary.length);
|
|
358
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
359
|
+
return bytes;
|
|
360
|
+
}
|
|
361
|
+
function toD1Value(value) {
|
|
362
|
+
switch (value.kind) {
|
|
363
|
+
case "null":
|
|
364
|
+
return null;
|
|
365
|
+
case "integer":
|
|
366
|
+
return value.integer;
|
|
367
|
+
case "float":
|
|
368
|
+
return value.float;
|
|
369
|
+
case "text":
|
|
370
|
+
return value.text;
|
|
371
|
+
case "blob":
|
|
372
|
+
return decodeBlob(value.blob);
|
|
373
|
+
case "boolean":
|
|
374
|
+
return value.boolean;
|
|
772
375
|
}
|
|
773
|
-
|
|
774
|
-
|
|
376
|
+
}
|
|
377
|
+
function toPositionalBindings(json) {
|
|
378
|
+
switch (json.kind) {
|
|
379
|
+
case "none":
|
|
380
|
+
return [];
|
|
381
|
+
case "positional":
|
|
382
|
+
return json.values.map(toD1Value);
|
|
383
|
+
case "named":
|
|
384
|
+
throw new Error("Cloudflare D1 adapter does not support named bindings yet");
|
|
775
385
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
eventHandlerModes.set(velementId, next);
|
|
386
|
+
}
|
|
387
|
+
function toWireValue(value) {
|
|
388
|
+
if (value === null || value === void 0) return { kind: "null" };
|
|
389
|
+
if (typeof value === "string") return { kind: "text", text: value };
|
|
390
|
+
if (typeof value === "boolean") return { kind: "boolean", boolean: value };
|
|
391
|
+
if (typeof value === "number") {
|
|
392
|
+
return Number.isInteger(value) ? { kind: "integer", integer: value } : { kind: "float", float: value };
|
|
784
393
|
}
|
|
785
|
-
|
|
786
|
-
|
|
394
|
+
if (value instanceof ArrayBuffer) {
|
|
395
|
+
const bytes = new Uint8Array(value);
|
|
396
|
+
let binary = "";
|
|
397
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
398
|
+
return { kind: "blob", blob: btoa(binary) };
|
|
787
399
|
}
|
|
788
|
-
|
|
789
|
-
const
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
headers: { "x-action": String(actionId >>> 0) },
|
|
794
|
-
body: formData
|
|
795
|
-
}).then(async (response) => {
|
|
796
|
-
const text = await response.text();
|
|
797
|
-
this._notifyFetchComplete(fetchId, response.status, text, false);
|
|
798
|
-
}).catch((error) => {
|
|
799
|
-
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
800
|
-
this._notifyFetchComplete(fetchId, 0, msg, true);
|
|
801
|
-
});
|
|
400
|
+
if (ArrayBuffer.isView(value)) {
|
|
401
|
+
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
402
|
+
let binary = "";
|
|
403
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
404
|
+
return { kind: "blob", blob: btoa(binary) };
|
|
802
405
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
return;
|
|
822
|
-
const isBinary = event.data instanceof ArrayBuffer;
|
|
823
|
-
const data = isBinary ? new Uint8Array(event.data) : textEncoder.encode(event.data);
|
|
824
|
-
const { ptr, len } = this._writeBytesToWasm(data);
|
|
825
|
-
invokeWasmExport(handler, wsId, ptr, len, isBinary ? 1 : 0);
|
|
826
|
-
};
|
|
827
|
-
ws.onerror = (_event) => {
|
|
828
|
-
const handler = this.#wsOnErrorHandler;
|
|
829
|
-
if (!handler)
|
|
830
|
-
return;
|
|
831
|
-
const { ptr, len } = this._writeStringToWasm("WebSocket error");
|
|
832
|
-
invokeWasmExport(handler, wsId, ptr, len);
|
|
833
|
-
};
|
|
834
|
-
ws.onclose = (event) => {
|
|
835
|
-
const handler = this.#wsOnCloseHandler;
|
|
836
|
-
if (!handler)
|
|
837
|
-
return;
|
|
838
|
-
const reason = event.reason || "";
|
|
839
|
-
const { ptr, len } = this._writeStringToWasm(reason);
|
|
840
|
-
invokeWasmExport(handler, wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
841
|
-
this.#websockets.delete(wsId);
|
|
842
|
-
};
|
|
843
|
-
this.#websockets.set(wsId, ws);
|
|
844
|
-
} catch (error) {
|
|
845
|
-
const handler = this.#wsOnErrorHandler;
|
|
846
|
-
if (handler) {
|
|
847
|
-
const msg = error instanceof Error ? error.message : "WebSocket connection failed";
|
|
848
|
-
const { ptr, len } = this._writeStringToWasm(msg);
|
|
849
|
-
invokeWasmExport(handler, wsId, ptr, len);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
406
|
+
return { kind: "text", text: String(value) };
|
|
407
|
+
}
|
|
408
|
+
function objectToWireRow(record) {
|
|
409
|
+
return {
|
|
410
|
+
fields: Object.entries(record).map(([name, value]) => ({
|
|
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));
|
|
852
424
|
}
|
|
853
|
-
|
|
854
|
-
const
|
|
855
|
-
if (
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
if (isBinary) {
|
|
859
|
-
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
860
|
-
} else {
|
|
861
|
-
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
862
|
-
}
|
|
425
|
+
function writeJson(buf_ptr, buf_max, value) {
|
|
426
|
+
const data = encoder3.encode(JSON.stringify(value));
|
|
427
|
+
if (data.length > buf_max) return -2;
|
|
428
|
+
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
429
|
+
return data.length;
|
|
863
430
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
if (!ws)
|
|
867
|
-
return;
|
|
868
|
-
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
|
|
869
|
-
try {
|
|
870
|
-
if (reason)
|
|
871
|
-
ws.close(code, reason);
|
|
872
|
-
else
|
|
873
|
-
ws.close(code);
|
|
874
|
-
} catch {
|
|
875
|
-
ws.close();
|
|
876
|
-
}
|
|
431
|
+
function binding(ns) {
|
|
432
|
+
return bindings[ns] ?? bindings["default"] ?? null;
|
|
877
433
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
} catch {}
|
|
885
|
-
}
|
|
886
|
-
this.#websockets.clear();
|
|
434
|
+
async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
|
|
435
|
+
const database = binding(readStr(ns_ptr, ns_len));
|
|
436
|
+
if (!database) return null;
|
|
437
|
+
const sql = readStr(sql_ptr, sql_len);
|
|
438
|
+
const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
|
|
439
|
+
return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
|
|
887
440
|
}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
parent.appendChild(child);
|
|
980
|
-
},
|
|
981
|
-
_ib: (parentId, childId, refId) => {
|
|
982
|
-
const parent = domNodes.get(parentId);
|
|
983
|
-
const child = domNodes.get(childId);
|
|
984
|
-
const ref = domNodes.get(refId) ?? null;
|
|
985
|
-
if (parent && child)
|
|
986
|
-
parent.insertBefore(child, ref);
|
|
987
|
-
},
|
|
988
|
-
_rc: (parentId, childId) => {
|
|
989
|
-
const parent = domNodes.get(parentId);
|
|
990
|
-
const child = domNodes.get(childId);
|
|
991
|
-
if (parent && child) {
|
|
992
|
-
parent.removeChild(child);
|
|
993
|
-
cleanupDomNodes(child);
|
|
994
|
-
}
|
|
995
|
-
},
|
|
996
|
-
_rpc: (parentId, newId, oldId) => {
|
|
997
|
-
const parent = domNodes.get(parentId);
|
|
998
|
-
const newChild = domNodes.get(newId);
|
|
999
|
-
const oldChild = domNodes.get(oldId);
|
|
1000
|
-
if (parent && newChild && oldChild) {
|
|
1001
|
-
parent.replaceChild(newChild, oldChild);
|
|
1002
|
-
cleanupDomNodes(oldChild);
|
|
1003
|
-
}
|
|
1004
|
-
},
|
|
1005
|
-
_getLocationHref: (bufPtr, bufLen) => {
|
|
1006
|
-
const bytes = textEncoder.encode(window.location.href);
|
|
1007
|
-
const len = Math.min(bytes.length, bufLen);
|
|
1008
|
-
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
1009
|
-
return len;
|
|
1010
|
-
},
|
|
1011
|
-
_getFormData: (vnodeId, bufPtr, bufLen) => {
|
|
1012
|
-
const form = domNodes.get(vnodeId);
|
|
1013
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
1014
|
-
return 0;
|
|
1015
|
-
const formData = new FormData(form);
|
|
1016
|
-
const urlEncoded = new URLSearchParams(formData).toString();
|
|
1017
|
-
const bytes = textEncoder.encode(urlEncoded);
|
|
1018
|
-
const len = Math.min(bytes.length, bufLen);
|
|
1019
|
-
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
1020
|
-
return len;
|
|
1021
|
-
},
|
|
1022
|
-
_submitFormAction: (vnodeId, actionId) => {
|
|
1023
|
-
const form = domNodes.get(vnodeId);
|
|
1024
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
1025
|
-
return;
|
|
1026
|
-
const formData = new FormData(form);
|
|
1027
|
-
fetch(window.location.href, {
|
|
1028
|
-
method: "POST",
|
|
1029
|
-
headers: { "x-action": String(actionId >>> 0) },
|
|
1030
|
-
body: formData
|
|
1031
|
-
}).catch(() => {});
|
|
1032
|
-
},
|
|
1033
|
-
_submitFormActionAsync: (vnodeId, actionId, statesPtr, statesLen, fetchId) => {
|
|
1034
|
-
const form = domNodes.get(vnodeId);
|
|
1035
|
-
if (!form || !(form instanceof HTMLFormElement))
|
|
1036
|
-
return;
|
|
1037
|
-
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
1038
|
-
bridgeRef.current?.submitFormActionAsync(form, actionId, statesJson, fetchId);
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
};
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
var domNodes = new Map;
|
|
1045
|
-
function cleanupDomNodes(node) {
|
|
1046
|
-
const ref = node.__zx_ref;
|
|
1047
|
-
if (ref !== undefined)
|
|
1048
|
-
domNodes.delete(BigInt(ref));
|
|
1049
|
-
const children = node.childNodes;
|
|
1050
|
-
for (let i = 0;i < children.length; i++)
|
|
1051
|
-
cleanupDomNodes(children[i]);
|
|
1052
|
-
}
|
|
1053
|
-
var SVG_TAG_START_INDEX = 140;
|
|
1054
|
-
var TAG_NAMES = [
|
|
1055
|
-
"aside",
|
|
1056
|
-
"fragment",
|
|
1057
|
-
"iframe",
|
|
1058
|
-
"slot",
|
|
1059
|
-
"img",
|
|
1060
|
-
"html",
|
|
1061
|
-
"base",
|
|
1062
|
-
"head",
|
|
1063
|
-
"link",
|
|
1064
|
-
"meta",
|
|
1065
|
-
"script",
|
|
1066
|
-
"style",
|
|
1067
|
-
"title",
|
|
1068
|
-
"address",
|
|
1069
|
-
"article",
|
|
1070
|
-
"body",
|
|
1071
|
-
"h1",
|
|
1072
|
-
"h6",
|
|
1073
|
-
"footer",
|
|
1074
|
-
"header",
|
|
1075
|
-
"h2",
|
|
1076
|
-
"h3",
|
|
1077
|
-
"h4",
|
|
1078
|
-
"h5",
|
|
1079
|
-
"hgroup",
|
|
1080
|
-
"nav",
|
|
1081
|
-
"section",
|
|
1082
|
-
"dd",
|
|
1083
|
-
"dl",
|
|
1084
|
-
"dt",
|
|
1085
|
-
"div",
|
|
1086
|
-
"figcaption",
|
|
1087
|
-
"figure",
|
|
1088
|
-
"hr",
|
|
1089
|
-
"li",
|
|
1090
|
-
"ol",
|
|
1091
|
-
"ul",
|
|
1092
|
-
"menu",
|
|
1093
|
-
"main",
|
|
1094
|
-
"p",
|
|
1095
|
-
"picture",
|
|
1096
|
-
"pre",
|
|
1097
|
-
"a",
|
|
1098
|
-
"abbr",
|
|
1099
|
-
"b",
|
|
1100
|
-
"bdi",
|
|
1101
|
-
"bdo",
|
|
1102
|
-
"br",
|
|
1103
|
-
"cite",
|
|
1104
|
-
"code",
|
|
1105
|
-
"data",
|
|
1106
|
-
"time",
|
|
1107
|
-
"dfn",
|
|
1108
|
-
"em",
|
|
1109
|
-
"i",
|
|
1110
|
-
"kbd",
|
|
1111
|
-
"mark",
|
|
1112
|
-
"q",
|
|
1113
|
-
"blockquote",
|
|
1114
|
-
"rp",
|
|
1115
|
-
"ruby",
|
|
1116
|
-
"rt",
|
|
1117
|
-
"rtc",
|
|
1118
|
-
"rb",
|
|
1119
|
-
"s",
|
|
1120
|
-
"del",
|
|
1121
|
-
"ins",
|
|
1122
|
-
"samp",
|
|
1123
|
-
"small",
|
|
1124
|
-
"span",
|
|
1125
|
-
"strong",
|
|
1126
|
-
"sub",
|
|
1127
|
-
"sup",
|
|
1128
|
-
"u",
|
|
1129
|
-
"var",
|
|
1130
|
-
"wbr",
|
|
1131
|
-
"area",
|
|
1132
|
-
"map",
|
|
1133
|
-
"audio",
|
|
1134
|
-
"source",
|
|
1135
|
-
"track",
|
|
1136
|
-
"video",
|
|
1137
|
-
"embed",
|
|
1138
|
-
"object",
|
|
1139
|
-
"param",
|
|
1140
|
-
"canvas",
|
|
1141
|
-
"noscript",
|
|
1142
|
-
"caption",
|
|
1143
|
-
"table",
|
|
1144
|
-
"col",
|
|
1145
|
-
"colgroup",
|
|
1146
|
-
"tbody",
|
|
1147
|
-
"tr",
|
|
1148
|
-
"thead",
|
|
1149
|
-
"tfoot",
|
|
1150
|
-
"td",
|
|
1151
|
-
"th",
|
|
1152
|
-
"button",
|
|
1153
|
-
"datalist",
|
|
1154
|
-
"option",
|
|
1155
|
-
"fieldset",
|
|
1156
|
-
"label",
|
|
1157
|
-
"form",
|
|
1158
|
-
"input",
|
|
1159
|
-
"keygen",
|
|
1160
|
-
"legend",
|
|
1161
|
-
"meter",
|
|
1162
|
-
"optgroup",
|
|
1163
|
-
"select",
|
|
1164
|
-
"output",
|
|
1165
|
-
"progress",
|
|
1166
|
-
"textarea",
|
|
1167
|
-
"details",
|
|
1168
|
-
"dialog",
|
|
1169
|
-
"menuitem",
|
|
1170
|
-
"summary",
|
|
1171
|
-
"content",
|
|
1172
|
-
"element",
|
|
1173
|
-
"shadow",
|
|
1174
|
-
"template",
|
|
1175
|
-
"acronym",
|
|
1176
|
-
"applet",
|
|
1177
|
-
"basefont",
|
|
1178
|
-
"font",
|
|
1179
|
-
"big",
|
|
1180
|
-
"blink",
|
|
1181
|
-
"center",
|
|
1182
|
-
"command",
|
|
1183
|
-
"dir",
|
|
1184
|
-
"frame",
|
|
1185
|
-
"frameset",
|
|
1186
|
-
"isindex",
|
|
1187
|
-
"listing",
|
|
1188
|
-
"marquee",
|
|
1189
|
-
"noembed",
|
|
1190
|
-
"plaintext",
|
|
1191
|
-
"spacer",
|
|
1192
|
-
"strike",
|
|
1193
|
-
"tt",
|
|
1194
|
-
"xmp",
|
|
1195
|
-
"animate",
|
|
1196
|
-
"animateMotion",
|
|
1197
|
-
"animateTransform",
|
|
1198
|
-
"circle",
|
|
1199
|
-
"clipPath",
|
|
1200
|
-
"defs",
|
|
1201
|
-
"desc",
|
|
1202
|
-
"ellipse",
|
|
1203
|
-
"feBlend",
|
|
1204
|
-
"feColorMatrix",
|
|
1205
|
-
"feComponentTransfer",
|
|
1206
|
-
"feComposite",
|
|
1207
|
-
"feConvolveMatrix",
|
|
1208
|
-
"feDiffuseLighting",
|
|
1209
|
-
"feDisplacementMap",
|
|
1210
|
-
"feDistantLight",
|
|
1211
|
-
"feDropShadow",
|
|
1212
|
-
"feFlood",
|
|
1213
|
-
"feFuncA",
|
|
1214
|
-
"feFuncB",
|
|
1215
|
-
"feFuncG",
|
|
1216
|
-
"feFuncR",
|
|
1217
|
-
"feGaussianBlur",
|
|
1218
|
-
"feImage",
|
|
1219
|
-
"feMerge",
|
|
1220
|
-
"feMergeNode",
|
|
1221
|
-
"feMorphology",
|
|
1222
|
-
"feOffset",
|
|
1223
|
-
"fePointLight",
|
|
1224
|
-
"feSpecularLighting",
|
|
1225
|
-
"feSpotLight",
|
|
1226
|
-
"feTile",
|
|
1227
|
-
"feTurbulence",
|
|
1228
|
-
"filter",
|
|
1229
|
-
"foreignObject",
|
|
1230
|
-
"g",
|
|
1231
|
-
"image",
|
|
1232
|
-
"line",
|
|
1233
|
-
"linearGradient",
|
|
1234
|
-
"marker",
|
|
1235
|
-
"mask",
|
|
1236
|
-
"metadata",
|
|
1237
|
-
"mpath",
|
|
1238
|
-
"path",
|
|
1239
|
-
"pattern",
|
|
1240
|
-
"polygon",
|
|
1241
|
-
"polyline",
|
|
1242
|
-
"radialGradient",
|
|
1243
|
-
"rect",
|
|
1244
|
-
"set",
|
|
1245
|
-
"stop",
|
|
1246
|
-
"svg",
|
|
1247
|
-
"switch",
|
|
1248
|
-
"symbol",
|
|
1249
|
-
"text",
|
|
1250
|
-
"textPath",
|
|
1251
|
-
"tspan",
|
|
1252
|
-
"use",
|
|
1253
|
-
"view"
|
|
1254
|
-
];
|
|
1255
|
-
var DELEGATED_EVENTS = [
|
|
1256
|
-
{ domType: "click", eventTypeId: 0 },
|
|
1257
|
-
{ domType: "dblclick", eventTypeId: 1 },
|
|
1258
|
-
{ domType: "input", eventTypeId: 2 },
|
|
1259
|
-
{ domType: "change", eventTypeId: 3 },
|
|
1260
|
-
{ domType: "submit", eventTypeId: 4 },
|
|
1261
|
-
{ domType: "focusin", eventTypeId: 5 },
|
|
1262
|
-
{ domType: "focusout", eventTypeId: 6 },
|
|
1263
|
-
{ domType: "keydown", eventTypeId: 7 },
|
|
1264
|
-
{ domType: "keyup", eventTypeId: 8 },
|
|
1265
|
-
{ domType: "keypress", eventTypeId: 9 },
|
|
1266
|
-
{ domType: "mouseenter", eventTypeId: 10 },
|
|
1267
|
-
{ domType: "mouseleave", eventTypeId: 11 },
|
|
1268
|
-
{ domType: "mousedown", eventTypeId: 12 },
|
|
1269
|
-
{ domType: "mouseup", eventTypeId: 13 },
|
|
1270
|
-
{ domType: "mousemove", eventTypeId: 14 },
|
|
1271
|
-
{ domType: "touchstart", eventTypeId: 15 },
|
|
1272
|
-
{ domType: "touchend", eventTypeId: 16 },
|
|
1273
|
-
{ domType: "touchmove", eventTypeId: 17 },
|
|
1274
|
-
{ domType: "scroll", eventTypeId: 18 }
|
|
1275
|
-
];
|
|
1276
|
-
var eventHandlerModes = new Map;
|
|
1277
|
-
function initEventDelegation(bridge, rootSelector = "body") {
|
|
1278
|
-
const root = document.querySelector(rootSelector);
|
|
1279
|
-
if (!root)
|
|
1280
|
-
return () => {};
|
|
1281
|
-
const removers = [];
|
|
1282
|
-
for (const delegatedEvent of DELEGATED_EVENTS) {
|
|
1283
|
-
const listener = (event) => {
|
|
1284
|
-
let target = event.target;
|
|
1285
|
-
while (target && target !== document.body) {
|
|
1286
|
-
const zxRef = target.__zx_ref;
|
|
1287
|
-
if (zxRef !== undefined) {
|
|
1288
|
-
bridge.eventbridge(BigInt(zxRef), delegatedEvent.eventTypeId, event);
|
|
1289
|
-
if (event.cancelBubble)
|
|
1290
|
-
break;
|
|
1291
|
-
}
|
|
1292
|
-
target = target.parentElement;
|
|
1293
|
-
}
|
|
1294
|
-
};
|
|
1295
|
-
const options = { passive: delegatedEvent.domType.startsWith("touch") || delegatedEvent.domType === "scroll" };
|
|
1296
|
-
root.addEventListener(delegatedEvent.domType, listener, options);
|
|
1297
|
-
removers.push(() => root.removeEventListener(delegatedEvent.domType, listener, options));
|
|
1298
|
-
}
|
|
1299
|
-
return () => {
|
|
1300
|
-
for (const remove of removers)
|
|
1301
|
-
remove();
|
|
1302
|
-
};
|
|
1303
|
-
}
|
|
1304
|
-
var DEFAULT_URL = "/assets/_/main.wasm";
|
|
1305
|
-
var activeRuntime = null;
|
|
1306
|
-
function buildDevtoolsLocation() {
|
|
1307
|
-
return {
|
|
1308
|
-
href: window.location.href,
|
|
1309
|
-
origin: window.location.origin,
|
|
1310
|
-
host: window.location.host,
|
|
1311
|
-
pathname: window.location.pathname
|
|
1312
|
-
};
|
|
1313
|
-
}
|
|
1314
|
-
function normalizeOptions(options = {}) {
|
|
1315
|
-
return {
|
|
1316
|
-
url: options.url,
|
|
1317
|
-
eventDelegationRoot: options.eventDelegationRoot,
|
|
1318
|
-
importObject: options.importObject,
|
|
1319
|
-
kv: options.kv
|
|
1320
|
-
};
|
|
1321
|
-
}
|
|
1322
|
-
function registerDevReinit(options) {
|
|
1323
|
-
if (typeof window === "undefined")
|
|
1324
|
-
return;
|
|
1325
|
-
const reinit = () => init(options);
|
|
1326
|
-
window.__zx_dev_reinit = reinit;
|
|
1327
|
-
window.__ZIEX_DEVTOOLS_GLOBAL_HOOK__ = {
|
|
1328
|
-
location: buildDevtoolsLocation(),
|
|
1329
|
-
reinit
|
|
1330
|
-
};
|
|
1331
|
-
}
|
|
1332
|
-
async function init(options = {}) {
|
|
1333
|
-
const normalizedOptions = normalizeOptions(options);
|
|
1334
|
-
if (activeRuntime) {
|
|
1335
|
-
activeRuntime.dispose();
|
|
1336
|
-
activeRuntime = null;
|
|
1337
|
-
}
|
|
1338
|
-
const url = options.url ?? document.getElementById("__$wasmlink")?.href ?? DEFAULT_URL;
|
|
1339
|
-
const bridgeRef = { current: null };
|
|
1340
|
-
let wasmMemory = null;
|
|
1341
|
-
const kvBindings = options.kv ?? createBrowserKVBindings();
|
|
1342
|
-
const kvImportObject = {
|
|
1343
|
-
__zx_kv: createKVImports(kvBindings, () => {
|
|
1344
|
-
if (wasmMemory)
|
|
1345
|
-
return wasmMemory;
|
|
1346
|
-
if (jsz.memory)
|
|
1347
|
-
return jsz.memory;
|
|
1348
|
-
throw new Error("WASM memory is not ready");
|
|
1349
|
-
})
|
|
1350
|
-
};
|
|
1351
|
-
const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), kvImportObject, options.importObject);
|
|
1352
|
-
const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
1353
|
-
const { instance } = source;
|
|
1354
|
-
wasmMemory = instance.exports.memory;
|
|
1355
|
-
jsz.memory = wasmMemory;
|
|
1356
|
-
const bridge = new ZxBridge(instance.exports);
|
|
1357
|
-
bridgeRef.current = bridge;
|
|
1358
|
-
domNodes.clear();
|
|
1359
|
-
const disposeDelegation = initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
|
|
1360
|
-
const main = wrapPromisingExport(instance.exports.mainClient);
|
|
1361
|
-
invokeWasmExport(main);
|
|
1362
|
-
activeRuntime = {
|
|
1363
|
-
options: normalizedOptions,
|
|
1364
|
-
dispose: () => {
|
|
1365
|
-
disposeDelegation();
|
|
1366
|
-
bridge.dispose();
|
|
1367
|
-
domNodes.clear();
|
|
1368
|
-
}
|
|
1369
|
-
};
|
|
1370
|
-
if (true)
|
|
1371
|
-
registerDevReinit(normalizedOptions);
|
|
1372
|
-
return { source, bridge };
|
|
1373
|
-
}
|
|
1374
|
-
|
|
1375
|
-
// src/runtime.ts
|
|
1376
|
-
var exports_runtime = {};
|
|
1377
|
-
__export(exports_runtime, {
|
|
1378
|
-
run: () => run,
|
|
1379
|
-
buildWsImports: () => buildWsImports,
|
|
1380
|
-
attachWebSocket: () => attachWebSocket
|
|
1381
|
-
});
|
|
1382
|
-
|
|
1383
|
-
// src/wasm/wasi.ts
|
|
1384
|
-
var decoder2 = new TextDecoder;
|
|
1385
|
-
var encoder2 = new TextEncoder;
|
|
1386
|
-
|
|
1387
|
-
class ZxWasiBridge {
|
|
1388
|
-
#alloc;
|
|
1389
|
-
#fetchCompleteHandler;
|
|
1390
|
-
#memory;
|
|
1391
|
-
#cb;
|
|
1392
|
-
#intervals = new Map;
|
|
1393
|
-
#memView = null;
|
|
1394
|
-
#memBuf = null;
|
|
1395
|
-
constructor(exports) {
|
|
1396
|
-
this.#memory = exports.memory;
|
|
1397
|
-
this.#alloc = exports.__zx_alloc;
|
|
1398
|
-
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
1399
|
-
this.#cb = exports.__zx_cb;
|
|
1400
|
-
}
|
|
1401
|
-
#view() {
|
|
1402
|
-
const buf = this.#memory.buffer;
|
|
1403
|
-
if (buf !== this.#memBuf) {
|
|
1404
|
-
this.#memBuf = buf;
|
|
1405
|
-
this.#memView = new Uint8Array(buf);
|
|
1406
|
-
}
|
|
1407
|
-
return this.#memView;
|
|
1408
|
-
}
|
|
1409
|
-
#readString(ptr, len) {
|
|
1410
|
-
return decoder2.decode(this.#view().subarray(ptr, ptr + len));
|
|
1411
|
-
}
|
|
1412
|
-
#writeBytes(ptr, data) {
|
|
1413
|
-
this.#view().set(data, ptr);
|
|
1414
|
-
}
|
|
1415
|
-
log(level, ptr, len) {
|
|
1416
|
-
const msg = decoder2.decode(this.#view().subarray(ptr, ptr + len));
|
|
1417
|
-
switch (level) {
|
|
1418
|
-
case 0:
|
|
1419
|
-
console.error(msg);
|
|
1420
|
-
break;
|
|
1421
|
-
case 1:
|
|
1422
|
-
console.warn(msg);
|
|
1423
|
-
break;
|
|
1424
|
-
case 3:
|
|
1425
|
-
console.debug(msg);
|
|
1426
|
-
break;
|
|
1427
|
-
default:
|
|
1428
|
-
console.log(msg);
|
|
1429
|
-
break;
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
1433
|
-
const url = this.#readString(urlPtr, urlLen);
|
|
1434
|
-
const method = methodLen > 0 ? this.#readString(methodPtr, methodLen) : "GET";
|
|
1435
|
-
const headersJson = headersLen > 0 ? this.#readString(headersPtr, headersLen) : "{}";
|
|
1436
|
-
const body = bodyLen > 0 ? this.#view().subarray(bodyPtr, bodyPtr + bodyLen) : undefined;
|
|
1437
|
-
let headers = {};
|
|
1438
|
-
try {
|
|
1439
|
-
headers = JSON.parse(headersJson);
|
|
1440
|
-
} catch {
|
|
1441
|
-
for (const line of headersJson.split(`
|
|
1442
|
-
`)) {
|
|
1443
|
-
const i = line.indexOf(":");
|
|
1444
|
-
if (i > 0)
|
|
1445
|
-
headers[line.slice(0, i)] = line.slice(i + 1);
|
|
1446
|
-
}
|
|
1447
|
-
}
|
|
1448
|
-
const controller = new AbortController;
|
|
1449
|
-
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
1450
|
-
fetch(url, {
|
|
1451
|
-
method,
|
|
1452
|
-
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
1453
|
-
body: method !== "GET" && method !== "HEAD" ? body : undefined,
|
|
1454
|
-
signal: controller.signal
|
|
1455
|
-
}).then(async (res) => {
|
|
1456
|
-
if (timeout)
|
|
1457
|
-
clearTimeout(timeout);
|
|
1458
|
-
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
1459
|
-
this.#notifyFetchComplete(fetchId, res.status, bytes, false);
|
|
1460
|
-
}).catch((err) => {
|
|
1461
|
-
if (timeout)
|
|
1462
|
-
clearTimeout(timeout);
|
|
1463
|
-
const msg = err.name === "AbortError" ? "Request timeout" : err.message ?? "Fetch failed";
|
|
1464
|
-
this.#notifyFetchComplete(fetchId, 0, msg, true);
|
|
1465
|
-
});
|
|
1466
|
-
}
|
|
1467
|
-
#notifyFetchComplete(fetchId, status, body, isError) {
|
|
1468
|
-
const encoded = typeof body === "string" ? encoder2.encode(body) : body;
|
|
1469
|
-
const ptr = this.#alloc(encoded.length);
|
|
1470
|
-
this.#writeBytes(ptr, encoded);
|
|
1471
|
-
this.#fetchCompleteHandler(fetchId, status, ptr, encoded.length, isError ? 1 : 0);
|
|
1472
|
-
}
|
|
1473
|
-
setTimeout(callbackId, delayMs) {
|
|
1474
|
-
setTimeout(() => this.#cb?.(3, callbackId, 0n), delayMs);
|
|
1475
|
-
}
|
|
1476
|
-
setInterval(callbackId, intervalMs) {
|
|
1477
|
-
const handle = setInterval(() => this.#cb?.(4, callbackId, 0n), intervalMs);
|
|
1478
|
-
this.#intervals.set(callbackId, handle);
|
|
1479
|
-
}
|
|
1480
|
-
clearInterval(callbackId) {
|
|
1481
|
-
const handle = this.#intervals.get(callbackId);
|
|
1482
|
-
if (handle !== undefined) {
|
|
1483
|
-
clearInterval(handle);
|
|
1484
|
-
this.#intervals.delete(callbackId);
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
static createImportObject(bridgeRef) {
|
|
1488
|
-
return {
|
|
1489
|
-
__zx: {
|
|
1490
|
-
_log: (level, ptr, len) => {
|
|
1491
|
-
bridgeRef.current?.log(level, ptr, len);
|
|
1492
|
-
},
|
|
1493
|
-
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1494
|
-
bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
|
|
1495
|
-
},
|
|
1496
|
-
_setTimeout: (callbackId, delayMs) => {
|
|
1497
|
-
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
1498
|
-
},
|
|
1499
|
-
_setInterval: (callbackId, intervalMs) => {
|
|
1500
|
-
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
1501
|
-
},
|
|
1502
|
-
_clearInterval: (callbackId) => {
|
|
1503
|
-
bridgeRef.current?.clearInterval(callbackId);
|
|
1504
|
-
}
|
|
1505
|
-
}
|
|
1506
|
-
};
|
|
1507
|
-
}
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
// src/db.ts
|
|
1511
|
-
function decodeBlob(base64) {
|
|
1512
|
-
const binary = atob(base64);
|
|
1513
|
-
const bytes = new Uint8Array(binary.length);
|
|
1514
|
-
for (let i = 0;i < binary.length; i++)
|
|
1515
|
-
bytes[i] = binary.charCodeAt(i);
|
|
1516
|
-
return bytes;
|
|
1517
|
-
}
|
|
1518
|
-
function toD1Value(value) {
|
|
1519
|
-
switch (value.kind) {
|
|
1520
|
-
case "null":
|
|
1521
|
-
return null;
|
|
1522
|
-
case "integer":
|
|
1523
|
-
return value.integer;
|
|
1524
|
-
case "float":
|
|
1525
|
-
return value.float;
|
|
1526
|
-
case "text":
|
|
1527
|
-
return value.text;
|
|
1528
|
-
case "blob":
|
|
1529
|
-
return decodeBlob(value.blob);
|
|
1530
|
-
case "boolean":
|
|
1531
|
-
return value.boolean;
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
function toPositionalBindings(json) {
|
|
1535
|
-
switch (json.kind) {
|
|
1536
|
-
case "none":
|
|
1537
|
-
return [];
|
|
1538
|
-
case "positional":
|
|
1539
|
-
return json.values.map(toD1Value);
|
|
1540
|
-
case "named":
|
|
1541
|
-
throw new Error("Cloudflare D1 adapter does not support named bindings yet");
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
function toWireValue(value) {
|
|
1545
|
-
if (value === null || value === undefined)
|
|
1546
|
-
return { kind: "null" };
|
|
1547
|
-
if (typeof value === "string")
|
|
1548
|
-
return { kind: "text", text: value };
|
|
1549
|
-
if (typeof value === "boolean")
|
|
1550
|
-
return { kind: "boolean", boolean: value };
|
|
1551
|
-
if (typeof value === "number") {
|
|
1552
|
-
return Number.isInteger(value) ? { kind: "integer", integer: value } : { kind: "float", float: value };
|
|
1553
|
-
}
|
|
1554
|
-
if (value instanceof ArrayBuffer) {
|
|
1555
|
-
const bytes = new Uint8Array(value);
|
|
1556
|
-
let binary = "";
|
|
1557
|
-
for (const byte of bytes)
|
|
1558
|
-
binary += String.fromCharCode(byte);
|
|
1559
|
-
return { kind: "blob", blob: btoa(binary) };
|
|
1560
|
-
}
|
|
1561
|
-
if (ArrayBuffer.isView(value)) {
|
|
1562
|
-
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
1563
|
-
let binary = "";
|
|
1564
|
-
for (const byte of bytes)
|
|
1565
|
-
binary += String.fromCharCode(byte);
|
|
1566
|
-
return { kind: "blob", blob: btoa(binary) };
|
|
1567
|
-
}
|
|
1568
|
-
return { kind: "text", text: String(value) };
|
|
1569
|
-
}
|
|
1570
|
-
function objectToWireRow(record) {
|
|
1571
|
-
return {
|
|
1572
|
-
fields: Object.entries(record).map(([name, value]) => ({
|
|
1573
|
-
name,
|
|
1574
|
-
value: toWireValue(value)
|
|
1575
|
-
}))
|
|
1576
|
-
};
|
|
1577
|
-
}
|
|
1578
|
-
function valuesToWireRows(rows) {
|
|
1579
|
-
return rows.map((row) => row.map((value) => toWireValue(value)));
|
|
1580
|
-
}
|
|
1581
|
-
function createD1Imports(bindings, getMemory) {
|
|
1582
|
-
const encoder3 = new TextEncoder;
|
|
1583
|
-
const decoder3 = new TextDecoder;
|
|
1584
|
-
function readStr(ptr, len) {
|
|
1585
|
-
return decoder3.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
1586
|
-
}
|
|
1587
|
-
function writeJson(buf_ptr, buf_max, value) {
|
|
1588
|
-
const data = encoder3.encode(JSON.stringify(value));
|
|
1589
|
-
if (data.length > buf_max)
|
|
1590
|
-
return -2;
|
|
1591
|
-
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
1592
|
-
return data.length;
|
|
1593
|
-
}
|
|
1594
|
-
function binding(ns) {
|
|
1595
|
-
return bindings[ns] ?? bindings["default"] ?? null;
|
|
1596
|
-
}
|
|
1597
|
-
async function statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len) {
|
|
1598
|
-
const database = binding(readStr(ns_ptr, ns_len));
|
|
1599
|
-
if (!database)
|
|
1600
|
-
return null;
|
|
1601
|
-
const sql = readStr(sql_ptr, sql_len);
|
|
1602
|
-
const bindingsJson = JSON.parse(readStr(bindings_ptr, bindings_len));
|
|
1603
|
-
return database.prepare(sql).bind(...toPositionalBindings(bindingsJson));
|
|
1604
|
-
}
|
|
1605
|
-
const Suspending = WebAssembly.Suspending;
|
|
1606
|
-
if (typeof Suspending !== "function") {
|
|
1607
|
-
return {
|
|
1608
|
-
db_open: (_ns, _ns_len) => -1,
|
|
1609
|
-
db_run: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
|
|
1610
|
-
db_get: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
|
|
1611
|
-
db_all: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
|
|
1612
|
-
db_values: (_a, _b, _c, _d, _e, _f, _g, _h) => -1
|
|
1613
|
-
};
|
|
1614
|
-
}
|
|
1615
|
-
return {
|
|
1616
|
-
db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
|
|
1617
|
-
db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
1618
|
-
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
1619
|
-
if (!stmt)
|
|
1620
|
-
return -1;
|
|
1621
|
-
const result = await stmt.run();
|
|
1622
|
-
return writeJson(buf_ptr, buf_max, {
|
|
1623
|
-
last_insert_rowid: result.meta?.last_row_id ?? 0,
|
|
1624
|
-
changes: result.meta?.changes ?? 0
|
|
1625
|
-
});
|
|
1626
|
-
}),
|
|
1627
|
-
db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
1628
|
-
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
1629
|
-
if (!stmt)
|
|
1630
|
-
return -1;
|
|
1631
|
-
const row = await stmt.first();
|
|
1632
|
-
if (!row)
|
|
1633
|
-
return 0;
|
|
1634
|
-
return writeJson(buf_ptr, buf_max, [objectToWireRow(row)]);
|
|
1635
|
-
}),
|
|
1636
|
-
db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
1637
|
-
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
1638
|
-
if (!stmt)
|
|
1639
|
-
return -1;
|
|
1640
|
-
const result = await stmt.all();
|
|
1641
|
-
return writeJson(buf_ptr, buf_max, (result.results ?? []).map(objectToWireRow));
|
|
1642
|
-
}),
|
|
1643
|
-
db_values: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
1644
|
-
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
1645
|
-
if (!stmt)
|
|
1646
|
-
return -1;
|
|
1647
|
-
const rows = await stmt.raw();
|
|
1648
|
-
return writeJson(buf_ptr, buf_max, valuesToWireRows(rows));
|
|
1649
|
-
})
|
|
1650
|
-
};
|
|
1651
|
-
}
|
|
1652
|
-
|
|
1653
|
-
// src/wasi.ts
|
|
1654
|
-
class ProcExit extends Error {
|
|
1655
|
-
code;
|
|
1656
|
-
constructor(code) {
|
|
1657
|
-
super(`proc_exit(${code})`);
|
|
1658
|
-
this.code = code;
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
function createWasiImports({
|
|
1662
|
-
request,
|
|
1663
|
-
stdinData,
|
|
1664
|
-
onStdout
|
|
1665
|
-
}) {
|
|
1666
|
-
const encoder3 = new TextEncoder;
|
|
1667
|
-
const url = new URL(request.url);
|
|
1668
|
-
const argStrings = [
|
|
1669
|
-
"wasm",
|
|
1670
|
-
"--pathname",
|
|
1671
|
-
url.pathname,
|
|
1672
|
-
"--method",
|
|
1673
|
-
request.method,
|
|
1674
|
-
"--search",
|
|
1675
|
-
url.search,
|
|
1676
|
-
"--url",
|
|
1677
|
-
url.href
|
|
1678
|
-
];
|
|
1679
|
-
request.headers.forEach((value, name) => {
|
|
1680
|
-
if (value)
|
|
1681
|
-
argStrings.push("--header", `${name}:${value}`);
|
|
1682
|
-
});
|
|
1683
|
-
const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\x00"));
|
|
1684
|
-
const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
|
|
1685
|
-
let wasmMemory = null;
|
|
1686
|
-
const setMemory = (m2) => {
|
|
1687
|
-
wasmMemory = m2;
|
|
1688
|
-
};
|
|
1689
|
-
const stdoutChunks = [];
|
|
1690
|
-
let stderrMeta = "";
|
|
1691
|
-
let stderrPartial = "";
|
|
1692
|
-
const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
1693
|
-
function processStderrChunk(chunk) {
|
|
1694
|
-
const text = stderrDecoder.decode(chunk, { stream: true });
|
|
1695
|
-
const lines = (stderrPartial + text).split(`
|
|
1696
|
-
`);
|
|
1697
|
-
stderrPartial = lines.pop() ?? "";
|
|
1698
|
-
for (const line of lines) {
|
|
1699
|
-
if (line.startsWith("__ZIEX_META__:")) {
|
|
1700
|
-
stderrMeta += line + `
|
|
1701
|
-
`;
|
|
1702
|
-
} else if (line.length > 0) {
|
|
1703
|
-
console.error("[ziex]", line);
|
|
1704
|
-
}
|
|
441
|
+
const Suspending = WebAssembly.Suspending;
|
|
442
|
+
if (typeof Suspending !== "function") {
|
|
443
|
+
return {
|
|
444
|
+
db_open: (_ns, _ns_len) => -1,
|
|
445
|
+
db_run: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
|
|
446
|
+
db_get: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
|
|
447
|
+
db_all: (_a, _b, _c, _d, _e, _f, _g, _h) => -1,
|
|
448
|
+
db_values: (_a, _b, _c, _d, _e, _f, _g, _h) => -1
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
db_open: (ns_ptr, ns_len) => binding(readStr(ns_ptr, ns_len)) ? 0 : -1,
|
|
453
|
+
db_run: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
454
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
455
|
+
if (!stmt) return -1;
|
|
456
|
+
const result = await stmt.run();
|
|
457
|
+
return writeJson(buf_ptr, buf_max, {
|
|
458
|
+
last_insert_rowid: result.meta?.last_row_id ?? 0,
|
|
459
|
+
changes: result.meta?.changes ?? 0
|
|
460
|
+
});
|
|
461
|
+
}),
|
|
462
|
+
db_get: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
463
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
464
|
+
if (!stmt) return -1;
|
|
465
|
+
const row = await stmt.first();
|
|
466
|
+
if (!row) return 0;
|
|
467
|
+
return writeJson(buf_ptr, buf_max, [objectToWireRow(row)]);
|
|
468
|
+
}),
|
|
469
|
+
db_all: new Suspending(async (ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len, buf_ptr, buf_max) => {
|
|
470
|
+
const stmt = await statement(ns_ptr, ns_len, sql_ptr, sql_len, bindings_ptr, bindings_len);
|
|
471
|
+
if (!stmt) return -1;
|
|
472
|
+
const result = await stmt.all();
|
|
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;
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
function createWasiImports({
|
|
492
|
+
request,
|
|
493
|
+
stdinData,
|
|
494
|
+
onStdout
|
|
495
|
+
}) {
|
|
496
|
+
const encoder3 = new TextEncoder();
|
|
497
|
+
const url = new URL(request.url);
|
|
498
|
+
const argStrings = [
|
|
499
|
+
"wasm",
|
|
500
|
+
"--pathname",
|
|
501
|
+
url.pathname,
|
|
502
|
+
"--method",
|
|
503
|
+
request.method,
|
|
504
|
+
"--search",
|
|
505
|
+
url.search,
|
|
506
|
+
"--url",
|
|
507
|
+
url.href
|
|
508
|
+
];
|
|
509
|
+
request.headers.forEach((value, name) => {
|
|
510
|
+
if (value) argStrings.push("--header", `${name}:${value}`);
|
|
511
|
+
});
|
|
512
|
+
const encodedArgs = argStrings.map((a) => encoder3.encode(a + "\0"));
|
|
513
|
+
const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
|
|
514
|
+
let wasmMemory = null;
|
|
515
|
+
const setMemory = (m2) => {
|
|
516
|
+
wasmMemory = m2;
|
|
517
|
+
};
|
|
518
|
+
const stdoutChunks = [];
|
|
519
|
+
let stderrMeta = "";
|
|
520
|
+
let stderrPartial = "";
|
|
521
|
+
const stderrDecoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
522
|
+
function processStderrChunk(chunk) {
|
|
523
|
+
const text = stderrDecoder.decode(chunk, { stream: true });
|
|
524
|
+
const lines = (stderrPartial + text).split("\n");
|
|
525
|
+
stderrPartial = lines.pop() ?? "";
|
|
526
|
+
for (const line of lines) {
|
|
527
|
+
if (line.startsWith("__ZIEX_META__:")) {
|
|
528
|
+
stderrMeta += line + "\n";
|
|
529
|
+
} else if (line.length > 0) {
|
|
530
|
+
console.error("[ziex]", line);
|
|
531
|
+
}
|
|
1705
532
|
}
|
|
1706
533
|
}
|
|
1707
534
|
let stdinOffset = 0;
|
|
@@ -1741,17 +568,14 @@ function createWasiImports({
|
|
|
1741
568
|
const dv = v();
|
|
1742
569
|
const mem = m();
|
|
1743
570
|
let written = 0;
|
|
1744
|
-
for (let i = 0;i < iovs_len; i++) {
|
|
571
|
+
for (let i = 0; i < iovs_len; i++) {
|
|
1745
572
|
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
1746
573
|
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
1747
574
|
const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
|
|
1748
575
|
if (fd === 1) {
|
|
1749
|
-
if (onStdout)
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
stdoutChunks.push(chunk);
|
|
1753
|
-
} else if (fd === 2)
|
|
1754
|
-
processStderrChunk(chunk);
|
|
576
|
+
if (onStdout) onStdout(chunk);
|
|
577
|
+
else stdoutChunks.push(chunk);
|
|
578
|
+
} else if (fd === 2) processStderrChunk(chunk);
|
|
1755
579
|
written += buf_len;
|
|
1756
580
|
}
|
|
1757
581
|
dv.setUint32(nwritten_ptr, written, true);
|
|
@@ -1762,7 +586,7 @@ function createWasiImports({
|
|
|
1762
586
|
const mem = m();
|
|
1763
587
|
const stdin = stdinData ?? new Uint8Array(0);
|
|
1764
588
|
let totalRead = 0;
|
|
1765
|
-
for (let i = 0;i < iovs_len; i++) {
|
|
589
|
+
for (let i = 0; i < iovs_len; i++) {
|
|
1766
590
|
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
1767
591
|
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
1768
592
|
if (fd === 0 && stdinOffset < stdin.length) {
|
|
@@ -1919,341 +743,1298 @@ function createWasiImports({
|
|
|
1919
743
|
v().setUint32(bufused_ptr, 0, true);
|
|
1920
744
|
return 76;
|
|
1921
745
|
},
|
|
746
|
+
// Stub for poll_oneoff - no blocking I/O in edge runtimes.
|
|
1922
747
|
poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
|
|
1923
748
|
v().setUint32(nevents_ptr, 0, true);
|
|
1924
749
|
return 0;
|
|
1925
750
|
}
|
|
1926
|
-
};
|
|
1927
|
-
function collectOutput() {
|
|
1928
|
-
const remaining = stderrDecoder.decode(
|
|
1929
|
-
const tail = stderrPartial + remaining;
|
|
1930
|
-
if (tail.length > 0) {
|
|
1931
|
-
if (tail.startsWith("__ZIEX_META__:"))
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
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
|
+
}
|
|
760
|
+
return {
|
|
761
|
+
stdout: mergeUint8Arrays(stdoutChunks),
|
|
762
|
+
stderrText: stderrMeta
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
return { wasiImport, setMemory, collectOutput };
|
|
766
|
+
}
|
|
767
|
+
function mergeUint8Arrays(arrays) {
|
|
768
|
+
const totalLen = arrays.reduce((sum, arr) => sum + arr.length, 0);
|
|
769
|
+
const result = new Uint8Array(totalLen);
|
|
770
|
+
let offset = 0;
|
|
771
|
+
for (const arr of arrays) {
|
|
772
|
+
result.set(arr, offset);
|
|
773
|
+
offset += arr.length;
|
|
774
|
+
}
|
|
775
|
+
return result;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// src/runtime.ts
|
|
779
|
+
function buildWsImports(Suspending, mem, decoder3, ws) {
|
|
780
|
+
const readStr = (ptr, len) => decoder3.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
781
|
+
return {
|
|
782
|
+
ws_upgrade: () => {
|
|
783
|
+
ws.upgraded = true;
|
|
784
|
+
},
|
|
785
|
+
ws_write: (ptr, len) => {
|
|
786
|
+
const data = new Uint8Array(mem().buffer, ptr, len).slice();
|
|
787
|
+
if (!ws.server) {
|
|
788
|
+
ws.pendingWrites.push(data);
|
|
789
|
+
} else {
|
|
790
|
+
ws.server.send(data);
|
|
791
|
+
}
|
|
792
|
+
},
|
|
793
|
+
ws_close: (code, reason_ptr, reason_len) => {
|
|
794
|
+
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
795
|
+
},
|
|
796
|
+
ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
|
|
797
|
+
if (ws._resolveFirstSuspend) {
|
|
798
|
+
const fn = ws._resolveFirstSuspend;
|
|
799
|
+
ws._resolveFirstSuspend = void 0;
|
|
800
|
+
fn();
|
|
801
|
+
}
|
|
802
|
+
const deliver = (bytes) => {
|
|
803
|
+
if (bytes === null) return -1;
|
|
804
|
+
const n = Math.min(bytes.length, buf_max);
|
|
805
|
+
new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
|
|
806
|
+
return n;
|
|
807
|
+
};
|
|
808
|
+
if (ws.messageQueue.length > 0) return deliver(ws.messageQueue.shift());
|
|
809
|
+
return new Promise((resolve) => {
|
|
810
|
+
ws.recvResolve = (bytes) => resolve(deliver(bytes));
|
|
811
|
+
});
|
|
812
|
+
}) : (_buf_ptr, _buf_max) => -1,
|
|
813
|
+
// Pub/sub - delegates to optional callbacks (real in DO, no-ops otherwise)
|
|
814
|
+
ws_subscribe: (ptr, len) => {
|
|
815
|
+
ws.subscribe?.(readStr(ptr, len));
|
|
816
|
+
},
|
|
817
|
+
ws_unsubscribe: (ptr, len) => {
|
|
818
|
+
ws.unsubscribe?.(readStr(ptr, len));
|
|
819
|
+
},
|
|
820
|
+
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
821
|
+
const topic = readStr(topic_ptr, topic_len);
|
|
822
|
+
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
823
|
+
return ws.publish?.(topic, data) ?? 0;
|
|
824
|
+
},
|
|
825
|
+
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
|
|
826
|
+
};
|
|
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) => {
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
function executeWasm(instance, jspi, Suspending, wsState) {
|
|
863
|
+
if (!jspi) {
|
|
864
|
+
try {
|
|
865
|
+
instance.exports._start();
|
|
866
|
+
} catch (e) {
|
|
867
|
+
if (!(e instanceof ProcExit)) throw e;
|
|
868
|
+
}
|
|
869
|
+
return Promise.resolve();
|
|
870
|
+
}
|
|
871
|
+
const start = WebAssembly.promising(instance.exports._start);
|
|
872
|
+
return start().catch((e) => {
|
|
873
|
+
if (e instanceof Error && e.message.startsWith("proc_exit")) return;
|
|
874
|
+
throw e;
|
|
875
|
+
}).finally(() => {
|
|
876
|
+
if (wsState.recvResolve) {
|
|
877
|
+
const res = wsState.recvResolve;
|
|
878
|
+
wsState.recvResolve = null;
|
|
879
|
+
res(null);
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
function parseZiexMeta(stderrText) {
|
|
884
|
+
const meta = { status: 200, headers: new Headers(), streaming: false };
|
|
885
|
+
const metaPrefix = "__ZIEX_META__:";
|
|
886
|
+
const metaLine = stderrText.split("\n").find((line) => line.startsWith(metaPrefix));
|
|
887
|
+
if (metaLine) {
|
|
888
|
+
try {
|
|
889
|
+
const parsed = JSON.parse(metaLine.slice(metaPrefix.length));
|
|
890
|
+
if (parsed.status) meta.status = parsed.status;
|
|
891
|
+
if (parsed.streaming === true) meta.streaming = true;
|
|
892
|
+
if (Array.isArray(parsed.headers)) {
|
|
893
|
+
for (const [name, value] of parsed.headers) {
|
|
894
|
+
meta.headers.append(name, value);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
} catch {
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
return meta;
|
|
901
|
+
}
|
|
902
|
+
async function run({
|
|
903
|
+
request,
|
|
904
|
+
env,
|
|
905
|
+
ctx,
|
|
906
|
+
module,
|
|
907
|
+
kv: kvBindings,
|
|
908
|
+
db: dbBindings,
|
|
909
|
+
imports,
|
|
910
|
+
wasi,
|
|
911
|
+
websocket: doNamespace
|
|
912
|
+
}) {
|
|
913
|
+
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
914
|
+
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
915
|
+
return doNamespace.get(id).fetch(request);
|
|
916
|
+
}
|
|
917
|
+
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
|
|
918
|
+
const stdoutChunks = [];
|
|
919
|
+
let streamWriter = null;
|
|
920
|
+
const { wasiImport, setMemory, collectOutput } = createWasiImports({
|
|
921
|
+
request,
|
|
922
|
+
stdinData,
|
|
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 });
|
|
958
|
+
}
|
|
959
|
+
const { stderrText: earlyStderrText } = collectOutput();
|
|
960
|
+
const earlyMeta = parseZiexMeta(earlyStderrText);
|
|
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 });
|
|
968
|
+
}
|
|
969
|
+
await wasmPromise;
|
|
970
|
+
const { stderrText } = collectOutput();
|
|
971
|
+
const meta = parseZiexMeta(stderrText);
|
|
972
|
+
const body = mergeUint8Arrays(stdoutChunks);
|
|
973
|
+
meta.headers.delete("transfer-encoding");
|
|
974
|
+
const nullBody = meta.status === 101 || meta.status === 204 || meta.status === 205 || meta.status === 304;
|
|
975
|
+
if (nullBody) {
|
|
976
|
+
meta.headers.delete("content-length");
|
|
977
|
+
return new Response(null, { status: meta.status, headers: meta.headers });
|
|
978
|
+
}
|
|
979
|
+
if (!meta.headers.has("content-length")) meta.headers.set("content-length", String(body.byteLength));
|
|
980
|
+
return new Response(body.buffer, { status: meta.status, headers: meta.headers });
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// src/app.ts
|
|
984
|
+
async function resolveModule(input) {
|
|
985
|
+
if (typeof input === "string") {
|
|
986
|
+
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
987
|
+
return WebAssembly.compileStreaming(fetch(input));
|
|
988
|
+
}
|
|
989
|
+
const url = input.startsWith("/") ? `file://${input}` : input;
|
|
990
|
+
return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
|
|
991
|
+
}
|
|
992
|
+
if (input instanceof URL) {
|
|
993
|
+
return WebAssembly.compileStreaming(fetch(input));
|
|
994
|
+
}
|
|
995
|
+
if (input instanceof Response) {
|
|
996
|
+
return WebAssembly.compileStreaming(input);
|
|
997
|
+
}
|
|
998
|
+
if (input instanceof ArrayBuffer) {
|
|
999
|
+
return WebAssembly.compile(input);
|
|
1000
|
+
}
|
|
1001
|
+
if (ArrayBuffer.isView(input)) {
|
|
1002
|
+
return WebAssembly.compile(input.buffer);
|
|
1003
|
+
}
|
|
1004
|
+
return input;
|
|
1005
|
+
}
|
|
1006
|
+
var Ziex = class {
|
|
1007
|
+
constructor(options) {
|
|
1008
|
+
this.resolved = null;
|
|
1009
|
+
/**
|
|
1010
|
+
* Fetch handler called by the runtime on every request.
|
|
1011
|
+
*
|
|
1012
|
+
* Arrow function so `this` is always the class instance, even when the
|
|
1013
|
+
* runtime extracts `fetch` from the exported object (e.g. Bun).
|
|
1014
|
+
*/
|
|
1015
|
+
this.fetch = async (request, env, ctx) => {
|
|
1016
|
+
const module = await this.getModule();
|
|
1017
|
+
const { wasi, imports, websocket } = this.options;
|
|
1018
|
+
return run({
|
|
1019
|
+
request,
|
|
1020
|
+
env,
|
|
1021
|
+
ctx,
|
|
1022
|
+
module,
|
|
1023
|
+
wasi,
|
|
1024
|
+
imports,
|
|
1025
|
+
kv: this.resolveKV(env),
|
|
1026
|
+
db: this.resolveDB(env),
|
|
1027
|
+
websocket: websocket !== void 0 ? env[websocket] : void 0
|
|
1028
|
+
});
|
|
1029
|
+
};
|
|
1030
|
+
this.options = options;
|
|
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] };
|
|
1047
|
+
}
|
|
1048
|
+
resolveDB(env) {
|
|
1049
|
+
const { db } = this.options;
|
|
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;
|
|
1936
1057
|
}
|
|
1058
|
+
return { default: env[db] };
|
|
1059
|
+
}
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
// ../../vendor/jsz/js/src/zigjs.ts
|
|
1063
|
+
var NAN_PREFIX = 2146959360;
|
|
1064
|
+
var predefined = {
|
|
1065
|
+
"nan": 0,
|
|
1066
|
+
"null": 1,
|
|
1067
|
+
"true": 2,
|
|
1068
|
+
"false": 3,
|
|
1069
|
+
"undefined": 4,
|
|
1070
|
+
"globalThis": 5,
|
|
1071
|
+
"runtime": 6
|
|
1072
|
+
};
|
|
1073
|
+
var PREDEFINED_ID_MAX = 6;
|
|
1074
|
+
var encoder2 = new TextEncoder();
|
|
1075
|
+
var decoder2 = new TextDecoder("utf-8");
|
|
1076
|
+
var ZigJS = class {
|
|
1077
|
+
constructor() {
|
|
1078
|
+
/**
|
|
1079
|
+
* The values, indexed by ID (number). Duplicate values can be in this
|
|
1080
|
+
* if they are loaded multiple times. That just acts as duplicate references.
|
|
1081
|
+
* */
|
|
1082
|
+
this.values = [NaN, null, true, false, void 0, globalThis, this];
|
|
1083
|
+
/**
|
|
1084
|
+
* When a value is removed from the values array, its ID is put
|
|
1085
|
+
* in the pool so that we can use it next. This avoids fragmentation in
|
|
1086
|
+
* our array keys.
|
|
1087
|
+
* */
|
|
1088
|
+
this.idPool = [];
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Returns the import object that should be merged with your import
|
|
1092
|
+
* object when instantiating your wasm instance. This injects the required
|
|
1093
|
+
* functions into the wasm environment.
|
|
1094
|
+
* */
|
|
1095
|
+
importObject() {
|
|
1937
1096
|
return {
|
|
1938
|
-
|
|
1939
|
-
|
|
1097
|
+
"zig-js": {
|
|
1098
|
+
valueGet: this.valueGet.bind(this),
|
|
1099
|
+
valueSet: this.valueSet.bind(this),
|
|
1100
|
+
valueDeinit: this.valueDeinit.bind(this),
|
|
1101
|
+
valueObjectCreate: this.valueObjectCreate.bind(this),
|
|
1102
|
+
valueStringCreate: this.valueStringCreate.bind(this),
|
|
1103
|
+
valueStringLen: this.valueStringLen.bind(this),
|
|
1104
|
+
valueStringCopy: this.valueStringCopy.bind(this),
|
|
1105
|
+
valueNew: this.valueNew.bind(this),
|
|
1106
|
+
funcApply: this.funcApply.bind(this)
|
|
1107
|
+
}
|
|
1940
1108
|
};
|
|
1941
1109
|
}
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
offset += arr.length;
|
|
1110
|
+
/**
|
|
1111
|
+
* Get a value from the JS environment.
|
|
1112
|
+
* */
|
|
1113
|
+
valueGet(out, id, ptr, len) {
|
|
1114
|
+
const val = this.loadValue(id);
|
|
1115
|
+
const str = this.loadString(ptr, len);
|
|
1116
|
+
const result = Reflect.get(val, str);
|
|
1117
|
+
this.storeValue(out, result);
|
|
1951
1118
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1119
|
+
/**
|
|
1120
|
+
* Set a value on an object.
|
|
1121
|
+
* */
|
|
1122
|
+
valueSet(id, ptr, len, refAddr) {
|
|
1123
|
+
const obj = this.loadValue(id);
|
|
1124
|
+
const str = this.loadString(ptr, len);
|
|
1125
|
+
const val = this.loadRef(refAddr);
|
|
1126
|
+
Reflect.set(obj, str, val);
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Dereference a value, allowing the JS environment to potentially GC it.
|
|
1130
|
+
* */
|
|
1131
|
+
valueDeinit(id) {
|
|
1132
|
+
if (id > PREDEFINED_ID_MAX) {
|
|
1133
|
+
this.values[id] = null;
|
|
1134
|
+
this.idPool.push(id);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Create an empty object.
|
|
1139
|
+
* */
|
|
1140
|
+
valueObjectCreate(out) {
|
|
1141
|
+
this.storeValue(out, new Object());
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Creates a string on the JS side from a UTF-8 encoded string in wasm memory.
|
|
1145
|
+
* */
|
|
1146
|
+
valueStringCreate(out, ptr, len) {
|
|
1147
|
+
const str = this.loadString(ptr, len);
|
|
1148
|
+
this.storeValue(out, str);
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Returns the length of the string given by id.
|
|
1152
|
+
* */
|
|
1153
|
+
valueStringLen(id) {
|
|
1154
|
+
const val = this.loadValue(id);
|
|
1155
|
+
const buf = encoder2.encode(val);
|
|
1156
|
+
return buf.byteLength;
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Copy the string at id "id" into the shared memory at ptr.
|
|
1160
|
+
* */
|
|
1161
|
+
valueStringCopy(id, ptr, max) {
|
|
1162
|
+
if (this.memory == null) return;
|
|
1163
|
+
const val = this.loadValue(id);
|
|
1164
|
+
const bytes = encoder2.encode(val);
|
|
1165
|
+
if (bytes.byteLength > max) return;
|
|
1166
|
+
if (bytes.length === 0) return;
|
|
1167
|
+
new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Call a constructor given by id.
|
|
1171
|
+
* */
|
|
1172
|
+
valueNew(out, id, argsAddr, argsLen) {
|
|
1173
|
+
const fn = this.loadValue(id);
|
|
1174
|
+
const args = [];
|
|
1175
|
+
for (let i = 0; i < argsLen; i++) {
|
|
1176
|
+
args.push(this.loadRef(argsAddr + i * 8));
|
|
1177
|
+
}
|
|
1178
|
+
const result = Reflect.construct(fn, args);
|
|
1179
|
+
this.storeValue(out, result);
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Call a function given by id.
|
|
1183
|
+
* */
|
|
1184
|
+
funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
|
|
1185
|
+
const fn = this.loadValue(id);
|
|
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));
|
|
1190
|
+
}
|
|
1191
|
+
const result = Reflect.apply(fn, thisVal, args);
|
|
1192
|
+
this.storeValue(out, result);
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* This can be used to load a value given by an ID. A WASM function
|
|
1196
|
+
* might return a value as an ID. This can be used to retrieve it.
|
|
1197
|
+
* */
|
|
1198
|
+
loadValue(id) {
|
|
1199
|
+
return this.values[id];
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* This removes the value from the values list and returns it. This
|
|
1203
|
+
* will not remove predefined values but can still be used to retrieve
|
|
1204
|
+
* them.
|
|
1205
|
+
* */
|
|
1206
|
+
deleteValue(id) {
|
|
1207
|
+
const val = this.values[id];
|
|
1208
|
+
this.valueDeinit(id);
|
|
1209
|
+
return val;
|
|
1210
|
+
}
|
|
1211
|
+
loadRef(refAddr) {
|
|
1212
|
+
if (this.memory == null) return;
|
|
1213
|
+
const view = new DataView(this.memory.buffer);
|
|
1214
|
+
const floatVal = view.getFloat64(refAddr, true);
|
|
1215
|
+
if (!isNaN(floatVal)) return floatVal;
|
|
1216
|
+
const id = this.loadRefId(refAddr);
|
|
1217
|
+
return this.values[id];
|
|
1218
|
+
}
|
|
1219
|
+
loadRefId(refAddr) {
|
|
1220
|
+
if (this.memory == null) return 0;
|
|
1221
|
+
return new DataView(this.memory.buffer).getUint32(refAddr, true);
|
|
1222
|
+
}
|
|
1223
|
+
storeValue(out, val) {
|
|
1224
|
+
if (this.memory == null) return;
|
|
1225
|
+
const view = new DataView(this.memory.buffer);
|
|
1226
|
+
if (typeof val === "number") {
|
|
1227
|
+
if (isNaN(val)) {
|
|
1228
|
+
view.setUint32(out, predefined.nan, true);
|
|
1229
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1966
1230
|
} else {
|
|
1967
|
-
|
|
1968
|
-
}
|
|
1969
|
-
},
|
|
1970
|
-
ws_close: (code, reason_ptr, reason_len) => {
|
|
1971
|
-
ws.server?.close(code, decoder3.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
1972
|
-
},
|
|
1973
|
-
ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
|
|
1974
|
-
if (ws._resolveFirstSuspend) {
|
|
1975
|
-
const fn = ws._resolveFirstSuspend;
|
|
1976
|
-
ws._resolveFirstSuspend = undefined;
|
|
1977
|
-
fn();
|
|
1231
|
+
view.setFloat64(out, val, true);
|
|
1978
1232
|
}
|
|
1979
|
-
|
|
1980
|
-
if (bytes === null)
|
|
1981
|
-
return -1;
|
|
1982
|
-
const n = Math.min(bytes.length, buf_max);
|
|
1983
|
-
new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
|
|
1984
|
-
return n;
|
|
1985
|
-
};
|
|
1986
|
-
if (ws.messageQueue.length > 0)
|
|
1987
|
-
return deliver(ws.messageQueue.shift());
|
|
1988
|
-
return new Promise((resolve) => {
|
|
1989
|
-
ws.recvResolve = (bytes) => resolve(deliver(bytes));
|
|
1990
|
-
});
|
|
1991
|
-
}) : (_buf_ptr, _buf_max) => -1,
|
|
1992
|
-
ws_subscribe: (ptr, len) => {
|
|
1993
|
-
ws.subscribe?.(readStr(ptr, len));
|
|
1994
|
-
},
|
|
1995
|
-
ws_unsubscribe: (ptr, len) => {
|
|
1996
|
-
ws.unsubscribe?.(readStr(ptr, len));
|
|
1997
|
-
},
|
|
1998
|
-
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
1999
|
-
const topic = readStr(topic_ptr, topic_len);
|
|
2000
|
-
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
2001
|
-
return ws.publish?.(topic, data) ?? 0;
|
|
2002
|
-
},
|
|
2003
|
-
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
|
|
2004
|
-
};
|
|
2005
|
-
}
|
|
2006
|
-
function attachWebSocket(ws) {
|
|
2007
|
-
const WebSocketPairCtor = globalThis.WebSocketPair;
|
|
2008
|
-
const pair = new WebSocketPairCtor;
|
|
2009
|
-
const client = pair[0];
|
|
2010
|
-
const server = pair[1];
|
|
2011
|
-
ws.server = server;
|
|
2012
|
-
server.accept();
|
|
2013
|
-
for (const data of ws.pendingWrites)
|
|
2014
|
-
server.send(data);
|
|
2015
|
-
ws.pendingWrites = [];
|
|
2016
|
-
server.addEventListener("message", (event) => {
|
|
2017
|
-
const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
|
|
2018
|
-
if (ws.recvResolve) {
|
|
2019
|
-
const res = ws.recvResolve;
|
|
2020
|
-
ws.recvResolve = null;
|
|
2021
|
-
res(data);
|
|
2022
|
-
} else {
|
|
2023
|
-
ws.messageQueue.push(data);
|
|
1233
|
+
return;
|
|
2024
1234
|
}
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
1235
|
+
if (val === null) {
|
|
1236
|
+
view.setUint32(out, predefined.null, true);
|
|
1237
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (val === void 0) {
|
|
1241
|
+
view.setUint32(out, predefined.undefined, true);
|
|
1242
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1243
|
+
return;
|
|
1244
|
+
}
|
|
1245
|
+
if (typeof val === "boolean") {
|
|
1246
|
+
view.setUint32(out, val ? predefined.true : predefined.false, true);
|
|
1247
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
if (typeof val === "bigint") {
|
|
1251
|
+
view.setFloat64(out, Number(val), true);
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
let id = this.idPool.pop();
|
|
1255
|
+
if (id === void 0) {
|
|
1256
|
+
id = this.values.length;
|
|
1257
|
+
}
|
|
1258
|
+
this.values[id] = val;
|
|
1259
|
+
let typeId = 0;
|
|
1260
|
+
switch (typeof val) {
|
|
1261
|
+
case "object":
|
|
1262
|
+
typeId = 1;
|
|
1263
|
+
break;
|
|
1264
|
+
case "string":
|
|
1265
|
+
typeId = 2;
|
|
1266
|
+
break;
|
|
1267
|
+
case "symbol":
|
|
1268
|
+
typeId = 3;
|
|
1269
|
+
break;
|
|
1270
|
+
case "function":
|
|
1271
|
+
typeId = 4;
|
|
1272
|
+
break;
|
|
2031
1273
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
1274
|
+
view.setUint32(out, Number(id), true);
|
|
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);
|
|
2034
1306
|
}
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
1307
|
+
var textDecoder = new TextDecoder();
|
|
1308
|
+
var textEncoder = new TextEncoder();
|
|
1309
|
+
var memoryView = null;
|
|
1310
|
+
var memoryBuffer = null;
|
|
1311
|
+
function getMemoryView() {
|
|
1312
|
+
const buf = jsz.memory.buffer;
|
|
1313
|
+
if (buf !== memoryBuffer) {
|
|
1314
|
+
memoryBuffer = buf;
|
|
1315
|
+
memoryView = new Uint8Array(buf);
|
|
1316
|
+
}
|
|
1317
|
+
return memoryView;
|
|
2039
1318
|
}
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
1319
|
+
var stringCache = /* @__PURE__ */ new Map();
|
|
1320
|
+
function stringCacheKey(ptr, len) {
|
|
1321
|
+
return ptr * 65536 + len;
|
|
1322
|
+
}
|
|
1323
|
+
function readString(ptr, len) {
|
|
1324
|
+
const key = stringCacheKey(ptr, len);
|
|
1325
|
+
const cached = stringCache.get(key);
|
|
1326
|
+
if (cached !== void 0) return cached;
|
|
1327
|
+
const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
1328
|
+
stringCache.set(key, str);
|
|
1329
|
+
return str;
|
|
1330
|
+
}
|
|
1331
|
+
function writeBytes(ptr, data) {
|
|
1332
|
+
getMemoryView().set(data, ptr);
|
|
1333
|
+
}
|
|
1334
|
+
function wrapPromisingExport(fn) {
|
|
1335
|
+
if (!fn) return void 0;
|
|
1336
|
+
const promising = WebAssembly.promising;
|
|
1337
|
+
if (typeof promising !== "function") return fn;
|
|
1338
|
+
return promising(fn);
|
|
1339
|
+
}
|
|
1340
|
+
function invokeWasmExport(fn, ...args) {
|
|
1341
|
+
if (!fn) return;
|
|
1342
|
+
const result = fn(...args);
|
|
1343
|
+
if (result && typeof result.then === "function") {
|
|
1344
|
+
void result.then(void 0, (error) => {
|
|
1345
|
+
console.error(error);
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
var ZxBridgeCore = class _ZxBridgeCore {
|
|
1350
|
+
#intervals = /* @__PURE__ */ new Map();
|
|
1351
|
+
#handler;
|
|
1352
|
+
#fetchCompleteHandler;
|
|
1353
|
+
constructor(exports) {
|
|
1354
|
+
this._alloc = exports.__zx_alloc;
|
|
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");
|
|
2047
1359
|
}
|
|
2048
|
-
|
|
1360
|
+
this.#fetchCompleteHandler = fetchCompleteHandler;
|
|
1361
|
+
if (exports.memory) jsz.memory = exports.memory;
|
|
2049
1362
|
}
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
1363
|
+
/** Invoke the unified callback handler */
|
|
1364
|
+
#invoke(type, id, data) {
|
|
1365
|
+
const handler = this.#handler;
|
|
1366
|
+
if (!handler) {
|
|
1367
|
+
console.warn("__zx_cb not exported from WASM");
|
|
2053
1368
|
return;
|
|
2054
|
-
throw e;
|
|
2055
|
-
}).finally(() => {
|
|
2056
|
-
if (wsState.recvResolve) {
|
|
2057
|
-
const res = wsState.recvResolve;
|
|
2058
|
-
wsState.recvResolve = null;
|
|
2059
|
-
res(null);
|
|
2060
1369
|
}
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
1370
|
+
const dataRef = storeValueGetRef(data);
|
|
1371
|
+
invokeWasmExport(handler, type, id, dataRef);
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* Async fetch with full options support.
|
|
1375
|
+
* Calls __zx_fetch_complete when done.
|
|
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 = {};
|
|
2069
1383
|
try {
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
for (const [name, value] of parsed.headers) {
|
|
2077
|
-
meta.headers.append(name, value);
|
|
1384
|
+
headers = JSON.parse(headersJson);
|
|
1385
|
+
} catch {
|
|
1386
|
+
for (const line of headersJson.split("\n")) {
|
|
1387
|
+
const colonIdx = line.indexOf(":");
|
|
1388
|
+
if (colonIdx > 0) {
|
|
1389
|
+
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
2078
1390
|
}
|
|
2079
1391
|
}
|
|
2080
|
-
}
|
|
1392
|
+
}
|
|
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
|
+
});
|
|
2081
1411
|
}
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
kv: kvBindings,
|
|
2090
|
-
db: dbBindings,
|
|
2091
|
-
imports,
|
|
2092
|
-
wasi,
|
|
2093
|
-
websocket: doNamespace
|
|
2094
|
-
}) {
|
|
2095
|
-
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
2096
|
-
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
2097
|
-
return doNamespace.get(id).fetch(request);
|
|
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);
|
|
2098
1419
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
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);
|
|
2110
1439
|
}
|
|
2111
|
-
});
|
|
2112
|
-
let wasmMemory = null;
|
|
2113
|
-
const mem = () => wasmMemory;
|
|
2114
|
-
const bridgeRef = { current: null };
|
|
2115
|
-
const Suspending = WebAssembly.Suspending;
|
|
2116
|
-
const jspi = typeof Suspending === "function";
|
|
2117
|
-
const wsState = {
|
|
2118
|
-
upgraded: false,
|
|
2119
|
-
server: null,
|
|
2120
|
-
pendingWrites: [],
|
|
2121
|
-
messageQueue: [],
|
|
2122
|
-
recvResolve: null
|
|
2123
|
-
};
|
|
2124
|
-
const instance = new WebAssembly.Instance(module, {
|
|
2125
|
-
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
2126
|
-
__zx_sys: buildSysImports(jspi, Suspending),
|
|
2127
|
-
__zx_ws: buildWsImports(jspi ? Suspending : null, mem, new TextDecoder, wsState),
|
|
2128
|
-
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
2129
|
-
__zx_db: createD1Imports(dbBindings ?? {}, mem),
|
|
2130
|
-
__zx_net: createFetchImports(mem),
|
|
2131
|
-
...imports ? imports(mem) : {},
|
|
2132
|
-
...ZxWasiBridge.createImportObject(bridgeRef)
|
|
2133
|
-
});
|
|
2134
|
-
wasmMemory = instance.exports.memory;
|
|
2135
|
-
setMemory(wasmMemory);
|
|
2136
|
-
bridgeRef.current = new ZxWasiBridge(instance.exports);
|
|
2137
|
-
const wasmPromise = executeWasm(instance, jspi, Suspending, wsState);
|
|
2138
|
-
if (wsState.upgraded) {
|
|
2139
|
-
const server = attachWebSocket(wsState);
|
|
2140
|
-
ctx?.waitUntil(wasmPromise);
|
|
2141
|
-
return new Response(null, { status: 101, webSocket: server.client });
|
|
2142
1440
|
}
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
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
|
+
}
|
|
1451
|
+
_writeBytesToWasm(data) {
|
|
1452
|
+
const ptr = this._alloc(data.length);
|
|
1453
|
+
writeBytes(ptr, data);
|
|
1454
|
+
return { ptr, len: data.length };
|
|
1455
|
+
}
|
|
1456
|
+
/** Log a message from WASM at the given level (0=error, 1=warn, 2=info, 3=debug) */
|
|
1457
|
+
static log(level, ptr, len) {
|
|
1458
|
+
const msg = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
1459
|
+
switch (level) {
|
|
1460
|
+
case 0:
|
|
1461
|
+
console.error(msg);
|
|
1462
|
+
break;
|
|
1463
|
+
case 1:
|
|
1464
|
+
console.warn(msg);
|
|
1465
|
+
break;
|
|
1466
|
+
case 3:
|
|
1467
|
+
console.debug(msg);
|
|
1468
|
+
break;
|
|
1469
|
+
default:
|
|
1470
|
+
console.log(msg);
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Create the core import object for WASM instantiation.
|
|
1476
|
+
* Includes only environment-agnostic bindings: log, fetch, and timers.
|
|
1477
|
+
* Use ZxBridge.createImportObject (from wasm/index.ts) in browser contexts
|
|
1478
|
+
* to additionally include DOM and WebSocket bindings.
|
|
1479
|
+
*/
|
|
1480
|
+
static createImportObject(bridgeRef) {
|
|
1481
|
+
return {
|
|
1482
|
+
...jsz.importObject(),
|
|
1483
|
+
__zx_net: createFetchImports(() => {
|
|
1484
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
1485
|
+
return jsz.memory;
|
|
1486
|
+
}),
|
|
1487
|
+
__zx: {
|
|
1488
|
+
_log: (level, ptr, len) => _ZxBridgeCore.log(level, ptr, len),
|
|
1489
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1490
|
+
bridgeRef.current?.fetchAsync(
|
|
1491
|
+
urlPtr,
|
|
1492
|
+
urlLen,
|
|
1493
|
+
methodPtr,
|
|
1494
|
+
methodLen,
|
|
1495
|
+
headersPtr,
|
|
1496
|
+
headersLen,
|
|
1497
|
+
bodyPtr,
|
|
1498
|
+
bodyLen,
|
|
1499
|
+
timeoutMs,
|
|
1500
|
+
fetchId
|
|
1501
|
+
);
|
|
1502
|
+
},
|
|
1503
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
1504
|
+
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
1505
|
+
},
|
|
1506
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
1507
|
+
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
1508
|
+
},
|
|
1509
|
+
_clearInterval: (callbackId) => {
|
|
1510
|
+
bridgeRef.current?.clearInterval(callbackId);
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
};
|
|
2153
1514
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
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
|
|
1535
|
+
);
|
|
2163
1536
|
}
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
return new Response(body.buffer, { status: meta.status, headers: meta.headers });
|
|
2167
|
-
}
|
|
2168
|
-
// src/app.ts
|
|
2169
|
-
async function resolveModule(input) {
|
|
2170
|
-
if (typeof input === "string") {
|
|
2171
|
-
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
2172
|
-
return WebAssembly.compileStreaming(fetch(input));
|
|
2173
|
-
}
|
|
2174
|
-
const url = input.startsWith("/") ? `file://${input}` : input;
|
|
2175
|
-
return WebAssembly.compile(await fetch(url).then((r) => r.arrayBuffer()));
|
|
1537
|
+
eventMaySuspend(velementId, eventTypeId) {
|
|
1538
|
+
return !!((eventHandlerModes.get(velementId) ?? 0) & 1 << eventTypeId);
|
|
2176
1539
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
1540
|
+
setEventHandlerMode(velementId, eventTypeId, maySuspend) {
|
|
1541
|
+
const bit = 1 << eventTypeId;
|
|
1542
|
+
const current = eventHandlerModes.get(velementId) ?? 0;
|
|
1543
|
+
const next = maySuspend ? current | bit : current & ~bit;
|
|
1544
|
+
if (next === 0) eventHandlerModes.delete(velementId);
|
|
1545
|
+
else eventHandlerModes.set(velementId, next);
|
|
2179
1546
|
}
|
|
2180
|
-
|
|
2181
|
-
|
|
1547
|
+
clearEventHandlerModes(velementId) {
|
|
1548
|
+
eventHandlerModes.delete(velementId);
|
|
2182
1549
|
}
|
|
2183
|
-
|
|
2184
|
-
|
|
1550
|
+
/** Submit a form action with bound-state round-trip. */
|
|
1551
|
+
submitFormActionAsync(form, actionId, statesJson, fetchId) {
|
|
1552
|
+
const formData = new FormData(form);
|
|
1553
|
+
formData.append("__$states", statesJson);
|
|
1554
|
+
fetch(window.location.href, {
|
|
1555
|
+
method: "POST",
|
|
1556
|
+
// `>>> 0` reinterprets the i32 from wasm as u32 (ids can exceed 2^31).
|
|
1557
|
+
headers: { "x-action": String(actionId >>> 0) },
|
|
1558
|
+
body: formData
|
|
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
|
+
});
|
|
2185
1566
|
}
|
|
2186
|
-
|
|
2187
|
-
|
|
1567
|
+
/**
|
|
1568
|
+
* Create and connect a WebSocket.
|
|
1569
|
+
* Calls __zx_ws_onopen, __zx_ws_onmessage, __zx_ws_onerror, __zx_ws_onclose.
|
|
1570
|
+
*/
|
|
1571
|
+
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
1572
|
+
const url = readString(urlPtr, urlLen);
|
|
1573
|
+
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
1574
|
+
const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : void 0;
|
|
1575
|
+
try {
|
|
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
|
+
}
|
|
1615
|
+
}
|
|
2188
1616
|
}
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
1617
|
+
/** Send data over WebSocket */
|
|
1618
|
+
wsSend(wsId, dataPtr, dataLen, isBinary) {
|
|
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
|
+
}
|
|
2197
1627
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
return
|
|
1628
|
+
/** Close WebSocket connection */
|
|
1629
|
+
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
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
|
+
}
|
|
2202
1639
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
result[name] = env[key];
|
|
1640
|
+
dispose() {
|
|
1641
|
+
super.dispose();
|
|
1642
|
+
eventHandlerModes.clear();
|
|
1643
|
+
for (const ws of this.#websockets.values()) {
|
|
1644
|
+
try {
|
|
1645
|
+
ws.close();
|
|
1646
|
+
} catch {
|
|
2211
1647
|
}
|
|
2212
|
-
return result;
|
|
2213
1648
|
}
|
|
2214
|
-
|
|
1649
|
+
this.#websockets.clear();
|
|
2215
1650
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
1651
|
+
/** Handle a DOM event (called by event delegation) */
|
|
1652
|
+
eventbridge(velementId, eventTypeId, event) {
|
|
1653
|
+
const eventRef = storeValueGetRef(event);
|
|
1654
|
+
if (this.eventMaySuspend(velementId, eventTypeId)) {
|
|
1655
|
+
invokeWasmExport(this.#eventbridgeAsync, velementId, eventTypeId, eventRef);
|
|
2219
1656
|
return;
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
1657
|
+
}
|
|
1658
|
+
invokeWasmExport(this.#eventbridge, velementId, eventTypeId, eventRef);
|
|
1659
|
+
}
|
|
1660
|
+
/** Create the full browser import object for WASM instantiation (includes DOM + WebSocket). */
|
|
1661
|
+
static createImportObject(bridgeRef) {
|
|
1662
|
+
return {
|
|
1663
|
+
...jsz.importObject(),
|
|
1664
|
+
__zx_net: createFetchImports(() => {
|
|
1665
|
+
if (!jsz.memory) throw new Error("WASM memory is not ready");
|
|
1666
|
+
return jsz.memory;
|
|
1667
|
+
}),
|
|
1668
|
+
__zx: {
|
|
1669
|
+
_log: (level, ptr, len) => ZxBridgeCore.log(level, ptr, len),
|
|
1670
|
+
_setEventHandlerMode: (vnodeId, eventTypeId, maySuspend) => {
|
|
1671
|
+
bridgeRef.current?.setEventHandlerMode(vnodeId, eventTypeId, maySuspend !== 0);
|
|
1672
|
+
},
|
|
1673
|
+
_clearEventHandlerModes: (vnodeId) => {
|
|
1674
|
+
bridgeRef.current?.clearEventHandlerModes(vnodeId);
|
|
1675
|
+
},
|
|
1676
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
1677
|
+
bridgeRef.current?.fetchAsync(
|
|
1678
|
+
urlPtr,
|
|
1679
|
+
urlLen,
|
|
1680
|
+
methodPtr,
|
|
1681
|
+
methodLen,
|
|
1682
|
+
headersPtr,
|
|
1683
|
+
headersLen,
|
|
1684
|
+
bodyPtr,
|
|
1685
|
+
bodyLen,
|
|
1686
|
+
timeoutMs,
|
|
1687
|
+
fetchId
|
|
1688
|
+
);
|
|
1689
|
+
},
|
|
1690
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
1691
|
+
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
1692
|
+
},
|
|
1693
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
1694
|
+
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
1695
|
+
},
|
|
1696
|
+
_clearInterval: (callbackId) => {
|
|
1697
|
+
bridgeRef.current?.clearInterval(callbackId);
|
|
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
|
+
}
|
|
2224
1811
|
}
|
|
2225
|
-
|
|
2226
|
-
}
|
|
2227
|
-
return { default: env[db] };
|
|
1812
|
+
};
|
|
2228
1813
|
}
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
module,
|
|
2237
|
-
wasi,
|
|
2238
|
-
imports,
|
|
2239
|
-
kv: this.resolveKV(env),
|
|
2240
|
-
db: this.resolveDB(env),
|
|
2241
|
-
websocket: websocket !== undefined ? env[websocket] : undefined
|
|
2242
|
-
});
|
|
2243
|
-
};
|
|
1814
|
+
};
|
|
1815
|
+
var domNodes = /* @__PURE__ */ new Map();
|
|
1816
|
+
function cleanupDomNodes(node) {
|
|
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]);
|
|
2244
1821
|
}
|
|
1822
|
+
var SVG_TAG_START_INDEX = 140;
|
|
1823
|
+
var TAG_NAMES = [
|
|
1824
|
+
"aside",
|
|
1825
|
+
"fragment",
|
|
1826
|
+
"iframe",
|
|
1827
|
+
"slot",
|
|
1828
|
+
"img",
|
|
1829
|
+
"html",
|
|
1830
|
+
"base",
|
|
1831
|
+
"head",
|
|
1832
|
+
"link",
|
|
1833
|
+
"meta",
|
|
1834
|
+
"script",
|
|
1835
|
+
"style",
|
|
1836
|
+
"title",
|
|
1837
|
+
"address",
|
|
1838
|
+
"article",
|
|
1839
|
+
"body",
|
|
1840
|
+
"h1",
|
|
1841
|
+
"h6",
|
|
1842
|
+
"footer",
|
|
1843
|
+
"header",
|
|
1844
|
+
"h2",
|
|
1845
|
+
"h3",
|
|
1846
|
+
"h4",
|
|
1847
|
+
"h5",
|
|
1848
|
+
"hgroup",
|
|
1849
|
+
"nav",
|
|
1850
|
+
"section",
|
|
1851
|
+
"dd",
|
|
1852
|
+
"dl",
|
|
1853
|
+
"dt",
|
|
1854
|
+
"div",
|
|
1855
|
+
"figcaption",
|
|
1856
|
+
"figure",
|
|
1857
|
+
"hr",
|
|
1858
|
+
"li",
|
|
1859
|
+
"ol",
|
|
1860
|
+
"ul",
|
|
1861
|
+
"menu",
|
|
1862
|
+
"main",
|
|
1863
|
+
"p",
|
|
1864
|
+
"picture",
|
|
1865
|
+
"pre",
|
|
1866
|
+
"a",
|
|
1867
|
+
"abbr",
|
|
1868
|
+
"b",
|
|
1869
|
+
"bdi",
|
|
1870
|
+
"bdo",
|
|
1871
|
+
"br",
|
|
1872
|
+
"cite",
|
|
1873
|
+
"code",
|
|
1874
|
+
"data",
|
|
1875
|
+
"time",
|
|
1876
|
+
"dfn",
|
|
1877
|
+
"em",
|
|
1878
|
+
"i",
|
|
1879
|
+
"kbd",
|
|
1880
|
+
"mark",
|
|
1881
|
+
"q",
|
|
1882
|
+
"blockquote",
|
|
1883
|
+
"rp",
|
|
1884
|
+
"ruby",
|
|
1885
|
+
"rt",
|
|
1886
|
+
"rtc",
|
|
1887
|
+
"rb",
|
|
1888
|
+
"s",
|
|
1889
|
+
"del",
|
|
1890
|
+
"ins",
|
|
1891
|
+
"samp",
|
|
1892
|
+
"small",
|
|
1893
|
+
"span",
|
|
1894
|
+
"strong",
|
|
1895
|
+
"sub",
|
|
1896
|
+
"sup",
|
|
1897
|
+
"u",
|
|
1898
|
+
"var",
|
|
1899
|
+
"wbr",
|
|
1900
|
+
"area",
|
|
1901
|
+
"map",
|
|
1902
|
+
"audio",
|
|
1903
|
+
"source",
|
|
1904
|
+
"track",
|
|
1905
|
+
"video",
|
|
1906
|
+
"embed",
|
|
1907
|
+
"object",
|
|
1908
|
+
"param",
|
|
1909
|
+
"canvas",
|
|
1910
|
+
"noscript",
|
|
1911
|
+
"caption",
|
|
1912
|
+
"table",
|
|
1913
|
+
"col",
|
|
1914
|
+
"colgroup",
|
|
1915
|
+
"tbody",
|
|
1916
|
+
"tr",
|
|
1917
|
+
"thead",
|
|
1918
|
+
"tfoot",
|
|
1919
|
+
"td",
|
|
1920
|
+
"th",
|
|
1921
|
+
"button",
|
|
1922
|
+
"datalist",
|
|
1923
|
+
"option",
|
|
1924
|
+
"fieldset",
|
|
1925
|
+
"label",
|
|
1926
|
+
"form",
|
|
1927
|
+
"input",
|
|
1928
|
+
"keygen",
|
|
1929
|
+
"legend",
|
|
1930
|
+
"meter",
|
|
1931
|
+
"optgroup",
|
|
1932
|
+
"select",
|
|
1933
|
+
"output",
|
|
1934
|
+
"progress",
|
|
1935
|
+
"textarea",
|
|
1936
|
+
"details",
|
|
1937
|
+
"dialog",
|
|
1938
|
+
"menuitem",
|
|
1939
|
+
"summary",
|
|
1940
|
+
"content",
|
|
1941
|
+
"element",
|
|
1942
|
+
"shadow",
|
|
1943
|
+
"template",
|
|
1944
|
+
"acronym",
|
|
1945
|
+
"applet",
|
|
1946
|
+
"basefont",
|
|
1947
|
+
"font",
|
|
1948
|
+
"big",
|
|
1949
|
+
"blink",
|
|
1950
|
+
"center",
|
|
1951
|
+
"command",
|
|
1952
|
+
"dir",
|
|
1953
|
+
"frame",
|
|
1954
|
+
"frameset",
|
|
1955
|
+
"isindex",
|
|
1956
|
+
"listing",
|
|
1957
|
+
"marquee",
|
|
1958
|
+
"noembed",
|
|
1959
|
+
"plaintext",
|
|
1960
|
+
"spacer",
|
|
1961
|
+
"strike",
|
|
1962
|
+
"tt",
|
|
1963
|
+
"xmp",
|
|
1964
|
+
// SVG Tags
|
|
1965
|
+
"animate",
|
|
1966
|
+
"animateMotion",
|
|
1967
|
+
"animateTransform",
|
|
1968
|
+
"circle",
|
|
1969
|
+
"clipPath",
|
|
1970
|
+
"defs",
|
|
1971
|
+
"desc",
|
|
1972
|
+
"ellipse",
|
|
1973
|
+
"feBlend",
|
|
1974
|
+
"feColorMatrix",
|
|
1975
|
+
"feComponentTransfer",
|
|
1976
|
+
"feComposite",
|
|
1977
|
+
"feConvolveMatrix",
|
|
1978
|
+
"feDiffuseLighting",
|
|
1979
|
+
"feDisplacementMap",
|
|
1980
|
+
"feDistantLight",
|
|
1981
|
+
"feDropShadow",
|
|
1982
|
+
"feFlood",
|
|
1983
|
+
"feFuncA",
|
|
1984
|
+
"feFuncB",
|
|
1985
|
+
"feFuncG",
|
|
1986
|
+
"feFuncR",
|
|
1987
|
+
"feGaussianBlur",
|
|
1988
|
+
"feImage",
|
|
1989
|
+
"feMerge",
|
|
1990
|
+
"feMergeNode",
|
|
1991
|
+
"feMorphology",
|
|
1992
|
+
"feOffset",
|
|
1993
|
+
"fePointLight",
|
|
1994
|
+
"feSpecularLighting",
|
|
1995
|
+
"feSpotLight",
|
|
1996
|
+
"feTile",
|
|
1997
|
+
"feTurbulence",
|
|
1998
|
+
"filter",
|
|
1999
|
+
"foreignObject",
|
|
2000
|
+
"g",
|
|
2001
|
+
"image",
|
|
2002
|
+
"line",
|
|
2003
|
+
"linearGradient",
|
|
2004
|
+
"marker",
|
|
2005
|
+
"mask",
|
|
2006
|
+
"metadata",
|
|
2007
|
+
"mpath",
|
|
2008
|
+
"path",
|
|
2009
|
+
"pattern",
|
|
2010
|
+
"polygon",
|
|
2011
|
+
"polyline",
|
|
2012
|
+
"radialGradient",
|
|
2013
|
+
"rect",
|
|
2014
|
+
"set",
|
|
2015
|
+
"stop",
|
|
2016
|
+
"svg",
|
|
2017
|
+
"switch",
|
|
2018
|
+
"symbol",
|
|
2019
|
+
"text",
|
|
2020
|
+
"textPath",
|
|
2021
|
+
"tspan",
|
|
2022
|
+
"use",
|
|
2023
|
+
"view"
|
|
2024
|
+
];
|
|
2025
|
+
var eventHandlerModes = /* @__PURE__ */ new Map();
|
|
2026
|
+
|
|
2245
2027
|
// src/cloudflare/do.ts
|
|
2246
2028
|
function createWebSocketDO(module, options) {
|
|
2247
2029
|
return class ZxWebSocketDO {
|
|
2248
|
-
doState;
|
|
2249
|
-
env;
|
|
2250
|
-
connections = new Map;
|
|
2251
2030
|
constructor(state, env) {
|
|
2031
|
+
/** All active connections in this room, keyed by their server-side WebSocket. */
|
|
2032
|
+
this.connections = /* @__PURE__ */ new Map();
|
|
2252
2033
|
this.doState = state;
|
|
2253
2034
|
this.env = env;
|
|
2254
2035
|
}
|
|
2255
2036
|
async fetch(request) {
|
|
2256
|
-
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) :
|
|
2037
|
+
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : void 0;
|
|
2257
2038
|
const { wasiImport, setMemory } = createWasiImports({ request, stdinData });
|
|
2258
2039
|
let wasmMemory = null;
|
|
2259
2040
|
const mem = () => wasmMemory;
|
|
@@ -2261,7 +2042,7 @@ function createWebSocketDO(module, options) {
|
|
|
2261
2042
|
const bridgeImports = ZxBridge.createImportObject(bridgeRef);
|
|
2262
2043
|
const Suspending = WebAssembly.Suspending;
|
|
2263
2044
|
const jspi = typeof Suspending === "function";
|
|
2264
|
-
const decoder3 = new TextDecoder;
|
|
2045
|
+
const decoder3 = new TextDecoder();
|
|
2265
2046
|
let _resolveFirstSuspend;
|
|
2266
2047
|
const firstSuspendPromise = new Promise((resolve) => {
|
|
2267
2048
|
_resolveFirstSuspend = resolve;
|
|
@@ -2274,7 +2055,7 @@ function createWebSocketDO(module, options) {
|
|
|
2274
2055
|
messageQueue: [],
|
|
2275
2056
|
recvResolve: null,
|
|
2276
2057
|
_resolveFirstSuspend,
|
|
2277
|
-
topics: new Set,
|
|
2058
|
+
topics: /* @__PURE__ */ new Set(),
|
|
2278
2059
|
subscribe: (topic) => connState.topics.add(topic),
|
|
2279
2060
|
unsubscribe: (topic) => connState.topics.delete(topic),
|
|
2280
2061
|
publish: (topic, data) => {
|
|
@@ -2284,7 +2065,8 @@ function createWebSocketDO(module, options) {
|
|
|
2284
2065
|
try {
|
|
2285
2066
|
ws.send(data);
|
|
2286
2067
|
count++;
|
|
2287
|
-
} catch {
|
|
2068
|
+
} catch {
|
|
2069
|
+
}
|
|
2288
2070
|
}
|
|
2289
2071
|
}
|
|
2290
2072
|
if (!connState.server && connState.topics.has(topic)) {
|
|
@@ -2296,7 +2078,8 @@ function createWebSocketDO(module, options) {
|
|
|
2296
2078
|
isSubscribed: (topic) => connState.topics.has(topic)
|
|
2297
2079
|
};
|
|
2298
2080
|
const sysImports = {
|
|
2299
|
-
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
|
|
2081
|
+
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {
|
|
2082
|
+
}
|
|
2300
2083
|
};
|
|
2301
2084
|
const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder3, connState);
|
|
2302
2085
|
const kvBindings = options?.kv?.(this.env);
|
|
@@ -2317,12 +2100,10 @@ function createWebSocketDO(module, options) {
|
|
|
2317
2100
|
const start = WebAssembly.promising(instance.exports._start);
|
|
2318
2101
|
const wasmPromise = start().catch((e) => {
|
|
2319
2102
|
wasmExited = true;
|
|
2320
|
-
if (e instanceof Error && e.message.startsWith("proc_exit"))
|
|
2321
|
-
return;
|
|
2103
|
+
if (e instanceof Error && e.message.startsWith("proc_exit")) return;
|
|
2322
2104
|
console.error("[ZxWebSocketDO] WASM error:", e);
|
|
2323
2105
|
}).finally(() => {
|
|
2324
|
-
if (connState.server)
|
|
2325
|
-
this.connections.delete(connState.server);
|
|
2106
|
+
if (connState.server) this.connections.delete(connState.server);
|
|
2326
2107
|
if (connState.recvResolve) {
|
|
2327
2108
|
const res = connState.recvResolve;
|
|
2328
2109
|
connState.recvResolve = null;
|
|
@@ -2341,8 +2122,8 @@ function createWebSocketDO(module, options) {
|
|
|
2341
2122
|
};
|
|
2342
2123
|
}
|
|
2343
2124
|
export {
|
|
2344
|
-
|
|
2345
|
-
exports_kv as kv,
|
|
2125
|
+
Ziex,
|
|
2346
2126
|
createWebSocketDO,
|
|
2347
|
-
|
|
2127
|
+
kv_exports as kv,
|
|
2128
|
+
runtime_exports as worker
|
|
2348
2129
|
};
|