@poe-platform/safe-js 0.1.721 → 0.1.723

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 (85) hide show
  1. package/README.md +36 -6
  2. package/dist/config-mutations/types.d.ts +3 -1
  3. package/dist/safe-js/chunks/{chunk-B4M6QVUV.js → chunk-3QQYJ4RQ.js} +3 -2
  4. package/dist/safe-js/chunks/chunk-3QQYJ4RQ.js.map +7 -0
  5. package/dist/safe-js/chunks/{chunk-BEXRQET4.js → chunk-5MT2LF3W.js} +3 -3
  6. package/dist/safe-js/chunks/{chunk-JNLY7IMV.js → chunk-7FCMZUZJ.js} +4 -4
  7. package/dist/safe-js/chunks/{chunk-BHYBD6SY.js → chunk-7TL6Z6LT.js} +58 -8
  8. package/dist/safe-js/chunks/chunk-7TL6Z6LT.js.map +7 -0
  9. package/dist/safe-js/chunks/{chunk-HYD4K4HN.js → chunk-BRBOVGNC.js} +63 -1
  10. package/dist/safe-js/chunks/chunk-BRBOVGNC.js.map +7 -0
  11. package/dist/safe-js/chunks/{chunk-4CX3HYRY.js → chunk-HY3Q377V.js} +2 -2
  12. package/dist/safe-js/chunks/{chunk-DNA7BMBY.js → chunk-IZ52PAOD.js} +8540 -7309
  13. package/dist/safe-js/chunks/{chunk-DNA7BMBY.js.map → chunk-IZ52PAOD.js.map} +4 -4
  14. package/dist/safe-js/chunks/{chunk-A4L72WXV.js → chunk-KHJDAEET.js} +10 -11
  15. package/dist/safe-js/chunks/chunk-KHJDAEET.js.map +7 -0
  16. package/dist/safe-js/chunks/{chunk-Q7B6JIMI.js → chunk-M6HUSN7X.js} +404 -117
  17. package/dist/safe-js/chunks/chunk-M6HUSN7X.js.map +7 -0
  18. package/dist/safe-js/chunks/{chunk-LPBTSTDG.js → chunk-QMZG576E.js} +4 -4
  19. package/dist/safe-js/chunks/{chunk-ILYJBA2D.js → chunk-RYVHEOHM.js} +1109 -100
  20. package/dist/safe-js/chunks/chunk-RYVHEOHM.js.map +7 -0
  21. package/dist/safe-js/chunks/{chunk-IS7YUCOF.js → chunk-SWQHZKYM.js} +2 -2
  22. package/dist/safe-js/chunks/{chunk-Y4LNCDCP.js → chunk-WF7HYDJ4.js} +4 -5
  23. package/dist/safe-js/chunks/{chunk-Y4LNCDCP.js.map → chunk-WF7HYDJ4.js.map} +2 -2
  24. package/dist/safe-js/chunks/{chunk-GMPZBMPA.js → chunk-Y5ZXQHL6.js} +3 -3
  25. package/dist/safe-js/chunks/{cli-runtime-YK2WE33M.js → cli-runtime-EPXCJ5AG.js} +14 -14
  26. package/dist/safe-js/chunks/{dump-ATWBOZWV.js → dump-TWVEBH5W.js} +4 -4
  27. package/dist/safe-js/chunks/{fs-D72Y52I5.js → fs-DSNHTHBT.js} +4 -4
  28. package/dist/safe-js/chunks/harness-RLA643GD.js +10 -0
  29. package/dist/safe-js/chunks/mcp-IEY7HXXT.js +11 -0
  30. package/dist/safe-js/chunks/migration-file-QMI45CSP.js +12 -0
  31. package/dist/safe-js/chunks/restore-R5PLLBST.js +13 -0
  32. package/dist/safe-js/chunks/run-QATVEFVQ.js +17 -0
  33. package/dist/safe-js/chunks/runtime-modules-5D7KDFMZ.js +10 -0
  34. package/dist/safe-js/cli.js +2 -2
  35. package/dist/safe-js/core.js +7 -7
  36. package/dist/safe-js/index.js +14 -14
  37. package/dist/safe-js/interp/async.d.ts +4 -1
  38. package/dist/safe-js/interp/budget.d.ts +12 -6
  39. package/dist/safe-js/interp/collection-iterator.d.ts +1 -1
  40. package/dist/safe-js/interp/host-bridge.d.ts +2 -0
  41. package/dist/safe-js/interp/host-capabilities.d.ts +13 -4
  42. package/dist/safe-js/interp/interpreter.d.ts +5 -1
  43. package/dist/safe-js/interp/intl-numberformat.d.ts +2 -2
  44. package/dist/safe-js/interp/jobs.d.ts +8 -0
  45. package/dist/safe-js/interp/scope.d.ts +9 -2
  46. package/dist/safe-js/interp/typed-array.d.ts +2 -2
  47. package/dist/safe-js/interp/values.d.ts +1 -0
  48. package/dist/safe-js/modules/registry.d.ts +4 -1
  49. package/dist/safe-js/modules/source-graph.d.ts +19 -1
  50. package/dist/safe-js/parse/compact-spans.d.ts +18 -0
  51. package/dist/safe-js/parse/dynamic-source.d.ts +3 -1
  52. package/dist/safe-js/parse/function-source.d.ts +1 -1
  53. package/dist/safe-js/parse/parser.d.ts +8 -3
  54. package/dist/safe-js/parse/tokenizer.d.ts +4 -0
  55. package/dist/safe-js/realm.d.ts +16 -3
  56. package/dist/safe-js/restore.d.ts +1 -0
  57. package/dist/safe-js/run.d.ts +10 -0
  58. package/package.json +2 -2
  59. package/dist/safe-js/chunks/chunk-A4L72WXV.js.map +0 -7
  60. package/dist/safe-js/chunks/chunk-B4M6QVUV.js.map +0 -7
  61. package/dist/safe-js/chunks/chunk-BHYBD6SY.js.map +0 -7
  62. package/dist/safe-js/chunks/chunk-HYD4K4HN.js.map +0 -7
  63. package/dist/safe-js/chunks/chunk-ILYJBA2D.js.map +0 -7
  64. package/dist/safe-js/chunks/chunk-Q7B6JIMI.js.map +0 -7
  65. package/dist/safe-js/chunks/harness-LUYCGWHZ.js +0 -10
  66. package/dist/safe-js/chunks/mcp-IWKZB2R2.js +0 -11
  67. package/dist/safe-js/chunks/migration-file-IXO5MLP4.js +0 -12
  68. package/dist/safe-js/chunks/restore-SI7HOC6C.js +0 -13
  69. package/dist/safe-js/chunks/run-SHI2PYR6.js +0 -17
  70. package/dist/safe-js/chunks/runtime-modules-OO72HTVF.js +0 -10
  71. /package/dist/safe-js/chunks/{chunk-BEXRQET4.js.map → chunk-5MT2LF3W.js.map} +0 -0
  72. /package/dist/safe-js/chunks/{chunk-JNLY7IMV.js.map → chunk-7FCMZUZJ.js.map} +0 -0
  73. /package/dist/safe-js/chunks/{chunk-4CX3HYRY.js.map → chunk-HY3Q377V.js.map} +0 -0
  74. /package/dist/safe-js/chunks/{chunk-LPBTSTDG.js.map → chunk-QMZG576E.js.map} +0 -0
  75. /package/dist/safe-js/chunks/{chunk-IS7YUCOF.js.map → chunk-SWQHZKYM.js.map} +0 -0
  76. /package/dist/safe-js/chunks/{chunk-GMPZBMPA.js.map → chunk-Y5ZXQHL6.js.map} +0 -0
  77. /package/dist/safe-js/chunks/{cli-runtime-YK2WE33M.js.map → cli-runtime-EPXCJ5AG.js.map} +0 -0
  78. /package/dist/safe-js/chunks/{dump-ATWBOZWV.js.map → dump-TWVEBH5W.js.map} +0 -0
  79. /package/dist/safe-js/chunks/{fs-D72Y52I5.js.map → fs-DSNHTHBT.js.map} +0 -0
  80. /package/dist/safe-js/chunks/{harness-LUYCGWHZ.js.map → harness-RLA643GD.js.map} +0 -0
  81. /package/dist/safe-js/chunks/{mcp-IWKZB2R2.js.map → mcp-IEY7HXXT.js.map} +0 -0
  82. /package/dist/safe-js/chunks/{migration-file-IXO5MLP4.js.map → migration-file-QMI45CSP.js.map} +0 -0
  83. /package/dist/safe-js/chunks/{restore-SI7HOC6C.js.map → restore-R5PLLBST.js.map} +0 -0
  84. /package/dist/safe-js/chunks/{run-SHI2PYR6.js.map → run-QATVEFVQ.js.map} +0 -0
  85. /package/dist/safe-js/chunks/{runtime-modules-OO72HTVF.js.map → runtime-modules-5D7KDFMZ.js.map} +0 -0
