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