@bastani/atomic 0.9.26 → 0.9.27-alpha.1

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  3. package/dist/builtin/intercom/index.bundle.mjs +21 -6
  4. package/dist/builtin/intercom/package.json +1 -1
  5. package/dist/builtin/mcp/package.json +1 -1
  6. package/dist/builtin/subagents/CHANGELOG.md +8 -0
  7. package/dist/builtin/subagents/package.json +1 -1
  8. package/dist/builtin/subagents/src/extension/index.bundle.mjs +693 -642
  9. package/dist/builtin/web-access/package.json +1 -1
  10. package/dist/builtin/workflows/CHANGELOG.md +8 -0
  11. package/dist/builtin/workflows/package.json +1 -1
  12. package/dist/builtin/workflows/src/extension/index.bundle.mjs +71 -20
  13. package/dist/builtin/workflows/src/index.js +31 -10
  14. package/dist/codemode-worker.js +3309 -0
  15. package/dist/config.d.ts +7 -1
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/config.js +38 -12
  18. package/dist/config.js.map +1 -1
  19. package/dist/core/agent-session-custom-message-commit.d.ts.map +1 -1
  20. package/dist/core/agent-session-custom-message-commit.js +6 -0
  21. package/dist/core/agent-session-custom-message-commit.js.map +1 -1
  22. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  23. package/dist/core/agent-session-extension-bindings.js +22 -6
  24. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  25. package/dist/core/agent-session-services.d.ts.map +1 -1
  26. package/dist/core/agent-session-services.js +3 -1
  27. package/dist/core/agent-session-services.js.map +1 -1
  28. package/dist/core/agent-session-tasks.js +9 -4
  29. package/dist/core/agent-session-tasks.js.map +1 -1
  30. package/dist/core/auth-storage-backends.d.ts +3 -0
  31. package/dist/core/auth-storage-backends.d.ts.map +1 -1
  32. package/dist/core/auth-storage-backends.js +45 -1
  33. package/dist/core/auth-storage-backends.js.map +1 -1
  34. package/dist/core/auth-storage.d.ts.map +1 -1
  35. package/dist/core/auth-storage.js +14 -0
  36. package/dist/core/auth-storage.js.map +1 -1
  37. package/dist/core/extensions/provider-types.d.ts +3 -2
  38. package/dist/core/extensions/provider-types.d.ts.map +1 -1
  39. package/dist/core/extensions/provider-types.js.map +1 -1
  40. package/dist/core/extensions/runner-events.d.ts.map +1 -1
  41. package/dist/core/extensions/runner-events.js +10 -1
  42. package/dist/core/extensions/runner-events.js.map +1 -1
  43. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  44. package/dist/extensions/codemode/execute.js +40 -6
  45. package/dist/extensions/codemode/execute.js.map +1 -1
  46. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  47. package/dist/extensions/codemode/tool.js +1 -0
  48. package/dist/extensions/codemode/tool.js.map +1 -1
  49. package/dist/extensions/mcp/tools.d.ts.map +1 -1
  50. package/dist/extensions/mcp/tools.js +4 -9
  51. package/dist/extensions/mcp/tools.js.map +1 -1
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +1 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/modes/interactive/interactive-agent-events.js +21 -0
  57. package/dist/modes/interactive/interactive-agent-events.js.map +1 -1
  58. package/dist/modes/interactive/interactive-mode-base.d.ts +1 -0
  59. package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
  60. package/dist/modes/interactive/interactive-mode-base.js +1 -0
  61. package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
  62. package/dist/modes/interactive/interactive-mode-helpers.js +1 -1
  63. package/dist/modes/interactive/interactive-mode-helpers.js.map +1 -1
  64. package/dist/modes/interactive/interactive-mode-surface.d.ts +1 -0
  65. package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
  66. package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
  67. package/dist/modes/interactive/interactive-process-lifecycle.js +7 -4
  68. package/dist/modes/interactive/interactive-process-lifecycle.js.map +1 -1
  69. package/dist/utils/output-files.d.ts +7 -0
  70. package/dist/utils/output-files.d.ts.map +1 -0
  71. package/dist/utils/output-files.js +20 -0
  72. package/dist/utils/output-files.js.map +1 -0
  73. package/docs/codemode.md +3 -3
  74. package/docs/extensions/api-reference.md +3 -1
  75. package/docs/extensions.md +2 -0
  76. package/docs/sdk.md +2 -0
  77. package/docs/settings.md +2 -0
  78. package/docs/subagents.md +4 -0
  79. package/docs/workflows/api-reference.md +6 -2
  80. package/docs/workflows/operations.md +10 -10
  81. package/npm-shrinkwrap.json +32 -32
  82. package/package.json +6 -6