package/README.md CHANGED
@@ -42,7 +42,7 @@ console.log(result.returnValue);
42
42
 
43
43
  - **JavaScript control flow:** functions and closures, classes, async/await, loops, destructuring, spread, templates, exceptions, and synchronous and asynchronous generators.
44
44
  - **Guest function objects:** own properties on functions and arrows; ordinary constructors with shared prototypes, inherited methods and `instanceof`. `Object.create`, `getPrototypeOf`, `setPrototypeOf`, own-property inspection, and data descriptors work on ordinary sandbox records.
45
- - **Data processing:** arrays, objects, strings, numbers, BigInt, Symbol, JSON, Math, Date, Map, Set, WeakMap, WeakSet, typed arrays, ArrayBuffer/DataView, promises, Intl APIs, and budgeted regular expressions.
45
+ - **Data processing:** arrays, objects, strings, numbers, BigInt, Symbol, JSON, Math, Date, Map, Set, WeakMap, WeakSet, typed arrays, ArrayBuffer/DataView, UTF-8 TextEncoder, promises, Intl APIs, and budgeted regular expressions.
46
46
  - **Language and object APIs:** guest `eval`, `Function` and async/generator function constructors, `Proxy`, `Reflect`, property descriptors, accessors, and prototype mutation. Dynamically generated code executes inside the interpreter with its existing capabilities and budgets.
