ziex 0.1.0-dev.785 → 0.1.0-dev.787
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.d.ts +96 -0
- package/aws-lambda/index.js +126 -0
- package/cloudflare/app.d.ts +95 -0
- package/cloudflare/index.d.ts +2 -0
- package/cloudflare/index.js +1160 -58
- package/cloudflare/kv.d.ts +8 -0
- package/cloudflare/worker.d.ts +111 -2
- package/hono/index.d.ts +92 -0
- package/hono/index.js +1515 -0
- package/index.d.ts +1 -9
- package/index.js +1496 -46
- package/package.json +16 -2
- package/vercel/index.d.ts +26 -0
- package/vercel/index.js +18 -0
- package/wasm/index.d.ts +4 -5
- package/wasm/index.js +161 -55
- package/wasm/init.js +161 -39
package/cloudflare/index.js
CHANGED
|
@@ -9,26 +9,879 @@ var __export = (target, all) => {
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// ../../vendor/jsz/js/src/zigjs.ts
|
|
13
|
+
var NAN_PREFIX = 2146959360;
|
|
14
|
+
var predefined = {
|
|
15
|
+
nan: 0,
|
|
16
|
+
null: 1,
|
|
17
|
+
true: 2,
|
|
18
|
+
false: 3,
|
|
19
|
+
undefined: 4,
|
|
20
|
+
globalThis: 5,
|
|
21
|
+
runtime: 6
|
|
22
|
+
};
|
|
23
|
+
var PREDEFINED_ID_MAX = 6;
|
|
24
|
+
var encoder = new TextEncoder;
|
|
25
|
+
var decoder = new TextDecoder("utf-8");
|
|
26
|
+
|
|
27
|
+
class ZigJS {
|
|
28
|
+
memory;
|
|
29
|
+
values = [NaN, null, true, false, undefined, globalThis, this];
|
|
30
|
+
idPool = [];
|
|
31
|
+
importObject() {
|
|
32
|
+
return {
|
|
33
|
+
"zig-js": {
|
|
34
|
+
valueGet: this.valueGet.bind(this),
|
|
35
|
+
valueSet: this.valueSet.bind(this),
|
|
36
|
+
valueDeinit: this.valueDeinit.bind(this),
|
|
37
|
+
valueObjectCreate: this.valueObjectCreate.bind(this),
|
|
38
|
+
valueStringCreate: this.valueStringCreate.bind(this),
|
|
39
|
+
valueStringLen: this.valueStringLen.bind(this),
|
|
40
|
+
valueStringCopy: this.valueStringCopy.bind(this),
|
|
41
|
+
valueNew: this.valueNew.bind(this),
|
|
42
|
+
funcApply: this.funcApply.bind(this)
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
valueGet(out, id, ptr, len) {
|
|
47
|
+
const val = this.loadValue(id);
|
|
48
|
+
const str = this.loadString(ptr, len);
|
|
49
|
+
const result = Reflect.get(val, str);
|
|
50
|
+
this.storeValue(out, result);
|
|
51
|
+
}
|
|
52
|
+
valueSet(id, ptr, len, refAddr) {
|
|
53
|
+
const obj = this.loadValue(id);
|
|
54
|
+
const str = this.loadString(ptr, len);
|
|
55
|
+
const val = this.loadRef(refAddr);
|
|
56
|
+
Reflect.set(obj, str, val);
|
|
57
|
+
}
|
|
58
|
+
valueDeinit(id) {
|
|
59
|
+
if (id > PREDEFINED_ID_MAX) {
|
|
60
|
+
this.values[id] = null;
|
|
61
|
+
this.idPool.push(id);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
valueObjectCreate(out) {
|
|
65
|
+
this.storeValue(out, new Object);
|
|
66
|
+
}
|
|
67
|
+
valueStringCreate(out, ptr, len) {
|
|
68
|
+
const str = this.loadString(ptr, len);
|
|
69
|
+
this.storeValue(out, str);
|
|
70
|
+
}
|
|
71
|
+
valueStringLen(id) {
|
|
72
|
+
const val = this.loadValue(id);
|
|
73
|
+
const buf = encoder.encode(val);
|
|
74
|
+
return buf.byteLength;
|
|
75
|
+
}
|
|
76
|
+
valueStringCopy(id, ptr, max) {
|
|
77
|
+
if (this.memory == null)
|
|
78
|
+
return;
|
|
79
|
+
const val = this.loadValue(id);
|
|
80
|
+
const bytes = encoder.encode(val);
|
|
81
|
+
if (bytes.byteLength > max)
|
|
82
|
+
return;
|
|
83
|
+
new Uint8Array(this.memory.buffer, ptr, bytes.length).set(bytes);
|
|
84
|
+
}
|
|
85
|
+
valueNew(out, id, argsAddr, argsLen) {
|
|
86
|
+
const fn = this.loadValue(id);
|
|
87
|
+
const args = [];
|
|
88
|
+
for (let i = 0;i < argsLen; i++) {
|
|
89
|
+
args.push(this.loadRef(argsAddr + i * 8));
|
|
90
|
+
}
|
|
91
|
+
const result = Reflect.construct(fn, args);
|
|
92
|
+
this.storeValue(out, result);
|
|
93
|
+
}
|
|
94
|
+
funcApply(out, id, thisRefAddr, argsAddr, argsLen) {
|
|
95
|
+
const fn = this.loadValue(id);
|
|
96
|
+
const thisVal = this.loadRef(thisRefAddr);
|
|
97
|
+
const args = [];
|
|
98
|
+
for (let i = 0;i < argsLen; i++) {
|
|
99
|
+
args.push(this.loadRef(argsAddr + i * 8));
|
|
100
|
+
}
|
|
101
|
+
const result = Reflect.apply(fn, thisVal, args);
|
|
102
|
+
this.storeValue(out, result);
|
|
103
|
+
}
|
|
104
|
+
loadValue(id) {
|
|
105
|
+
return this.values[id];
|
|
106
|
+
}
|
|
107
|
+
deleteValue(id) {
|
|
108
|
+
const val = this.values[id];
|
|
109
|
+
this.valueDeinit(id);
|
|
110
|
+
return val;
|
|
111
|
+
}
|
|
112
|
+
loadRef(refAddr) {
|
|
113
|
+
if (this.memory == null)
|
|
114
|
+
return;
|
|
115
|
+
const view = new DataView(this.memory.buffer);
|
|
116
|
+
const floatVal = view.getFloat64(refAddr, true);
|
|
117
|
+
if (!isNaN(floatVal))
|
|
118
|
+
return floatVal;
|
|
119
|
+
const id = this.loadRefId(refAddr);
|
|
120
|
+
return this.values[id];
|
|
121
|
+
}
|
|
122
|
+
loadRefId(refAddr) {
|
|
123
|
+
if (this.memory == null)
|
|
124
|
+
return 0;
|
|
125
|
+
return new DataView(this.memory.buffer).getUint32(refAddr, true);
|
|
126
|
+
}
|
|
127
|
+
storeValue(out, val) {
|
|
128
|
+
if (this.memory == null)
|
|
129
|
+
return;
|
|
130
|
+
const view = new DataView(this.memory.buffer);
|
|
131
|
+
if (typeof val === "number") {
|
|
132
|
+
if (isNaN(val)) {
|
|
133
|
+
view.setUint32(out, predefined.nan, true);
|
|
134
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
135
|
+
} else {
|
|
136
|
+
view.setFloat64(out, val, true);
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (val === null) {
|
|
141
|
+
view.setUint32(out, predefined.null, true);
|
|
142
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (val === undefined) {
|
|
146
|
+
view.setUint32(out, predefined.undefined, true);
|
|
147
|
+
view.setUint32(out + 4, NAN_PREFIX, true);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
let id = this.idPool.pop();
|
|
151
|
+
if (id === undefined) {
|
|
152
|
+
id = this.values.length;
|
|
153
|
+
}
|
|
154
|
+
this.values[id] = val;
|
|
155
|
+
let typeId = 0;
|
|
156
|
+
switch (typeof val) {
|
|
157
|
+
case "object":
|
|
158
|
+
typeId = 1;
|
|
159
|
+
break;
|
|
160
|
+
case "string":
|
|
161
|
+
typeId = 2;
|
|
162
|
+
break;
|
|
163
|
+
case "symbol":
|
|
164
|
+
typeId = 3;
|
|
165
|
+
break;
|
|
166
|
+
case "function":
|
|
167
|
+
typeId = 4;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
view.setUint32(out, Number(id), true);
|
|
171
|
+
view.setUint32(out + 4, NAN_PREFIX | typeId, true);
|
|
172
|
+
}
|
|
173
|
+
loadString(ptr, len) {
|
|
174
|
+
if (this.memory == null)
|
|
175
|
+
return "";
|
|
176
|
+
const arr = new Uint8ClampedArray(this.memory.buffer, ptr, Number(len));
|
|
177
|
+
const data = arr.slice();
|
|
178
|
+
return decoder.decode(data);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// src/wasm/index.ts
|
|
182
|
+
var CallbackType = {
|
|
183
|
+
Event: 0,
|
|
184
|
+
FetchSuccess: 1,
|
|
185
|
+
FetchError: 2,
|
|
186
|
+
Timeout: 3,
|
|
187
|
+
Interval: 4,
|
|
188
|
+
WebSocketOpen: 5,
|
|
189
|
+
WebSocketMessage: 6,
|
|
190
|
+
WebSocketError: 7,
|
|
191
|
+
WebSocketClose: 8
|
|
192
|
+
};
|
|
193
|
+
var jsz = new ZigJS;
|
|
194
|
+
var tempRefBuffer = new ArrayBuffer(8);
|
|
195
|
+
var tempRefView = new DataView(tempRefBuffer);
|
|
196
|
+
function storeValueGetRef(val) {
|
|
197
|
+
const originalMemory = jsz.memory;
|
|
198
|
+
jsz.memory = { buffer: tempRefBuffer };
|
|
199
|
+
jsz.storeValue(0, val);
|
|
200
|
+
jsz.memory = originalMemory;
|
|
201
|
+
return tempRefView.getBigUint64(0, true);
|
|
202
|
+
}
|
|
203
|
+
var textDecoder = new TextDecoder;
|
|
204
|
+
var textEncoder = new TextEncoder;
|
|
205
|
+
var memoryView = null;
|
|
206
|
+
var memoryBuffer = null;
|
|
207
|
+
function getMemoryView() {
|
|
208
|
+
const buf = jsz.memory.buffer;
|
|
209
|
+
if (buf !== memoryBuffer) {
|
|
210
|
+
memoryBuffer = buf;
|
|
211
|
+
memoryView = new Uint8Array(buf);
|
|
212
|
+
}
|
|
213
|
+
return memoryView;
|
|
214
|
+
}
|
|
215
|
+
var stringCache = new Map;
|
|
216
|
+
function stringCacheKey(ptr, len) {
|
|
217
|
+
return ptr * 65536 + len;
|
|
218
|
+
}
|
|
219
|
+
function readString(ptr, len) {
|
|
220
|
+
const key = stringCacheKey(ptr, len);
|
|
221
|
+
const cached = stringCache.get(key);
|
|
222
|
+
if (cached !== undefined)
|
|
223
|
+
return cached;
|
|
224
|
+
const str = textDecoder.decode(getMemoryView().subarray(ptr, ptr + len));
|
|
225
|
+
stringCache.set(key, str);
|
|
226
|
+
return str;
|
|
227
|
+
}
|
|
228
|
+
function writeBytes(ptr, data) {
|
|
229
|
+
getMemoryView().set(data, ptr);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
class ZxBridge {
|
|
233
|
+
#intervals = new Map;
|
|
234
|
+
#websockets = new Map;
|
|
235
|
+
#alloc;
|
|
236
|
+
#handler;
|
|
237
|
+
#fetchCompleteHandler;
|
|
238
|
+
#wsOnOpenHandler;
|
|
239
|
+
#wsOnMessageHandler;
|
|
240
|
+
#wsOnErrorHandler;
|
|
241
|
+
#wsOnCloseHandler;
|
|
242
|
+
constructor(exports) {
|
|
243
|
+
this.#alloc = exports.__zx_alloc;
|
|
244
|
+
this.#handler = exports.__zx_cb;
|
|
245
|
+
this.#fetchCompleteHandler = exports.__zx_fetch_complete;
|
|
246
|
+
this.#wsOnOpenHandler = exports.__zx_ws_onopen;
|
|
247
|
+
this.#wsOnMessageHandler = exports.__zx_ws_onmessage;
|
|
248
|
+
this.#wsOnErrorHandler = exports.__zx_ws_onerror;
|
|
249
|
+
this.#wsOnCloseHandler = exports.__zx_ws_onclose;
|
|
250
|
+
this.#eventbridge = exports.__zx_eventbridge;
|
|
251
|
+
}
|
|
252
|
+
#invoke(type, id, data) {
|
|
253
|
+
const handler = this.#handler;
|
|
254
|
+
if (!handler) {
|
|
255
|
+
console.warn("__zx_cb not exported from WASM");
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const dataRef = storeValueGetRef(data);
|
|
259
|
+
handler(type, id, dataRef);
|
|
260
|
+
}
|
|
261
|
+
fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) {
|
|
262
|
+
const url = readString(urlPtr, urlLen);
|
|
263
|
+
const method = methodLen > 0 ? readString(methodPtr, methodLen) : "GET";
|
|
264
|
+
const headersJson = headersLen > 0 ? readString(headersPtr, headersLen) : "{}";
|
|
265
|
+
const body = bodyLen > 0 ? readString(bodyPtr, bodyLen) : undefined;
|
|
266
|
+
let headers = {};
|
|
267
|
+
try {
|
|
268
|
+
headers = JSON.parse(headersJson);
|
|
269
|
+
} catch {
|
|
270
|
+
for (const line of headersJson.split(`
|
|
271
|
+
`)) {
|
|
272
|
+
const colonIdx = line.indexOf(":");
|
|
273
|
+
if (colonIdx > 0) {
|
|
274
|
+
headers[line.slice(0, colonIdx)] = line.slice(colonIdx + 1);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const controller = new AbortController;
|
|
279
|
+
const timeout = timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
280
|
+
const fetchOptions = {
|
|
281
|
+
method,
|
|
282
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
283
|
+
body: method !== "GET" && method !== "HEAD" ? body : undefined,
|
|
284
|
+
signal: controller.signal
|
|
285
|
+
};
|
|
286
|
+
fetch(url, fetchOptions).then(async (response) => {
|
|
287
|
+
if (timeout)
|
|
288
|
+
clearTimeout(timeout);
|
|
289
|
+
const text = await response.text();
|
|
290
|
+
this.#notifyFetchComplete(fetchId, response.status, text, false);
|
|
291
|
+
}).catch((error) => {
|
|
292
|
+
if (timeout)
|
|
293
|
+
clearTimeout(timeout);
|
|
294
|
+
const isAbort = error.name === "AbortError";
|
|
295
|
+
const errorMsg = isAbort ? "Request timeout" : error.message ?? "Fetch failed";
|
|
296
|
+
this.#notifyFetchComplete(fetchId, 0, errorMsg, true);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
#notifyFetchComplete(fetchId, statusCode, body, isError) {
|
|
300
|
+
const handler = this.#fetchCompleteHandler;
|
|
301
|
+
const encoded = textEncoder.encode(body);
|
|
302
|
+
const ptr = this.#alloc(encoded.length);
|
|
303
|
+
writeBytes(ptr, encoded);
|
|
304
|
+
handler(fetchId, statusCode, ptr, encoded.length, isError ? 1 : 0);
|
|
305
|
+
}
|
|
306
|
+
submitFormActionAsync(form, statesJson, fetchId) {
|
|
307
|
+
const formData = new FormData(form);
|
|
308
|
+
formData.append("__zx_states", statesJson);
|
|
309
|
+
fetch(window.location.href, {
|
|
310
|
+
method: "POST",
|
|
311
|
+
headers: { "X-ZX-Action": "1" },
|
|
312
|
+
body: formData
|
|
313
|
+
}).then(async (response) => {
|
|
314
|
+
const text = await response.text();
|
|
315
|
+
this.#notifyFetchComplete(fetchId, response.status, text, false);
|
|
316
|
+
}).catch((error) => {
|
|
317
|
+
const msg = error instanceof Error ? error.message : "Fetch failed";
|
|
318
|
+
this.#notifyFetchComplete(fetchId, 0, msg, true);
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
setTimeout(callbackId, delayMs) {
|
|
322
|
+
setTimeout(() => {
|
|
323
|
+
this.#invoke(CallbackType.Timeout, callbackId, null);
|
|
324
|
+
}, delayMs);
|
|
325
|
+
}
|
|
326
|
+
setInterval(callbackId, intervalMs) {
|
|
327
|
+
const handle = setInterval(() => {
|
|
328
|
+
this.#invoke(CallbackType.Interval, callbackId, null);
|
|
329
|
+
}, intervalMs);
|
|
330
|
+
this.#intervals.set(callbackId, handle);
|
|
331
|
+
}
|
|
332
|
+
clearInterval(callbackId) {
|
|
333
|
+
const handle = this.#intervals.get(callbackId);
|
|
334
|
+
if (handle !== undefined) {
|
|
335
|
+
clearInterval(handle);
|
|
336
|
+
this.#intervals.delete(callbackId);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) {
|
|
340
|
+
const url = readString(urlPtr, urlLen);
|
|
341
|
+
const protocolsStr = protocolsLen > 0 ? readString(protocolsPtr, protocolsLen) : "";
|
|
342
|
+
const protocols = protocolsStr ? protocolsStr.split(",").map((p) => p.trim()).filter(Boolean) : undefined;
|
|
343
|
+
try {
|
|
344
|
+
const ws = protocols && protocols.length > 0 ? new WebSocket(url, protocols) : new WebSocket(url);
|
|
345
|
+
ws.binaryType = "arraybuffer";
|
|
346
|
+
ws.onopen = () => {
|
|
347
|
+
const handler = this.#wsOnOpenHandler;
|
|
348
|
+
if (!handler)
|
|
349
|
+
return;
|
|
350
|
+
const protocol = ws.protocol || "";
|
|
351
|
+
const { ptr, len } = this.#writeStringToWasm(protocol);
|
|
352
|
+
handler(wsId, ptr, len);
|
|
353
|
+
};
|
|
354
|
+
ws.onmessage = (event) => {
|
|
355
|
+
const handler = this.#wsOnMessageHandler;
|
|
356
|
+
if (!handler)
|
|
357
|
+
return;
|
|
358
|
+
const isBinary = event.data instanceof ArrayBuffer;
|
|
359
|
+
let data;
|
|
360
|
+
if (isBinary) {
|
|
361
|
+
data = new Uint8Array(event.data);
|
|
362
|
+
} else {
|
|
363
|
+
data = textEncoder.encode(event.data);
|
|
364
|
+
}
|
|
365
|
+
const { ptr, len } = this.#writeBytesToWasm(data);
|
|
366
|
+
handler(wsId, ptr, len, isBinary ? 1 : 0);
|
|
367
|
+
};
|
|
368
|
+
ws.onerror = (event) => {
|
|
369
|
+
const handler = this.#wsOnErrorHandler;
|
|
370
|
+
if (!handler)
|
|
371
|
+
return;
|
|
372
|
+
const msg = "WebSocket error";
|
|
373
|
+
const { ptr, len } = this.#writeStringToWasm(msg);
|
|
374
|
+
handler(wsId, ptr, len);
|
|
375
|
+
};
|
|
376
|
+
ws.onclose = (event) => {
|
|
377
|
+
const handler = this.#wsOnCloseHandler;
|
|
378
|
+
if (!handler)
|
|
379
|
+
return;
|
|
380
|
+
const reason = event.reason || "";
|
|
381
|
+
const { ptr, len } = this.#writeStringToWasm(reason);
|
|
382
|
+
handler(wsId, event.code, ptr, len, event.wasClean ? 1 : 0);
|
|
383
|
+
this.#websockets.delete(wsId);
|
|
384
|
+
};
|
|
385
|
+
this.#websockets.set(wsId, ws);
|
|
386
|
+
} catch (error) {
|
|
387
|
+
const handler = this.#wsOnErrorHandler;
|
|
388
|
+
if (handler) {
|
|
389
|
+
const msg = error instanceof Error ? error.message : "WebSocket connection failed";
|
|
390
|
+
const { ptr, len } = this.#writeStringToWasm(msg);
|
|
391
|
+
handler(wsId, ptr, len);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
wsSend(wsId, dataPtr, dataLen, isBinary) {
|
|
396
|
+
const ws = this.#websockets.get(wsId);
|
|
397
|
+
if (!ws || ws.readyState !== WebSocket.OPEN)
|
|
398
|
+
return;
|
|
399
|
+
const memory = getMemoryView();
|
|
400
|
+
if (isBinary) {
|
|
401
|
+
ws.send(memory.slice(dataPtr, dataPtr + dataLen));
|
|
402
|
+
} else {
|
|
403
|
+
ws.send(textDecoder.decode(memory.subarray(dataPtr, dataPtr + dataLen)));
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
wsClose(wsId, code, reasonPtr, reasonLen) {
|
|
407
|
+
const ws = this.#websockets.get(wsId);
|
|
408
|
+
if (!ws)
|
|
409
|
+
return;
|
|
410
|
+
const reason = reasonLen > 0 ? readString(reasonPtr, reasonLen) : undefined;
|
|
411
|
+
try {
|
|
412
|
+
if (reason) {
|
|
413
|
+
ws.close(code, reason);
|
|
414
|
+
} else {
|
|
415
|
+
ws.close(code);
|
|
416
|
+
}
|
|
417
|
+
} catch {
|
|
418
|
+
ws.close();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
#writeStringToWasm(str) {
|
|
422
|
+
const encoded = textEncoder.encode(str);
|
|
423
|
+
return this.#writeBytesToWasm(encoded);
|
|
424
|
+
}
|
|
425
|
+
#writeBytesToWasm(data) {
|
|
426
|
+
const ptr = this.#alloc(data.length);
|
|
427
|
+
writeBytes(ptr, data);
|
|
428
|
+
return { ptr, len: data.length };
|
|
429
|
+
}
|
|
430
|
+
#eventbridge;
|
|
431
|
+
eventbridge(velementId, eventTypeId, event) {
|
|
432
|
+
if (!this.#eventbridge)
|
|
433
|
+
return;
|
|
434
|
+
const eventRef = storeValueGetRef(event);
|
|
435
|
+
this.#eventbridge(velementId, eventTypeId, eventRef);
|
|
436
|
+
}
|
|
437
|
+
static createImportObject(bridgeRef) {
|
|
438
|
+
return {
|
|
439
|
+
...jsz.importObject(),
|
|
440
|
+
__zx: {
|
|
441
|
+
_fetchAsync: (urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId) => {
|
|
442
|
+
bridgeRef.current?.fetchAsync(urlPtr, urlLen, methodPtr, methodLen, headersPtr, headersLen, bodyPtr, bodyLen, timeoutMs, fetchId);
|
|
443
|
+
},
|
|
444
|
+
_setTimeout: (callbackId, delayMs) => {
|
|
445
|
+
bridgeRef.current?.setTimeout(callbackId, delayMs);
|
|
446
|
+
},
|
|
447
|
+
_setInterval: (callbackId, intervalMs) => {
|
|
448
|
+
bridgeRef.current?.setInterval(callbackId, intervalMs);
|
|
449
|
+
},
|
|
450
|
+
_clearInterval: (callbackId) => {
|
|
451
|
+
bridgeRef.current?.clearInterval(callbackId);
|
|
452
|
+
},
|
|
453
|
+
_wsConnect: (wsId, urlPtr, urlLen, protocolsPtr, protocolsLen) => {
|
|
454
|
+
bridgeRef.current?.wsConnect(wsId, urlPtr, urlLen, protocolsPtr, protocolsLen);
|
|
455
|
+
},
|
|
456
|
+
_wsSend: (wsId, dataPtr, dataLen, isBinary) => {
|
|
457
|
+
bridgeRef.current?.wsSend(wsId, dataPtr, dataLen, isBinary);
|
|
458
|
+
},
|
|
459
|
+
_wsClose: (wsId, code, reasonPtr, reasonLen) => {
|
|
460
|
+
bridgeRef.current?.wsClose(wsId, code, reasonPtr, reasonLen);
|
|
461
|
+
},
|
|
462
|
+
_ce: (id, vnodeId) => {
|
|
463
|
+
const tagName = TAG_NAMES[id];
|
|
464
|
+
const el = id >= SVG_TAG_START_INDEX ? document.createElementNS("http://www.w3.org/2000/svg", tagName) : document.createElement(tagName);
|
|
465
|
+
el.__zx_ref = Number(vnodeId);
|
|
466
|
+
domNodes.set(vnodeId, el);
|
|
467
|
+
return storeValueGetRef(el);
|
|
468
|
+
},
|
|
469
|
+
_ct: (ptr, len, vnodeId) => {
|
|
470
|
+
const text = readString(ptr, len);
|
|
471
|
+
const node = document.createTextNode(text);
|
|
472
|
+
node.__zx_ref = Number(vnodeId);
|
|
473
|
+
domNodes.set(vnodeId, node);
|
|
474
|
+
return storeValueGetRef(node);
|
|
475
|
+
},
|
|
476
|
+
_sa: (vnodeId, namePtr, nameLen, valPtr, valLen) => {
|
|
477
|
+
domNodes.get(vnodeId)?.setAttribute(readString(namePtr, nameLen), readString(valPtr, valLen));
|
|
478
|
+
},
|
|
479
|
+
_ra: (vnodeId, namePtr, nameLen) => {
|
|
480
|
+
domNodes.get(vnodeId)?.removeAttribute(readString(namePtr, nameLen));
|
|
481
|
+
},
|
|
482
|
+
_snv: (vnodeId, ptr, len) => {
|
|
483
|
+
const node = domNodes.get(vnodeId);
|
|
484
|
+
if (node)
|
|
485
|
+
node.nodeValue = readString(ptr, len);
|
|
486
|
+
},
|
|
487
|
+
_ac: (parentId, childId) => {
|
|
488
|
+
const parent = domNodes.get(parentId);
|
|
489
|
+
const child = domNodes.get(childId);
|
|
490
|
+
if (parent && child)
|
|
491
|
+
parent.appendChild(child);
|
|
492
|
+
},
|
|
493
|
+
_ib: (parentId, childId, refId) => {
|
|
494
|
+
const parent = domNodes.get(parentId);
|
|
495
|
+
const child = domNodes.get(childId);
|
|
496
|
+
const ref = domNodes.get(refId) ?? null;
|
|
497
|
+
if (parent && child)
|
|
498
|
+
parent.insertBefore(child, ref);
|
|
499
|
+
},
|
|
500
|
+
_rc: (parentId, childId) => {
|
|
501
|
+
const parent = domNodes.get(parentId);
|
|
502
|
+
const child = domNodes.get(childId);
|
|
503
|
+
if (parent && child) {
|
|
504
|
+
parent.removeChild(child);
|
|
505
|
+
cleanupDomNodes(child);
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
_rpc: (parentId, newId, oldId) => {
|
|
509
|
+
const parent = domNodes.get(parentId);
|
|
510
|
+
const newChild = domNodes.get(newId);
|
|
511
|
+
const oldChild = domNodes.get(oldId);
|
|
512
|
+
if (parent && newChild && oldChild) {
|
|
513
|
+
parent.replaceChild(newChild, oldChild);
|
|
514
|
+
cleanupDomNodes(oldChild);
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
_getLocationHref: (bufPtr, bufLen) => {
|
|
518
|
+
const bytes = textEncoder.encode(window.location.href);
|
|
519
|
+
const len = Math.min(bytes.length, bufLen);
|
|
520
|
+
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
521
|
+
return len;
|
|
522
|
+
},
|
|
523
|
+
_getFormData: (vnodeId, bufPtr, bufLen) => {
|
|
524
|
+
const form = domNodes.get(vnodeId);
|
|
525
|
+
if (!form || !(form instanceof HTMLFormElement))
|
|
526
|
+
return 0;
|
|
527
|
+
const formData = new FormData(form);
|
|
528
|
+
const urlEncoded = new URLSearchParams(formData).toString();
|
|
529
|
+
const bytes = textEncoder.encode(urlEncoded);
|
|
530
|
+
const len = Math.min(bytes.length, bufLen);
|
|
531
|
+
writeBytes(bufPtr, bytes.subarray(0, len));
|
|
532
|
+
return len;
|
|
533
|
+
},
|
|
534
|
+
_submitFormAction: (vnodeId) => {
|
|
535
|
+
const form = domNodes.get(vnodeId);
|
|
536
|
+
if (!form || !(form instanceof HTMLFormElement))
|
|
537
|
+
return;
|
|
538
|
+
const formData = new FormData(form);
|
|
539
|
+
fetch(window.location.href, {
|
|
540
|
+
method: "POST",
|
|
541
|
+
headers: { "X-ZX-Action": "1" },
|
|
542
|
+
body: formData
|
|
543
|
+
}).catch(() => {});
|
|
544
|
+
},
|
|
545
|
+
_submitFormActionAsync: (vnodeId, statesPtr, statesLen, fetchId) => {
|
|
546
|
+
const form = domNodes.get(vnodeId);
|
|
547
|
+
if (!form || !(form instanceof HTMLFormElement))
|
|
548
|
+
return;
|
|
549
|
+
const statesJson = statesLen > 0 ? readString(statesPtr, statesLen) : "[]";
|
|
550
|
+
bridgeRef.current?.submitFormActionAsync(form, statesJson, fetchId);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
var domNodes = new Map;
|
|
557
|
+
function cleanupDomNodes(node) {
|
|
558
|
+
const ref = node.__zx_ref;
|
|
559
|
+
if (ref !== undefined)
|
|
560
|
+
domNodes.delete(BigInt(ref));
|
|
561
|
+
const children = node.childNodes;
|
|
562
|
+
for (let i = 0;i < children.length; i++)
|
|
563
|
+
cleanupDomNodes(children[i]);
|
|
564
|
+
}
|
|
565
|
+
var SVG_TAG_START_INDEX = 140;
|
|
566
|
+
var TAG_NAMES = [
|
|
567
|
+
"aside",
|
|
568
|
+
"fragment",
|
|
569
|
+
"iframe",
|
|
570
|
+
"slot",
|
|
571
|
+
"img",
|
|
572
|
+
"html",
|
|
573
|
+
"base",
|
|
574
|
+
"head",
|
|
575
|
+
"link",
|
|
576
|
+
"meta",
|
|
577
|
+
"script",
|
|
578
|
+
"style",
|
|
579
|
+
"title",
|
|
580
|
+
"address",
|
|
581
|
+
"article",
|
|
582
|
+
"body",
|
|
583
|
+
"h1",
|
|
584
|
+
"h6",
|
|
585
|
+
"footer",
|
|
586
|
+
"header",
|
|
587
|
+
"h2",
|
|
588
|
+
"h3",
|
|
589
|
+
"h4",
|
|
590
|
+
"h5",
|
|
591
|
+
"hgroup",
|
|
592
|
+
"nav",
|
|
593
|
+
"section",
|
|
594
|
+
"dd",
|
|
595
|
+
"dl",
|
|
596
|
+
"dt",
|
|
597
|
+
"div",
|
|
598
|
+
"figcaption",
|
|
599
|
+
"figure",
|
|
600
|
+
"hr",
|
|
601
|
+
"li",
|
|
602
|
+
"ol",
|
|
603
|
+
"ul",
|
|
604
|
+
"menu",
|
|
605
|
+
"main",
|
|
606
|
+
"p",
|
|
607
|
+
"picture",
|
|
608
|
+
"pre",
|
|
609
|
+
"a",
|
|
610
|
+
"abbr",
|
|
611
|
+
"b",
|
|
612
|
+
"bdi",
|
|
613
|
+
"bdo",
|
|
614
|
+
"br",
|
|
615
|
+
"cite",
|
|
616
|
+
"code",
|
|
617
|
+
"data",
|
|
618
|
+
"time",
|
|
619
|
+
"dfn",
|
|
620
|
+
"em",
|
|
621
|
+
"i",
|
|
622
|
+
"kbd",
|
|
623
|
+
"mark",
|
|
624
|
+
"q",
|
|
625
|
+
"blockquote",
|
|
626
|
+
"rp",
|
|
627
|
+
"ruby",
|
|
628
|
+
"rt",
|
|
629
|
+
"rtc",
|
|
630
|
+
"rb",
|
|
631
|
+
"s",
|
|
632
|
+
"del",
|
|
633
|
+
"ins",
|
|
634
|
+
"samp",
|
|
635
|
+
"small",
|
|
636
|
+
"span",
|
|
637
|
+
"strong",
|
|
638
|
+
"sub",
|
|
639
|
+
"sup",
|
|
640
|
+
"u",
|
|
641
|
+
"var",
|
|
642
|
+
"wbr",
|
|
643
|
+
"area",
|
|
644
|
+
"map",
|
|
645
|
+
"audio",
|
|
646
|
+
"source",
|
|
647
|
+
"track",
|
|
648
|
+
"video",
|
|
649
|
+
"embed",
|
|
650
|
+
"object",
|
|
651
|
+
"param",
|
|
652
|
+
"canvas",
|
|
653
|
+
"noscript",
|
|
654
|
+
"caption",
|
|
655
|
+
"table",
|
|
656
|
+
"col",
|
|
657
|
+
"colgroup",
|
|
658
|
+
"tbody",
|
|
659
|
+
"tr",
|
|
660
|
+
"thead",
|
|
661
|
+
"tfoot",
|
|
662
|
+
"td",
|
|
663
|
+
"th",
|
|
664
|
+
"button",
|
|
665
|
+
"datalist",
|
|
666
|
+
"option",
|
|
667
|
+
"fieldset",
|
|
668
|
+
"label",
|
|
669
|
+
"form",
|
|
670
|
+
"input",
|
|
671
|
+
"keygen",
|
|
672
|
+
"legend",
|
|
673
|
+
"meter",
|
|
674
|
+
"optgroup",
|
|
675
|
+
"select",
|
|
676
|
+
"output",
|
|
677
|
+
"progress",
|
|
678
|
+
"textarea",
|
|
679
|
+
"details",
|
|
680
|
+
"dialog",
|
|
681
|
+
"menuitem",
|
|
682
|
+
"summary",
|
|
683
|
+
"content",
|
|
684
|
+
"element",
|
|
685
|
+
"shadow",
|
|
686
|
+
"template",
|
|
687
|
+
"acronym",
|
|
688
|
+
"applet",
|
|
689
|
+
"basefont",
|
|
690
|
+
"font",
|
|
691
|
+
"big",
|
|
692
|
+
"blink",
|
|
693
|
+
"center",
|
|
694
|
+
"command",
|
|
695
|
+
"dir",
|
|
696
|
+
"frame",
|
|
697
|
+
"frameset",
|
|
698
|
+
"isindex",
|
|
699
|
+
"listing",
|
|
700
|
+
"marquee",
|
|
701
|
+
"noembed",
|
|
702
|
+
"plaintext",
|
|
703
|
+
"spacer",
|
|
704
|
+
"strike",
|
|
705
|
+
"tt",
|
|
706
|
+
"xmp",
|
|
707
|
+
"animate",
|
|
708
|
+
"animateMotion",
|
|
709
|
+
"animateTransform",
|
|
710
|
+
"circle",
|
|
711
|
+
"clipPath",
|
|
712
|
+
"defs",
|
|
713
|
+
"desc",
|
|
714
|
+
"ellipse",
|
|
715
|
+
"feBlend",
|
|
716
|
+
"feColorMatrix",
|
|
717
|
+
"feComponentTransfer",
|
|
718
|
+
"feComposite",
|
|
719
|
+
"feConvolveMatrix",
|
|
720
|
+
"feDiffuseLighting",
|
|
721
|
+
"feDisplacementMap",
|
|
722
|
+
"feDistantLight",
|
|
723
|
+
"feDropShadow",
|
|
724
|
+
"feFlood",
|
|
725
|
+
"feFuncA",
|
|
726
|
+
"feFuncB",
|
|
727
|
+
"feFuncG",
|
|
728
|
+
"feFuncR",
|
|
729
|
+
"feGaussianBlur",
|
|
730
|
+
"feImage",
|
|
731
|
+
"feMerge",
|
|
732
|
+
"feMergeNode",
|
|
733
|
+
"feMorphology",
|
|
734
|
+
"feOffset",
|
|
735
|
+
"fePointLight",
|
|
736
|
+
"feSpecularLighting",
|
|
737
|
+
"feSpotLight",
|
|
738
|
+
"feTile",
|
|
739
|
+
"feTurbulence",
|
|
740
|
+
"filter",
|
|
741
|
+
"foreignObject",
|
|
742
|
+
"g",
|
|
743
|
+
"image",
|
|
744
|
+
"line",
|
|
745
|
+
"linearGradient",
|
|
746
|
+
"marker",
|
|
747
|
+
"mask",
|
|
748
|
+
"metadata",
|
|
749
|
+
"mpath",
|
|
750
|
+
"path",
|
|
751
|
+
"pattern",
|
|
752
|
+
"polygon",
|
|
753
|
+
"polyline",
|
|
754
|
+
"radialGradient",
|
|
755
|
+
"rect",
|
|
756
|
+
"set",
|
|
757
|
+
"stop",
|
|
758
|
+
"svg",
|
|
759
|
+
"switch",
|
|
760
|
+
"symbol",
|
|
761
|
+
"text",
|
|
762
|
+
"textPath",
|
|
763
|
+
"tspan",
|
|
764
|
+
"use",
|
|
765
|
+
"view"
|
|
766
|
+
];
|
|
767
|
+
var DELEGATED_EVENTS = [
|
|
768
|
+
"click",
|
|
769
|
+
"dblclick",
|
|
770
|
+
"input",
|
|
771
|
+
"change",
|
|
772
|
+
"submit",
|
|
773
|
+
"focus",
|
|
774
|
+
"blur",
|
|
775
|
+
"keydown",
|
|
776
|
+
"keyup",
|
|
777
|
+
"keypress",
|
|
778
|
+
"mouseenter",
|
|
779
|
+
"mouseleave",
|
|
780
|
+
"mousedown",
|
|
781
|
+
"mouseup",
|
|
782
|
+
"mousemove",
|
|
783
|
+
"touchstart",
|
|
784
|
+
"touchend",
|
|
785
|
+
"touchmove",
|
|
786
|
+
"scroll"
|
|
787
|
+
];
|
|
788
|
+
var EVENT_TYPE_MAP = {
|
|
789
|
+
click: 0,
|
|
790
|
+
dblclick: 1,
|
|
791
|
+
input: 2,
|
|
792
|
+
change: 3,
|
|
793
|
+
submit: 4,
|
|
794
|
+
focus: 5,
|
|
795
|
+
blur: 6,
|
|
796
|
+
keydown: 7,
|
|
797
|
+
keyup: 8,
|
|
798
|
+
keypress: 9,
|
|
799
|
+
mouseenter: 10,
|
|
800
|
+
mouseleave: 11,
|
|
801
|
+
mousedown: 12,
|
|
802
|
+
mouseup: 13,
|
|
803
|
+
mousemove: 14,
|
|
804
|
+
touchstart: 15,
|
|
805
|
+
touchend: 16,
|
|
806
|
+
touchmove: 17,
|
|
807
|
+
scroll: 18
|
|
808
|
+
};
|
|
809
|
+
function initEventDelegation(bridge, rootSelector = "body") {
|
|
810
|
+
const root = document.querySelector(rootSelector);
|
|
811
|
+
if (!root)
|
|
812
|
+
return;
|
|
813
|
+
for (const eventType of DELEGATED_EVENTS) {
|
|
814
|
+
root.addEventListener(eventType, (event) => {
|
|
815
|
+
let target = event.target;
|
|
816
|
+
while (target && target !== document.body) {
|
|
817
|
+
const zxRef = target.__zx_ref;
|
|
818
|
+
if (zxRef !== undefined) {
|
|
819
|
+
bridge.eventbridge(BigInt(zxRef), EVENT_TYPE_MAP[eventType] ?? 0, event);
|
|
820
|
+
if (event.cancelBubble)
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
target = target.parentElement;
|
|
824
|
+
}
|
|
825
|
+
}, { passive: eventType.startsWith("touch") || eventType === "scroll" });
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
var DEFAULT_URL = "/assets/main.wasm";
|
|
829
|
+
async function init(options = {}) {
|
|
830
|
+
const url = options.url ?? DEFAULT_URL;
|
|
831
|
+
const bridgeRef = { current: null };
|
|
832
|
+
const importObject = Object.assign({}, ZxBridge.createImportObject(bridgeRef), options.importObject);
|
|
833
|
+
const source = await WebAssembly.instantiateStreaming(fetch(url), importObject);
|
|
834
|
+
const { instance } = source;
|
|
835
|
+
jsz.memory = instance.exports.memory;
|
|
836
|
+
const bridge = new ZxBridge(instance.exports);
|
|
837
|
+
bridgeRef.current = bridge;
|
|
838
|
+
initEventDelegation(bridge, options.eventDelegationRoot ?? "body");
|
|
839
|
+
const main = instance.exports.mainClient;
|
|
840
|
+
if (typeof main === "function")
|
|
841
|
+
main();
|
|
842
|
+
return { source, bridge };
|
|
843
|
+
}
|
|
844
|
+
|
|
12
845
|
// src/cloudflare/worker.ts
|
|
13
846
|
var exports_worker = {};
|
|
14
847
|
__export(exports_worker, {
|
|
15
848
|
run: () => run,
|
|
16
849
|
respond: () => respond,
|
|
17
|
-
prepare: () => prepare
|
|
850
|
+
prepare: () => prepare,
|
|
851
|
+
createWebSocketDO: () => createWebSocketDO
|
|
18
852
|
});
|
|
19
853
|
|
|
20
854
|
// src/cloudflare/kv.ts
|
|
21
855
|
var exports_kv = {};
|
|
22
856
|
__export(exports_kv, {
|
|
857
|
+
createMemoryKV: () => createMemoryKV,
|
|
23
858
|
createKVImports: () => createKVImports
|
|
24
859
|
});
|
|
860
|
+
function createMemoryKV() {
|
|
861
|
+
const store = new Map;
|
|
862
|
+
return {
|
|
863
|
+
async get(key) {
|
|
864
|
+
return store.get(key) ?? null;
|
|
865
|
+
},
|
|
866
|
+
async put(key, value) {
|
|
867
|
+
store.set(key, value);
|
|
868
|
+
},
|
|
869
|
+
async delete(key) {
|
|
870
|
+
store.delete(key);
|
|
871
|
+
},
|
|
872
|
+
async list(options) {
|
|
873
|
+
const keys = [...store.keys()].filter((k) => !options?.prefix || k.startsWith(options.prefix)).map((name) => ({ name }));
|
|
874
|
+
return { keys };
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
}
|
|
25
878
|
function createKVImports(bindings, getMemory) {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
879
|
+
const encoder2 = new TextEncoder;
|
|
880
|
+
const decoder2 = new TextDecoder;
|
|
28
881
|
function readStr(ptr, len) {
|
|
29
|
-
return
|
|
882
|
+
return decoder2.decode(new Uint8Array(getMemory().buffer, ptr, len));
|
|
30
883
|
}
|
|
31
|
-
function
|
|
884
|
+
function writeBytes2(buf_ptr, buf_max, data) {
|
|
32
885
|
if (data.length > buf_max)
|
|
33
886
|
return -2;
|
|
34
887
|
new Uint8Array(getMemory().buffer, buf_ptr, data.length).set(data);
|
|
@@ -38,6 +891,14 @@ function createKVImports(bindings, getMemory) {
|
|
|
38
891
|
return bindings[ns] ?? bindings["default"] ?? null;
|
|
39
892
|
}
|
|
40
893
|
const Suspending = WebAssembly.Suspending;
|
|
894
|
+
if (typeof Suspending !== "function") {
|
|
895
|
+
return {
|
|
896
|
+
kv_get: (_ns, _nsLen, _key, _keyLen, _buf, _max) => -1,
|
|
897
|
+
kv_put: (_ns, _nsLen, _key, _keyLen, _val, _valLen) => 0,
|
|
898
|
+
kv_delete: (_ns, _nsLen, _key, _keyLen) => 0,
|
|
899
|
+
kv_list: (_ns, _nsLen, _pfx, _pfxLen, buf_ptr, buf_max) => writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"))
|
|
900
|
+
};
|
|
901
|
+
}
|
|
41
902
|
return {
|
|
42
903
|
kv_get: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, buf_ptr, buf_max) => {
|
|
43
904
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
@@ -46,7 +907,7 @@ function createKVImports(bindings, getMemory) {
|
|
|
46
907
|
const value = await b.get(readStr(key_ptr, key_len));
|
|
47
908
|
if (value === null)
|
|
48
909
|
return -1;
|
|
49
|
-
return
|
|
910
|
+
return writeBytes2(buf_ptr, buf_max, encoder2.encode(value));
|
|
50
911
|
}),
|
|
51
912
|
kv_put: new Suspending(async (ns_ptr, ns_len, key_ptr, key_len, val_ptr, val_len) => {
|
|
52
913
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
@@ -65,10 +926,10 @@ function createKVImports(bindings, getMemory) {
|
|
|
65
926
|
kv_list: new Suspending(async (ns_ptr, ns_len, prefix_ptr, prefix_len, buf_ptr, buf_max) => {
|
|
66
927
|
const b = binding(readStr(ns_ptr, ns_len));
|
|
67
928
|
if (!b)
|
|
68
|
-
return
|
|
929
|
+
return writeBytes2(buf_ptr, buf_max, encoder2.encode("[]"));
|
|
69
930
|
const prefix = readStr(prefix_ptr, prefix_len);
|
|
70
931
|
const result = await b.list(prefix.length > 0 ? { prefix } : undefined);
|
|
71
|
-
return
|
|
932
|
+
return writeBytes2(buf_ptr, buf_max, encoder2.encode(JSON.stringify(result.keys.map((k) => k.name))));
|
|
72
933
|
})
|
|
73
934
|
};
|
|
74
935
|
}
|
|
@@ -83,10 +944,11 @@ class ProcExit extends Error {
|
|
|
83
944
|
}
|
|
84
945
|
function createWasiImports({
|
|
85
946
|
request,
|
|
86
|
-
stdinData
|
|
947
|
+
stdinData,
|
|
948
|
+
onStdout
|
|
87
949
|
}) {
|
|
88
|
-
const
|
|
89
|
-
const
|
|
950
|
+
const encoder2 = new TextEncoder;
|
|
951
|
+
const decoder2 = new TextDecoder;
|
|
90
952
|
const url = new URL(request.url);
|
|
91
953
|
const argStrings = [
|
|
92
954
|
"wasm",
|
|
@@ -97,12 +959,11 @@ function createWasiImports({
|
|
|
97
959
|
"--search",
|
|
98
960
|
url.search
|
|
99
961
|
];
|
|
100
|
-
|
|
101
|
-
const value = request.headers.get(name);
|
|
962
|
+
request.headers.forEach((value, name) => {
|
|
102
963
|
if (value)
|
|
103
964
|
argStrings.push("--header", `${name}:${value}`);
|
|
104
|
-
}
|
|
105
|
-
const encodedArgs = argStrings.map((a) =>
|
|
965
|
+
});
|
|
966
|
+
const encodedArgs = argStrings.map((a) => encoder2.encode(a + "\x00"));
|
|
106
967
|
const argBufSize = encodedArgs.reduce((s, a) => s + a.length, 0);
|
|
107
968
|
let wasmMemory = null;
|
|
108
969
|
const setMemory = (m2) => {
|
|
@@ -151,9 +1012,12 @@ function createWasiImports({
|
|
|
151
1012
|
const buf_ptr = dv.getUint32(iovs_ptr + i * 8, true);
|
|
152
1013
|
const buf_len = dv.getUint32(iovs_ptr + i * 8 + 4, true);
|
|
153
1014
|
const chunk = mem.slice(buf_ptr, buf_ptr + buf_len);
|
|
154
|
-
if (fd === 1)
|
|
155
|
-
|
|
156
|
-
|
|
1015
|
+
if (fd === 1) {
|
|
1016
|
+
if (onStdout)
|
|
1017
|
+
onStdout(chunk);
|
|
1018
|
+
else
|
|
1019
|
+
stdoutChunks.push(chunk);
|
|
1020
|
+
} else if (fd === 2)
|
|
157
1021
|
stderrChunks.push(chunk);
|
|
158
1022
|
written += buf_len;
|
|
159
1023
|
}
|
|
@@ -262,65 +1126,284 @@ function createWasiImports({
|
|
|
262
1126
|
fd_readdir(_fd, _buf, _buf_len, _cookie, bufused_ptr) {
|
|
263
1127
|
v().setUint32(bufused_ptr, 0, true);
|
|
264
1128
|
return 76;
|
|
1129
|
+
},
|
|
1130
|
+
poll_oneoff(_in, _out, _nsubscriptions, nevents_ptr) {
|
|
1131
|
+
v().setUint32(nevents_ptr, 0, true);
|
|
1132
|
+
return 0;
|
|
265
1133
|
}
|
|
266
1134
|
};
|
|
267
1135
|
function collectOutput() {
|
|
268
1136
|
return {
|
|
269
1137
|
stdout: mergeUint8Arrays(stdoutChunks),
|
|
270
|
-
stderrText:
|
|
1138
|
+
stderrText: decoder2.decode(mergeUint8Arrays(stderrChunks))
|
|
271
1139
|
};
|
|
272
1140
|
}
|
|
273
1141
|
return { wasiImport, setMemory, collectOutput };
|
|
274
1142
|
}
|
|
275
|
-
function buildResponse({
|
|
276
|
-
stdout,
|
|
277
|
-
stderrText
|
|
278
|
-
}) {
|
|
279
|
-
const meta = parseEdgeMeta(stderrText);
|
|
280
|
-
return new Response(stdout.buffer, {
|
|
281
|
-
status: meta.status,
|
|
282
|
-
headers: meta.headers
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
1143
|
async function run({
|
|
286
1144
|
request,
|
|
287
1145
|
env,
|
|
288
1146
|
ctx,
|
|
289
1147
|
module,
|
|
290
1148
|
kv: kvBindings,
|
|
291
|
-
imports
|
|
1149
|
+
imports,
|
|
1150
|
+
wasi,
|
|
1151
|
+
websocket: doNamespace
|
|
292
1152
|
}) {
|
|
1153
|
+
if (doNamespace && request.headers.get("upgrade")?.toLowerCase() === "websocket") {
|
|
1154
|
+
const id = doNamespace.idFromName(new URL(request.url).pathname);
|
|
1155
|
+
return doNamespace.get(id).fetch(request);
|
|
1156
|
+
}
|
|
293
1157
|
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
|
|
294
|
-
const {
|
|
1158
|
+
const { readable, writable } = new TransformStream;
|
|
1159
|
+
const stdoutWriter = writable.getWriter();
|
|
1160
|
+
const { wasiImport, setMemory, collectOutput } = createWasiImports({
|
|
1161
|
+
request,
|
|
1162
|
+
stdinData,
|
|
1163
|
+
onStdout: (chunk) => {
|
|
1164
|
+
stdoutWriter.write(chunk);
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
295
1167
|
let wasmMemory = null;
|
|
296
1168
|
const mem = () => wasmMemory;
|
|
1169
|
+
const bridgeRef = { current: null };
|
|
1170
|
+
const bridgeImports = ZxBridge.createImportObject(bridgeRef);
|
|
1171
|
+
const decoder2 = new TextDecoder;
|
|
1172
|
+
const Suspending = WebAssembly.Suspending;
|
|
1173
|
+
const jspi = typeof Suspending === "function";
|
|
1174
|
+
const sysImports = {
|
|
1175
|
+
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((resolve) => setTimeout(resolve, ms))) : (_ms) => {}
|
|
1176
|
+
};
|
|
1177
|
+
const wsState = {
|
|
1178
|
+
upgraded: false,
|
|
1179
|
+
server: null,
|
|
1180
|
+
pendingWrites: [],
|
|
1181
|
+
messageQueue: [],
|
|
1182
|
+
recvResolve: null
|
|
1183
|
+
};
|
|
1184
|
+
const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder2, wsState);
|
|
297
1185
|
const instance = new WebAssembly.Instance(module, {
|
|
298
|
-
wasi_snapshot_preview1: wasiImport,
|
|
299
|
-
|
|
300
|
-
|
|
1186
|
+
wasi_snapshot_preview1: { ...wasi?.wasiImport, ...wasiImport },
|
|
1187
|
+
__zx_sys: sysImports,
|
|
1188
|
+
__zx_ws: wsImports,
|
|
1189
|
+
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
1190
|
+
...imports ? imports(mem) : {},
|
|
1191
|
+
...bridgeImports
|
|
301
1192
|
});
|
|
302
1193
|
wasmMemory = instance.exports.memory;
|
|
303
1194
|
setMemory(wasmMemory);
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
1195
|
+
const bridge = new ZxBridge(instance.exports);
|
|
1196
|
+
bridgeRef.current = bridge;
|
|
1197
|
+
let wasmPromise;
|
|
1198
|
+
if (jspi) {
|
|
1199
|
+
const start = WebAssembly.promising(instance.exports._start);
|
|
1200
|
+
wasmPromise = start().catch((e) => {
|
|
1201
|
+
if (e instanceof Error && e.message.startsWith("proc_exit"))
|
|
1202
|
+
return;
|
|
309
1203
|
throw e;
|
|
1204
|
+
}).finally(() => {
|
|
1205
|
+
stdoutWriter.close();
|
|
1206
|
+
if (wsState.recvResolve) {
|
|
1207
|
+
const res = wsState.recvResolve;
|
|
1208
|
+
wsState.recvResolve = null;
|
|
1209
|
+
res(null);
|
|
1210
|
+
}
|
|
1211
|
+
});
|
|
1212
|
+
} else {
|
|
1213
|
+
try {
|
|
1214
|
+
instance.exports._start();
|
|
1215
|
+
} catch (e) {
|
|
1216
|
+
if (!(e instanceof ProcExit))
|
|
1217
|
+
throw e;
|
|
1218
|
+
}
|
|
1219
|
+
stdoutWriter.close();
|
|
1220
|
+
wasmPromise = Promise.resolve();
|
|
310
1221
|
}
|
|
311
|
-
|
|
1222
|
+
if (wsState.upgraded) {
|
|
1223
|
+
const server = attachWebSocket(wsState);
|
|
1224
|
+
ctx?.waitUntil(wasmPromise);
|
|
1225
|
+
return new Response(null, { status: 101, webSocket: server.client });
|
|
1226
|
+
}
|
|
1227
|
+
const { stderrText } = collectOutput();
|
|
1228
|
+
const meta = parseEdgeMeta(stderrText);
|
|
1229
|
+
return new Response(readable, {
|
|
1230
|
+
status: meta.status,
|
|
1231
|
+
headers: meta.headers
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
function buildWsImports(Suspending, mem, decoder2, ws) {
|
|
1235
|
+
const readStr = (ptr, len) => decoder2.decode(new Uint8Array(mem().buffer, ptr, len));
|
|
1236
|
+
return {
|
|
1237
|
+
ws_upgrade: () => {
|
|
1238
|
+
ws.upgraded = true;
|
|
1239
|
+
},
|
|
1240
|
+
ws_write: (ptr, len) => {
|
|
1241
|
+
const data = new Uint8Array(mem().buffer, ptr, len).slice();
|
|
1242
|
+
if (!ws.server) {
|
|
1243
|
+
ws.pendingWrites.push(data);
|
|
1244
|
+
} else {
|
|
1245
|
+
ws.server.send(data);
|
|
1246
|
+
}
|
|
1247
|
+
},
|
|
1248
|
+
ws_close: (code, reason_ptr, reason_len) => {
|
|
1249
|
+
ws.server?.close(code, decoder2.decode(new Uint8Array(mem().buffer, reason_ptr, reason_len)));
|
|
1250
|
+
},
|
|
1251
|
+
ws_recv: Suspending ? new Suspending(async (buf_ptr, buf_max) => {
|
|
1252
|
+
if (ws._resolveFirstSuspend) {
|
|
1253
|
+
const fn = ws._resolveFirstSuspend;
|
|
1254
|
+
ws._resolveFirstSuspend = undefined;
|
|
1255
|
+
fn();
|
|
1256
|
+
}
|
|
1257
|
+
const deliver = (bytes) => {
|
|
1258
|
+
if (bytes === null)
|
|
1259
|
+
return -1;
|
|
1260
|
+
const n = Math.min(bytes.length, buf_max);
|
|
1261
|
+
new Uint8Array(mem().buffer, buf_ptr, n).set(bytes.subarray(0, n));
|
|
1262
|
+
return n;
|
|
1263
|
+
};
|
|
1264
|
+
if (ws.messageQueue.length > 0)
|
|
1265
|
+
return deliver(ws.messageQueue.shift());
|
|
1266
|
+
return new Promise((resolve) => {
|
|
1267
|
+
ws.recvResolve = (bytes) => resolve(deliver(bytes));
|
|
1268
|
+
});
|
|
1269
|
+
}) : (_buf_ptr, _buf_max) => -1,
|
|
1270
|
+
ws_subscribe: (ptr, len) => {
|
|
1271
|
+
ws.subscribe?.(readStr(ptr, len));
|
|
1272
|
+
},
|
|
1273
|
+
ws_unsubscribe: (ptr, len) => {
|
|
1274
|
+
ws.unsubscribe?.(readStr(ptr, len));
|
|
1275
|
+
},
|
|
1276
|
+
ws_publish: (topic_ptr, topic_len, data_ptr, data_len) => {
|
|
1277
|
+
const topic = readStr(topic_ptr, topic_len);
|
|
1278
|
+
const data = new Uint8Array(mem().buffer, data_ptr, data_len).slice();
|
|
1279
|
+
return ws.publish?.(topic, data) ?? 0;
|
|
1280
|
+
},
|
|
1281
|
+
ws_is_subscribed: (ptr, len) => ws.isSubscribed?.(readStr(ptr, len)) ? 1 : 0
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
function attachWebSocket(ws) {
|
|
1285
|
+
const WebSocketPairCtor = globalThis.WebSocketPair;
|
|
1286
|
+
const pair = new WebSocketPairCtor;
|
|
1287
|
+
const client = pair[0];
|
|
1288
|
+
const server = pair[1];
|
|
1289
|
+
ws.server = server;
|
|
1290
|
+
server.accept();
|
|
1291
|
+
for (const data of ws.pendingWrites)
|
|
1292
|
+
server.send(data);
|
|
1293
|
+
ws.pendingWrites = [];
|
|
1294
|
+
server.addEventListener("message", (event) => {
|
|
1295
|
+
const data = typeof event.data === "string" ? new TextEncoder().encode(event.data) : new Uint8Array(event.data);
|
|
1296
|
+
if (ws.recvResolve) {
|
|
1297
|
+
const res = ws.recvResolve;
|
|
1298
|
+
ws.recvResolve = null;
|
|
1299
|
+
res(data);
|
|
1300
|
+
} else {
|
|
1301
|
+
ws.messageQueue.push(data);
|
|
1302
|
+
}
|
|
1303
|
+
});
|
|
1304
|
+
server.addEventListener("close", () => {
|
|
1305
|
+
if (ws.recvResolve) {
|
|
1306
|
+
const res = ws.recvResolve;
|
|
1307
|
+
ws.recvResolve = null;
|
|
1308
|
+
res(null);
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
1311
|
+
return { client };
|
|
1312
|
+
}
|
|
1313
|
+
function createWebSocketDO(module, options) {
|
|
1314
|
+
return class ZxWebSocketDO {
|
|
1315
|
+
doState;
|
|
1316
|
+
env;
|
|
1317
|
+
connections = new Map;
|
|
1318
|
+
constructor(state, env) {
|
|
1319
|
+
this.doState = state;
|
|
1320
|
+
this.env = env;
|
|
1321
|
+
}
|
|
1322
|
+
async fetch(request) {
|
|
1323
|
+
const stdinData = request.body ? new Uint8Array(await request.arrayBuffer()) : undefined;
|
|
1324
|
+
const { wasiImport, setMemory } = createWasiImports({ request, stdinData });
|
|
1325
|
+
let wasmMemory = null;
|
|
1326
|
+
const mem = () => wasmMemory;
|
|
1327
|
+
const bridgeRef = { current: null };
|
|
1328
|
+
const bridgeImports = ZxBridge.createImportObject(bridgeRef);
|
|
1329
|
+
const Suspending = WebAssembly.Suspending;
|
|
1330
|
+
const jspi = typeof Suspending === "function";
|
|
1331
|
+
const decoder2 = new TextDecoder;
|
|
1332
|
+
let _resolveFirstSuspend;
|
|
1333
|
+
const firstSuspendPromise = new Promise((resolve) => {
|
|
1334
|
+
_resolveFirstSuspend = resolve;
|
|
1335
|
+
});
|
|
1336
|
+
let wasmExited = false;
|
|
1337
|
+
const connState = {
|
|
1338
|
+
upgraded: false,
|
|
1339
|
+
server: null,
|
|
1340
|
+
pendingWrites: [],
|
|
1341
|
+
messageQueue: [],
|
|
1342
|
+
recvResolve: null,
|
|
1343
|
+
_resolveFirstSuspend,
|
|
1344
|
+
topics: new Set,
|
|
1345
|
+
subscribe: (topic) => connState.topics.add(topic),
|
|
1346
|
+
unsubscribe: (topic) => connState.topics.delete(topic),
|
|
1347
|
+
publish: (topic, data) => {
|
|
1348
|
+
let count = 0;
|
|
1349
|
+
for (const [ws, conn] of this.connections) {
|
|
1350
|
+
if (conn.topics.has(topic)) {
|
|
1351
|
+
try {
|
|
1352
|
+
ws.send(data);
|
|
1353
|
+
count++;
|
|
1354
|
+
} catch {}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
if (!connState.server && connState.topics.has(topic)) {
|
|
1358
|
+
connState.pendingWrites.push(data.slice());
|
|
1359
|
+
count++;
|
|
1360
|
+
}
|
|
1361
|
+
return count;
|
|
1362
|
+
},
|
|
1363
|
+
isSubscribed: (topic) => connState.topics.has(topic)
|
|
1364
|
+
};
|
|
1365
|
+
const sysImports = {
|
|
1366
|
+
sleep_ms: jspi ? new Suspending(async (ms) => new Promise((r) => setTimeout(r, ms))) : (_ms) => {}
|
|
1367
|
+
};
|
|
1368
|
+
const wsImports = buildWsImports(jspi ? Suspending : null, mem, decoder2, connState);
|
|
1369
|
+
const kvBindings = options?.kv?.(this.env);
|
|
1370
|
+
const instance = new WebAssembly.Instance(module, {
|
|
1371
|
+
wasi_snapshot_preview1: wasiImport,
|
|
1372
|
+
__zx_sys: sysImports,
|
|
1373
|
+
__zx_ws: wsImports,
|
|
1374
|
+
__zx_kv: createKVImports(kvBindings ?? { default: createMemoryKV() }, mem),
|
|
1375
|
+
...options?.imports ? options.imports(mem) : {},
|
|
1376
|
+
...bridgeImports
|
|
1377
|
+
});
|
|
1378
|
+
wasmMemory = instance.exports.memory;
|
|
1379
|
+
setMemory(wasmMemory);
|
|
1380
|
+
bridgeRef.current = new ZxBridge(instance.exports);
|
|
1381
|
+
const start = WebAssembly.promising(instance.exports._start);
|
|
1382
|
+
const wasmPromise = start().catch((e) => {
|
|
1383
|
+
wasmExited = true;
|
|
1384
|
+
if (e instanceof Error && e.message.startsWith("proc_exit"))
|
|
1385
|
+
return;
|
|
1386
|
+
console.error("[ZxWebSocketDO] WASM error:", e);
|
|
1387
|
+
}).finally(() => {
|
|
1388
|
+
if (connState.server)
|
|
1389
|
+
this.connections.delete(connState.server);
|
|
1390
|
+
if (connState.recvResolve) {
|
|
1391
|
+
const res = connState.recvResolve;
|
|
1392
|
+
connState.recvResolve = null;
|
|
1393
|
+
res(null);
|
|
1394
|
+
}
|
|
1395
|
+
});
|
|
1396
|
+
await Promise.race([firstSuspendPromise, wasmPromise]);
|
|
1397
|
+
if (!connState.upgraded || wasmExited) {
|
|
1398
|
+
return new Response("WebSocket upgrade expected", { status: 426 });
|
|
1399
|
+
}
|
|
1400
|
+
const { client } = attachWebSocket(connState);
|
|
1401
|
+
this.connections.set(connState.server, connState);
|
|
1402
|
+
this.doState.waitUntil(wasmPromise);
|
|
1403
|
+
return new Response(null, { status: 101, webSocket: client });
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
312
1406
|
}
|
|
313
|
-
var FORWARDED_HEADERS = [
|
|
314
|
-
"content-type",
|
|
315
|
-
"accept",
|
|
316
|
-
"authorization",
|
|
317
|
-
"cookie",
|
|
318
|
-
"user-agent",
|
|
319
|
-
"referer",
|
|
320
|
-
"x-forwarded-for",
|
|
321
|
-
"x-forwarded-proto",
|
|
322
|
-
"x-real-ip"
|
|
323
|
-
];
|
|
324
1407
|
function parseEdgeMeta(stderrText) {
|
|
325
1408
|
const meta = { status: 200, headers: new Headers };
|
|
326
1409
|
const metaPrefix = "__EDGE_META__:";
|
|
@@ -376,12 +1459,9 @@ function prepare({
|
|
|
376
1459
|
"--search",
|
|
377
1460
|
url.search
|
|
378
1461
|
];
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
args.push("--header", `${name}:${value}`);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
1462
|
+
request.headers.forEach((value, name) => {
|
|
1463
|
+
args.push("--header", `${name}:${value}`);
|
|
1464
|
+
});
|
|
385
1465
|
const stdin = request.body ?? undefined;
|
|
386
1466
|
return { args, stdout, stderr, stdin };
|
|
387
1467
|
}
|
|
@@ -405,7 +1485,29 @@ async function respond({
|
|
|
405
1485
|
headers: meta.headers
|
|
406
1486
|
});
|
|
407
1487
|
}
|
|
1488
|
+
// src/cloudflare/app.ts
|
|
1489
|
+
class Ziex {
|
|
1490
|
+
options;
|
|
1491
|
+
constructor(options) {
|
|
1492
|
+
this.options = options;
|
|
1493
|
+
}
|
|
1494
|
+
fetch(request, env, ctx) {
|
|
1495
|
+
const { module, wasi, imports, kv, websocket } = this.options;
|
|
1496
|
+
return run({
|
|
1497
|
+
request,
|
|
1498
|
+
env,
|
|
1499
|
+
ctx,
|
|
1500
|
+
module,
|
|
1501
|
+
wasi,
|
|
1502
|
+
imports,
|
|
1503
|
+
kv: kv?.(env),
|
|
1504
|
+
websocket: websocket?.(env)
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
408
1508
|
export {
|
|
409
1509
|
exports_worker as worker,
|
|
410
|
-
exports_kv as kv
|
|
1510
|
+
exports_kv as kv,
|
|
1511
|
+
createWebSocketDO,
|
|
1512
|
+
Ziex
|
|
411
1513
|
};
|