@@ -0,0 +1,3309 @@
1
+ // ../../node_modules/@earendil-works/pi-codemode/dist/runtime/worker.js
2
+ import { parentPort, workerData } from "node:worker_threads";
3
+
4
+ // ../../node_modules/quickjs-wasi/dist/wasi-shim.js
5
+ function createWasiShim(memoryAccessor) {
6
+ const ERRNO_SUCCESS = 0;
7
+ const ERRNO_BADF = 8;
8
+ const ERRNO_NOSYS = 52;
9
+ const CLOCK_REALTIME = 0;
10
+ const CLOCK_MONOTONIC = 1;
11
+ return {
12
+ clock_time_get(clockId, _precision, resultPtr) {
13
+ const mem = memoryAccessor();
14
+ const view = new DataView(mem.buffer);
15
+ if (clockId === CLOCK_REALTIME || clockId === CLOCK_MONOTONIC) {
16
+ const timeNs = BigInt(Date.now()) * 1000000n;
17
+ view.setBigUint64(resultPtr, timeNs, true);
18
+ return ERRNO_SUCCESS;
19
+ }
20
+ return ERRNO_NOSYS;
21
+ },
22
+ fd_write(fd, iovsPtr, iovsLen, nwrittenPtr) {
23
+ const mem = memoryAccessor();
24
+ const view = new DataView(mem.buffer);
25
+ const bytes = new Uint8Array(mem.buffer);
26
+ let totalWritten = 0;
27
+ if (fd !== 1 && fd !== 2) {
28
+ return ERRNO_BADF;
29
+ }
30
+ for (let i = 0; i < iovsLen; i++) {
31
+ const bufPtr = view.getUint32(iovsPtr + i * 8, true);
32
+ const bufLen = view.getUint32(iovsPtr + i * 8 + 4, true);
33
+ const chunk = bytes.slice(bufPtr, bufPtr + bufLen);
34
+ const text = new TextDecoder().decode(chunk);
35
+ if (fd === 1) {
36
+ if (typeof process !== "undefined" && process.stdout) {
37
+ process.stdout.write(text);
38
+ } else {
39
+ console.log(text);
40
+ }
41
+ } else {
42
+ if (typeof process !== "undefined" && process.stderr) {
43
+ process.stderr.write(text);
44
+ } else {
45
+ console.error(text);
46
+ }
47
+ }
48
+ totalWritten += bufLen;
49
+ }
50
+ view.setUint32(nwrittenPtr, totalWritten, true);
51
+ return ERRNO_SUCCESS;
52
+ },
53
+ fd_close(_fd) {
54
+ return ERRNO_NOSYS;
55
+ },
56
+ fd_fdstat_get(fd, statPtr) {
57
+ const mem = memoryAccessor();
58
+ const view = new DataView(mem.buffer);
59
+ if (fd === 1 || fd === 2) {
60
+ view.setUint8(statPtr, 2);
61
+ view.setUint16(statPtr + 2, 0, true);
62
+ view.setBigUint64(statPtr + 8, 0n, true);
63
+ view.setBigUint64(statPtr + 16, 0n, true);
64
+ return ERRNO_SUCCESS;
65
+ }
66
+ return ERRNO_BADF;
67
+ },
68
+ fd_seek(_fd, _offset, _whence, _resultPtr) {
69
+ return ERRNO_NOSYS;
70
+ },
71
+ random_get(bufPtr, bufLen) {
72
+ const mem = memoryAccessor();
73
+ const bytes = new Uint8Array(mem.buffer, bufPtr, bufLen);
74
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
75
+ crypto.getRandomValues(bytes);
76
+ } else {
77
+ for (let i = 0; i < bufLen; i++) {
78
+ bytes[i] = Math.floor(Math.random() * 256);
79
+ }
80
+ }
81
+ return ERRNO_SUCCESS;
82
+ }
83
+ };
84
+ }
85
+
86
+ // ../../node_modules/quickjs-wasi/dist/extensions.js
87
+ var decoder = new TextDecoder();
88
+ function parseVersionString(memory, ptr) {
89
+ const mem = new Uint8Array(memory.buffer);
90
+ let end = ptr;
91
+ while (mem[end] !== 0)
92
+ end++;
93
+ if (end === ptr)
94
+ return {};
95
+ const str = decoder.decode(mem.slice(ptr, end));
96
+ const result = {};
97
+ for (const line of str.split("\n")) {
98
+ const eq = line.indexOf("=");
99
+ if (eq > 0) {
100
+ result[line.slice(0, eq)] = line.slice(eq + 1);
101
+ }
102
+ }
103
+ return result;
104
+ }
105
+ function extractExtensionVersions(ext, memory) {
106
+ const versionsFnName = `qjs_ext_${ext.name.replace(/-/g, "_")}_versions`;
107
+ const versionsFn = ext.instance.exports[versionsFnName];
108
+ if (typeof versionsFn !== "function")
109
+ return void 0;
110
+ const ptr = versionsFn();
111
+ if (ptr === 0)
112
+ return void 0;
113
+ return parseVersionString(memory, ptr);
114
+ }
115
+ function readULEB128(bytes, offset) {
116
+ let result = 0;
117
+ let shift = 0;
118
+ while (offset.value < bytes.length) {
119
+ const byte = bytes[offset.value++];
120
+ result |= (byte & 127) << shift;
121
+ if ((byte & 128) === 0)
122
+ break;
123
+ shift += 7;
124
+ }
125
+ return result;
126
+ }
127
+ function parseDylink(module) {
128
+ const sections = WebAssembly.Module.customSections(module, "dylink.0");
129
+ if (sections.length === 0)
130
+ return null;
131
+ const bytes = new Uint8Array(sections[0]);
132
+ const offset = { value: 0 };
133
+ const info = {
134
+ memorySize: 0,
135
+ memoryAlignment: 0,
136
+ tableSize: 0,
137
+ tableAlignment: 0,
138
+ needed: []
139
+ };
140
+ while (offset.value < bytes.length) {
141
+ const subsectionType = readULEB128(bytes, offset);
142
+ const subsectionSize = readULEB128(bytes, offset);
143
+ const subsectionEnd = offset.value + subsectionSize;
144
+ if (subsectionType === 1) {
145
+ info.memorySize = readULEB128(bytes, offset);
146
+ info.memoryAlignment = readULEB128(bytes, offset);
147
+ info.tableSize = readULEB128(bytes, offset);
148
+ info.tableAlignment = readULEB128(bytes, offset);
149
+ } else if (subsectionType === 2) {
150
+ const count = readULEB128(bytes, offset);
151
+ for (let i = 0; i < count; i++) {
152
+ const len = readULEB128(bytes, offset);
153
+ const name = new TextDecoder().decode(bytes.slice(offset.value, offset.value + len));
154
+ offset.value += len;
155
+ info.needed.push(name);
156
+ }
157
+ }
158
+ offset.value = subsectionEnd;
159
+ }
160
+ return info;
161
+ }
162
+ async function loadExtension(descriptor, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy, allocBase) {
163
+ let module;
164
+ if (descriptor.wasm instanceof WebAssembly.Module) {
165
+ module = descriptor.wasm;
166
+ } else {
167
+ module = await WebAssembly.compile(descriptor.wasm);
168
+ }
169
+ const dylink = parseDylink(module);
170
+ if (!dylink) {
171
+ throw new Error(`Extension "${descriptor.name}" is not a WASM shared library (missing dylink.0 section)`);
172
+ }
173
+ const memory = mainExports.memory;
174
+ const table = mainExports.__indirect_function_table;
175
+ const stackPointer = mainExports.__stack_pointer;
176
+ const mallocFn = mainExports.malloc;
177
+ if (!memory)
178
+ throw new Error("Main module does not export memory");
179
+ if (!table)
180
+ throw new Error("Main module does not export __indirect_function_table");
181
+ if (!mallocFn)
182
+ throw new Error("Main module does not export malloc");
183
+ let memoryBase;
184
+ let tableBase;
185
+ if (allocBase) {
186
+ memoryBase = allocBase.memoryBase;
187
+ tableBase = allocBase.tableBase;
188
+ } else {
189
+ if (dylink.memorySize > 0) {
190
+ memoryBase = mallocFn(dylink.memorySize);
191
+ if (memoryBase === 0) {
192
+ throw new Error(`Failed to allocate ${dylink.memorySize} bytes for extension "${descriptor.name}"`);
193
+ }
194
+ new Uint8Array(memory.buffer, memoryBase, dylink.memorySize).fill(0);
195
+ } else {
196
+ memoryBase = 0;
197
+ }
198
+ }
199
+ if (allocBase) {
200
+ tableBase = allocBase.tableBase;
201
+ if (tableBase + dylink.tableSize > table.length) {
202
+ table.grow(tableBase + dylink.tableSize - table.length);
203
+ }
204
+ } else {
205
+ tableBase = table.length;
206
+ if (dylink.tableSize > 0) {
207
+ table.grow(dylink.tableSize);
208
+ }
209
+ }
210
+ const extImports = WebAssembly.Module.imports(module);
211
+ const importObj = {
212
+ env: {},
213
+ "GOT.mem": {},
214
+ "GOT.func": {}
215
+ };
216
+ const needsWasi = extImports.some((imp) => imp.module === "wasi_snapshot_preview1");
217
+ if (needsWasi) {
218
+ const extWasi = descriptor.wasi && memoryProxy ? descriptor.wasi(memoryProxy) : void 0;
219
+ importObj["wasi_snapshot_preview1"] = {
220
+ ...wasiBuiltins,
221
+ // 1. Built-in defaults (lowest priority)
222
+ ...extWasi,
223
+ // 2. Extension-provided
224
+ ...wasiUserOverrides
225
+ // 3. User overrides (highest priority)
226
+ };
227
+ }
228
+ const extExportNames = new Set(WebAssembly.Module.exports(module).filter((e) => e.kind === "function").map((e) => e.name));
229
+ const unresolvedFuncs = /* @__PURE__ */ new Set();
230
+ for (const imp of extImports) {
231
+ if (imp.module === "env") {
232
+ if (imp.name === "memory" && imp.kind === "memory") {
233
+ importObj.env.memory = memory;
234
+ } else if (imp.name === "__indirect_function_table" && imp.kind === "table") {
235
+ importObj.env.__indirect_function_table = table;
236
+ } else if (imp.name === "__memory_base" && imp.kind === "global") {
237
+ importObj.env.__memory_base = new WebAssembly.Global({ value: "i32", mutable: false }, memoryBase);
238
+ } else if (imp.name === "__table_base" && imp.kind === "global") {
239
+ importObj.env.__table_base = new WebAssembly.Global({ value: "i32", mutable: false }, tableBase);
240
+ } else if (imp.name === "__stack_pointer" && imp.kind === "global") {
241
+ importObj.env.__stack_pointer = stackPointer;
242
+ } else if (imp.kind === "function") {
243
+ const resolved = mainExports[imp.name];
244
+ if (resolved && typeof resolved === "function") {
245
+ importObj.env[imp.name] = resolved;
246
+ } else {
247
+ unresolvedFuncs.add(imp.name);
248
+ importObj.env[imp.name] = () => {
249
+ throw new Error(`Extension "${descriptor.name}" called unresolved symbol: env.${imp.name}`);
250
+ };
251
+ }
252
+ } else if (imp.kind === "global") {
253
+ const resolved = mainExports[imp.name];
254
+ if (resolved instanceof WebAssembly.Global) {
255
+ importObj.env[imp.name] = resolved;
256
+ } else {
257
+ importObj.env[imp.name] = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
258
+ }
259
+ }
260
+ } else if (imp.module === "GOT.mem" && imp.kind === "global") {
261
+ importObj["GOT.mem"][imp.name] = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
262
+ } else if (imp.module === "GOT.func" && imp.kind === "global") {
263
+ const resolved = mainExports[imp.name];
264
+ if (resolved && typeof resolved === "function") {
265
+ const idx = table.length;
266
+ table.grow(1);
267
+ table.set(idx, resolved);
268
+ importObj["GOT.func"][imp.name] = new WebAssembly.Global({ value: "i32", mutable: true }, idx);
269
+ } else {
270
+ importObj["GOT.func"][imp.name] = new WebAssembly.Global({ value: "i32", mutable: true }, 0);
271
+ }
272
+ }
273
+ }
274
+ const selfResolvable = [...unresolvedFuncs].filter((name) => extExportNames.has(name));
275
+ const wrappers = {};
276
+ for (const name of selfResolvable) {
277
+ const wrapper = { target: null };
278
+ wrappers[name] = wrapper;
279
+ importObj.env[name] = (...args) => {
280
+ if (!wrapper.target) {
281
+ throw new Error(`Extension "${descriptor.name}" called unresolved symbol during init: env.${name}`);
282
+ }
283
+ return wrapper.target(...args);
284
+ };
285
+ }
286
+ const instance = await WebAssembly.instantiate(module, importObj);
287
+ const extExports = instance.exports;
288
+ for (const name of selfResolvable) {
289
+ const selfExport = extExports[name];
290
+ if (typeof selfExport === "function") {
291
+ wrappers[name].target = selfExport;
292
+ }
293
+ }
294
+ if (typeof extExports.__wasm_apply_data_relocs === "function") {
295
+ extExports.__wasm_apply_data_relocs();
296
+ }
297
+ if (typeof extExports.__wasm_call_ctors === "function") {
298
+ extExports.__wasm_call_ctors();
299
+ }
300
+ const initFn = descriptor.initFn ?? `qjs_ext_${descriptor.name.replace(/-/g, "_")}_init`;
301
+ const ext = {
302
+ name: descriptor.name,
303
+ module,
304
+ instance,
305
+ dylink,
306
+ memoryBase,
307
+ tableBase,
308
+ initFn
309
+ };
310
+ ext.versions = extractExtensionVersions(ext, memory);
311
+ return ext;
312
+ }
313
+ function initExtension(ext, mainExports) {
314
+ const initFunc = ext.instance.exports[ext.initFn];
315
+ if (typeof initFunc !== "function") {
316
+ throw new Error(`Extension "${ext.name}" does not export init function "${ext.initFn}"`);
317
+ }
318
+ const ctxPtr = mainExports.qjs_get_context_ptr();
319
+ const rtPtr = mainExports.qjs_get_runtime_ptr();
320
+ const result = initFunc(ctxPtr, rtPtr);
321
+ if (result !== 0) {
322
+ throw new Error(`Extension "${ext.name}" init function returned error code ${result}`);
323
+ }
324
+ }
325
+ async function restoreExtensions(descriptors, extensionMeta, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy) {
326
+ const loaded = [];
327
+ for (const meta of extensionMeta) {
328
+ const descriptor = descriptors.find((d) => d.name === meta.name);
329
+ if (!descriptor) {
330
+ throw new Error(`Extension "${meta.name}" required by snapshot but not provided`);
331
+ }
332
+ const ext = await loadExtension(descriptor, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy, {
333
+ memoryBase: meta.memoryBase,
334
+ tableBase: meta.tableBase
335
+ });
336
+ ext.initFn = meta.initFn;
337
+ loaded.push(ext);
338
+ }
339
+ return loaded;
340
+ }
341
+
342
+ // ../../node_modules/quickjs-wasi/dist/version.js
343
+ var VERSION = "3.6.2";
344
+
345
+ // ../../node_modules/quickjs-wasi/dist/index.js
346
+ var __addDisposableResource = function(env, value, async) {
347
+ if (value !== null && value !== void 0) {
348
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
349
+ var dispose, inner;
350
+ if (async) {
351
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
352
+ dispose = value[Symbol.asyncDispose];
353
+ }
354
+ if (dispose === void 0) {
355
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
356
+ dispose = value[Symbol.dispose];
357
+ if (async) inner = dispose;
358
+ }
359
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
360
+ if (inner) dispose = function() {
361
+ try {
362
+ inner.call(this);
363
+ } catch (e) {
364
+ return Promise.reject(e);
365
+ }
366
+ };
367
+ env.stack.push({ value, dispose, async });
368
+ } else if (async) {
369
+ env.stack.push({ async: true });
370
+ }
371
+ return value;
372
+ };
373
+ var __disposeResources = /* @__PURE__ */ (function(SuppressedError2) {
374
+ return function(env) {
375
+ function fail(e) {
376
+ env.error = env.hasError ? new SuppressedError2(e, env.error, "An error was suppressed during disposal.") : e;
377
+ env.hasError = true;
378
+ }
379
+ var r, s = 0;
380
+ function next() {
381
+ while (r = env.stack.pop()) {
382
+ try {
383
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
384
+ if (r.dispose) {
385
+ var result = r.dispose.call(r.value);
386
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
387
+ fail(e);
388
+ return next();
389
+ });
390
+ } else s |= 1;
391
+ } catch (e) {
392
+ fail(e);
393
+ }
394
+ }
395
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
396
+ if (env.hasError) throw env.error;
397
+ }
398
+ return next();
399
+ };
400
+ })(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
401
+ var e = new Error(message);
402
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
403
+ });
404
+ var MAX_STACK_SIZE = 512 * 1024;
405
+ var EvalFlags = {
406
+ /** Global script mode (default). */
407
+ TYPE_GLOBAL: 0,
408
+ /**
409
+ * Module mode. `evalCode()` returns a handle to a Promise that resolves
410
+ * to the module's namespace object (its exports), or rejects if module
411
+ * evaluation throws. Use together with `executePendingJobs()` and
412
+ * `resolvePromise()`.
413
+ */
414
+ TYPE_MODULE: 1 << 0,
415
+ /** Force strict mode. */
416
+ STRICT: 1 << 3,
417
+ /** Compile only; do not execute. */
418
+ COMPILE_ONLY: 1 << 5,
419
+ /** Omit stack frames before this eval from Error backtraces. */
420
+ BACKTRACE_BARRIER: 1 << 6,
421
+ /**
422
+ * Allow top-level `await` in global scripts. When used, `evalCode()`
423
+ * returns a handle to a Promise that resolves to the completion value.
424
+ * Use together with `executePendingJobs()` and `resolvePromise()`.
425
+ */
426
+ ASYNC: 1 << 7
427
+ };
428
+ var CompileFlags = {
429
+ /** Strip source code from the bytecode (smaller output, no source in errors). */
430
+ STRIP_SOURCE: 1 << 4,
431
+ /** Strip debug information (line numbers, etc.) from the bytecode. */
432
+ STRIP_DEBUG: 1 << 5
433
+ };
434
+ var Intrinsics = {
435
+ /** `Date` constructor and prototype methods. */
436
+ DATE: 1 << 0,
437
+ /** `eval()` and `Function()` constructor. */
438
+ EVAL: 1 << 1,
439
+ /** `RegExp` constructor, prototype methods, and regex literals. */
440
+ REGEXP: 1 << 2,
441
+ /** `JSON.parse()` and `JSON.stringify()`. */
442
+ JSON: 1 << 3,
443
+ /** `Proxy` and `Reflect`. */
444
+ PROXY: 1 << 4,
445
+ /** `Map`, `Set`, `WeakMap`, `WeakSet`. */
446
+ MAP_SET: 1 << 5,
447
+ /** `ArrayBuffer`, `TypedArray` variants, `DataView`. */
448
+ TYPED_ARRAYS: 1 << 6,
449
+ /** `Promise`, `async`/`await`. */
450
+ PROMISE: 1 << 7,
451
+ /** `BigInt`. Note: BigInt is part of BaseObjects in quickjs-ng and cannot be fully removed. */
452
+ BIG_INT: 1 << 8,
453
+ /** `WeakRef` and `FinalizationRegistry`. */
454
+ WEAK_REF: 1 << 9,
455
+ /** `performance.now()`. */
456
+ PERFORMANCE: 1 << 10,
457
+ /** `DOMException` class. */
458
+ DOM_EXCEPTION: 1 << 11,
459
+ /**
460
+ * `atob()` and `btoa()` global functions. Also pulls in `DOMException` as
461
+ * a dependency (errors thrown by these functions are `DOMException`s).
462
+ */
463
+ ATOB_BTOA: 1 << 12,
464
+ /** All intrinsics enabled (default). */
465
+ ALL: 4294967295
466
+ };
467
+ var SNAPSHOT_MAGIC = 1363825491;
468
+ var SNAPSHOT_VERSION = 2;
469
+ var SNAPSHOT_HEADER_SIZE = 24;
470
+ var QuickJS = class _QuickJS {
471
+ exports;
472
+ module;
473
+ instance;
474
+ encoder = new TextEncoder();
475
+ decoder = new TextDecoder();
476
+ disposed = false;
477
+ /** Registry of host callbacks, keyed by function name */
478
+ hostCallbacks = /* @__PURE__ */ new Map();
479
+ /** Counter for internal-only callbacks (e.g. promise settle handlers) */
480
+ nextInternalId = 1;
481
+ interruptHandler = null;
482
+ unhandledRejectionHandler = null;
483
+ moduleNormalizeHandler = null;
484
+ moduleLoadHandler = null;
485
+ timezoneOffsetHandler = null;
486
+ // Cached singleton handles
487
+ _global = null;
488
+ _versions = null;
489
+ _undefined = null;
490
+ _null = null;
491
+ _true = null;
492
+ _false = null;
493
+ // Handles that must be freed on dispose (e.g. unresolved promise resolve/reject functions)
494
+ _ownedHandles = /* @__PURE__ */ new Set();
495
+ /**
496
+ * The innermost active `withScope()` batch, if any. New non-singleton
497
+ * handles register themselves here so they can be freed together.
498
+ * @internal
499
+ */
500
+ _activeScope = null;
501
+ /** Loaded extensions in deterministic order */
502
+ loadedExtensions = [];
503
+ constructor(module) {
504
+ this.module = module;
505
+ this.instance = null;
506
+ this.exports = null;
507
+ }
508
+ setInstance(instance) {
509
+ this.instance = instance;
510
+ this.exports = instance.exports;
511
+ }
512
+ // ---- Cached property accessors ----
513
+ /**
514
+ * Version information for the runtime and loaded native libraries.
515
+ * Always includes `"quickjs-wasi"` (the npm package version) and
516
+ * `"quickjs"` (the QuickJS engine version). Extensions may contribute
517
+ * additional entries for their native dependencies (e.g. `"ada"`, `"mbedtls"`).
518
+ */
519
+ get versions() {
520
+ this.assertNotDisposed();
521
+ if (!this._versions) {
522
+ const result = {
523
+ "quickjs-wasi": VERSION,
524
+ quickjs: this.readCString(this.exports.qjs_get_quickjs_version())
525
+ };
526
+ for (const ext of this.loadedExtensions) {
527
+ if (ext.versions) {
528
+ Object.assign(result, ext.versions);
529
+ }
530
+ }
531
+ this._versions = result;
532
+ }
533
+ return this._versions;
534
+ }
535
+ /** The global object. Cached; do not dispose. */
536
+ get global() {
537
+ if (!this._global) {
538
+ this._global = new JSValueHandle(this, this.exports.qjs_get_global(), true);
539
+ }
540
+ return this._global;
541
+ }
542
+ /** The undefined value. Cached; do not dispose. */
543
+ get undefined() {
544
+ if (!this._undefined) {
545
+ this._undefined = new JSValueHandle(this, this.exports.qjs_get_undefined(), true);
546
+ }
547
+ return this._undefined;
548
+ }
549
+ /** The null value. Cached; do not dispose. */
550
+ get null() {
551
+ if (!this._null) {
552
+ this._null = new JSValueHandle(this, this.exports.qjs_get_null(), true);
553
+ }
554
+ return this._null;
555
+ }
556
+ /** The true value. Cached; do not dispose. */
557
+ get true() {
558
+ if (!this._true) {
559
+ this._true = new JSValueHandle(this, this.exports.qjs_get_true(), true);
560
+ }
561
+ return this._true;
562
+ }
563
+ /** The false value. Cached; do not dispose. */
564
+ get false() {
565
+ if (!this._false) {
566
+ this._false = new JSValueHandle(this, this.exports.qjs_get_false(), true);
567
+ }
568
+ return this._false;
569
+ }
570
+ /**
571
+ * Create a fresh QuickJS VM instance.
572
+ *
573
+ * @param options - Optional configuration. Can also pass raw WASM bytes
574
+ * directly for backwards compatibility.
575
+ */
576
+ static async create(options) {
577
+ const opts = _QuickJS.normalizeOptions(options);
578
+ const module = await _QuickJS.resolveModule(opts.wasm);
579
+ const vm = new _QuickJS(module);
580
+ const { instance, wasiBuiltins, wasiUserOverrides, memoryProxy } = await _QuickJS.instantiate(module, vm, opts.wasi);
581
+ vm.setInstance(instance);
582
+ vm.exports._initialize();
583
+ const result = opts.intrinsics !== void 0 ? vm.exports.qjs_init2(opts.intrinsics) : vm.exports.qjs_init();
584
+ if (result !== 0) {
585
+ throw new Error("Failed to initialize QuickJS runtime");
586
+ }
587
+ if (opts.extensions) {
588
+ const mainExports = instance.exports;
589
+ for (const desc of opts.extensions) {
590
+ const ext = await loadExtension(desc, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy);
591
+ vm.loadedExtensions.push(ext);
592
+ initExtension(ext, mainExports);
593
+ }
594
+ }
595
+ _QuickJS.applyLimits(vm, opts);
596
+ return vm;
597
+ }
598
+ /**
599
+ * Restore a QuickJS VM from a snapshot.
600
+ *
601
+ * @param snapshot - The snapshot to restore from.
602
+ * @param options - Optional configuration. Can also pass raw WASM bytes
603
+ * directly for backwards compatibility.
604
+ */
605
+ static async restore(snapshot, options) {
606
+ const opts = _QuickJS.normalizeOptions(options);
607
+ const module = await _QuickJS.resolveModule(opts.wasm);
608
+ const vm = new _QuickJS(module);
609
+ const { instance, wasiBuiltins, wasiUserOverrides, memoryProxy } = await _QuickJS.instantiate(module, vm, opts.wasi);
610
+ vm.setInstance(instance);
611
+ const mainExports = instance.exports;
612
+ const exportedMemory = vm.exports.memory;
613
+ const currentPages = exportedMemory.buffer.byteLength / 65536;
614
+ const neededPages = Math.ceil(snapshot.memory.byteLength / 65536);
615
+ if (neededPages > currentPages) {
616
+ exportedMemory.grow(neededPages - currentPages);
617
+ }
618
+ if (snapshot.extensions.length > 0) {
619
+ const descriptors = opts.extensions ?? [];
620
+ vm.loadedExtensions = await restoreExtensions(descriptors, snapshot.extensions, mainExports, wasiBuiltins, wasiUserOverrides, memoryProxy);
621
+ }
622
+ const dst = new Uint8Array(exportedMemory.buffer);
623
+ dst.set(snapshot.memory);
624
+ vm.exports.qjs_set_runtime_and_context(snapshot.runtimePtr, snapshot.contextPtr);
625
+ vm.exports.__stack_pointer.value = snapshot.stackPointer;
626
+ _QuickJS.applyLimits(vm, opts);
627
+ return vm;
628
+ }
629
+ // ---- Snapshot serialization ----
630
+ /**
631
+ * Serialize a snapshot to a binary buffer for persistent storage.
632
+ *
633
+ * The format includes a versioned header followed by the raw memory.
634
+ * Apply your own compression (gzip, zstd, etc.) on top for smaller
635
+ * storage. The memory compresses well due to its large zero regions.
636
+ *
637
+ * Format (version 1):
638
+ * ```
639
+ * Offset Size Field
640
+ * 0 4 Magic: "QJSS" (0x514A5353, big-endian)
641
+ * 4 1 Version: 1
642
+ * 5 3 Reserved (zero)
643
+ * 8 4 Memory size in bytes (u32 little-endian)
644
+ * 12 4 Stack pointer (u32 little-endian)
645
+ * 16 4 Runtime pointer (u32 little-endian)
646
+ * 20 4 Context pointer (u32 little-endian)
647
+ * 24 N Memory data (N = memory size from offset 8)
648
+ * ```
649
+ */
650
+ static serializeSnapshot(snapshot) {
651
+ const textEncoder = new TextEncoder();
652
+ let extMetaSize = 4;
653
+ const extEncodedNames = [];
654
+ const extEncodedInitFns = [];
655
+ for (const ext of snapshot.extensions) {
656
+ const nameBytes = textEncoder.encode(ext.name);
657
+ const initFnBytes = textEncoder.encode(ext.initFn);
658
+ extEncodedNames.push(nameBytes);
659
+ extEncodedInitFns.push(initFnBytes);
660
+ extMetaSize += 4 + nameBytes.length + 4 + 4 + 4 + initFnBytes.length;
661
+ }
662
+ const totalSize = SNAPSHOT_HEADER_SIZE + extMetaSize + snapshot.memory.byteLength;
663
+ const buffer = new ArrayBuffer(totalSize);
664
+ const view = new DataView(buffer);
665
+ const bytes = new Uint8Array(buffer);
666
+ view.setUint32(0, SNAPSHOT_MAGIC, false);
667
+ view.setUint8(4, SNAPSHOT_VERSION);
668
+ view.setUint32(8, snapshot.memory.byteLength, true);
669
+ view.setUint32(12, snapshot.stackPointer, true);
670
+ view.setUint32(16, snapshot.runtimePtr, true);
671
+ view.setUint32(20, snapshot.contextPtr, true);
672
+ let offset = SNAPSHOT_HEADER_SIZE;
673
+ view.setUint32(offset, snapshot.extensions.length, true);
674
+ offset += 4;
675
+ for (let i = 0; i < snapshot.extensions.length; i++) {
676
+ const ext = snapshot.extensions[i];
677
+ const nameBytes = extEncodedNames[i];
678
+ const initFnBytes = extEncodedInitFns[i];
679
+ view.setUint32(offset, nameBytes.length, true);
680
+ offset += 4;
681
+ bytes.set(nameBytes, offset);
682
+ offset += nameBytes.length;
683
+ view.setUint32(offset, ext.memoryBase, true);
684
+ offset += 4;
685
+ view.setUint32(offset, ext.tableBase, true);
686
+ offset += 4;
687
+ view.setUint32(offset, initFnBytes.length, true);
688
+ offset += 4;
689
+ bytes.set(initFnBytes, offset);
690
+ offset += initFnBytes.length;
691
+ }
692
+ bytes.set(snapshot.memory, offset);
693
+ return bytes;
694
+ }
695
+ /**
696
+ * Deserialize a snapshot from a binary buffer produced by `serializeSnapshot()`.
697
+ */
698
+ static deserializeSnapshot(data) {
699
+ if (data.length < SNAPSHOT_HEADER_SIZE) {
700
+ throw new Error("Invalid snapshot: too small");
701
+ }
702
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
703
+ const magic = view.getUint32(0, false);
704
+ if (magic !== SNAPSHOT_MAGIC) {
705
+ throw new Error(`Invalid snapshot: bad magic (expected 0x${SNAPSHOT_MAGIC.toString(16)}, got 0x${magic.toString(16)})`);
706
+ }
707
+ const version = view.getUint8(4);
708
+ if (version !== SNAPSHOT_VERSION && version !== 1) {
709
+ throw new Error(`Unsupported snapshot version: ${version} (expected ${SNAPSHOT_VERSION})`);
710
+ }
711
+ const memorySize = view.getUint32(8, true);
712
+ const stackPointer = view.getUint32(12, true);
713
+ const runtimePtr = view.getUint32(16, true);
714
+ const contextPtr = view.getUint32(20, true);
715
+ let extensions = [];
716
+ let memoryOffset = SNAPSHOT_HEADER_SIZE;
717
+ if (version >= 2) {
718
+ const extCount = view.getUint32(24, true);
719
+ let offset = 28;
720
+ const textDecoder = new TextDecoder();
721
+ for (let i = 0; i < extCount; i++) {
722
+ const nameLen = view.getUint32(offset, true);
723
+ offset += 4;
724
+ const name = textDecoder.decode(data.slice(offset, offset + nameLen));
725
+ offset += nameLen;
726
+ const memBase = view.getUint32(offset, true);
727
+ offset += 4;
728
+ const tblBase = view.getUint32(offset, true);
729
+ offset += 4;
730
+ const initFnLen = view.getUint32(offset, true);
731
+ offset += 4;
732
+ const initFn = textDecoder.decode(data.slice(offset, offset + initFnLen));
733
+ offset += initFnLen;
734
+ extensions.push({ name, memoryBase: memBase, tableBase: tblBase, initFn });
735
+ }
736
+ memoryOffset = offset;
737
+ }
738
+ const expectedSize = memoryOffset + memorySize;
739
+ if (data.length < expectedSize) {
740
+ throw new Error(`Invalid snapshot: expected ${expectedSize} bytes, got ${data.length}`);
741
+ }
742
+ const memory = data.slice(memoryOffset, memoryOffset + memorySize);
743
+ return { memory, stackPointer, runtimePtr, contextPtr, extensions };
744
+ }
745
+ // ---- Internal instantiation helpers ----
746
+ static normalizeOptions(options) {
747
+ if (!options) {
748
+ return { wasm: void 0 };
749
+ }
750
+ if (options instanceof WebAssembly.Module)
751
+ return { wasm: options };
752
+ if (typeof options === "object" && ("wasm" in options || "wasi" in options || "memoryLimit" in options || "maxStackSize" in options || "interruptHandler" in options || "onUnhandledRejection" in options || "moduleLoader" in options || "intrinsics" in options || "extensions" in options || "timezoneOffset" in options)) {
753
+ const opts = options;
754
+ if (opts.maxStackSize !== void 0 && (!Number.isInteger(opts.maxStackSize) || opts.maxStackSize < 0 || opts.maxStackSize > MAX_STACK_SIZE)) {
755
+ throw new RangeError(`maxStackSize must be an integer between 0 and ${MAX_STACK_SIZE}`);
756
+ }
757
+ return opts;
758
+ }
759
+ return { wasm: options };
760
+ }
761
+ static applyLimits(vm, opts) {
762
+ if (opts.memoryLimit !== void 0) {
763
+ vm.exports.qjs_set_memory_limit(opts.memoryLimit);
764
+ }
765
+ if (opts.maxStackSize !== void 0) {
766
+ vm.exports.qjs_set_max_stack_size(opts.maxStackSize);
767
+ }
768
+ if (opts.interruptHandler) {
769
+ vm.interruptHandler = opts.interruptHandler;
770
+ vm.exports.qjs_set_interrupt_handler(1);
771
+ }
772
+ if (opts.onUnhandledRejection) {
773
+ vm.unhandledRejectionHandler = opts.onUnhandledRejection;
774
+ vm.exports.qjs_set_promise_rejection_handler(1);
775
+ }
776
+ if (opts.moduleLoader) {
777
+ vm.moduleLoadHandler = opts.moduleLoader.load;
778
+ vm.moduleNormalizeHandler = opts.moduleLoader.normalize ?? null;
779
+ vm.exports.qjs_set_module_loader(1);
780
+ }
781
+ const tz = opts.timezoneOffset;
782
+ if (typeof tz === "function") {
783
+ vm.timezoneOffsetHandler = (timeSecs) => -tz(timeSecs) * 60;
784
+ } else if (typeof tz === "number") {
785
+ const offsetSecs = -tz * 60;
786
+ vm.timezoneOffsetHandler = () => offsetSecs;
787
+ } else {
788
+ vm.timezoneOffsetHandler = (timeSecs) => {
789
+ return -new Date(timeSecs * 1e3).getTimezoneOffset() * 60;
790
+ };
791
+ }
792
+ }
793
+ static async resolveModule(wasmInput) {
794
+ if (wasmInput instanceof WebAssembly.Module) {
795
+ return wasmInput;
796
+ }
797
+ if (wasmInput) {
798
+ return WebAssembly.compile(wasmInput);
799
+ }
800
+ throw new TypeError("QuickJS: `wasm` option is required. Provide WASM bytes or a compiled `WebAssembly.Module`. The binary is shipped at `quickjs-wasi/quickjs.wasm` and can be loaded via your environment's preferred mechanism (e.g. `fetch()`, `node:fs/promises`, or a bundler import like Vite's `?url`).");
801
+ }
802
+ static async instantiate(module, vm, wasiOptions) {
803
+ let memory = null;
804
+ const memoryProxy = new Proxy({}, {
805
+ get(_target, prop) {
806
+ return memory[prop];
807
+ }
808
+ });
809
+ const wasiBuiltins = createWasiShim(() => memory);
810
+ const wasiUserOverrides = wasiOptions ? wasiOptions(memoryProxy) : void 0;
811
+ const wasiShim = { ...wasiBuiltins, ...wasiUserOverrides };
812
+ const hostCall = (namePtr, nameLen, thisPtr, argc, argvPtr) => {
813
+ return vm.handleHostCall(namePtr, nameLen, thisPtr, argc, argvPtr);
814
+ };
815
+ const hostInterrupt = () => {
816
+ return vm.interruptHandler ? vm.interruptHandler() ? 1 : 0 : 0;
817
+ };
818
+ const hostPromiseRejection = (promisePtr, reasonPtr, isHandled) => {
819
+ if (!vm.unhandledRejectionHandler) {
820
+ vm.exports.qjs_free_value(promisePtr);
821
+ vm.exports.qjs_free_value(reasonPtr);
822
+ return;
823
+ }
824
+ const promise = new JSValueHandle(vm, promisePtr);
825
+ const reason = new JSValueHandle(vm, reasonPtr);
826
+ try {
827
+ vm.unhandledRejectionHandler(promise, reason, isHandled !== 0);
828
+ } finally {
829
+ promise.dispose();
830
+ reason.dispose();
831
+ }
832
+ };
833
+ const throwIntoContext = (err) => {
834
+ const errHandle = vm.newError(err instanceof Error ? err : String(err));
835
+ vm.exports.qjs_throw(errHandle.ptr);
836
+ errHandle.dispose();
837
+ };
838
+ const assertSyncString = (value, callbackName) => {
839
+ if (typeof value === "string")
840
+ return value;
841
+ const got = value !== null && typeof value === "object" && typeof value.then === "function" ? "a Promise" : `type ${typeof value}`;
842
+ throw new TypeError(`moduleLoader.${callbackName} must synchronously return a string (got ${got}). Async module loading is not supported. Pre-fetch module sources instead (see the "ES Modules" section of the quickjs-wasi README).`);
843
+ };
844
+ const hostModuleNormalize = (baseNamePtr, namePtr) => {
845
+ if (!vm.moduleNormalizeHandler) {
846
+ const name = vm.readCString(namePtr);
847
+ return vm.writeString(name).ptr;
848
+ }
849
+ const baseName = vm.readCString(baseNamePtr);
850
+ const specifier = vm.readCString(namePtr);
851
+ try {
852
+ const normalized = assertSyncString(vm.moduleNormalizeHandler(baseName, specifier), "normalize");
853
+ return vm.writeString(normalized).ptr;
854
+ } catch (err) {
855
+ throwIntoContext(err);
856
+ return 0;
857
+ }
858
+ };
859
+ const hostModuleLoad = (namePtr, outLenPtr) => {
860
+ if (!vm.moduleLoadHandler)
861
+ return 0;
862
+ const name = vm.readCString(namePtr);
863
+ try {
864
+ const source = assertSyncString(vm.moduleLoadHandler(name), "load");
865
+ const { ptr, len } = vm.writeString(source);
866
+ new Uint32Array(vm.exports.memory.buffer, outLenPtr, 1)[0] = len;
867
+ return ptr;
868
+ } catch (err) {
869
+ throwIntoContext(err);
870
+ return 0;
871
+ }
872
+ };
873
+ const hostGetTimezoneOffset = (hi, lo) => {
874
+ const timeSecs = Number(BigInt(hi) << 32n | BigInt(lo >>> 0));
875
+ return vm.timezoneOffsetHandler ? vm.timezoneOffsetHandler(timeSecs) : 0;
876
+ };
877
+ const instance = await WebAssembly.instantiate(module, {
878
+ env: {
879
+ host_call: hostCall,
880
+ host_interrupt: hostInterrupt,
881
+ host_promise_rejection: hostPromiseRejection,
882
+ host_module_normalize: hostModuleNormalize,
883
+ host_module_load: hostModuleLoad,
884
+ host_get_timezone_offset: hostGetTimezoneOffset
885
+ },
886
+ wasi_snapshot_preview1: wasiShim
887
+ });
888
+ memory = instance.exports.memory;
889
+ return { instance, wasiBuiltins, wasiUserOverrides, memoryProxy };
890
+ }
891
+ /**
892
+ * Called from WASM when a host function is invoked from QuickJS code.
893
+ */
894
+ handleHostCall(namePtr, nameLen, thisPtr, argc, argvPtr) {
895
+ const name = this.decoder.decode(new Uint8Array(this.exports.memory.buffer, namePtr, nameLen));
896
+ const callback = this.hostCallbacks.get(name);
897
+ if (!callback) {
898
+ const errHandle = this.newError(`Host callback "${name}" is not registered: it was unregistered, its ephemeral function handle was disposed, or it was never re-registered after a snapshot restore.`);
899
+ this.exports.qjs_throw(errHandle.ptr);
900
+ errHandle.dispose();
901
+ return 0;
902
+ }
903
+ const thisHandle = new JSValueHandle(this, thisPtr, false, true);
904
+ const args = [];
905
+ if (argc > 0 && argvPtr !== 0) {
906
+ const view = new DataView(this.exports.memory.buffer);
907
+ for (let i = 0; i < argc; i++) {
908
+ const argPtr = view.getUint32(argvPtr + i * 4, true);
909
+ args.push(new JSValueHandle(this, argPtr, false, true));
910
+ }
911
+ }
912
+ try {
913
+ const result = callback.call(thisHandle, ...args);
914
+ return this.exports.qjs_dup_value(result.ptr);
915
+ } catch (err) {
916
+ const errHandle = this.newError(err instanceof Error ? err : String(err));
917
+ this.exports.qjs_throw(errHandle.ptr);
918
+ errHandle.dispose();
919
+ return 0;
920
+ }
921
+ }
922
+ // ---- String helpers ----
923
+ /** Write a JS string into WASM memory, returning the pointer. Caller must free. */
924
+ writeString(str) {
925
+ const encoded = encodeWtf8(str);
926
+ const ptr = this.exports.wasm_malloc(encoded.length + 1);
927
+ if (ptr === 0)
928
+ throw new Error("wasm_malloc failed");
929
+ const mem = new Uint8Array(this.exports.memory.buffer);
930
+ mem.set(encoded, ptr);
931
+ mem[ptr + encoded.length] = 0;
932
+ return { ptr, len: encoded.length };
933
+ }
934
+ /** Read a null-terminated C string from WASM memory */
935
+ readCString(ptr) {
936
+ const mem = new Uint8Array(this.exports.memory.buffer);
937
+ let end = ptr;
938
+ while (mem[end] !== 0)
939
+ end++;
940
+ return this.decoder.decode(mem.slice(ptr, end));
941
+ }
942
+ // ---- Public API ----
943
+ /**
944
+ * Check if a result handle is an exception and throw a JSException if so.
945
+ * Used internally by evalCode and callFunction.
946
+ */
947
+ throwIfException(result) {
948
+ if (this.exports.qjs_is_exception(result.ptr) !== 0) {
949
+ const exc = this.getException();
950
+ result.dispose();
951
+ this._ownedHandles.add(exc);
952
+ throw new JSException(exc);
953
+ }
954
+ return result;
955
+ }
956
+ /**
957
+ * Evaluate JavaScript code and return the result as a handle.
958
+ * If the code throws, a `JSException` (which extends `Error`) is thrown
959
+ * on the host side, matching standard JavaScript semantics.
960
+ *
961
+ * @param code - The JavaScript source code to evaluate.
962
+ * @param filename - Optional filename for error stack traces (default `'<eval>'`).
963
+ * @param flags - Optional bitwise OR of `EvalFlags.*` constants.
964
+ * For example, pass `EvalFlags.ASYNC` to allow top-level `await`; the
965
+ * returned handle will be a Promise that resolves to the completion value.
966
+ * With `EvalFlags.TYPE_MODULE` the returned handle is a Promise that
967
+ * resolves to the module's namespace object (its exports).
968
+ */
969
+ evalCode(code, filename = "<eval>", flags = 0) {
970
+ this.assertNotDisposed();
971
+ const codeStr = this.writeString(code);
972
+ const fnStr = this.writeString(filename);
973
+ const resultPtr = this.exports.qjs_eval(codeStr.ptr, codeStr.len, fnStr.ptr, flags);
974
+ this.exports.wasm_free(codeStr.ptr);
975
+ this.exports.wasm_free(fnStr.ptr);
976
+ return this.throwIfException(new JSValueHandle(this, resultPtr));
977
+ }
978
+ /**
979
+ * Compile JavaScript source code to bytecode without executing it.
980
+ * The returned `Uint8Array` can be stored, transferred, or later executed
981
+ * with `evalBytecode()`.
982
+ *
983
+ * @param code - The JavaScript source code to compile.
984
+ * @param filename - Optional filename for error stack traces (default `'<compile>'`).
985
+ * @param evalFlags - Optional bitwise OR of `EvalFlags.*` constants.
986
+ * Use `EvalFlags.TYPE_MODULE` to compile as a module.
987
+ * @param compileFlags - Optional bitwise OR of `CompileFlags.*` constants.
988
+ * Use `CompileFlags.STRIP_SOURCE` and/or `CompileFlags.STRIP_DEBUG` to
989
+ * reduce bytecode size.
990
+ */
991
+ compile(code, filename = "<compile>", evalFlags = 0, compileFlags = 0) {
992
+ this.assertNotDisposed();
993
+ const codeStr = this.writeString(code);
994
+ const fnStr = this.writeString(filename);
995
+ const outLenPtr = this.exports.wasm_malloc(4);
996
+ const bufPtr = this.exports.qjs_compile(codeStr.ptr, codeStr.len, fnStr.ptr, evalFlags, compileFlags, outLenPtr);
997
+ this.exports.wasm_free(codeStr.ptr);
998
+ this.exports.wasm_free(fnStr.ptr);
999
+ if (bufPtr === 0) {
1000
+ this.exports.wasm_free(outLenPtr);
1001
+ const exc = this.getException();
1002
+ throw new Error(`Compilation error: ${exc.toString()}`);
1003
+ }
1004
+ const outLen = new Uint32Array(this.exports.memory.buffer, outLenPtr, 1)[0];
1005
+ this.exports.wasm_free(outLenPtr);
1006
+ const bytecode = new Uint8Array(this.exports.memory.buffer, bufPtr, outLen).slice();
1007
+ this.exports.wasm_free(bufPtr);
1008
+ return bytecode;
1009
+ }
1010
+ /**
1011
+ * Execute previously compiled bytecode (from `compile()`).
1012
+ * Returns the evaluation result as a handle.
1013
+ *
1014
+ * For module bytecode (compiled with `EvalFlags.TYPE_MODULE`), the
1015
+ * returned handle is a Promise that resolves to the module's namespace
1016
+ * object (its exports).
1017
+ *
1018
+ * @param bytecode - The bytecode `Uint8Array` from `compile()`.
1019
+ */
1020
+ evalBytecode(bytecode) {
1021
+ this.assertNotDisposed();
1022
+ const bufPtr = this.exports.wasm_malloc(bytecode.byteLength);
1023
+ new Uint8Array(this.exports.memory.buffer, bufPtr, bytecode.byteLength).set(bytecode);
1024
+ const resultPtr = this.exports.qjs_eval_bytecode(bufPtr, bytecode.byteLength);
1025
+ this.exports.wasm_free(bufPtr);
1026
+ return this.throwIfException(new JSValueHandle(this, resultPtr));
1027
+ }
1028
+ /**
1029
+ * Execute all pending microtask jobs (promise reactions, etc.)
1030
+ * Returns the number of jobs executed.
1031
+ */
1032
+ executePendingJobs() {
1033
+ this.assertNotDisposed();
1034
+ let count = 0;
1035
+ while (this.exports.qjs_is_job_pending()) {
1036
+ const result = this.exports.qjs_execute_pending_job();
1037
+ if (result < 0) {
1038
+ const exc = this.getException();
1039
+ throw new Error(`Job execution error: ${exc.toString()}`);
1040
+ }
1041
+ count++;
1042
+ }
1043
+ return count;
1044
+ }
1045
+ /**
1046
+ * Explicitly trigger garbage collection. QuickJS runs GC automatically,
1047
+ * but this can be useful to reclaim memory at a known point or before
1048
+ * taking a snapshot.
1049
+ */
1050
+ runGC() {
1051
+ this.assertNotDisposed();
1052
+ this.exports.qjs_run_gc();
1053
+ }
1054
+ /**
1055
+ * The GC threshold in bytes. When allocated memory exceeds this value,
1056
+ * garbage collection is triggered automatically. Set to 0 to disable
1057
+ * automatic GC.
1058
+ */
1059
+ get gcThreshold() {
1060
+ this.assertNotDisposed();
1061
+ return this.exports.qjs_get_gc_threshold();
1062
+ }
1063
+ set gcThreshold(threshold) {
1064
+ this.assertNotDisposed();
1065
+ this.exports.qjs_set_gc_threshold(threshold);
1066
+ }
1067
+ /**
1068
+ * Get detailed memory usage statistics from the QuickJS runtime.
1069
+ * Returns counts and sizes for atoms, strings, objects, functions, etc.
1070
+ */
1071
+ getMemoryUsage() {
1072
+ this.assertNotDisposed();
1073
+ const bufPtr = this.exports.wasm_malloc(26 * 8);
1074
+ this.exports.qjs_compute_memory_usage(bufPtr);
1075
+ const view = new BigInt64Array(this.exports.memory.buffer, bufPtr, 26);
1076
+ const result = {
1077
+ mallocSize: Number(view[0]),
1078
+ mallocLimit: Number(view[1]),
1079
+ memoryUsedSize: Number(view[2]),
1080
+ mallocCount: Number(view[3]),
1081
+ memoryUsedCount: Number(view[4]),
1082
+ atomCount: Number(view[5]),
1083
+ atomSize: Number(view[6]),
1084
+ strCount: Number(view[7]),
1085
+ strSize: Number(view[8]),
1086
+ objCount: Number(view[9]),
1087
+ objSize: Number(view[10]),
1088
+ propCount: Number(view[11]),
1089
+ propSize: Number(view[12]),
1090
+ shapeCount: Number(view[13]),
1091
+ shapeSize: Number(view[14]),
1092
+ jsFuncCount: Number(view[15]),
1093
+ jsFuncSize: Number(view[16]),
1094
+ jsFuncCodeSize: Number(view[17]),
1095
+ jsFuncPc2lineCount: Number(view[18]),
1096
+ jsFuncPc2lineSize: Number(view[19]),
1097
+ cFuncCount: Number(view[20]),
1098
+ arrayCount: Number(view[21]),
1099
+ fastArrayCount: Number(view[22]),
1100
+ fastArrayElements: Number(view[23]),
1101
+ binaryObjectCount: Number(view[24]),
1102
+ binaryObjectSize: Number(view[25])
1103
+ };
1104
+ this.exports.wasm_free(bufPtr);
1105
+ return result;
1106
+ }
1107
+ /**
1108
+ * Get the global object. Prefer the cached `vm.global` property.
1109
+ */
1110
+ getGlobal() {
1111
+ this.assertNotDisposed();
1112
+ return new JSValueHandle(this, this.exports.qjs_get_global());
1113
+ }
1114
+ /**
1115
+ * Create a new QuickJS string value.
1116
+ */
1117
+ newString(str) {
1118
+ this.assertNotDisposed();
1119
+ const { ptr, len } = this.writeString(str);
1120
+ const resultPtr = this.exports.qjs_new_string(ptr, len);
1121
+ this.exports.wasm_free(ptr);
1122
+ return new JSValueHandle(this, resultPtr);
1123
+ }
1124
+ /**
1125
+ * Create a new QuickJS number value.
1126
+ */
1127
+ newNumber(num) {
1128
+ this.assertNotDisposed();
1129
+ return new JSValueHandle(this, this.exports.qjs_new_number(num));
1130
+ }
1131
+ /**
1132
+ * Create a new QuickJS BigInt value.
1133
+ */
1134
+ newBigInt(val) {
1135
+ this.assertNotDisposed();
1136
+ const lo = Number(val & 0xffffffffn);
1137
+ const hi = Number(val >> 32n & 0xffffffffn);
1138
+ return new JSValueHandle(this, this.exports.qjs_new_big_int64(lo, hi));
1139
+ }
1140
+ /**
1141
+ * Create a new QuickJS object value.
1142
+ */
1143
+ newObject() {
1144
+ this.assertNotDisposed();
1145
+ return new JSValueHandle(this, this.exports.qjs_new_object());
1146
+ }
1147
+ /**
1148
+ * Create a new QuickJS array value.
1149
+ */
1150
+ newArray() {
1151
+ this.assertNotDisposed();
1152
+ return new JSValueHandle(this, this.exports.qjs_new_array());
1153
+ }
1154
+ /**
1155
+ * Create a global symbol (`Symbol.for(description)`).
1156
+ * Global symbols with the same description are always the same symbol,
1157
+ * even across snapshot/restore.
1158
+ */
1159
+ newSymbolFor(description) {
1160
+ this.assertNotDisposed();
1161
+ const { ptr, len } = this.writeString(description);
1162
+ const result = new JSValueHandle(this, this.exports.qjs_new_symbol(ptr, len, 1));
1163
+ this.exports.wasm_free(ptr);
1164
+ return result;
1165
+ }
1166
+ /**
1167
+ * Create a new QuickJS ArrayBuffer by copying data from a host buffer.
1168
+ */
1169
+ newArrayBuffer(data) {
1170
+ this.assertNotDisposed();
1171
+ const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
1172
+ const ptr = this.exports.wasm_malloc(bytes.length);
1173
+ if (ptr === 0)
1174
+ throw new Error("wasm_malloc failed");
1175
+ new Uint8Array(this.exports.memory.buffer).set(bytes, ptr);
1176
+ const result = new JSValueHandle(this, this.exports.qjs_new_array_buffer(ptr, bytes.length));
1177
+ this.exports.wasm_free(ptr);
1178
+ return result;
1179
+ }
1180
+ /**
1181
+ * Create a new QuickJS Uint8Array by copying data from a host buffer.
1182
+ */
1183
+ newUint8Array(data) {
1184
+ this.assertNotDisposed();
1185
+ const ptr = this.exports.wasm_malloc(data.length);
1186
+ if (ptr === 0)
1187
+ throw new Error("wasm_malloc failed");
1188
+ new Uint8Array(this.exports.memory.buffer).set(data, ptr);
1189
+ const result = new JSValueHandle(this, this.exports.qjs_new_uint8_array(ptr, data.length));
1190
+ this.exports.wasm_free(ptr);
1191
+ return result;
1192
+ }
1193
+ /**
1194
+ * Get undefined. Prefer the cached `vm.undefined` property.
1195
+ */
1196
+ getUndefined() {
1197
+ this.assertNotDisposed();
1198
+ return new JSValueHandle(this, this.exports.qjs_get_undefined());
1199
+ }
1200
+ /**
1201
+ * Get null. Prefer the cached `vm.null` property.
1202
+ */
1203
+ getNull() {
1204
+ this.assertNotDisposed();
1205
+ return new JSValueHandle(this, this.exports.qjs_get_null());
1206
+ }
1207
+ /**
1208
+ * Get true. Prefer the cached `vm.true` property.
1209
+ */
1210
+ getTrue() {
1211
+ this.assertNotDisposed();
1212
+ return new JSValueHandle(this, this.exports.qjs_get_true());
1213
+ }
1214
+ /**
1215
+ * Get false. Prefer the cached `vm.false` property.
1216
+ */
1217
+ getFalse() {
1218
+ this.assertNotDisposed();
1219
+ return new JSValueHandle(this, this.exports.qjs_get_false());
1220
+ }
1221
+ /**
1222
+ * Create a new QuickJS function backed by a host callback.
1223
+ *
1224
+ * When the function is called inside QuickJS, the host callback is invoked
1225
+ * with the `this` value and arguments as JSValueHandles.
1226
+ */
1227
+ newFunction(name, fn) {
1228
+ this.assertNotDisposed();
1229
+ if (this.hostCallbacks.has(name)) {
1230
+ throw new Error(`Host callback with name "${name}" is already registered`);
1231
+ }
1232
+ this.hostCallbacks.set(name, fn);
1233
+ const { ptr: namePtr, len: nameLen } = this.writeString(name);
1234
+ const resultPtr = this.exports.qjs_new_host_function(namePtr, nameLen, 0);
1235
+ this.exports.wasm_free(namePtr);
1236
+ return new JSValueHandle(this, resultPtr);
1237
+ }
1238
+ /**
1239
+ * Run `fn` with a handle scope: every handle created during the call is
1240
+ * disposed when it returns, except those passed to `scope.escape()`.
1241
+ *
1242
+ * This is the bulk alternative to disposing handles individually, for code
1243
+ * that creates many intermediates, such as walking a large value:
1244
+ *
1245
+ * ```ts
1246
+ * const name = vm.withScope((scope) => {
1247
+ * const user = root.getProp('user'); // freed automatically
1248
+ * const profile = user.getProp('profile'); // freed automatically
1249
+ * return scope.escape(profile.getProp('name'));
1250
+ * });
1251
+ * ```
1252
+ *
1253
+ * Scopes nest: `escape()` transfers the handle to the enclosing scope when
1254
+ * there is one, so it is still cleaned up at the outer boundary.
1255
+ *
1256
+ * `fn` must be synchronous. Handles created after an `await` are outside
1257
+ * the scope, because it closes as soon as `fn` returns.
1258
+ *
1259
+ * Host callbacks are safe to trigger inside a scope: the `this`/argument
1260
+ * handles the trampoline passes to a callback wrap C-owned pointers and
1261
+ * are exempt from scope tracking (see `handleHostCall`), so the scope
1262
+ * frees only handles the host actually owns. Handles a callback CREATES
1263
+ * (including `dup()`s of its arguments) are tracked normally.
1264
+ */
1265
+ withScope(fn) {
1266
+ this.assertNotDisposed();
1267
+ const enclosing = this._activeScope;
1268
+ const tracked = /* @__PURE__ */ new Set();
1269
+ this._activeScope = tracked;
1270
+ const scope = {
1271
+ escape: (handle) => {
1272
+ tracked.delete(handle);
1273
+ enclosing?.add(handle);
1274
+ return handle;
1275
+ }
1276
+ };
1277
+ try {
1278
+ return fn(scope);
1279
+ } finally {
1280
+ this._activeScope = enclosing;
1281
+ for (const handle of tracked)
1282
+ handle.dispose();
1283
+ }
1284
+ }
1285
+ /**
1286
+ * Export a handle as a snapshot-portable token.
1287
+ *
1288
+ * A handle's heap box lives in the VM's linear memory, so a
1289
+ * `snapshot()` taken while the handle is alive carries it, and a VM
1290
+ * restored from that snapshot has the identical box at the identical
1291
+ * offset. `importHandle(token)` on the restored VM (or on this VM)
1292
+ * re-materializes an owned handle for the same guest value without
1293
+ * evaluating any guest code.
1294
+ *
1295
+ * Contract:
1296
+ * - the handle must stay undisposed until after `snapshot()`; its
1297
+ * box (and the reference it holds) must be part of the memory image;
1298
+ * - the token is only meaningful to THIS VM and VMs restored from a
1299
+ * snapshot of it taken while the handle was alive;
1300
+ * - `importHandle` duplicates the underlying value (fresh reference,
1301
+ * fresh box), so it can be called any number of times and each
1302
+ * returned handle is independently owned and disposable. The
1303
+ * exported box's own reference is intentionally never released on
1304
+ * restored VMs (one retained reference per VM image, reclaimed
1305
+ * with the VM).
1306
+ *
1307
+ * The intended use is boot-time capture: snapshot a VM after capturing
1308
+ * references to pristine intrinsics but BEFORE evaluating untrusted or
1309
+ * user code, then restore per task and import the captured handles,
1310
+ * guaranteeing the references predate anything user code patched,
1311
+ * without re-running capture code in the restored VM (where user-
1312
+ * patched globals could observe it). See vercel/workflow's host-side
1313
+ * serde for a worked example.
1314
+ */
1315
+ exportHandle(handle) {
1316
+ this.assertNotDisposed();
1317
+ if (handle.vm !== this) {
1318
+ throw new Error("exportHandle: handle belongs to a different VM");
1319
+ }
1320
+ if (handle.disposed) {
1321
+ throw new Error("exportHandle: handle is disposed");
1322
+ }
1323
+ if (handle._isBorrowed) {
1324
+ throw new Error("exportHandle: cannot export a borrowed handle (host-callback this/argument); its box is freed when the callback returns. dup() it and export the duplicate.");
1325
+ }
1326
+ return handle.ptr;
1327
+ }
1328
+ /**
1329
+ * Re-materialize a handle from a token produced by `exportHandle`,
1330
+ * on this VM, or on a VM restored from a snapshot taken while the
1331
+ * exported handle was alive. Returns a NEW owned handle (the
1332
+ * underlying value's refcount is incremented); dispose it like any
1333
+ * other handle. See `exportHandle` for the full contract.
1334
+ */
1335
+ importHandle(token) {
1336
+ this.assertNotDisposed();
1337
+ if (!Number.isInteger(token) || token <= 0 || token >= this.exports.memory.buffer.byteLength) {
1338
+ throw new Error(`importHandle: invalid token ${token}`);
1339
+ }
1340
+ return new JSValueHandle(this, this.exports.qjs_dup_value(token));
1341
+ }
1342
+ /**
1343
+ * Create a QuickJS function backed by a host callback whose registration is
1344
+ * tied to the returned handle: disposing the handle unregisters the
1345
+ * callback.
1346
+ *
1347
+ * Use this for short-lived callbacks (e.g. a visitor passed to
1348
+ * `Map.prototype.forEach`) where the name is an implementation detail.
1349
+ * `newFunction()` keeps its callback registered for the lifetime of the VM
1350
+ * (by design, so that names can be re-registered after a snapshot is
1351
+ * restored), which makes it unsuitable for callbacks created in a loop.
1352
+ *
1353
+ * The guest must not retain the function past disposal: calling it after
1354
+ * the handle is disposed throws, because the callback is gone. Ephemeral
1355
+ * functions do not survive snapshot/restore.
1356
+ */
1357
+ newEphemeralFunction(fn) {
1358
+ this.assertNotDisposed();
1359
+ const name = `__ephemeral:${this.nextInternalId++}`;
1360
+ this.hostCallbacks.set(name, fn);
1361
+ const { ptr: namePtr, len: nameLen } = this.writeString(name);
1362
+ const resultPtr = this.exports.qjs_new_host_function(namePtr, nameLen, 0);
1363
+ this.exports.wasm_free(namePtr);
1364
+ const handle = new JSValueHandle(this, resultPtr);
1365
+ handle._onDispose = () => {
1366
+ this.hostCallbacks.delete(name);
1367
+ };
1368
+ return handle;
1369
+ }
1370
+ /**
1371
+ * Remove a host callback registered with `newFunction()` or
1372
+ * `registerHostCallback()`. Returns true if a callback was removed.
1373
+ *
1374
+ * Any QuickJS function still referencing the name will throw when called,
1375
+ * so only unregister once the guest can no longer reach it.
1376
+ */
1377
+ unregisterHostCallback(name) {
1378
+ return this.hostCallbacks.delete(name);
1379
+ }
1380
+ /**
1381
+ * Create an internal host function that bypasses the duplicate-name check.
1382
+ * Used for ephemeral callbacks (promise settle handlers, resolvePromise, etc.)
1383
+ * that are not intended to survive snapshot/restore.
1384
+ */
1385
+ newInternalFunction(name, fn) {
1386
+ this.hostCallbacks.set(name, fn);
1387
+ const { ptr: namePtr, len: nameLen } = this.writeString(name);
1388
+ const resultPtr = this.exports.qjs_new_host_function(namePtr, nameLen, 0);
1389
+ this.exports.wasm_free(namePtr);
1390
+ return new JSValueHandle(this, resultPtr);
1391
+ }
1392
+ /**
1393
+ * Create a new promise.
1394
+ *
1395
+ * Returns a Deferred with:
1396
+ * - `handle` - the QuickJS promise object
1397
+ * - `settled` - a host Promise that resolves when the QuickJS promise settles
1398
+ * - `resolve(value)` - resolve the promise with a QuickJS value
1399
+ * - `reject(value)` - reject the promise with a QuickJS value
1400
+ */
1401
+ newPromise() {
1402
+ this.assertNotDisposed();
1403
+ const resolveOutPtr = this.exports.wasm_malloc(4);
1404
+ const rejectOutPtr = this.exports.wasm_malloc(4);
1405
+ const promisePtr = this.exports.qjs_new_promise(resolveOutPtr, rejectOutPtr);
1406
+ const view = new DataView(this.exports.memory.buffer);
1407
+ const resolvePtr = view.getUint32(resolveOutPtr, true);
1408
+ const rejectPtr = view.getUint32(rejectOutPtr, true);
1409
+ this.exports.wasm_free(resolveOutPtr);
1410
+ this.exports.wasm_free(rejectOutPtr);
1411
+ const promiseHandle = new JSValueHandle(this, promisePtr);
1412
+ const resolveHandle = new JSValueHandle(this, resolvePtr);
1413
+ const rejectHandle = new JSValueHandle(this, rejectPtr);
1414
+ const vm = this;
1415
+ vm._ownedHandles.add(resolveHandle);
1416
+ vm._ownedHandles.add(rejectHandle);
1417
+ let _settled = null;
1418
+ return {
1419
+ handle: promiseHandle,
1420
+ get settled() {
1421
+ if (!_settled) {
1422
+ let settledResolve;
1423
+ _settled = new Promise((res) => {
1424
+ settledResolve = res;
1425
+ });
1426
+ const settleName = `__settle:${vm.nextInternalId++}`;
1427
+ const onSettleFn = vm.newInternalFunction(settleName, () => {
1428
+ settledResolve();
1429
+ vm.hostCallbacks.delete(settleName);
1430
+ return vm.undefined;
1431
+ });
1432
+ vm.promiseThenRaw(promiseHandle, onSettleFn, onSettleFn).dispose();
1433
+ onSettleFn.dispose();
1434
+ }
1435
+ return _settled;
1436
+ },
1437
+ resolve(value) {
1438
+ vm.callFunctionRaw(resolveHandle, vm.undefined, value).dispose();
1439
+ vm._ownedHandles.delete(resolveHandle);
1440
+ resolveHandle.dispose();
1441
+ },
1442
+ reject(value) {
1443
+ vm.callFunctionRaw(rejectHandle, vm.undefined, value).dispose();
1444
+ vm._ownedHandles.delete(rejectHandle);
1445
+ rejectHandle.dispose();
1446
+ }
1447
+ };
1448
+ }
1449
+ /**
1450
+ * Resolve a promise handle. Returns a host-side Promise that resolves
1451
+ * with the settled value/error of the QuickJS promise.
1452
+ *
1453
+ * If the handle is not a promise, it is treated as an already-fulfilled value.
1454
+ *
1455
+ * The returned host Promise resolves to `{ value: JSValueHandle }` on
1456
+ * fulfillment or `{ error: JSValueHandle }` on rejection.
1457
+ */
1458
+ resolvePromise(promiseHandle) {
1459
+ this.assertNotDisposed();
1460
+ if (!this.exports.qjs_is_promise(promiseHandle.ptr)) {
1461
+ return Promise.resolve({ value: promiseHandle.dup() });
1462
+ }
1463
+ const state = this.exports.qjs_promise_state(promiseHandle.ptr);
1464
+ if (state === 1) {
1465
+ return Promise.resolve({ value: new JSValueHandle(this, this.exports.qjs_promise_result(promiseHandle.ptr)) });
1466
+ } else if (state === 2) {
1467
+ return Promise.resolve({ error: new JSValueHandle(this, this.exports.qjs_promise_result(promiseHandle.ptr)) });
1468
+ }
1469
+ return new Promise((hostResolve) => {
1470
+ const id = this.nextInternalId++;
1471
+ const fulfilledName = `__onFulfilled:${id}`;
1472
+ const rejectedName = `__onRejected:${id}`;
1473
+ const onFulfilled = this.newInternalFunction(fulfilledName, (...args) => {
1474
+ const val = args[0]?.dup() ?? this.undefined;
1475
+ this.hostCallbacks.delete(fulfilledName);
1476
+ this.hostCallbacks.delete(rejectedName);
1477
+ hostResolve({ value: val });
1478
+ return this.undefined;
1479
+ });
1480
+ const onRejected = this.newInternalFunction(rejectedName, (...args) => {
1481
+ const val = args[0]?.dup() ?? this.undefined;
1482
+ this.hostCallbacks.delete(fulfilledName);
1483
+ this.hostCallbacks.delete(rejectedName);
1484
+ hostResolve({ error: val });
1485
+ return this.undefined;
1486
+ });
1487
+ this.promiseThenRaw(promiseHandle, onFulfilled, onRejected).dispose();
1488
+ onFulfilled.dispose();
1489
+ onRejected.dispose();
1490
+ });
1491
+ }
1492
+ /**
1493
+ * Subscribe to a promise without executing guest code, via quickjs-ng's
1494
+ * JS_PromiseThen: no Promise.prototype.then lookup, no Symbol.species.
1495
+ * Returns the chained promise. Handler handles are borrowed (caller
1496
+ * still owns and disposes them).
1497
+ * @internal
1498
+ */
1499
+ promiseThenRaw(promise, onFulfilled, onRejected) {
1500
+ return new JSValueHandle(this, this.exports.qjs_promise_then(promise.ptr, onFulfilled.ptr, onRejected.ptr));
1501
+ }
1502
+ /**
1503
+ * Mark a promise as handled: an eventual (or already-recorded) rejection
1504
+ * will not be reported to `onUnhandledRejection`. Useful when the host
1505
+ * observes a rejection through other means (e.g. `resolvePromise()`) and
1506
+ * wants to suppress the unhandled-rejection callback for it.
1507
+ *
1508
+ * No-op if the handle is not a promise.
1509
+ */
1510
+ markPromiseHandled(promise) {
1511
+ this.assertNotDisposed();
1512
+ this.exports.qjs_promise_mark_as_handled(promise.ptr);
1513
+ }
1514
+ /**
1515
+ * Call a QuickJS function. If the function throws, a `JSException`
1516
+ * is thrown on the host side.
1517
+ */
1518
+ callFunction(func, thisVal, ...args) {
1519
+ return this.throwIfException(this.callFunctionRaw(func, thisVal, ...args));
1520
+ }
1521
+ /**
1522
+ * Invoke a QuickJS constructor with `new`, i.e. `new ctor(...args)`.
1523
+ * If the constructor throws (including when `ctor` is not a constructor),
1524
+ * a `JSException` is thrown on the host side.
1525
+ *
1526
+ * This is the counterpart to `callFunction` for building values inside
1527
+ * the VM from the host, e.g. `new Date(iso)` on a constructor captured
1528
+ * before any user code ran.
1529
+ */
1530
+ construct(ctor, ...args) {
1531
+ this.assertNotDisposed();
1532
+ const argc = args.length;
1533
+ let argvPtr = 0;
1534
+ if (argc > 0) {
1535
+ argvPtr = this.exports.wasm_malloc(argc * 4);
1536
+ const view = new DataView(this.exports.memory.buffer);
1537
+ for (let i = 0; i < argc; i++) {
1538
+ view.setUint32(argvPtr + i * 4, args[i].ptr, true);
1539
+ }
1540
+ }
1541
+ const resultPtr = this.exports.qjs_call_constructor(ctor.ptr, argc, argvPtr);
1542
+ if (argvPtr)
1543
+ this.exports.wasm_free(argvPtr);
1544
+ return this.throwIfException(new JSValueHandle(this, resultPtr));
1545
+ }
1546
+ /**
1547
+ * Internal: call a QuickJS function without throwing on exception.
1548
+ * Used by promise plumbing where exceptions are handled differently.
1549
+ */
1550
+ callFunctionRaw(func, thisVal, ...args) {
1551
+ this.assertNotDisposed();
1552
+ const argc = args.length;
1553
+ let argvPtr = 0;
1554
+ if (argc > 0) {
1555
+ argvPtr = this.exports.wasm_malloc(argc * 4);
1556
+ const view = new DataView(this.exports.memory.buffer);
1557
+ for (let i = 0; i < argc; i++) {
1558
+ view.setUint32(argvPtr + i * 4, args[i].ptr, true);
1559
+ }
1560
+ }
1561
+ const resultPtr = this.exports.qjs_call(func.ptr, thisVal.ptr, argc, argvPtr);
1562
+ if (argvPtr)
1563
+ this.exports.wasm_free(argvPtr);
1564
+ return new JSValueHandle(this, resultPtr);
1565
+ }
1566
+ /**
1567
+ * Set a property on an object. Accepts string or JSValueHandle as key.
1568
+ * JSValueHandle keys support symbols (including `Symbol.for()`).
1569
+ */
1570
+ setProp(obj, key, value) {
1571
+ this.assertNotDisposed();
1572
+ if (typeof key === "string") {
1573
+ const { ptr: namePtr } = this.writeString(key);
1574
+ this.exports.qjs_set_prop_string(obj.ptr, namePtr, value.ptr);
1575
+ this.exports.wasm_free(namePtr);
1576
+ } else {
1577
+ this.exports.qjs_set_prop_value(obj.ptr, key.ptr, value.ptr);
1578
+ }
1579
+ }
1580
+ /**
1581
+ * Define a property on an object with explicit property descriptor flags.
1582
+ * Unlike `setProp`, this allows controlling `writable`, `enumerable`, and
1583
+ * `configurable` attributes, matching `Object.defineProperty()` semantics.
1584
+ * Accepts string or JSValueHandle as key (JSValueHandle keys support symbols).
1585
+ *
1586
+ * All flags default to `false` when not specified.
1587
+ */
1588
+ defineProp(obj, key, value, descriptor) {
1589
+ this.assertNotDisposed();
1590
+ let flags = 0;
1591
+ if (descriptor?.configurable)
1592
+ flags |= 1;
1593
+ if (descriptor?.writable)
1594
+ flags |= 2;
1595
+ if (descriptor?.enumerable)
1596
+ flags |= 4;
1597
+ if (typeof key === "string") {
1598
+ const { ptr: namePtr } = this.writeString(key);
1599
+ this.exports.qjs_define_prop_string(obj.ptr, namePtr, value.ptr, flags);
1600
+ this.exports.wasm_free(namePtr);
1601
+ } else {
1602
+ this.exports.qjs_define_prop_value(obj.ptr, key.ptr, value.ptr, flags);
1603
+ }
1604
+ }
1605
+ /**
1606
+ * Get a property from an object using a JSValueHandle key.
1607
+ * Supports symbol keys (including `Symbol.for()`).
1608
+ */
1609
+ getProp(obj, key) {
1610
+ this.assertNotDisposed();
1611
+ return new JSValueHandle(this, this.exports.qjs_get_prop_value(obj.ptr, key.ptr));
1612
+ }
1613
+ /**
1614
+ * Get the current exception, if any.
1615
+ */
1616
+ getException() {
1617
+ this.assertNotDisposed();
1618
+ return new JSValueHandle(this, this.exports.qjs_get_exception());
1619
+ }
1620
+ /**
1621
+ * Create a new QuickJS Error object.
1622
+ * Accepts a string message or a native Error object.
1623
+ */
1624
+ newError(messageOrError) {
1625
+ this.assertNotDisposed();
1626
+ const errPtr = this.exports.qjs_new_error();
1627
+ const errHandle = new JSValueHandle(this, errPtr);
1628
+ if (typeof messageOrError === "string") {
1629
+ const msgHandle = this.newString(messageOrError);
1630
+ errHandle.setProp("message", msgHandle);
1631
+ msgHandle.dispose();
1632
+ } else {
1633
+ const msgHandle = this.newString(messageOrError.message);
1634
+ errHandle.setProp("message", msgHandle);
1635
+ msgHandle.dispose();
1636
+ if (messageOrError.name) {
1637
+ const nameHandle = this.newString(messageOrError.name);
1638
+ errHandle.setProp("name", nameHandle);
1639
+ nameHandle.dispose();
1640
+ }
1641
+ if (messageOrError.stack) {
1642
+ const stackHandle = this.newString(messageOrError.stack);
1643
+ errHandle.setProp("stack", stackHandle);
1644
+ stackHandle.dispose();
1645
+ }
1646
+ }
1647
+ return errHandle;
1648
+ }
1649
+ /**
1650
+ * Get the typeof a handle as a string.
1651
+ */
1652
+ typeof(handle) {
1653
+ this.assertNotDisposed();
1654
+ const e = this.exports;
1655
+ if (e.qjs_is_undefined(handle.ptr))
1656
+ return "undefined";
1657
+ if (e.qjs_is_null(handle.ptr))
1658
+ return "object";
1659
+ if (e.qjs_is_bool(handle.ptr))
1660
+ return "boolean";
1661
+ if (e.qjs_is_number(handle.ptr))
1662
+ return "number";
1663
+ if (e.qjs_is_big_int(handle.ptr))
1664
+ return "bigint";
1665
+ if (e.qjs_is_string(handle.ptr))
1666
+ return "string";
1667
+ if (e.qjs_is_symbol(handle.ptr))
1668
+ return "symbol";
1669
+ if (e.qjs_is_function(handle.ptr))
1670
+ return "function";
1671
+ if (e.qjs_is_object(handle.ptr))
1672
+ return "object";
1673
+ return "unknown";
1674
+ }
1675
+ /**
1676
+ * Convert a QuickJS handle to a host JavaScript value.
1677
+ * Handles strings, numbers, booleans, null, undefined, bigint, arrays,
1678
+ * errors, functions, and plain objects. Circular references in objects
1679
+ * are returned as `undefined`.
1680
+ */
1681
+ dump(handle) {
1682
+ this.assertNotDisposed();
1683
+ return this._dump(handle, /* @__PURE__ */ new Map());
1684
+ }
1685
+ _dump(handle, visited) {
1686
+ const e = this.exports;
1687
+ if (e.qjs_is_undefined(handle.ptr))
1688
+ return void 0;
1689
+ if (e.qjs_is_null(handle.ptr))
1690
+ return null;
1691
+ if (e.qjs_is_bool(handle.ptr))
1692
+ return e.qjs_get_bool(handle.ptr) !== 0;
1693
+ if (e.qjs_is_number(handle.ptr))
1694
+ return e.qjs_get_float64(handle.ptr);
1695
+ if (e.qjs_is_string(handle.ptr))
1696
+ return handle.toString();
1697
+ if (e.qjs_is_big_int(handle.ptr))
1698
+ return handle.toBigInt();
1699
+ if (e.qjs_is_symbol(handle.ptr)) {
1700
+ const descOutPtr = e.wasm_malloc(4);
1701
+ const kind = e.qjs_get_symbol_description(handle.ptr, descOutPtr);
1702
+ const view = new DataView(e.memory.buffer);
1703
+ const descPtr = view.getUint32(descOutPtr, true);
1704
+ e.wasm_free(descOutPtr);
1705
+ if (kind === 1) {
1706
+ const descHandle = new JSValueHandle(this, descPtr);
1707
+ const description = descHandle.toString();
1708
+ descHandle.dispose();
1709
+ return Symbol.for(description);
1710
+ } else if (kind === 2) {
1711
+ const descHandle = new JSValueHandle(this, descPtr);
1712
+ descHandle.dispose();
1713
+ return void 0;
1714
+ }
1715
+ return void 0;
1716
+ }
1717
+ if (e.qjs_is_array_buffer(handle.ptr))
1718
+ return handle.toArrayBuffer();
1719
+ if (e.qjs_is_exception(handle.ptr)) {
1720
+ const exc = this.getException();
1721
+ const msg = exc.toString();
1722
+ exc.dispose();
1723
+ return new Error(msg);
1724
+ }
1725
+ if (e.qjs_is_function(handle.ptr))
1726
+ return void 0;
1727
+ if (e.qjs_is_object(handle.ptr)) {
1728
+ const objPtr = e.qjs_get_value_ptr(handle.ptr);
1729
+ if (objPtr) {
1730
+ const existing = visited.get(objPtr);
1731
+ if (existing !== void 0)
1732
+ return existing;
1733
+ }
1734
+ }
1735
+ if (e.qjs_is_object(handle.ptr)) {
1736
+ const byteOffsetPtr = e.wasm_malloc(4);
1737
+ const byteLengthPtr = e.wasm_malloc(4);
1738
+ const bytesPerElemPtr = e.wasm_malloc(4);
1739
+ const abPtr = e.qjs_get_typed_array_buffer(handle.ptr, byteOffsetPtr, byteLengthPtr, bytesPerElemPtr);
1740
+ const abHandle = new JSValueHandle(this, abPtr);
1741
+ if (e.qjs_is_exception(abHandle.ptr) === 0) {
1742
+ const view = new DataView(e.memory.buffer);
1743
+ const byteOffset = view.getUint32(byteOffsetPtr, true);
1744
+ const byteLength = view.getUint32(byteLengthPtr, true);
1745
+ const bytesPerElement = view.getUint32(bytesPerElemPtr, true);
1746
+ e.wasm_free(byteOffsetPtr);
1747
+ e.wasm_free(byteLengthPtr);
1748
+ e.wasm_free(bytesPerElemPtr);
1749
+ const abLenPtr = e.wasm_malloc(4);
1750
+ const abDataPtr = e.qjs_get_array_buffer(abHandle.ptr, abLenPtr);
1751
+ e.wasm_free(abLenPtr);
1752
+ abHandle.dispose();
1753
+ if (abDataPtr !== 0) {
1754
+ const rawBytes = new Uint8Array(e.memory.buffer, abDataPtr + byteOffset, byteLength).slice();
1755
+ switch (bytesPerElement) {
1756
+ case 1:
1757
+ return rawBytes;
1758
+ case 2:
1759
+ return new Uint16Array(rawBytes.buffer);
1760
+ case 4:
1761
+ return new Uint32Array(rawBytes.buffer);
1762
+ case 8:
1763
+ return new Float64Array(rawBytes.buffer);
1764
+ default:
1765
+ return rawBytes;
1766
+ }
1767
+ }
1768
+ } else {
1769
+ abHandle.dispose();
1770
+ e.wasm_free(byteOffsetPtr);
1771
+ e.wasm_free(byteLengthPtr);
1772
+ e.wasm_free(bytesPerElemPtr);
1773
+ }
1774
+ }
1775
+ if (e.qjs_is_array(handle.ptr)) {
1776
+ const lenHandle = handle.getProp("length");
1777
+ const len = e.qjs_get_float64(lenHandle.ptr);
1778
+ lenHandle.dispose();
1779
+ const arr = [];
1780
+ const objPtr = e.qjs_get_value_ptr(handle.ptr);
1781
+ if (objPtr)
1782
+ visited.set(objPtr, arr);
1783
+ for (let i = 0; i < len; i++) {
1784
+ const elemPtr = e.qjs_get_prop_uint32(handle.ptr, i);
1785
+ const elemHandle = new JSValueHandle(this, elemPtr);
1786
+ arr.push(this._dump(elemHandle, visited));
1787
+ elemHandle.dispose();
1788
+ }
1789
+ return arr;
1790
+ }
1791
+ if (e.qjs_is_error(handle.ptr)) {
1792
+ const nameHandle = handle.getProp("name");
1793
+ const msgHandle = handle.getProp("message");
1794
+ const stackHandle = handle.getProp("stack");
1795
+ const name = nameHandle.isUndefined ? "Error" : nameHandle.toString();
1796
+ const message = msgHandle.isUndefined ? "" : msgHandle.toString();
1797
+ const stack = stackHandle.isUndefined ? void 0 : stackHandle.toString();
1798
+ nameHandle.dispose();
1799
+ msgHandle.dispose();
1800
+ stackHandle.dispose();
1801
+ const err = new Error(message);
1802
+ err.name = name;
1803
+ if (stack !== void 0) {
1804
+ err.stack = stack;
1805
+ }
1806
+ return err;
1807
+ }
1808
+ if (e.qjs_is_object(handle.ptr)) {
1809
+ const keysPtr = e.qjs_get_own_property_names(handle.ptr);
1810
+ const keysHandle = new JSValueHandle(this, keysPtr);
1811
+ if (e.qjs_is_exception(keysHandle.ptr) !== 0) {
1812
+ keysHandle.dispose();
1813
+ return {};
1814
+ }
1815
+ const lenHandle = keysHandle.getProp("length");
1816
+ const len = e.qjs_get_float64(lenHandle.ptr);
1817
+ lenHandle.dispose();
1818
+ const obj = {};
1819
+ const objPtr = e.qjs_get_value_ptr(handle.ptr);
1820
+ if (objPtr)
1821
+ visited.set(objPtr, obj);
1822
+ for (let i = 0; i < len; i++) {
1823
+ const keyPtr = e.qjs_get_prop_uint32(keysHandle.ptr, i);
1824
+ const keyHandle = new JSValueHandle(this, keyPtr);
1825
+ const key = keyHandle.toString();
1826
+ keyHandle.dispose();
1827
+ const valHandle = handle.getProp(key);
1828
+ obj[key] = this._dump(valHandle, visited);
1829
+ valHandle.dispose();
1830
+ }
1831
+ keysHandle.dispose();
1832
+ return obj;
1833
+ }
1834
+ return void 0;
1835
+ }
1836
+ /**
1837
+ * Convert a host JavaScript value to a QuickJS handle.
1838
+ */
1839
+ hostToHandle(value) {
1840
+ this.assertNotDisposed();
1841
+ if (value === void 0)
1842
+ return this.undefined;
1843
+ if (value === null)
1844
+ return this.null;
1845
+ if (value === true)
1846
+ return this.true;
1847
+ if (value === false)
1848
+ return this.false;
1849
+ if (typeof value === "number")
1850
+ return this.newNumber(value);
1851
+ if (typeof value === "string")
1852
+ return this.newString(value);
1853
+ if (typeof value === "bigint")
1854
+ return this.newBigInt(value);
1855
+ if (typeof value === "symbol") {
1856
+ const key = Symbol.keyFor(value);
1857
+ if (key !== void 0) {
1858
+ return this.newSymbolFor(key);
1859
+ }
1860
+ throw new Error(`Cannot convert local symbol to QuickJS handle. Use Symbol.for() for cross-boundary symbols.`);
1861
+ }
1862
+ if (value instanceof Promise) {
1863
+ const deferred = this.newPromise();
1864
+ value.then((r) => {
1865
+ deferred.resolve(this.hostToHandle(r));
1866
+ this.executePendingJobs();
1867
+ }, (err) => {
1868
+ deferred.reject(this.hostToHandle(err));
1869
+ this.executePendingJobs();
1870
+ });
1871
+ return deferred.handle;
1872
+ }
1873
+ if (value instanceof Error) {
1874
+ return this.newError(value);
1875
+ }
1876
+ if (value instanceof ArrayBuffer) {
1877
+ return this.newArrayBuffer(value);
1878
+ }
1879
+ if (value instanceof Uint8Array) {
1880
+ return this.newUint8Array(value);
1881
+ }
1882
+ if (ArrayBuffer.isView(value)) {
1883
+ return this.newArrayBuffer(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
1884
+ }
1885
+ if (Array.isArray(value)) {
1886
+ const arr = this.newArray();
1887
+ for (let i = 0; i < value.length; i++) {
1888
+ const elemHandle = this.hostToHandle(value[i]);
1889
+ this.exports.qjs_set_prop_uint32(arr.ptr, i, elemHandle.ptr);
1890
+ elemHandle.dispose();
1891
+ }
1892
+ return arr;
1893
+ }
1894
+ if (typeof value === "object" && value !== null) {
1895
+ const obj = this.newObject();
1896
+ for (const [key, val] of Object.entries(value)) {
1897
+ const valHandle = this.hostToHandle(val);
1898
+ obj.setProp(key, valHandle);
1899
+ valHandle.dispose();
1900
+ }
1901
+ return obj;
1902
+ }
1903
+ return this.undefined;
1904
+ }
1905
+ // ---- Snapshot / Restore ----
1906
+ /**
1907
+ * Snapshot the entire VM state.
1908
+ *
1909
+ * Returns a snapshot containing the full WASM linear memory. Use
1910
+ * `QuickJS.serializeSnapshot()` to convert to a versioned binary
1911
+ * buffer for persistent storage.
1912
+ */
1913
+ snapshot() {
1914
+ this.assertNotDisposed();
1915
+ return {
1916
+ memory: new Uint8Array(this.exports.memory.buffer).slice(),
1917
+ stackPointer: this.exports.__stack_pointer.value,
1918
+ runtimePtr: this.exports.qjs_get_runtime_ptr(),
1919
+ contextPtr: this.exports.qjs_get_context_ptr(),
1920
+ extensions: this.loadedExtensions.map((ext) => ({
1921
+ name: ext.name,
1922
+ memoryBase: ext.memoryBase,
1923
+ tableBase: ext.tableBase,
1924
+ initFn: ext.initFn
1925
+ }))
1926
+ };
1927
+ }
1928
+ /**
1929
+ * Re-register a host callback after restoring from a snapshot.
1930
+ * The name must match the name passed to `newFunction()` before the snapshot.
1931
+ */
1932
+ registerHostCallback(name, fn) {
1933
+ this.hostCallbacks.set(name, fn);
1934
+ }
1935
+ /**
1936
+ * Dispose the VM, releasing all references to the WASM instance
1937
+ * so it can be garbage collected by the host JS engine.
1938
+ */
1939
+ dispose() {
1940
+ if (!this.disposed) {
1941
+ this.disposed = true;
1942
+ this._global = null;
1943
+ this._undefined = null;
1944
+ this._null = null;
1945
+ this._true = null;
1946
+ this._false = null;
1947
+ this._ownedHandles.clear();
1948
+ this.hostCallbacks.clear();
1949
+ this._activeScope = null;
1950
+ this.exports = null;
1951
+ this.instance = null;
1952
+ this.module = null;
1953
+ }
1954
+ }
1955
+ /**
1956
+ * Support for `using` declarations (Explicit Resource Management).
1957
+ * Automatically disposes the VM when it goes out of scope.
1958
+ *
1959
+ * ```typescript
1960
+ * using vm = await QuickJS.create(wasmBytes);
1961
+ * vm.evalCode('1 + 2');
1962
+ * // vm is automatically disposed here
1963
+ * ```
1964
+ */
1965
+ [Symbol.dispose]() {
1966
+ this.dispose();
1967
+ }
1968
+ assertNotDisposed() {
1969
+ if (this.disposed) {
1970
+ throw new Error("QuickJS instance has been disposed");
1971
+ }
1972
+ }
1973
+ // ---- Internal accessors for JSValueHandle ----
1974
+ /** @internal */
1975
+ _getExports() {
1976
+ return this.exports;
1977
+ }
1978
+ /** @internal */
1979
+ _getMemory() {
1980
+ return this.exports.memory;
1981
+ }
1982
+ /** @internal */
1983
+ _writeString(str) {
1984
+ return this.writeString(str);
1985
+ }
1986
+ /** @internal */
1987
+ _readCString(ptr) {
1988
+ return this.readCString(ptr);
1989
+ }
1990
+ };
1991
+ function stringKeyNeedsValuePath(key) {
1992
+ return key.includes("\0") || LONE_SURROGATE_RE.test(key);
1993
+ }
1994
+ var wtf8Decoder = new TextDecoder();
1995
+ var wtf8Encoder = new TextEncoder();
1996
+ var LONE_SURROGATE_RE = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF]))|(?:(?<![\uD800-\uDBFF])[\uDC00-\uDFFF])/;
1997
+ function encodeWtf8(str) {
1998
+ if (!LONE_SURROGATE_RE.test(str))
1999
+ return wtf8Encoder.encode(str);
2000
+ const bytes = [];
2001
+ for (let i = 0; i < str.length; i++) {
2002
+ const code = str.charCodeAt(i);
2003
+ if (code < 128) {
2004
+ bytes.push(code);
2005
+ } else if (code < 2048) {
2006
+ bytes.push(192 | code >> 6, 128 | code & 63);
2007
+ } else if (code >= 55296 && code <= 56319 && i + 1 < str.length) {
2008
+ const next = str.charCodeAt(i + 1);
2009
+ if (next >= 56320 && next <= 57343) {
2010
+ const cp = 65536 + (code - 55296 << 10) + (next - 56320);
2011
+ bytes.push(240 | cp >> 18, 128 | cp >> 12 & 63, 128 | cp >> 6 & 63, 128 | cp & 63);
2012
+ i++;
2013
+ continue;
2014
+ }
2015
+ bytes.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63);
2016
+ } else {
2017
+ bytes.push(224 | code >> 12, 128 | code >> 6 & 63, 128 | code & 63);
2018
+ }
2019
+ }
2020
+ return new Uint8Array(bytes);
2021
+ }
2022
+ function decodeWtf8(bytes) {
2023
+ let hasSurrogateSequence = false;
2024
+ for (let i2 = 0; i2 < bytes.length - 1; i2++) {
2025
+ if (bytes[i2] === 237 && bytes[i2 + 1] >= 160 && bytes[i2 + 1] <= 191) {
2026
+ hasSurrogateSequence = true;
2027
+ break;
2028
+ }
2029
+ }
2030
+ if (!hasSurrogateSequence)
2031
+ return wtf8Decoder.decode(bytes);
2032
+ let out = "";
2033
+ let i = 0;
2034
+ while (i < bytes.length) {
2035
+ const b0 = bytes[i];
2036
+ if (b0 < 128) {
2037
+ out += String.fromCharCode(b0);
2038
+ i += 1;
2039
+ } else if (b0 < 224) {
2040
+ out += String.fromCharCode((b0 & 31) << 6 | bytes[i + 1] & 63);
2041
+ i += 2;
2042
+ } else if (b0 < 240) {
2043
+ out += String.fromCharCode((b0 & 15) << 12 | (bytes[i + 1] & 63) << 6 | bytes[i + 2] & 63);
2044
+ i += 3;
2045
+ } else {
2046
+ const cp = (b0 & 7) << 18 | (bytes[i + 1] & 63) << 12 | (bytes[i + 2] & 63) << 6 | bytes[i + 3] & 63;
2047
+ out += String.fromCodePoint(cp);
2048
+ i += 4;
2049
+ }
2050
+ }
2051
+ return out;
2052
+ }
2053
+ var JSException = class extends Error {
2054
+ /**
2055
+ * A live handle to the QuickJS exception value. You can read custom
2056
+ * properties, call methods, etc. Must be disposed when done.
2057
+ */
2058
+ handle;
2059
+ // Cached values so they survive handle disposal / VM teardown.
2060
+ // Using # fields keeps them out of console.log / Object.keys output.
2061
+ #name;
2062
+ #message;
2063
+ #stack;
2064
+ /** @internal */
2065
+ constructor(handle) {
2066
+ const env_1 = { stack: [], error: void 0, hasError: false };
2067
+ try {
2068
+ super();
2069
+ this.handle = handle;
2070
+ delete this.stack;
2071
+ const msgHandle = __addDisposableResource(env_1, handle.getProp("message"), false);
2072
+ this.#name = handle.getProp("name").consume((h) => h.isUndefined ? "Error" : h.toString());
2073
+ this.#message = msgHandle.isUndefined ? handle.toString() : msgHandle.toString();
2074
+ this.#stack = handle.getProp("stack").consume((h) => h.isUndefined ? void 0 : h.toString());
2075
+ } catch (e_1) {
2076
+ env_1.error = e_1;
2077
+ env_1.hasError = true;
2078
+ } finally {
2079
+ __disposeResources(env_1);
2080
+ }
2081
+ }
2082
+ get name() {
2083
+ return this.#name;
2084
+ }
2085
+ set name(v) {
2086
+ this.#name = v;
2087
+ }
2088
+ get message() {
2089
+ return this.#message;
2090
+ }
2091
+ set message(v) {
2092
+ this.#message = v;
2093
+ }
2094
+ get stack() {
2095
+ return this.#stack;
2096
+ }
2097
+ set stack(v) {
2098
+ this.#stack = v;
2099
+ }
2100
+ dispose() {
2101
+ this.handle.dispose();
2102
+ }
2103
+ [Symbol.dispose]() {
2104
+ this.handle.dispose();
2105
+ }
2106
+ };
2107
+ var JSValueHandle = class _JSValueHandle {
2108
+ /** The QuickJS VM instance this handle belongs to. */
2109
+ vm;
2110
+ /** @internal */
2111
+ ptr;
2112
+ disposed_ = false;
2113
+ /**
2114
+ * When true, this handle is a cached singleton (e.g. `undefined`, `null`,
2115
+ * `true`, `false`, the global object) and `dispose()` is a no-op. This
2116
+ * prevents code that routinely disposes handles (such as the object/array
2117
+ * branches of `hostToHandle`) from freeing the shared heap `JSValue*` that
2118
+ * the cached singleton still references, which would corrupt later reads.
2119
+ * @internal
2120
+ */
2121
+ singleton;
2122
+ /**
2123
+ * When true, this handle wraps a `JSValue*` OWNED BY THE C CALLER: the
2124
+ * `this`/argument handles the host-call trampoline passes to a host
2125
+ * callback (`handleHostCall`). The C side frees those values after the
2126
+ * call returns, so `dispose()` is a no-op and the handle is never
2127
+ * registered with an active `withScope()` (either would double-free
2128
+ * the guest value and corrupt the heap). A callback that needs to
2129
+ * retain an argument past its own invocation must `dup()` it; the
2130
+ * duplicate takes a fresh reference and behaves like any owned handle.
2131
+ * @internal
2132
+ */
2133
+ borrowed;
2134
+ /**
2135
+ * Extra cleanup to run when this handle is disposed. Used by
2136
+ * `newEphemeralFunction()` to unregister its host callback.
2137
+ * @internal
2138
+ */
2139
+ _onDispose;
2140
+ constructor(vm, ptr, singleton = false, borrowed = false) {
2141
+ this.vm = vm;
2142
+ this.ptr = ptr;
2143
+ this.singleton = singleton;
2144
+ this.borrowed = borrowed;
2145
+ if (!singleton && !borrowed)
2146
+ vm._activeScope?.add(this);
2147
+ }
2148
+ /**
2149
+ * Whether this handle wraps a C-owned pointer (host-callback
2150
+ * `this`/arguments). Borrowed handles must never be exported as
2151
+ * snapshot tokens: the trampoline frees their boxes after the
2152
+ * callback returns. @internal
2153
+ */
2154
+ get _isBorrowed() {
2155
+ return this.borrowed;
2156
+ }
2157
+ /**
2158
+ * Whether `dispose()` has been called on this handle.
2159
+ *
2160
+ * Note that handle methods do not currently guard against use after
2161
+ * disposal: reading from a disposed handle reads freed memory. Check this
2162
+ * when a handle's lifetime is managed elsewhere (e.g. by `withScope()`).
2163
+ */
2164
+ get disposed() {
2165
+ return this.disposed_;
2166
+ }
2167
+ get isUndefined() {
2168
+ return this.vm._getExports().qjs_is_undefined(this.ptr) !== 0;
2169
+ }
2170
+ get isNull() {
2171
+ return this.vm._getExports().qjs_is_null(this.ptr) !== 0;
2172
+ }
2173
+ /**
2174
+ * Get the promise state: 0 = pending, 1 = fulfilled, 2 = rejected
2175
+ */
2176
+ get isBool() {
2177
+ return this.vm._getExports().qjs_is_bool(this.ptr) !== 0;
2178
+ }
2179
+ get isNumber() {
2180
+ return this.vm._getExports().qjs_is_number(this.ptr) !== 0;
2181
+ }
2182
+ get isString() {
2183
+ return this.vm._getExports().qjs_is_string(this.ptr) !== 0;
2184
+ }
2185
+ get isSymbol() {
2186
+ return this.vm._getExports().qjs_is_symbol(this.ptr) !== 0;
2187
+ }
2188
+ get isBigInt() {
2189
+ return this.vm._getExports().qjs_is_big_int(this.ptr) !== 0;
2190
+ }
2191
+ get isObject() {
2192
+ return this.vm._getExports().qjs_is_object(this.ptr) !== 0;
2193
+ }
2194
+ get isArray() {
2195
+ return this.vm._getExports().qjs_is_array(this.ptr) !== 0;
2196
+ }
2197
+ get isFunction() {
2198
+ return this.vm._getExports().qjs_is_function(this.ptr) !== 0;
2199
+ }
2200
+ get isError() {
2201
+ return this.vm._getExports().qjs_is_error(this.ptr) !== 0;
2202
+ }
2203
+ get isPromise() {
2204
+ return this.vm._getExports().qjs_is_promise(this.ptr) !== 0;
2205
+ }
2206
+ get isArrayBuffer() {
2207
+ return this.vm._getExports().qjs_is_array_buffer(this.ptr) !== 0;
2208
+ }
2209
+ /**
2210
+ * Whether this value is a Proxy exotic object.
2211
+ *
2212
+ * This is an engine-level check: it never fires proxy traps and cannot
2213
+ * be determined (or spoofed) from within guest JavaScript. Use
2214
+ * {@link getProxyTarget} / {@link getProxyHandler} to introspect a
2215
+ * detected proxy without executing guest code.
2216
+ */
2217
+ get isProxy() {
2218
+ return this.vm._getExports().qjs_is_proxy(this.ptr) !== 0;
2219
+ }
2220
+ /**
2221
+ * Whether this value is a Map (engine brand check: trap-free,
2222
+ * spoof-proof, and unaffected by prototype/constructor mutation).
2223
+ * A Proxy wrapping a Map returns false.
2224
+ */
2225
+ get isMap() {
2226
+ return this.vm._getExports().qjs_is_map(this.ptr) !== 0;
2227
+ }
2228
+ /**
2229
+ * Whether this value is a Set (engine brand check: trap-free,
2230
+ * spoof-proof, and unaffected by prototype/constructor mutation).
2231
+ * A Proxy wrapping a Set returns false.
2232
+ */
2233
+ get isSet() {
2234
+ return this.vm._getExports().qjs_is_set(this.ptr) !== 0;
2235
+ }
2236
+ /**
2237
+ * Whether this value is a Date (engine brand check: trap-free,
2238
+ * spoof-proof, and unaffected by prototype/constructor mutation).
2239
+ * A Proxy wrapping a Date returns false.
2240
+ */
2241
+ get isDate() {
2242
+ return this.vm._getExports().qjs_is_date(this.ptr) !== 0;
2243
+ }
2244
+ /**
2245
+ * Whether this value is a RegExp (engine brand check: trap-free,
2246
+ * spoof-proof, and unaffected by prototype/constructor mutation).
2247
+ * A Proxy wrapping a RegExp returns false.
2248
+ */
2249
+ get isRegExp() {
2250
+ return this.vm._getExports().qjs_is_regexp(this.ptr) !== 0;
2251
+ }
2252
+ /** Whether this value is a WeakRef (engine brand check). */
2253
+ get isWeakRef() {
2254
+ return this.vm._getExports().qjs_is_weak_ref(this.ptr) !== 0;
2255
+ }
2256
+ /** Whether this value is a WeakMap (engine brand check). */
2257
+ get isWeakMap() {
2258
+ return this.vm._getExports().qjs_is_weak_map(this.ptr) !== 0;
2259
+ }
2260
+ /** Whether this value is a WeakSet (engine brand check). */
2261
+ get isWeakSet() {
2262
+ return this.vm._getExports().qjs_is_weak_set(this.ptr) !== 0;
2263
+ }
2264
+ /** Whether this value is a DataView (engine brand check). */
2265
+ get isDataView() {
2266
+ return this.vm._getExports().qjs_is_data_view(this.ptr) !== 0;
2267
+ }
2268
+ /**
2269
+ * A numeric identity for the underlying heap value, or 0 for values that
2270
+ * are not heap-allocated (numbers, booleans, `null`, `undefined`).
2271
+ *
2272
+ * Two handles to the same underlying object always report the same
2273
+ * identity, and two live handles to different objects always report
2274
+ * different identities, so this is the value to key a `Map` on when
2275
+ * deduplicating or detecting cycles across handles (`dump()` uses it for
2276
+ * exactly that).
2277
+ *
2278
+ * The identity is only meaningful while the value is alive; it is an
2279
+ * address, so it may be reused after every handle to the value has been
2280
+ * disposed. Do not persist it, and do not treat it as unforgeable: a
2281
+ * number read out of the guest can trivially collide with one.
2282
+ */
2283
+ get identity() {
2284
+ return this.vm._getExports().qjs_get_value_ptr(this.ptr);
2285
+ }
2286
+ /**
2287
+ * Extract the value as a boolean, applying JavaScript truthiness
2288
+ * (equivalent to `!!value` inside the VM).
2289
+ */
2290
+ toBoolean() {
2291
+ return this.vm._getExports().qjs_get_bool(this.ptr) !== 0;
2292
+ }
2293
+ /**
2294
+ * The internal QuickJS class ID of this value, or 0 for non-objects.
2295
+ * Useful as a generic engine-level brand when no dedicated `is*`
2296
+ * getter exists. Class IDs are stable within a VM instance but are an
2297
+ * engine implementation detail, so prefer the dedicated getters.
2298
+ */
2299
+ get classId() {
2300
+ return this.vm._getExports().qjs_get_class_id(this.ptr);
2301
+ }
2302
+ /**
2303
+ * The engine-level class name of this value, e.g. `"Object"`, `"Map"`,
2304
+ * `"Date"`, `"RegExp"`, or the registered name of an extension-defined
2305
+ * class like `"URL"`, or `undefined` for non-objects and unnamed
2306
+ * internal classes.
2307
+ *
2308
+ * Unlike `constructorName` (which reads the `constructor` and `name`
2309
+ * properties and can therefore fire getters/proxy traps and be spoofed),
2310
+ * this is trap-free: it reads the engine's class table directly, never
2311
+ * executes guest code, and cannot be forged by reassigning prototypes or
2312
+ * constructors. Note that the engine registers the Proxy class under the
2313
+ * name `"Object"` (mirroring `Object.prototype.toString`), so use `isProxy`
2314
+ * to detect proxies and `getProxyTarget()` to read the target's brand.
2315
+ */
2316
+ get className() {
2317
+ const h = new _JSValueHandle(this.vm, this.vm._getExports().qjs_get_class_name(this.ptr));
2318
+ if (this.vm._getExports().qjs_is_exception(h.ptr) !== 0) {
2319
+ h.dispose();
2320
+ throw new JSException(this.vm.getException());
2321
+ }
2322
+ try {
2323
+ return h.isUndefined ? void 0 : h.toString();
2324
+ } finally {
2325
+ h.dispose();
2326
+ }
2327
+ }
2328
+ get promiseState() {
2329
+ return this.vm._getExports().qjs_promise_state(this.ptr);
2330
+ }
2331
+ /**
2332
+ * Get the typeof this value as a string.
2333
+ * Returns the same values as the native `typeof` operator.
2334
+ */
2335
+ get typeof() {
2336
+ return this.vm.typeof(this);
2337
+ }
2338
+ /**
2339
+ * Get the length property of this value (for arrays, strings, etc.).
2340
+ */
2341
+ get length() {
2342
+ const h = this.getProp("length");
2343
+ const n = h.toNumber();
2344
+ h.dispose();
2345
+ return n;
2346
+ }
2347
+ /**
2348
+ * Get the constructor name of this object, or undefined if unavailable.
2349
+ */
2350
+ get constructorName() {
2351
+ const ctor = this.getProp("constructor");
2352
+ if (ctor.isUndefined || ctor.isNull) {
2353
+ ctor.dispose();
2354
+ return void 0;
2355
+ }
2356
+ const name = ctor.getProp("name");
2357
+ ctor.dispose();
2358
+ if (name.isUndefined || name.isNull) {
2359
+ name.dispose();
2360
+ return void 0;
2361
+ }
2362
+ const result = name.toString();
2363
+ name.dispose();
2364
+ return result;
2365
+ }
2366
+ /**
2367
+ * Get the own enumerable string property names (equivalent to Object.keys()).
2368
+ */
2369
+ keys() {
2370
+ const e = this.vm._getExports();
2371
+ const keysPtr = e.qjs_get_own_property_names(this.ptr);
2372
+ const keysHandle = new _JSValueHandle(this.vm, keysPtr);
2373
+ if (e.qjs_is_exception(keysHandle.ptr) !== 0) {
2374
+ keysHandle.dispose();
2375
+ return [];
2376
+ }
2377
+ const lenHandle = keysHandle.getProp("length");
2378
+ const len = e.qjs_get_float64(lenHandle.ptr);
2379
+ lenHandle.dispose();
2380
+ const result = [];
2381
+ for (let i = 0; i < len; i++) {
2382
+ const keyPtr = e.qjs_get_prop_uint32(keysHandle.ptr, i);
2383
+ const keyHandle = new _JSValueHandle(this.vm, keyPtr);
2384
+ result.push(keyHandle.toString());
2385
+ keyHandle.dispose();
2386
+ }
2387
+ keysHandle.dispose();
2388
+ return result;
2389
+ }
2390
+ /**
2391
+ * Get all own property names including non-enumerable ones
2392
+ * (equivalent to Object.getOwnPropertyNames()).
2393
+ */
2394
+ getOwnPropertyNames() {
2395
+ const e = this.vm._getExports();
2396
+ const keysPtr = e.qjs_get_own_property_names_all(this.ptr);
2397
+ const keysHandle = new _JSValueHandle(this.vm, keysPtr);
2398
+ if (e.qjs_is_exception(keysHandle.ptr) !== 0) {
2399
+ keysHandle.dispose();
2400
+ return [];
2401
+ }
2402
+ const lenHandle = keysHandle.getProp("length");
2403
+ const len = e.qjs_get_float64(lenHandle.ptr);
2404
+ lenHandle.dispose();
2405
+ const result = [];
2406
+ for (let i = 0; i < len; i++) {
2407
+ const keyPtr = e.qjs_get_prop_uint32(keysHandle.ptr, i);
2408
+ const keyHandle = new _JSValueHandle(this.vm, keyPtr);
2409
+ result.push(keyHandle.toString());
2410
+ keyHandle.dispose();
2411
+ }
2412
+ keysHandle.dispose();
2413
+ return result;
2414
+ }
2415
+ /**
2416
+ * Get ALL own property keys (strings and symbols), including
2417
+ * non-enumerable (equivalent to Reflect.ownKeys()).
2418
+ *
2419
+ * String keys are returned as strings; symbol keys are returned as
2420
+ * JSValueHandles which the caller must dispose.
2421
+ *
2422
+ * Trap-free for ordinary objects; fires the `ownKeys` trap for a
2423
+ * Proxy (check {@link isProxy} first if that matters).
2424
+ */
2425
+ getOwnPropertyKeys() {
2426
+ const e = this.vm._getExports();
2427
+ const keysPtr = e.qjs_get_own_property_keys(this.ptr);
2428
+ const keysHandle = new _JSValueHandle(this.vm, keysPtr);
2429
+ if (e.qjs_is_exception(keysHandle.ptr) !== 0) {
2430
+ keysHandle.dispose();
2431
+ return [];
2432
+ }
2433
+ const lenHandle = keysHandle.getProp("length");
2434
+ const len = e.qjs_get_float64(lenHandle.ptr);
2435
+ lenHandle.dispose();
2436
+ const result = [];
2437
+ for (let i = 0; i < len; i++) {
2438
+ const keyPtr = e.qjs_get_prop_uint32(keysHandle.ptr, i);
2439
+ const keyHandle = new _JSValueHandle(this.vm, keyPtr);
2440
+ if (keyHandle.isSymbol) {
2441
+ result.push(keyHandle);
2442
+ } else {
2443
+ result.push(keyHandle.toString());
2444
+ keyHandle.dispose();
2445
+ }
2446
+ }
2447
+ keysHandle.dispose();
2448
+ return result;
2449
+ }
2450
+ /**
2451
+ * Get the own property descriptor for a key WITHOUT invoking getters
2452
+ * (equivalent to Object.getOwnPropertyDescriptor()).
2453
+ *
2454
+ * This is the safe way to inspect a property that may be an accessor:
2455
+ * a data property yields `{ value, writable, enumerable, configurable }`,
2456
+ * an accessor property yields `{ get, set, enumerable, configurable }`
2457
+ * where `get`/`set` are handles to the accessor functions themselves
2458
+ * (never invoked). Returns undefined if there is no such own property.
2459
+ *
2460
+ * The `value`/`get`/`set` handles are owned by the caller and must be
2461
+ * disposed.
2462
+ *
2463
+ * Trap-free for ordinary objects; fires the `getOwnPropertyDescriptor`
2464
+ * trap for a Proxy (check {@link isProxy} first if that matters).
2465
+ */
2466
+ getOwnPropertyDescriptor(key) {
2467
+ const env_2 = { stack: [], error: void 0, hasError: false };
2468
+ try {
2469
+ const e = this.vm._getExports();
2470
+ let keyHandle;
2471
+ let keyPtr;
2472
+ if (typeof key === "string") {
2473
+ keyHandle = this.vm.newString(key);
2474
+ keyPtr = keyHandle.ptr;
2475
+ } else {
2476
+ keyPtr = key.ptr;
2477
+ }
2478
+ const descPtr = e.qjs_get_own_property_descriptor(this.ptr, keyPtr);
2479
+ keyHandle?.dispose();
2480
+ if (descPtr === 0)
2481
+ return void 0;
2482
+ const descHandle = __addDisposableResource(env_2, new _JSValueHandle(this.vm, descPtr), false);
2483
+ if (e.qjs_is_exception(descHandle.ptr) !== 0) {
2484
+ throw new JSException(this.vm.getException());
2485
+ }
2486
+ const enumerable = descHandle.getProp("enumerable").consume((h) => e.qjs_get_bool(h.ptr) !== 0);
2487
+ const configurable = descHandle.getProp("configurable").consume((h) => e.qjs_get_bool(h.ptr) !== 0);
2488
+ if (descHandle.hasOwnProperty("value")) {
2489
+ return {
2490
+ value: descHandle.getProp("value"),
2491
+ writable: descHandle.getProp("writable").consume((h) => e.qjs_get_bool(h.ptr) !== 0),
2492
+ enumerable,
2493
+ configurable
2494
+ };
2495
+ }
2496
+ return {
2497
+ get: descHandle.getProp("get"),
2498
+ set: descHandle.getProp("set"),
2499
+ enumerable,
2500
+ configurable
2501
+ };
2502
+ } catch (e_2) {
2503
+ env_2.error = e_2;
2504
+ env_2.hasError = true;
2505
+ } finally {
2506
+ __disposeResources(env_2);
2507
+ }
2508
+ }
2509
+ /**
2510
+ * Check if a property is an own property (equivalent to Object.prototype.hasOwnProperty).
2511
+ */
2512
+ hasOwnProperty(name) {
2513
+ if (stringKeyNeedsValuePath(name)) {
2514
+ const env_3 = { stack: [], error: void 0, hasError: false };
2515
+ try {
2516
+ const keyHandle = __addDisposableResource(env_3, this.vm.newString(name), false);
2517
+ return this.vm._getExports().qjs_has_own_property_value(this.ptr, keyHandle.ptr) === 1;
2518
+ } catch (e_3) {
2519
+ env_3.error = e_3;
2520
+ env_3.hasError = true;
2521
+ } finally {
2522
+ __disposeResources(env_3);
2523
+ }
2524
+ }
2525
+ const { ptr: namePtr } = this.vm._writeString(name);
2526
+ const result = this.vm._getExports().qjs_has_own_property(this.ptr, namePtr);
2527
+ this.vm._getExports().wasm_free(namePtr);
2528
+ return result === 1;
2529
+ }
2530
+ /**
2531
+ * Check if a property is enumerable (equivalent to Object.prototype.propertyIsEnumerable).
2532
+ */
2533
+ propertyIsEnumerable(name) {
2534
+ if (stringKeyNeedsValuePath(name)) {
2535
+ const env_4 = { stack: [], error: void 0, hasError: false };
2536
+ try {
2537
+ const keyHandle = __addDisposableResource(env_4, this.vm.newString(name), false);
2538
+ return this.vm._getExports().qjs_property_is_enumerable_value(this.ptr, keyHandle.ptr) === 1;
2539
+ } catch (e_4) {
2540
+ env_4.error = e_4;
2541
+ env_4.hasError = true;
2542
+ } finally {
2543
+ __disposeResources(env_4);
2544
+ }
2545
+ }
2546
+ const { ptr: namePtr } = this.vm._writeString(name);
2547
+ const result = this.vm._getExports().qjs_property_is_enumerable(this.ptr, namePtr);
2548
+ this.vm._getExports().wasm_free(namePtr);
2549
+ return result === 1;
2550
+ }
2551
+ /**
2552
+ * Get the prototype of this object (equivalent to Object.getPrototypeOf()).
2553
+ */
2554
+ getPrototypeOf() {
2555
+ const protoPtr = this.vm._getExports().qjs_get_prototype_of(this.ptr);
2556
+ return new _JSValueHandle(this.vm, protoPtr);
2557
+ }
2558
+ /**
2559
+ * Get the `[[ProxyTarget]]` of this Proxy without firing any traps.
2560
+ * Throws {@link JSException} if this value is not a Proxy; check
2561
+ * {@link isProxy} first. Note the target may itself be a Proxy.
2562
+ */
2563
+ getProxyTarget() {
2564
+ const ptr = this.vm._getExports().qjs_get_proxy_target(this.ptr);
2565
+ const handle = new _JSValueHandle(this.vm, ptr);
2566
+ if (this.vm._getExports().qjs_is_exception(handle.ptr) !== 0) {
2567
+ handle.dispose();
2568
+ throw new JSException(this.vm.getException());
2569
+ }
2570
+ return handle;
2571
+ }
2572
+ /**
2573
+ * Get the `[[ProxyHandler]]` of this Proxy without firing any traps.
2574
+ * Throws {@link JSException} if this value is not a Proxy; check
2575
+ * {@link isProxy} first.
2576
+ */
2577
+ getProxyHandler() {
2578
+ const ptr = this.vm._getExports().qjs_get_proxy_handler(this.ptr);
2579
+ const handle = new _JSValueHandle(this.vm, ptr);
2580
+ if (this.vm._getExports().qjs_is_exception(handle.ptr) !== 0) {
2581
+ handle.dispose();
2582
+ throw new JSException(this.vm.getException());
2583
+ }
2584
+ return handle;
2585
+ }
2586
+ /**
2587
+ * Get a property by name.
2588
+ */
2589
+ getProp(name) {
2590
+ if (stringKeyNeedsValuePath(name)) {
2591
+ const env_5 = { stack: [], error: void 0, hasError: false };
2592
+ try {
2593
+ const keyHandle = __addDisposableResource(env_5, this.vm.newString(name), false);
2594
+ return this.vm.getProp(this, keyHandle);
2595
+ } catch (e_5) {
2596
+ env_5.error = e_5;
2597
+ env_5.hasError = true;
2598
+ } finally {
2599
+ __disposeResources(env_5);
2600
+ }
2601
+ }
2602
+ const { ptr: namePtr } = this.vm._writeString(name);
2603
+ const resultPtr = this.vm._getExports().qjs_get_prop_string(this.ptr, namePtr);
2604
+ this.vm._getExports().wasm_free(namePtr);
2605
+ return new _JSValueHandle(this.vm, resultPtr);
2606
+ }
2607
+ /**
2608
+ * Set a property by name.
2609
+ */
2610
+ setProp(name, value) {
2611
+ if (stringKeyNeedsValuePath(name)) {
2612
+ const env_6 = { stack: [], error: void 0, hasError: false };
2613
+ try {
2614
+ const keyHandle = __addDisposableResource(env_6, this.vm.newString(name), false);
2615
+ this.vm.setProp(this, keyHandle, value);
2616
+ return;
2617
+ } catch (e_6) {
2618
+ env_6.error = e_6;
2619
+ env_6.hasError = true;
2620
+ } finally {
2621
+ __disposeResources(env_6);
2622
+ }
2623
+ }
2624
+ const { ptr: namePtr } = this.vm._writeString(name);
2625
+ this.vm._getExports().qjs_set_prop_string(this.ptr, namePtr, value.ptr);
2626
+ this.vm._getExports().wasm_free(namePtr);
2627
+ }
2628
+ /**
2629
+ * Define a property with explicit property descriptor flags.
2630
+ * Unlike `setProp`, this allows controlling `writable`, `enumerable`, and
2631
+ * `configurable` attributes, matching `Object.defineProperty()` semantics.
2632
+ * Accepts string or JSValueHandle as key (JSValueHandle keys support symbols).
2633
+ *
2634
+ * All flags default to `false` when not specified.
2635
+ */
2636
+ defineProp(key, value, descriptor) {
2637
+ let flags = 0;
2638
+ if (descriptor?.configurable)
2639
+ flags |= 1;
2640
+ if (descriptor?.writable)
2641
+ flags |= 2;
2642
+ if (descriptor?.enumerable)
2643
+ flags |= 4;
2644
+ if (typeof key === "string") {
2645
+ if (stringKeyNeedsValuePath(key)) {
2646
+ const env_7 = { stack: [], error: void 0, hasError: false };
2647
+ try {
2648
+ const keyHandle = __addDisposableResource(env_7, this.vm.newString(key), false);
2649
+ this.vm._getExports().qjs_define_prop_value(this.ptr, keyHandle.ptr, value.ptr, flags);
2650
+ return;
2651
+ } catch (e_7) {
2652
+ env_7.error = e_7;
2653
+ env_7.hasError = true;
2654
+ } finally {
2655
+ __disposeResources(env_7);
2656
+ }
2657
+ }
2658
+ const { ptr: namePtr } = this.vm._writeString(key);
2659
+ this.vm._getExports().qjs_define_prop_string(this.ptr, namePtr, value.ptr, flags);
2660
+ this.vm._getExports().wasm_free(namePtr);
2661
+ } else {
2662
+ this.vm._getExports().qjs_define_prop_value(this.ptr, key.ptr, value.ptr, flags);
2663
+ }
2664
+ }
2665
+ /**
2666
+ * Extract the value as a number.
2667
+ */
2668
+ toNumber() {
2669
+ return this.vm._getExports().qjs_get_float64(this.ptr);
2670
+ }
2671
+ /**
2672
+ * Extract the value as a BigInt.
2673
+ */
2674
+ toBigInt() {
2675
+ const e = this.vm._getExports();
2676
+ const loPtr = e.wasm_malloc(4);
2677
+ const hiPtr = e.wasm_malloc(4);
2678
+ const ret = e.qjs_get_big_int64(this.ptr, loPtr, hiPtr);
2679
+ if (ret !== 0) {
2680
+ e.wasm_free(loPtr);
2681
+ e.wasm_free(hiPtr);
2682
+ throw new Error("Failed to convert value to BigInt");
2683
+ }
2684
+ const view = new DataView(e.memory.buffer);
2685
+ const lo = view.getUint32(loPtr, true);
2686
+ const hi = view.getInt32(hiPtr, true);
2687
+ e.wasm_free(loPtr);
2688
+ e.wasm_free(hiPtr);
2689
+ return BigInt(hi) << 32n | BigInt(lo);
2690
+ }
2691
+ /**
2692
+ * Extract the value as an ArrayBuffer (copies from WASM memory).
2693
+ * Works on ArrayBuffer values. For typed arrays, gets the underlying buffer.
2694
+ */
2695
+ toArrayBuffer() {
2696
+ const e = this.vm._getExports();
2697
+ const lenOutPtr = e.wasm_malloc(4);
2698
+ if (e.qjs_is_array_buffer(this.ptr)) {
2699
+ const dataPtr = e.qjs_get_array_buffer(this.ptr, lenOutPtr);
2700
+ if (dataPtr === 0) {
2701
+ e.wasm_free(lenOutPtr);
2702
+ throw new Error("Failed to get ArrayBuffer data");
2703
+ }
2704
+ const view2 = new DataView(e.memory.buffer);
2705
+ const len = view2.getUint32(lenOutPtr, true);
2706
+ e.wasm_free(lenOutPtr);
2707
+ return new Uint8Array(e.memory.buffer, dataPtr, len).slice().buffer;
2708
+ }
2709
+ e.wasm_free(lenOutPtr);
2710
+ const byteOffsetPtr = e.wasm_malloc(4);
2711
+ const byteLengthPtr = e.wasm_malloc(4);
2712
+ const bytesPerElemPtr = e.wasm_malloc(4);
2713
+ const abPtr = e.qjs_get_typed_array_buffer(this.ptr, byteOffsetPtr, byteLengthPtr, bytesPerElemPtr);
2714
+ const abHandle = new _JSValueHandle(this.vm, abPtr);
2715
+ if (this.vm._getExports().qjs_is_exception(abHandle.ptr) !== 0) {
2716
+ abHandle.dispose();
2717
+ e.wasm_free(byteOffsetPtr);
2718
+ e.wasm_free(byteLengthPtr);
2719
+ e.wasm_free(bytesPerElemPtr);
2720
+ throw new Error("Value is not an ArrayBuffer or typed array");
2721
+ }
2722
+ const view = new DataView(e.memory.buffer);
2723
+ const byteOffset = view.getUint32(byteOffsetPtr, true);
2724
+ const byteLength = view.getUint32(byteLengthPtr, true);
2725
+ e.wasm_free(byteOffsetPtr);
2726
+ e.wasm_free(byteLengthPtr);
2727
+ e.wasm_free(bytesPerElemPtr);
2728
+ const abLenPtr = e.wasm_malloc(4);
2729
+ const abDataPtr = e.qjs_get_array_buffer(abHandle.ptr, abLenPtr);
2730
+ e.wasm_free(abLenPtr);
2731
+ abHandle.dispose();
2732
+ if (abDataPtr === 0) {
2733
+ throw new Error("Failed to get ArrayBuffer data from typed array");
2734
+ }
2735
+ return new Uint8Array(e.memory.buffer, abDataPtr + byteOffset, byteLength).slice().buffer;
2736
+ }
2737
+ /**
2738
+ * Extract the value as a Uint8Array (copies from WASM memory).
2739
+ * Works on Uint8Array, ArrayBuffer, and other typed array values.
2740
+ */
2741
+ toUint8Array() {
2742
+ return new Uint8Array(this.toArrayBuffer());
2743
+ }
2744
+ /**
2745
+ * Extract the value as a string. Works on any value.
2746
+ *
2747
+ * For values that are not already strings this performs a JavaScript
2748
+ * string conversion, which **executes guest code**: `toString()` /
2749
+ * `valueOf()` / `Symbol.toPrimitive` on the value or its prototype chain,
2750
+ * and proxy traps. Guard with `isString` when the caller must not run guest
2751
+ * code, and call a captured intrinsic (e.g. `URL.prototype.toString` via
2752
+ * `vm.callFunction`) when a specific conversion is wanted.
2753
+ */
2754
+ toString() {
2755
+ const e = this.vm._getExports();
2756
+ const lenPtr = e.wasm_malloc(4);
2757
+ if (lenPtr === 0)
2758
+ throw new Error("wasm_malloc failed");
2759
+ try {
2760
+ const cstrPtr = e.qjs_get_string_len(this.ptr, lenPtr);
2761
+ if (cstrPtr === 0)
2762
+ return "<null>";
2763
+ const len = new DataView(e.memory.buffer).getUint32(lenPtr, true);
2764
+ const bytes = new Uint8Array(e.memory.buffer, cstrPtr, len);
2765
+ const str = decodeWtf8(bytes);
2766
+ e.qjs_free_cstring(cstrPtr);
2767
+ return str;
2768
+ } finally {
2769
+ e.wasm_free(lenPtr);
2770
+ }
2771
+ }
2772
+ /**
2773
+ * Use this handle, then dispose it. Returns the callback's return value.
2774
+ */
2775
+ consume(fn) {
2776
+ try {
2777
+ return fn(this);
2778
+ } finally {
2779
+ this.dispose();
2780
+ }
2781
+ }
2782
+ /**
2783
+ * Duplicate this handle (increment refcount).
2784
+ */
2785
+ dup() {
2786
+ return new _JSValueHandle(this.vm, this.vm._getExports().qjs_dup_value(this.ptr));
2787
+ }
2788
+ /**
2789
+ * Dispose this handle, freeing the heap-allocated JSValue.
2790
+ * Safe to call after the VM has been disposed (becomes a no-op).
2791
+ */
2792
+ dispose() {
2793
+ if (this.singleton || this.borrowed)
2794
+ return;
2795
+ if (!this.disposed_) {
2796
+ this.disposed_ = true;
2797
+ this._onDispose?.();
2798
+ this._onDispose = void 0;
2799
+ const exports = this.vm._getExports();
2800
+ if (exports) {
2801
+ exports.qjs_free_value(this.ptr);
2802
+ }
2803
+ }
2804
+ }
2805
+ /**
2806
+ * Support for `using` declarations (Explicit Resource Management).
2807
+ * Automatically disposes the handle when it goes out of scope.
2808
+ *
2809
+ * ```typescript
2810
+ * using result = vm.evalCode('1 + 2');
2811
+ * console.log(result.toNumber()); // 3
2812
+ * // result is automatically disposed here
2813
+ * ```
2814
+ */
2815
+ [Symbol.dispose]() {
2816
+ this.dispose();
2817
+ }
2818
+ };
2819
+
2820
+ // ../../node_modules/@earendil-works/pi-codemode/dist/runtime/prelude-source.js
2821
+ var MAX_STORE_VALUE_CHARS = 256 * 1024;
2822
+ var MAX_STORE_TOTAL_CHARS = 1024 * 1024;
2823
+ var MAX_OUTPUT_CHARS = 16 * 1024 * 1024;
2824
+ var MAX_OUTPUT_ITEMS = 1e5;
2825
+ var IMAGE_HELPER_EXPECTS = "image expects a non-empty image URL string, an object with image_url, or a raw MCP image block";
2826
+ var PRELUDE_SOURCE = `(function (bridge, toolsJson, globalsJson, storeJson) {
2827
+ "use strict";
2828
+ const stringify = JSON.stringify;
2829
+ const parse = JSON.parse;
2830
+ const promiseThen = Promise.prototype.then;
2831
+ const ErrorCtor = Error;
2832
+ const TypeErrorCtor = TypeError;
2833
+ const RangeErrorCtor = RangeError;
2834
+ const pending = new Map();
2835
+ let nextId = 1;
2836
+ let finished = false;
2837
+ // Thrown by exit() to unwind the script after it already reported success.
2838
+ const EXIT = Object.freeze({});
2839
+
2840
+ function done(ok, payload, writes) {
2841
+ if (finished) return;
2842
+ finished = true;
2843
+ bridge("done", ok, payload, writes);
2844
+ }
2845
+
2846
+ function serialize(value) {
2847
+ return value === undefined ? undefined : stringify(value);
2848
+ }
2849
+
2850
+ // QuickJS stacks list frames only. Prefix "Name: message" like V8 so the
2851
+ // text reads the same as a Node error, and drop this prelude's frames.
2852
+ function errorText(error) {
2853
+ const head = error.message ? error.name + ": " + error.message : String(error.name);
2854
+ const frames =
2855
+ typeof error.stack === "string"
2856
+ ? error.stack.split("\\n").filter((line) => line.trim() && !line.includes("codemode-prelude.js"))
2857
+ : [];
2858
+ return [head, ...frames].join("\\n");
2859
+ }
2860
+
2861
+ function format(value) {
2862
+ if (typeof value === "string") return value;
2863
+ if (value instanceof ErrorCtor) return errorText(value);
2864
+ try {
2865
+ const json = stringify(value);
2866
+ return json === undefined ? String(value) : json;
2867
+ } catch {
2868
+ return String(value);
2869
+ }
2870
+ }
2871
+
2872
+ function describeError(error) {
2873
+ if (error instanceof ErrorCtor) {
2874
+ return stringify({ name: error.name, message: error.message, stack: errorText(error) });
2875
+ }
2876
+ return stringify({ message: format(error) });
2877
+ }
2878
+
2879
+ function caller(kind, name, spread) {
2880
+ return (...args) =>
2881
+ new Promise((resolve, reject) => {
2882
+ let json;
2883
+ try {
2884
+ json = serialize(spread ? args : args[0]);
2885
+ } catch (error) {
2886
+ reject(error);
2887
+ return;
2888
+ }
2889
+ const id = nextId++;
2890
+ pending.set(id, { resolve, reject });
2891
+ bridge(kind, id, name, json);
2892
+ });
2893
+ }
2894
+
2895
+ const tools = Object.create(null);
2896
+ const allTools = [];
2897
+ for (const { name, jsName, description } of parse(toolsJson)) {
2898
+ const fn = caller("call", name);
2899
+ // The first tool wins when two names normalize to the same identifier.
2900
+ if (!(jsName in tools)) {
2901
+ tools[jsName] = fn;
2902
+ allTools.push(Object.freeze({ name: jsName, description }));
2903
+ }
2904
+ if (!(name in tools)) tools[name] = fn;
2905
+ }
2906
+ Object.freeze(tools);
2907
+ Object.freeze(allTools);
2908
+
2909
+ // Reading a member that does not exist throws an error that names the close matches, instead of
2910
+ // a later "not a function". \`in\` checks still work.
2911
+ const comparable = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "");
2912
+ function guard(target, label, names, hint) {
2913
+ return new Proxy(target, {
2914
+ get(object, property, receiver) {
2915
+ if (typeof property !== "string" || property in object || property in Object.prototype || property === "then" || property === "toJSON") {
2916
+ return Reflect.get(object, property, receiver);
2917
+ }
2918
+ const wanted = comparable(property);
2919
+ const exact = names.filter((name) => comparable(name) === wanted);
2920
+ const close = exact.length > 0 ? exact : names.filter((name) => wanted && (comparable(name).includes(wanted) || wanted.includes(comparable(name))));
2921
+ let message = label + "." + property + " does not exist.";
2922
+ if (close.length > 0) message += " Did you mean " + close.slice(0, 5).map((name) => label + "." + name).join(", ") + "?";
2923
+ else if (names.length <= 20) message += " Available: " + names.join(", ") + ".";
2924
+ if (hint) message += " " + hint;
2925
+ message += ' Check for a member with "' + property + '" in ' + label + ".";
2926
+ throw new TypeErrorCtor(message);
2927
+ },
2928
+ });
2929
+ }
2930
+ const toolsProxy = guard(
2931
+ tools,
2932
+ "tools",
2933
+ allTools.map((tool) => tool.name),
2934
+ "ALL_TOOLS lists every tool; searchTools(query) finds tools by topic.",
2935
+ );
2936
+
2937
+ const namespaces = new Map();
2938
+ for (const { name, spread } of parse(globalsJson)) {
2939
+ const fn = caller("global", name, spread);
2940
+ const dot = name.indexOf(".");
2941
+ if (dot === -1) {
2942
+ Object.defineProperty(globalThis, name, { value: fn, enumerable: true });
2943
+ continue;
2944
+ }
2945
+ const namespace = name.slice(0, dot);
2946
+ if (!namespaces.has(namespace)) namespaces.set(namespace, Object.create(null));
2947
+ namespaces.get(namespace)[name.slice(dot + 1)] = fn;
2948
+ }
2949
+ for (const [namespace, members] of namespaces) {
2950
+ Object.freeze(members);
2951
+ const value = guard(members, namespace, Object.keys(members));
2952
+ Object.defineProperty(globalThis, namespace, { value, enumerable: true });
2953
+ }
2954
+
2955
+ // key -> JSON text. Sizes count key and JSON characters.
2956
+ const stored = new Map(Object.entries(parse(storeJson)));
2957
+ const writes = new Map();
2958
+ let storedChars = 0;
2959
+ for (const [key, json] of stored) storedChars += key.length + json.length;
2960
+
2961
+ const STORE_HINT =
2962
+ "store() is for small state such as IDs or summaries. Show images with image(), keep large data in variables, or write it to a file with a tool.";
2963
+
2964
+ function checkKey(name, key) {
2965
+ if (typeof key !== "string") throw new TypeError(name + "() key must be a string");
2966
+ }
2967
+
2968
+ function store(key, value) {
2969
+ checkKey("store", key);
2970
+ const previous = stored.has(key) ? key.length + stored.get(key).length : 0;
2971
+ if (value === undefined) {
2972
+ stored.delete(key);
2973
+ storedChars -= previous;
2974
+ writes.set(key, undefined);
2975
+ return;
2976
+ }
2977
+ let json;
2978
+ try {
2979
+ json = stringify(value);
2980
+ } catch (error) {
2981
+ throw new TypeError("store(" + stringify(key) + ") value is not JSON-serializable: " + format(error));
2982
+ }
2983
+ if (json === undefined) {
2984
+ throw new TypeError("store(" + stringify(key) + ") value is not JSON-serializable");
2985
+ }
2986
+ if (json.length > ${MAX_STORE_VALUE_CHARS}) {
2987
+ throw new RangeError(
2988
+ "store(" + stringify(key) + ") value has " + json.length + " characters of JSON, more than the limit of ${MAX_STORE_VALUE_CHARS}. " +
2989
+ STORE_HINT,
2990
+ );
2991
+ }
2992
+ const next = storedChars - previous + key.length + json.length;
2993
+ if (next > ${MAX_STORE_TOTAL_CHARS}) {
2994
+ throw new RangeError(
2995
+ "store is full: stored values would exceed ${MAX_STORE_TOTAL_CHARS} characters of JSON. Delete keys with store(key, undefined). " +
2996
+ STORE_HINT,
2997
+ );
2998
+ }
2999
+ stored.set(key, json);
3000
+ storedChars = next;
3001
+ writes.set(key, json);
3002
+ }
3003
+
3004
+ function load(key) {
3005
+ checkKey("load", key);
3006
+ const json = stored.get(key);
3007
+ return json === undefined ? undefined : parse(json);
3008
+ }
3009
+
3010
+ function serializeWrites() {
3011
+ const entries = [];
3012
+ for (const [key, json] of writes) entries.push(json === undefined ? [key] : [key, json]);
3013
+ return stringify(entries);
3014
+ }
3015
+
3016
+ Object.defineProperty(globalThis, "store", { value: store, enumerable: true });
3017
+ Object.defineProperty(globalThis, "load", { value: load, enumerable: true });
3018
+
3019
+ let outputChars = 0;
3020
+ let outputItems = 0;
3021
+
3022
+ // Past the output limits the script fails: done() reports the error, so catching it does not
3023
+ // resume output, and the host ends the script.
3024
+ function output(kind, data, mimeType) {
3025
+ if (finished) return;
3026
+ outputChars += data.length;
3027
+ outputItems++;
3028
+ if (outputChars > ${MAX_OUTPUT_CHARS} || outputItems > ${MAX_OUTPUT_ITEMS}) {
3029
+ const error = new RangeErrorCtor(
3030
+ "script output exceeded the limit of ${MAX_OUTPUT_CHARS} characters or ${MAX_OUTPUT_ITEMS} text(), image(), and console calls. " +
3031
+ "Print a summary instead, or write large data to a file with a tool.",
3032
+ );
3033
+ done(false, describeError(error));
3034
+ throw error;
3035
+ }
3036
+ bridge("output", kind, data, mimeType);
3037
+ }
3038
+
3039
+ // Primitives become their string form, everything else JSON.
3040
+ function outputText(value) {
3041
+ if (value === undefined || value === null || typeof value !== "object" && typeof value !== "function") {
3042
+ return String(value);
3043
+ }
3044
+ const json = stringify(value);
3045
+ return json === undefined ? String(value) : json;
3046
+ }
3047
+
3048
+ function text(value) {
3049
+ let rendered;
3050
+ try {
3051
+ rendered = outputText(value);
3052
+ } catch (error) {
3053
+ throw new TypeErrorCtor(error instanceof ErrorCtor ? error.message : String(error));
3054
+ }
3055
+ output("text", rendered);
3056
+ }
3057
+
3058
+ function imageUrl(value) {
3059
+ if (typeof value === "string") return value;
3060
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
3061
+ throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
3062
+ }
3063
+ if (value.image_url !== undefined) {
3064
+ if (typeof value.image_url !== "string") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
3065
+ return value.image_url;
3066
+ }
3067
+ if (typeof value.type !== "string") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
3068
+ if (value.type !== "image") {
3069
+ throw new TypeErrorCtor('image only accepts MCP image blocks, got "' + value.type + '"');
3070
+ }
3071
+ if (typeof value.data !== "string" || value.data === "") throw new TypeErrorCtor("image expected MCP image data");
3072
+ if (value.data.toLowerCase().startsWith("data:")) return value.data;
3073
+ return "data:;base64," + value.data;
3074
+ }
3075
+
3076
+ // Base64 of the signatures of the formats providers accept inline (PNG, JPEG except
3077
+ // JPEG-LS, GIF, "RIFF....WEBP"). Signatures start at byte 0, so their encodings are prefixes.
3078
+ const IMAGE_SIGNATURES = [
3079
+ ["image/png", /^iVBORw0KGg/],
3080
+ ["image/jpeg", /^[/]9j[/](?!9)/],
3081
+ ["image/gif", /^R0lGOD[dl]h/],
3082
+ ["image/webp", /^UklG.{8}RUJQ/],
3083
+ ];
3084
+
3085
+ function image(value) {
3086
+ const url = imageUrl(value);
3087
+ if (url === "") throw new TypeErrorCtor(${JSON.stringify(IMAGE_HELPER_EXPECTS)});
3088
+ const colon = url.indexOf(":");
3089
+ const scheme = colon === -1 ? "" : url.slice(0, colon).toLowerCase();
3090
+ if (scheme === "http" || scheme === "https") {
3091
+ throw new TypeErrorCtor("remote image URLs are not supported in tool outputs. Pass a base64 data URI instead");
3092
+ }
3093
+ const comma = url.indexOf(",");
3094
+ const header = comma === -1 ? [] : url.slice(colon + 1, comma).split(";");
3095
+ if (scheme !== "data" || comma === -1 || header.slice(1).every((part) => part.toLowerCase() !== "base64")) {
3096
+ throw new TypeErrorCtor("invalid image output. Pass a base64 data URI instead");
3097
+ }
3098
+ // Providers reject the whole request on a bad image, and a persisted image block would be
3099
+ // resent on every later turn. Line breaks from wrapped base64 are dropped. The declared type
3100
+ // is ignored in favor of the detected one, as providers also reject mismatches.
3101
+ const data = url.slice(comma + 1).replace(/\\s+/g, "");
3102
+ if (data.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(data)) {
3103
+ throw new TypeErrorCtor("invalid image output. The image data is not valid base64 (truncated or corrupted?)");
3104
+ }
3105
+ const head = data.slice(0, 16);
3106
+ const signature = IMAGE_SIGNATURES.find(([, pattern]) => pattern.test(head));
3107
+ if (!signature) {
3108
+ throw new TypeErrorCtor("invalid image output. The image data is not a PNG, JPEG, GIF, or WebP image");
3109
+ }
3110
+ output("image", data, signature[0]);
3111
+ }
3112
+
3113
+ function exit() {
3114
+ let writesJson;
3115
+ try {
3116
+ writesJson = serializeWrites();
3117
+ } catch (error) {
3118
+ done(false, describeError(error));
3119
+ throw EXIT;
3120
+ }
3121
+ done(true, undefined, writesJson);
3122
+ throw EXIT;
3123
+ }
3124
+
3125
+ const console = {};
3126
+ for (const level of ["log", "info", "warn", "error", "debug"]) {
3127
+ console[level] = (...args) => {
3128
+ output("text", args.map(format).join(" "));
3129
+ };
3130
+ }
3131
+ Object.freeze(console);
3132
+
3133
+ Object.defineProperty(globalThis, "tools", { value: toolsProxy, enumerable: true });
3134
+ Object.defineProperty(globalThis, "ALL_TOOLS", { value: allTools, enumerable: true });
3135
+ Object.defineProperty(globalThis, "console", { value: console, enumerable: true });
3136
+ Object.defineProperty(globalThis, "text", { value: text, enumerable: true });
3137
+ Object.defineProperty(globalThis, "image", { value: image, enumerable: true });
3138
+ Object.defineProperty(globalThis, "exit", { value: exit, enumerable: true });
3139
+
3140
+ return {
3141
+ settle(id, ok, payload) {
3142
+ const entry = pending.get(id);
3143
+ if (!entry) return;
3144
+ pending.delete(id);
3145
+ if (!ok) {
3146
+ entry.reject(new ErrorCtor(payload));
3147
+ return;
3148
+ }
3149
+ let value;
3150
+ try {
3151
+ value = payload === undefined ? undefined : parse(payload);
3152
+ } catch (error) {
3153
+ entry.reject(error);
3154
+ return;
3155
+ }
3156
+ entry.resolve(value);
3157
+ },
3158
+ run(fn) {
3159
+ let promise;
3160
+ try {
3161
+ promise = fn(toolsProxy, console);
3162
+ } catch (error) {
3163
+ done(false, describeError(error));
3164
+ return;
3165
+ }
3166
+ promiseThen.call(
3167
+ promise,
3168
+ (value) => {
3169
+ let json;
3170
+ try {
3171
+ json = serialize(value);
3172
+ } catch (error) {
3173
+ done(false, describeError(error));
3174
+ return;
3175
+ }
3176
+ done(true, json, serializeWrites());
3177
+ },
3178
+ (error) => {
3179
+ done(false, describeError(error));
3180
+ },
3181
+ );
3182
+ },
3183
+ stalled() {
3184
+ if (finished || pending.size > 0) return false;
3185
+ done(
3186
+ false,
3187
+ stringify({
3188
+ name: "Error",
3189
+ message:
3190
+ "The script is waiting on a promise that can never settle: no tool call is pending, and timers do not exist here.",
3191
+ }),
3192
+ );
3193
+ return true;
3194
+ },
3195
+ };
3196
+ })`;
3197
+
3198
+ // ../../node_modules/@earendil-works/pi-codemode/dist/runtime/protocol.js
3199
+ function isHostToWorkerMessage(value) {
3200
+ return typeof value === "object" && value !== null && value.type === "result";
3201
+ }
3202
+
3203
+ // ../../node_modules/@earendil-works/pi-codemode/dist/runtime/worker.js
3204
+ function post(message) {
3205
+ parentPort?.postMessage(message);
3206
+ }
3207
+ function crash(error) {
3208
+ post({ type: "crash", message: error instanceof Error ? `${error.name}: ${error.message}` : String(error) });
3209
+ }
3210
+ function discardOutput(memory) {
3211
+ return {
3212
+ fd_write(_fd, iovsPtr, iovsLen, nwrittenPtr) {
3213
+ const view = new DataView(memory.buffer);
3214
+ let written = 0;
3215
+ for (let i = 0; i < iovsLen; i++) {
3216
+ written += view.getUint32(iovsPtr + i * 8 + 4, true);
3217
+ }
3218
+ view.setUint32(nwrittenPtr, written, true);
3219
+ return 0;
3220
+ }
3221
+ };
3222
+ }
3223
+ function describeException(error) {
3224
+ const head = error.message ? `${error.name}: ${error.message}` : error.name;
3225
+ const stack = error.stack?.trimEnd();
3226
+ return JSON.stringify({ name: error.name, message: error.message, stack: stack ? `${head}
3227
+ ${stack}` : head });
3228
+ }
3229
+ async function main(data) {
3230
+ const interrupt = new Int32Array(data.interrupt);
3231
+ const vm = await QuickJS.create({
3232
+ wasm: data.wasm,
3233
+ memoryLimit: data.memoryLimitBytes,
3234
+ // Without a guard, deep recursion overflows the wasm stack and traps instead of throwing a
3235
+ // catchable RangeError.
3236
+ maxStackSize: MAX_STACK_SIZE,
3237
+ interruptHandler: () => Atomics.load(interrupt, 0) !== 0,
3238
+ wasi: discardOutput
3239
+ });
3240
+ const bridge = vm.newFunction("bridge", (kind, a, b, c) => {
3241
+ switch (kind.toString()) {
3242
+ case "call":
3243
+ case "global":
3244
+ post({
3245
+ type: "call",
3246
+ id: a.toNumber(),
3247
+ target: kind.toString() === "call" ? "tool" : "global",
3248
+ name: b.toString(),
3249
+ args: c === void 0 || c.isUndefined ? void 0 : c.toString()
3250
+ });
3251
+ break;
3252
+ case "output":
3253
+ post({
3254
+ type: "output",
3255
+ item: a.toString() === "image" ? { type: "image", data: b.toString(), mimeType: c.toString() } : { type: "text", text: b.toString() }
3256
+ });
3257
+ break;
3258
+ case "done":
3259
+ if (a.toBoolean()) {
3260
+ post({
3261
+ type: "done",
3262
+ ok: true,
3263
+ value: b === void 0 || b.isUndefined ? void 0 : b.toString(),
3264
+ writes: c.toString()
3265
+ });
3266
+ } else {
3267
+ post({ type: "done", ok: false, error: b.toString() });
3268
+ }
3269
+ break;
3270
+ }
3271
+ return vm.undefined;
3272
+ });
3273
+ const api = vm.withScope((scope) => scope.escape(vm.callFunction(vm.evalCode(PRELUDE_SOURCE, "codemode-prelude.js"), vm.undefined, bridge, vm.newString(JSON.stringify(data.tools)), vm.newString(JSON.stringify(data.globals)), vm.newString(JSON.stringify(data.store)))));
3274
+ const settle = api.getProp("settle");
3275
+ const run = api.getProp("run");
3276
+ const stalled = api.getProp("stalled");
3277
+ const drain = () => {
3278
+ vm.executePendingJobs();
3279
+ vm.callFunction(stalled, api).dispose();
3280
+ };
3281
+ parentPort?.on("message", (message) => {
3282
+ if (!isHostToWorkerMessage(message))
3283
+ return;
3284
+ try {
3285
+ vm.withScope(() => {
3286
+ vm.callFunction(settle, api, vm.newNumber(message.id), message.ok ? vm.true : vm.false, message.payload === void 0 ? vm.undefined : vm.newString(message.payload));
3287
+ });
3288
+ drain();
3289
+ } catch (error) {
3290
+ crash(error);
3291
+ }
3292
+ });
3293
+ let fn;
3294
+ try {
3295
+ fn = vm.evalCode(`(async (tools, console) => {${data.code}
3296
+ })`, "codemode.js");
3297
+ } catch (error) {
3298
+ if (!(error instanceof JSException))
3299
+ throw error;
3300
+ post({ type: "done", ok: false, error: describeException(error) });
3301
+ return;
3302
+ }
3303
+ vm.callFunction(run, api, fn).dispose();
3304
+ fn.dispose();
3305
+ drain();
3306
+ }
3307
+ if (parentPort) {
3308
+ main(workerData).catch(crash);
3309
+ }