47
47
  - **Additional built-ins:** all eight Temporal types and `Temporal.Now`, iterator helpers, disposable stacks, `WeakRef`, `FinalizationRegistry`, `SharedArrayBuffer`, and `Atomics`. Availability does not imply complete conformance or portable recovery; see the limitations below.
48
48
  - **Explicit capabilities:** static imports and dynamic `import()` resolve against host-supplied modules, not arbitrary npm packages or files. Optional helpers cover agents, MCP tools, files, environment reads, time, logging, and metrics.
@@ -214,6 +214,10 @@ try {
214
214
 
215
215
  This prints `2`. Evaluations share declarations, closures and object identity without rerunning earlier source. Budgets are cumulative. `evaluate(source, { filename? })` returns `ok`, `returnValue` or `error`, and `stats`; it can also reject. Concurrent evaluations are rejected. Deferred callbacks can run while guest code awaits their result; overlapping invocation of the same callback is rejected. Close cancels pending work, revokes capabilities and awaits cleanup; repeated close does not rerun cleanup. Unhandled execution failures also close the realm.
216
216
 
217
+ For scripts whose completion value is unused, call `evaluate(source, { discardResult: true })`. A successful result omits `returnValue`, so guest values with custom prototypes can remain inside the realm without crossing the data-copy boundary. Effects, resource limits and error handling still apply. `realm.supportsDiscardResult` is an immutable `true` marker for adapters that support older SDK versions.
218
+
219
+ Execution gives host timers and cancellation turns between guest nodes after elapsed host time as well as interpreter work. This preserves guest job ownership and resource checks. A synchronous native call or an individual data scan can still delay delivery; cancellation is cooperative.
220
+
217
221
  `createRealm(options?)` accepts `bindings`, `modules`, `budget`, `clock`, `signal`, `sink` and `randomSeed` as described below, plus:
218
222
 
219
223
  | Option | Purpose / default |
@@ -222,17 +226,35 @@ This prints `2`. Evaluations share declarations, closures and object identity wi
222
226
  | `grants` | Granted capability names; `[]`. Every requested capability must be granted before any extension setup runs. |
223
227
  | `builtinOverrides` | Optional `{ console: "extension-name" }` authorizes that registered extension to replace only the builtin console. It must declare `console` and export a host object created in the realm. No overrides by default. |
224
228
  | `limits` | Positive integer caps: `extensions: 32`, `hostObjects: 1024`, `callbacks: 1024`, `guestReferences: 1024`, `cleanups: 1024`, `nestedEvaluations: 16`. Collection budgets also apply. |
229
+ | `stringCompilation` | Optional `"allow"` (default) or `"deny"`. Denial raises a catchable guest EvalError for string eval and Function/AsyncFunction/GeneratorFunction/AsyncGeneratorFunction compilation, including retained callbacks. Host source evaluation remains available. This is separate from WebAssembly compilation policy. |
225
230
  | `classicScripts` | Optional boolean, default `false`. Evaluations use classic Script grammar with persistent globals: top-level `this` is the intrinsic global object, `var` and functions create global properties, and `let`/`const` remain lexical. Injected capabilities stay immutable lexical bindings. Explicit source modules retain module semantics. |
231
+ | `classicScriptErrors` | Optional `"fatal"` (default) or `"report"`; reporting requires `classicScripts: true`. Ordinary escaped Script exceptions return `ok: false` with `recoverable: true` while preserving realm state. Syntax, budget, cancellation, module, callback and unhandled rejection failures remain fatal. |
232
+ | `callbackScheduling` | Optional `"after-prefix"` for a trusted host scheduler. Allows later source after every admitted callback finishes its synchronous prefix, while their asynchronous tails remain pending. Omit for exclusive source evaluation. |
233
+ | `sourceResolver` | Explicitly grants source text and a canonical identity for each imported source. Classic Scripts use their evaluation filename as the referrer, including later calls to saved functions and generators. No filesystem or network access is granted by default. |
234
+ | `sourceImportTimeoutMs` | Optional integer from 1 to 2147483647, disabled by default. Limits elapsed host time for each dynamic source import across resolution, linking and evaluation, including top-level await. Expiry revokes the entire realm with a deadline budget error. Timers are cooperative; synchronous host work can delay delivery. |
226
235
 
227
236
  Classic Scripts reject top-level return, await and static imports/exports. This
228
237
  option preserves declaration history across evaluations and checkpoints; browser
229
- window aliases and callback scheduling belong to the host. Source-resolved dynamic
230
- imports from classic Scripts require separate support.
238
+ window aliases and callback scheduling belong to the host. Dynamic source imports
239
+ require an explicit `sourceResolver` and share canonical module instances with
240
+ source-module evaluations. `realm.sourceModuleStatus()` returns an immutable
241
+ snapshot with `pendingImports`, `preparedModules`, `fulfilledImports` and
242
+ `rejectedImports`; it rejects after realm revocation. Import settlement does not
243
+ establish application readiness.
231
244
 
232
245
  Ordinary host arguments/results are still copied. To preserve live native identity, explicitly create a host object. A guest function crossing to the host becomes an opaque callback: invoke it with `realm.invokeCallback(callback, { thisValue?, args? })`, then `realm.releaseCallback(callback)` when no longer needed. Inside a declared and granted `context.nestedOperation`, await `context.invokeCallback` to settle the full guest result, including nested host calls and returned promises. Callbacks and live objects cannot cross realms or survive close. For deferred arguments that must preserve guest identity, opt into retained references as described below.
233
246
 
234
247
  Need synchronous effects without waiting for an async callback's tail? Use `realm.startCallback(callback, options)` or `context.startCallback(callback, options)`. The frozen `CallbackInvocation` exposes two promises: await `synchronous` when the guest function returns or its async body reaches its first `await`; await `result` for the final value. Interpreter implementation awaits and budget work do not complete the prefix. Ordinary throws reject both promises; nonfatal async-function errors reject only `result`, even before the first `await`. Close, abort and fatal errors reject still-pending handles without changing a completed prefix. The same callback limits, identity and reentry rules apply; no extra grant is required. Calls started outside a host operation are queued in invocation order. Browser event/default-action policy remains the host's responsibility.
235
248
 
249
+ With `callbackScheduling: "after-prefix"`, the host must retain and observe callback
250
+ results. Source remains exclusive, including top-level await; guest-owned host
251
+ operations cannot use this option to admit another source. All work shares the
252
+ realm queue and cumulative limits. Suspended frames remain included in full graph
253
+ accounting. Compilation tickets and allocation charges may remain conservatively
254
+ held until pending work completes. External close waits for canceled work and
255
+ cleanup; close from a guest-owned host operation initiates cancellation and rejects
256
+ with `reentry` instead of awaiting its own caller.
257
+
236
258
  <details>
237
259
  <summary>Trusted extensions and live host objects</summary>
238
260
 
@@ -297,7 +319,7 @@ Supply your own bounded `journal`; this does not add browser console behavior. W
297
319
  | `signal` | Realm cancellation signal; aborted on close or failure. |
298
320
  | `onCleanup(fn)` | Register a sync/async disposer. Cleanup runs in reverse order, awaits every disposer, and reports failures without skipping the rest. |
299
321
  | `chargeWork(units = 1)` | Charge a nonnegative integer against the shared execution budget. Fatal exhaustion cannot be swallowed to continue execution. |
300
- | `createHostObject({ properties?, methods?, indexed?, named? })` | Create a realm-owned capability. Properties declare synchronous `get`/`set` functions; methods are host functions. Optional `indexed` and `named` expose bounded live members. Undeclared members expose no native prototype. |
322
+ | `createHostObject({ properties?, methods?, indexed?, named?, expandos? })` | Create a realm-owned capability. Properties declare synchronous `get`/`set` functions; methods are host functions. Optional `indexed` and `named` expose bounded live members. Optional `expandos` stores guest fields with guest identity preserved. Undeclared members expose no native prototype. |
301
323
  | `createArrayBufferReference(buffer)` | Create an opaque live reference to a fixed, attached, plain ArrayBuffer without own metadata. Requires declared and granted `array-buffer:share`; full buffer bytes count against array/data budgets and `limits.guestReferences`. |
302
324
  | `invokeCallback(callback, { thisValue?, args? })` | Invoke a captured guest function with the realm's state, cancellation and budgets. Same operation as on the realm. |
303
325
  | `startCallback(callback, { thisValue?, args? })` | Return separate `synchronous` and `result` promises for the same realm-owned invocation. Also available on the realm. |
@@ -307,6 +329,8 @@ Supply your own bounded `journal`; this does not add browser console behavior. W
307
329
  | `nestedOperation(fn)` | During setup, mark a host operation authorized to run nested source. Requires declared and granted `source:nested`. |
308
330
  | `evaluateNested(source)` | Only inside that extension's authorized operation. Completes before the enclosing call returns to guest code, shares scope/budgets, and propagates errors. Parallel nested evaluations and ordinary source reentry are rejected. |
309
331
 
332
+ Use `expandos: { maxKeys, maxKeyCodeUnits, assertActive? }` to allow guest assignment, deletion and enumeration of string and symbol fields. `maxKeys` must be 1–65,536; `maxKeyCodeUnits` must be 1–1,048,576 and counts string keys plus symbol descriptions in UTF-16 units. Guest graphs and closures remain subject to the realm's data budget. The optional synchronous `assertActive` hook must return `undefined` and can enforce the publisher's lifetime. Declared members, indexed names and prototype-related names remain protected. Expandos cannot be combined with `named`; arbitrary descriptors and prototype links remain unsupported.
333
+
310
334
  For a timer-shaped `schedule(callback, delay, ...args)`, register `context.retainGuestArguments(schedule, 2)`. The host receives normal callback/delay values and opaque `GuestReference` handles for the remaining arguments. Pass those handles to `context.invokeCallback(callback, { args })` to recover the original guest objects and observe mutations made after scheduling. References also work as callback receivers and host return values, including cycles, closures, primitives and live host objects.
311
335
 
312
336
  For a trusted native buffer such as WebAssembly memory, use `context.createArrayBufferReference(buffer)` and return the handle from a host property or operation. Guest ArrayBuffer views then share its bytes with the host, preserving identity and bidirectional writes. Ordinary host buffers still copy. Shared, resizable, detached, subclassed and proxy buffers reject, as do buffers with own properties or symbols. After native memory growth detaches the old buffer, create a new reference to the new buffer; the old reference continues to denote the detached buffer.
@@ -389,10 +413,12 @@ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same re
389
413
  | --- | --- |
390
414
  | `bindings` | Global input values and host functions; none by default. |
391
415
  | `modules` | Module names mapped to export records or Maps; none by default. |
416
+ | `importSpecifiers` | Optional exact names admitted beyond bare imports in harness execution; every name still requires explicit registration in `modules`. Supply the same allowlist to `restore` or snapshot replay. This does not load native, local, or network modules. |
392
417
  | `extensions`, `grants`, `builtinOverrides`, `limits` | Opt into a one-shot extension realm; see the supported options and lifetime rules above. |
393
418
  | `budget` | A `Budget` instance. Without one, only the default call-depth limit of 1,000 is configured. |
394
419
  | `signal` | Host `AbortSignal` for cancellation. |
395
420
  | `filename` | Diagnostic filename; defaults to `<input>`. |
421
+ | `sourceLocation` | Optional trusted callback mapping one-based guest stack `{ line, column }` positions to `{ filename, line, column }`. Return `undefined` to retain a generated frame. It changes diagnostics only; re-supply it when resuming snapshots. |
396
422
  | `entryPointArgs` | Arguments for invoking the default-exported function. Omit for top-level execution only. |
397
423
  | `importMeta` | Host-supplied fields exposed through `import.meta`. |
398
424
  | `sink` | Console destination with `log(...args)` and `error(...args)`; defaults to the host console. |
@@ -412,8 +438,12 @@ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same re
412
438
  | `deadline` | Absolute epoch milliseconds or a `Date`, not a duration. |
413
439
  | `maxCallDepth` | Nested interpreter calls. |
414
440
  | `stringLength`, `arrayLength` | Individual string and array lengths. |
441
+ | `regexSourceLength` | Optional regex source cap; positive safe integer, unlimited when omitted. The general `stringLength` limit also applies. |
442
+ | `regexCompileAllocations` | Optional per-regex compilation allocation cap; positive safe integer, unlimited when omitted. Compilation still charges work and retained data against the shared budget. |
415
443
  | `dataSize` | Retained sandbox data units, not bytes of process memory. |
416
444
 
445
+ `JSON.parse` checks both parse paths before building native objects: input work counts toward steps and deadlines, array lengths and object member counts use `arrayLength`, and nesting uses `maxCallDepth` with an additional ceiling of 256 containers. Parsing requires room for a conservative temporary allocation bound of `16 * text.length + 8` data units alongside existing data; whitespace and duplicate keys count toward this bound.
446
+
417
447
  There are no runtime environment variables to set. `makeEnvModule({ allow, values? })` grants reads of names in `allow`; `values` supplies an explicit string map instead of reading the host's `process.env`. Disallowed reads throw `EnvAccessError`; allowed but unset names return `undefined`. Agent and MCP integrations may require their own credentials.
418
448
 
419
449
  <details>
@@ -491,7 +521,7 @@ Factories return exports to register in `modules`; calling a factory alone does
491
521
  | --- | --- |
492
522
  | `makeAgentModule(spawnAgent, options?)` | Inject the agent runner. Options: `defaultRetry`, `onEvent`, `otelSink`. Exposes `spawn`, `spawn.retry`, and `spawn.parallel`; call options follow this table. |
493
523
  | `makeMcpModule(options)` | Required `servers` map: stdio `{ command, args?, cwd?, env? }` or HTTP `{ url, headers? }`. Options: `requestTimeoutMs` (30,000), `closeTimeoutMs` (1,000), `maxToolPages` (100), `signal`, and injected `fetch`/`spawn`. Named clients expose `tools`, `tool`, `toolBatch`, and `close`; close managed clients when finished. A custom connector function is also accepted. |
494
- | `makeFsModule(options?)` | Node-backed `{ root?, fs? }`, or shared-filesystem `{ adapter, root?, cwd?, signal? }`; do not combine `fs` and `adapter`. Node access without `root` is unconfined. With an adapter, `root` confines access and `cwd` selects the virtual relative-path base; without `root`, explicit `cwd` also confines access. Omitting both uses virtual `/`. Read text with `readFile(path, "utf8")`; see the [module methods](src/modules/fs.ts) and [filesystem package](../safe-fs/README.md). |
524
+ | `makeFsModule(options?)` | Node-backed `{ root?, fs? }`, or shared-filesystem `{ adapter, root?, cwd?, signal? }`; do not combine `fs` and `adapter`. Node access without `root` is unconfined. Rooted calls sharing the same adapter or Node implementation are serialized through path checks and backend completion to prevent guest namespace races. External host mutations or distinct adapters over the same storage require independent backend confinement. With an adapter, `root` confines access and `cwd` selects the virtual relative-path base; without `root`, explicit `cwd` also confines access. Omitting both uses virtual `/`. Adapter text reads pass a byte cap derived conservatively from the guest string and remaining data limits to the backend before decoding. Each read is also capped at 419,430 input bytes. A shared 16 MiB host read allowance reserves ten bytes per input byte for collection, copies, encoding expansion and admission; concurrent reads that exceed it reject, and reservations release after the underlying read settles and decoding finishes, including when cancellation rejects the caller earlier. Native Node/injected `fs` implementations retain their own read behavior. Read text with `readFile(path, "utf8")`; see the [module methods](src/modules/fs.ts) and [filesystem package](../safe-fs/README.md). |
495
525
  | `makeEnvModule(namesOrOptions)` | Allowed-name array or `{ allow, values? }`; exposes `get(name)`. `parseEnvConfig(json)` accepts the object form. |
496
526
  | `makeTimeModule(options?)` | `now`, `random`, `seed`, `signal`; exposes `now`, `random`, `sleep`, `uuid`. Defaults to host time/randomness; `seed` makes the random generator deterministic, and explicit `random` takes precedence. |
497
527
  | `makeLogModule(sink)` | Sends timestamped `info`, `error`, and `event` entries to your callback. |
@@ -521,7 +551,7 @@ functions can still be retained by custom Promise constructors.
521
551
  - `restore(snapshot, { source })` validates state for compatible source; pass it as `run`'s `snapshot` option. It does not run the program.
522
552
  - `new FileSnapshotBackend(path, { writeMaxAttempts?, writeRetryDelayMs? })` defaults to 3 write attempts and a 100 ms retry delay.
523
553
  - `createReplayableRandom({ seed?, snapshot? })` supplies `next`, `seed`, `snapshot`, and `restore` for reproducible random sequences.
524
- - `declareHostOperation(fn, policy, { onReplay? })` declares `re-issue` or `read-side-effect` recovery policy. `registerPendingHostCallPolicy({ moduleId, operation, policy })` registers it by name. Only mark operations re-issuable when repeating them is acceptable; a declaration does not implement deduplication or external recovery.
554
+ - `declareHostOperation(fn, policy, { onReplay?, awaitResult? })` declares `re-issue` or `read-side-effect` recovery policy. `registerPendingHostCallPolicy({ moduleId, operation, policy })` registers it by name. Only mark operations re-issuable when repeating them is acceptable; a declaration does not implement deduplication or external recovery. With `awaitResult: true`, an asynchronous host operation completes before the guest call returns its copied value or throws its error, without exposing a guest Promise. This is an explicit host capability; the host event loop still runs, and cancellation, value budgets, and host-call recovery still apply.
525
555
  - `inspectSnapshotMigration(snapshot, { source })` inspects outstanding work. `migrateSnapshot(snapshot, { source, targetSource, state, reconciliation })` creates a continuation checkpoint. Reconciliation supplies `checkpointDigest`, `quiescent`, and `calls`; each call has `callId` and disposition `not-performed`, `fulfilled` with `value`, or `rejected` with `reason`.
526
556
  - `migrateSnapshotFile(options)` accepts `snapshotPath`, `sourcePath`, `targetSourcePath`, `planPath`, `outputPath`, `inspect`, `dryRun`, and `cwd`. Inspect mode needs the checkpoint and original source; migration also needs the target, plan, and new output path. See [continuation migration](MIGRATION.md) before changing a checkpointed program.
527
557
 
@@ -13,7 +13,7 @@ export interface FileSystem {
13
13
  }): Promise<void>;
14
14
  mkdir(path: string, options?: {
15
15
  recursive: boolean;
16
- }): Promise<void>;
16
+ }): Promise<unknown>;
17
17
  rename(oldPath: string, newPath: string): Promise<void>;
18
18
  unlink(path: string): Promise<void>;
19
19
  rm?(path: string, options?: {
@@ -52,6 +52,8 @@ export interface PathMapper {
52
52
  }): string;
53
53
  }
54
54
  export interface MutationContext {
55
+ /** Path operations for the filesystem namespace; defaults to native host paths. */
56
+ paths?: typeof import("node:path");
55
57
  /** Filesystem interface - required */
56
58
  fs: FileSystem;
57
59
  /** Home directory for ~ expansion - required */
@@ -8,7 +8,7 @@ import {
8
8
  numericTypedArrayConstructors,
9
9
  parseModule,
10
10
  tokenize
11
- } from "./chunk-ILYJBA2D.js";
11
+ } from "./chunk-RYVHEOHM.js";
12
12
 
13
13
  // packages/safe-js/src/lint/rules/AS001.ts
14
14
  function AS001(source, options = {}) {
@@ -708,6 +708,7 @@ var KNOWN_RUNTIME_GLOBALS = [
708
708
  "structuredClone",
709
709
  "SyntaxError",
710
710
  "Temporal",
711
+ "TextEncoder",
711
712
  "TypeError",
712
713
  "URIError",
713
714
  "undefined",
@@ -11176,4 +11177,4 @@ function hasOnlyRegexLiteralDiagnostics(diagnostics) {
11176
11177
  export {
11177
11178
  lint
11178
11179
  };
11179
- //# sourceMappingURL=chunk-B4M6QVUV.js.map
11180
+ //# sourceMappingURL=chunk-3QQYJ4RQ.js.map