@poe-platform/safe-js 0.1.734 → 0.1.736

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 (56) hide show
  1. package/README.md +11 -11
  2. package/dist/safe-js/chunks/{chunk-X3CKAZQ4.js → chunk-33AKDRQ4.js} +3 -3
  3. package/dist/safe-js/chunks/{chunk-K4T4EBED.js → chunk-356QH3RB.js} +7 -3
  4. package/dist/safe-js/chunks/chunk-356QH3RB.js.map +7 -0
  5. package/dist/safe-js/chunks/{chunk-RULU2F5J.js → chunk-762WTEEI.js} +2 -2
  6. package/dist/safe-js/chunks/{chunk-E4XLBT7R.js → chunk-7AHNAUR5.js} +2 -2
  7. package/dist/safe-js/chunks/{chunk-W4SWUHCQ.js → chunk-FUUG7UIZ.js} +4 -4
  8. package/dist/safe-js/chunks/{chunk-PSVV3IG2.js → chunk-IKRAX7Z5.js} +3 -3
  9. package/dist/safe-js/chunks/{chunk-GNEORAQI.js → chunk-LELXBLG2.js} +22 -12
  10. package/dist/safe-js/chunks/chunk-LELXBLG2.js.map +7 -0
  11. package/dist/safe-js/chunks/{chunk-MDIWQFYU.js → chunk-SBFOCNNW.js} +196 -142
  12. package/dist/safe-js/chunks/{chunk-MDIWQFYU.js.map → chunk-SBFOCNNW.js.map} +3 -3
  13. package/dist/safe-js/chunks/{chunk-KETIFEA7.js → chunk-TAC75RFB.js} +2 -2
  14. package/dist/safe-js/chunks/{chunk-P64CQIUA.js → chunk-UVJ27MVC.js} +3 -3
  15. package/dist/safe-js/chunks/{chunk-QKO4FATZ.js → chunk-VQGYRKM4.js} +36 -10
  16. package/dist/safe-js/chunks/{chunk-QKO4FATZ.js.map → chunk-VQGYRKM4.js.map} +2 -2
  17. package/dist/safe-js/chunks/{chunk-O4IDRXW7.js → chunk-WDEOWDLS.js} +4 -4
  18. package/dist/safe-js/chunks/{chunk-WS2FJBH6.js → chunk-ZNAW4ZDX.js} +2 -2
  19. package/dist/safe-js/chunks/{cli-runtime-ZSOTNIVC.js → cli-runtime-FMSBDP7G.js} +11 -11
  20. package/dist/safe-js/chunks/{dump-RGRC3CG3.js → dump-2IM3WE2J.js} +4 -4
  21. package/dist/safe-js/chunks/harness-ZLV6ZBEU.js +11 -0
  22. package/dist/safe-js/chunks/{mcp-2Z4XWHKW.js → mcp-42AFDWT3.js} +4 -4
  23. package/dist/safe-js/chunks/{migration-file-KRXQYI3Q.js → migration-file-AYLLA72K.js} +5 -5
  24. package/dist/safe-js/chunks/restore-SGQO4E4M.js +14 -0
  25. package/dist/safe-js/chunks/{run-ZSFX66RN.js → run-Q5Z4TRQO.js} +7 -7
  26. package/dist/safe-js/chunks/{runtime-modules-A3U2DKFL.js → runtime-modules-3P6FZJ55.js} +4 -4
  27. package/dist/safe-js/cli.js +2 -2
  28. package/dist/safe-js/core.js +7 -7
  29. package/dist/safe-js/index.js +13 -13
  30. package/dist/safe-js/interp/host-bridge.d.ts +3 -1
  31. package/dist/safe-js/interp/host-capabilities.d.ts +5 -5
  32. package/dist/safe-js/modules/fs.d.ts +4 -1
  33. package/dist/safe-js/modules/fs.js +3 -3
  34. package/dist/safe-js/snapshot/validation.d.ts +1 -1
  35. package/package.json +2 -2
  36. package/dist/safe-js/chunks/chunk-GNEORAQI.js.map +0 -7
  37. package/dist/safe-js/chunks/chunk-K4T4EBED.js.map +0 -7
  38. package/dist/safe-js/chunks/harness-UMOMFXDT.js +0 -11
  39. package/dist/safe-js/chunks/restore-GEO7VN2R.js +0 -14
  40. /package/dist/safe-js/chunks/{chunk-X3CKAZQ4.js.map → chunk-33AKDRQ4.js.map} +0 -0
  41. /package/dist/safe-js/chunks/{chunk-RULU2F5J.js.map → chunk-762WTEEI.js.map} +0 -0
  42. /package/dist/safe-js/chunks/{chunk-E4XLBT7R.js.map → chunk-7AHNAUR5.js.map} +0 -0
  43. /package/dist/safe-js/chunks/{chunk-W4SWUHCQ.js.map → chunk-FUUG7UIZ.js.map} +0 -0
  44. /package/dist/safe-js/chunks/{chunk-PSVV3IG2.js.map → chunk-IKRAX7Z5.js.map} +0 -0
  45. /package/dist/safe-js/chunks/{chunk-KETIFEA7.js.map → chunk-TAC75RFB.js.map} +0 -0
  46. /package/dist/safe-js/chunks/{chunk-P64CQIUA.js.map → chunk-UVJ27MVC.js.map} +0 -0
  47. /package/dist/safe-js/chunks/{chunk-O4IDRXW7.js.map → chunk-WDEOWDLS.js.map} +0 -0
  48. /package/dist/safe-js/chunks/{chunk-WS2FJBH6.js.map → chunk-ZNAW4ZDX.js.map} +0 -0
  49. /package/dist/safe-js/chunks/{cli-runtime-ZSOTNIVC.js.map → cli-runtime-FMSBDP7G.js.map} +0 -0
  50. /package/dist/safe-js/chunks/{dump-RGRC3CG3.js.map → dump-2IM3WE2J.js.map} +0 -0
  51. /package/dist/safe-js/chunks/{harness-UMOMFXDT.js.map → harness-ZLV6ZBEU.js.map} +0 -0
  52. /package/dist/safe-js/chunks/{mcp-2Z4XWHKW.js.map → mcp-42AFDWT3.js.map} +0 -0
  53. /package/dist/safe-js/chunks/{migration-file-KRXQYI3Q.js.map → migration-file-AYLLA72K.js.map} +0 -0
  54. /package/dist/safe-js/chunks/{restore-GEO7VN2R.js.map → restore-SGQO4E4M.js.map} +0 -0
  55. /package/dist/safe-js/chunks/{run-ZSFX66RN.js.map → run-Q5Z4TRQO.js.map} +0 -0
  56. /package/dist/safe-js/chunks/{runtime-modules-A3U2DKFL.js.map → runtime-modules-3P6FZJ55.js.map} +0 -0
package/README.md CHANGED
@@ -342,7 +342,7 @@ Supply your own bounded `journal`; this does not add browser console behavior. W
342
342
  | `nestedOperation(fn)` | During setup, mark a host operation authorized to run nested source. Requires declared and granted `source:nested`. |
343
343
  | `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. |
344
344
 
345
- 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.
345
+ Use `expandos: { maxKeys, maxKeyCodeUnits, assertActive? }` to allow guest assignment, deletion and enumeration of string and symbol fields. `maxKeys` and `maxKeyCodeUnits` accept positive integer caps or `Infinity` and default to `Infinity`. Key code units count 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.
346
346
 
347
347
  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.
348
348
 
@@ -362,7 +362,7 @@ const collection = context.createHostObject({ indexed: {
362
362
  } });
363
363
  ```
364
364
 
365
- `length()` and `get(index)` must be synchronous. `maxLength` is required: an integer from 1 to 65,536. Every reported length must be a nonnegative integer within that cap and the execution array-length budget. Return existing `HostObject` handles for elements that need live identity; ordinary results use the normal copy boundary.
365
+ `length()` and `get(index)` must be synchronous. `maxLength` is optional and defaults to `Infinity`; configure a positive integer cap when needed. Every reported length must be a nonnegative integer within that cap and the execution array-length budget. Return existing `HostObject` handles for elements that need live identity; ordinary results use the normal copy boundary.
366
366
 
367
367
  Saved collections observe current host contents. Index reads, `Object.keys`/`values`/`entries`, `Object.hasOwn`, `in`, `for...in`, `for...of`, array/object spread and `Array.from` use the live view. Enumerable keys include current indices and fixed members, but not `length`. `Array.from` preserves element identity and interleaves mapping with reads. Noncanonical and out-of-range indices never call `get`; fixed members cannot reuse `length` or canonical index names. Enumeration and traversal consume execution budgets, without eagerly allocating virtual properties.
368
368
 
@@ -385,8 +385,8 @@ const attributesObject = context.createHostObject({ named });
385
385
  | `get(name)` | Synchronous value provider, called only for a currently present name. Existing host conversion and identity rules apply. |
386
386
  | `set(name, value)` | Optional synchronous setter, including new names. Receives the normally converted host value; assignment returns the original guest RHS. Omit to keep named writes disabled. |
387
387
  | `delete(name)` | Optional synchronous deleter returning a boolean. Absent names return `true` without calling it; existing names return its result. Omit to keep deletion disabled. |
388
- | `maxKeys` | Required positive integer, at most 65,536. |
389
- | `maxKeyCodeUnits` | Required positive aggregate key-length cap, at most 1,048,576 UTF-16 code units. Execution, array, string and data budgets also apply. |
388
+ | `maxKeys` | Optional positive integer cap; defaults to `Infinity`. |
389
+ | `maxKeyCodeUnits` | Optional positive aggregate key-length cap in UTF-16 code units; defaults to `Infinity`. Execution, array, string and data budgets also apply. |
390
390
  | `enumerable` | Defaults to `true`. Set `false` to keep names readable and visible to `in`/`Object.hasOwn`, but omit them from keys/values/entries, object spread and `for...in`. |
391
391
 
392
392
  Fixed properties/methods take precedence over names. With `indexed`, numeric indices and `length` remain indexed members. Enumeration deduplicates collisions; names removed by an earlier getter are skipped. Named-only objects are not iterable—combine `named` with `indexed` when you need numeric collection access and `for...of`.
@@ -430,7 +430,7 @@ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same re
430
430
  | `modules` | Module names mapped to export records or Maps; none by default. |
431
431
  | `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. |
432
432
  | `extensions`, `grants`, `builtinOverrides`, `limits` | Opt into a one-shot extension realm; see the supported options and lifetime rules above. |
433
- | `budget` | A `Budget` instance. Without one, only the default call-depth limit of 1,000 is configured. |
433
+ | `budget` | A `Budget` instance. Limits default to `Infinity` when omitted. |
434
434
  | `signal` | Host `AbortSignal` for cancellation. |
435
435
  | `filename` | Diagnostic filename; defaults to `<input>`. |
436
436
  | `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. |
@@ -451,13 +451,13 @@ For one-shot use, `run(source, { extensions, grants, ... })` accepts the same re
451
451
  | --- | --- |
452
452
  | `maxSteps` | Interpreter work counter. |
453
453
  | `deadline` | Absolute epoch milliseconds or a `Date`, not a duration. |
454
- | `maxCallDepth` | Nested interpreter calls. |
454
+ | `maxCallDepth` | Nested interpreter calls, parser nesting, and snapshot validation depth. |
455
455
  | `stringLength`, `arrayLength` | Individual string and array lengths. |
456
456
  | `regexSourceLength` | Optional regex source cap; positive safe integer, unlimited when omitted. The general `stringLength` limit also applies. |
457
457
  | `regexCompileAllocations` | Optional per-regex compilation allocation cap; positive safe integer, unlimited when omitted. Compilation still charges work and retained data against the shared budget. |
458
458
  | `dataSize` | Retained sandbox data units, not bytes of process memory. |
459
459
 
460
- `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.
460
+ `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` only when explicitly configured. 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.
461
461
 
462
462
  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.
463
463
 
@@ -510,8 +510,8 @@ settlement data remains separately copied, and independent imports stay isolated
510
510
  Newly encountered imported Promises that have settled also support completed
511
511
  replay, including aliases across separate host outcomes and cyclic fulfillment
512
512
  data. Replay uses the original settlement data, not later guest mutations.
513
- Cross-outcome reconstruction enforces the combined nesting limit without
514
- recursively expanding the host stack. Newly encountered imported Promises that
513
+ Cross-outcome reconstruction handles deeply nested data without recursively
514
+ expanding the host stack. Newly encountered imported Promises that
515
515
  are still pending can be checkpointed for replay. Restoring them requires a
516
516
  matching proof from `hostCallResumeProvider`; the original input or host operation
517
517
  is not repeated. Aliases share one reconciliation request. Proofs may introduce
@@ -536,7 +536,7 @@ Factories return exports to register in `modules`; calling a factory alone does
536
536
  | --- | --- |
537
537
  | `makeAgentModule(spawnAgent, options?)` | Inject the agent runner. Options: `defaultRetry`, `onEvent`, `otelSink`. Exposes `spawn`, `spawn.retry`, and `spawn.parallel`; call options follow this table. |
538
538
  | `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. |
539
- | `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. Optional `readFileMaxBytes` and `hostReadMemoryLimit` default to `Infinity` and accept explicit `Infinity`. A finite host allowance reserves ten bytes per input byte for collection, copies, encoding expansion and admission across concurrent reads from that module; 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). |
539
+ | `makeFsModule(options?)` | Node-backed `{ root?, fs? }`, or shared-filesystem `{ adapter, root?, cwd?, signal? }`; do not combine `fs` and `adapter`. Pass safe-fs instances through `adapter`; supplying one as `fs` throws at construction. Named methods, default imports and `promises` imports expose the same asynchronous filesystem operations. 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. Optional `readFileMaxBytes` and `hostReadMemoryLimit` default to `Infinity` and accept explicit `Infinity`. A finite host allowance reserves ten bytes per input byte for collection, copies, encoding expansion and admission across concurrent reads from that module; 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). |
540
540
  | `makeEnvModule(namesOrOptions)` | Allowed-name array or `{ allow, values? }`; exposes `get(name)`. `parseEnvConfig(json)` accepts the object form. |
541
541
  | `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. |
542
542
  | `makeLogModule(sink)` | Sends timestamped `info`, `error`, and `event` entries to your callback. |
@@ -566,7 +566,7 @@ functions can still be retained by custom Promise constructors.
566
566
  - `restore(snapshot, { source })` validates state for compatible source; pass it as `run`'s `snapshot` option. It does not run the program.
567
567
  - `new FileSnapshotBackend(path, { writeMaxAttempts?, writeRetryDelayMs? })` defaults to 3 write attempts and a 100 ms retry delay.
568
568
  - `createReplayableRandom({ seed?, snapshot? })` supplies `next`, `seed`, `snapshot`, and `restore` for reproducible random sequences. Unseeded generators use Web Crypto entropy; unseeded `makeTimeModule().uuid()` uses `globalThis.crypto.randomUUID()`.
569
- - `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.
569
+ - `declareHostOperation(fn, policy, { onReplay?, awaitResult?, callbackScheduling? })` 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. Use `callbackScheduling: "after-prefix"` for event-style APIs whose callbacks must wait for the current guest synchronous work to finish or explicitly await. Callbacks can then await other callbacks without blocking their admission. The default keeps inline callback behavior; `after-prefix` cannot be combined with `awaitResult: true`.
570
570
  - `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`.
571
571
  - `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.
572
572
 
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  SnapshotNotReadyError,
3
3
  serializeSafeJSSnapshot
4
- } from "./chunk-MDIWQFYU.js";
4
+ } from "./chunk-SBFOCNNW.js";
5
5
  import {
6
6
  SandboxError
7
- } from "./chunk-QKO4FATZ.js";
7
+ } from "./chunk-VQGYRKM4.js";
8
8
 
9
9
  // packages/safe-js/src/snapshot/dump.ts
10
10
  var RUN_DUMP_CONTROLLER = /* @__PURE__ */ Symbol("SafeJS.run-dump-controller");
@@ -195,4 +195,4 @@ export {
195
195
  dumpCurrent,
196
196
  serializeRunSnapshot
197
197
  };
198
- //# sourceMappingURL=chunk-X3CKAZQ4.js.map
198
+ //# sourceMappingURL=chunk-33AKDRQ4.js.map
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  declareBudgetedHostOperation,
9
9
  declareHostOperation
10
- } from "./chunk-MDIWQFYU.js";
10
+ } from "./chunk-SBFOCNNW.js";
11
11
  import {
12
12
  basename,
13
13
  dirname,
@@ -271,6 +271,9 @@ function makeFsModule(options = {}) {
271
271
  throw new TypeError("Filesystem read limits must be non-negative safe integers or Infinity.");
272
272
  }
273
273
  let reservedHostReadMemory = 0;
274
+ if (options.fs && "capabilities" in options.fs) {
275
+ throw new TypeError("Pass safe-fs FileSystem through the adapter option, not fs.");
276
+ }
274
277
  if (options.adapter !== void 0 && options.fs !== void 0) {
275
278
  throw new TypeError("fs module accepts either adapter or fs, not both.");
276
279
  }
@@ -320,7 +323,7 @@ function makeFsModule(options = {}) {
320
323
  declareBudgetedHostOperation(directRead, boundedRead);
321
324
  readFile = directRead;
322
325
  }
323
- return {
326
+ const module = {
324
327
  access: bind(fs, "access", "re-issue"),
325
328
  appendFile: bind(fs, "appendFile", "read-side-effect"),
326
329
  chmod: bind(fs, "chmod", "read-side-effect"),
@@ -353,6 +356,7 @@ function makeFsModule(options = {}) {
353
356
  COPYFILE_EXCL: constants.COPYFILE_EXCL
354
357
  }
355
358
  };
359
+ return { ...module, default: module, promises: module };
356
360
  }
357
361
  function assertSupportedPlatform() {
358
362
  if (hostPlatform !== "win32") {
@@ -742,4 +746,4 @@ export {
742
746
  FS_OPTION_SURFACE,
743
747
  makeFsModule
744
748
  };
745
- //# sourceMappingURL=chunk-K4T4EBED.js.map
749
+ //# sourceMappingURL=chunk-356QH3RB.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/modules/fs.ts", "../../src/modules/canonical-path.ts"],
4
+ "sourcesContent": ["import { fsConstants as nodeFsConstants, hostFs as nodeFsPromises, hostPlatform, inspect } from \"#safe-js-platform\";\nimport type { FsBridgeDirent as Dirent, FsBridgeStats as Stats, FsBridgeEncoding } from \"@poe-code/safe-fs/core\";\ntype PathLike = string | Uint8Array | URL;\n\nimport { dirname, isAbsolute, resolve, sep } from \"./paths.js\";\n\nimport { accessDeniedSystemError } from \"#safe-js-platform\";\nimport { createFsBridge } from \"@poe-code/safe-fs/core\";\nimport { fsCodec } from \"./fs-codec.js\";\nimport {\n type EntryComparison,\n type FileSystem,\n FsError,\n isPathWithin\n} from \"@poe-code/safe-fs/core\";\n\nimport type { Budget } from \"../interp/budget.js\";\nimport { getOwnErrorCode, type SystemError } from \"../error-codes.js\";\nimport { declareHostOperation, declareBudgetedHostOperation } from \"../interp/host-bridge.js\";\nimport {\n type CanonicalPathFs,\n containsPath,\n resolveCanonicalPath,\n type Stat\n} from \"./canonical-path.js\";\nimport type { PendingHostCallPolicyMode } from \"../snapshot/policy.js\";\n\ntype FsOperationName =\n | \"access\"\n | \"appendFile\"\n | \"chmod\"\n | \"copyFile\"\n | \"cp\"\n | \"link\"\n | \"lstat\"\n | \"mkdir\"\n | \"mkdtemp\"\n | \"readFile\"\n | \"readdir\"\n | \"readlink\"\n | \"realpath\"\n | \"rename\"\n | \"rm\"\n | \"rmdir\"\n | \"stat\"\n | \"symlink\"\n | \"truncate\"\n | \"utimes\"\n | \"writeFile\";\n\n// Operations whose node result already crosses into the sandbox unchanged.\ntype FsPassthroughName = Exclude<\n FsOperationName,\n \"lstat\" | \"mkdtemp\" | \"readFile\" | \"readdir\" | \"readlink\" | \"realpath\" | \"stat\"\n>;\n\n// Whether node answers with a Buffer when an encoding is not given: readFile\n// defaults to a Buffer, while readdir, readlink, realpath, and mkdtemp default to\n// utf8 yet still answer with one for a buffer encoding.\nconst BUFFER_BY_DEFAULT = {\n readFile: true,\n readdir: false,\n readlink: false,\n realpath: false,\n mkdtemp: false\n} as const;\n\n// Why each option node declares cannot be honoured here, written once for every\n// operation that declares it.\nconst REFUSED_OPTION_REASONS = {\n signal:\n \"the sandbox has no AbortController, and cancelling a run is the host's to request rather than the script's\",\n // @types/node declares this on fs/promises stat and lstat and types\n // `throwIfNoEntry: false` as answering `Stats | undefined`, but the typings are\n // ahead of node: only the synchronous API reads the option. Forwarding it would\n // leave a script holding the ENOENT rejection the typings told it to expect\n // undefined for, so it is refused rather than dropped.\n throwIfNoEntry:\n \"only node's synchronous stat reads it and fs/promises rejects a missing path whatever it says, so catch the ENOENT rejection instead\",\n // cp's filter is a callback the host would invoke, which a sandbox closure can cross the\n // bridge to serve. It is refused for what happens around the call rather than during it:\n // the digest that identifies a host call across a snapshot is built by stringifying the\n // arguments, and a function does not survive that, so cp(filter: keep) and\n // cp(filter: drop) are one call to the resume machinery.\n filter:\n \"a closure is dropped from the digest that identifies a host call across a snapshot, so a resumed run could reconcile against a copy that took a different set of files, and under a root it would read the rewritten host paths rather than the ones the script wrote \u2014 walk the tree with readdir and copy the entries you want instead\"\n} as const;\n\nconst UNKNOWN_OPTION_REASON =\n \"node declares no such option for it, and an unrecognised option is refused rather than silently ignored\";\n\n// Refused by the root rather than by the module, so it is kept apart from the refusals\n// above: with no root there is no boundary to cross and node's own option is honoured.\n//\n// cp is the one operation that reads a whole tree in a single call, which makes it the one\n// whose src and dest are not the only paths it touches. Those two are canonicalized and\n// proven inside root; a symlink nested inside the tree is never seen. With dereference node\n// copies what such a link points at rather than the link, landing content from outside root\n// inside it under a name every later check reads as contained \u2014 so the option would hand a\n// script the reads the root exists to refuse. Without dereference the link is copied as a\n// link, which stays unreadable, so only this option is refused.\nconst ROOT_REFUSED_DEREFERENCE_REASON =\n \"a root canonicalizes cp's src and dest but never the paths nested inside the tree, so node would copy an escaping link's target inside root where the script could read it \u2014 copy without dereference and a nested link stays a link the root still refuses to read through\";\n\ntype FsOptionSurface = {\n // Which argument node reads the options bag from.\n readonly argument: number;\n readonly honoured: readonly string[];\n readonly refused: readonly (keyof typeof REFUSED_OPTION_REASONS)[];\n};\n\n// Every operation node gives an options bag, the argument it reads the bag from,\n// and each option split into the ones forwarded to node untouched and the ones\n// refused by name. An option node honours and this table omits is refused as\n// unknown, so a silently ignored option is not reachable; the audit in\n// fs.option-surface.test.ts proves the split covers node's own typings, which is\n// what keeps a handle, stream, or watcher option node adds later from passing\n// through unclassified.\n//\n// The operations absent here are the ones node gives no options bag: access,\n// chmod, copyFile, truncate, and utimes read a trailing mode, length, or time\n// that node validates itself, and link, rename, and symlink take paths alone.\n//\n// rmdir carries maxRetries and retryDelay because node validates both (its\n// recursive option is deprecated but still honoured), even though @types/node has\n// already dropped rmdir's options argument for a future node that removes them.\nexport const FS_OPTION_SURFACE: Record<\n | \"appendFile\"\n | \"cp\"\n | \"lstat\"\n | \"mkdir\"\n | \"mkdtemp\"\n | \"readFile\"\n | \"readdir\"\n | \"readlink\"\n | \"realpath\"\n | \"rm\"\n | \"rmdir\"\n | \"stat\"\n | \"writeFile\",\n FsOptionSurface\n> = {\n appendFile: {\n argument: 2,\n honoured: [\"encoding\", \"mode\", \"flag\", \"flush\"],\n // node's appendFile forwards to writeFile, so it honours a signal even though\n // @types/node does not declare one for it.\n refused: [\"signal\"]\n },\n // node reads cp's bag from a parameter it names opts rather than options, and validates\n // every key it knows \u2014 while still ignoring one it does not, which is what the unknown\n // refusal covers. mode is copyFile's flag set rather than a permission.\n cp: {\n argument: 2,\n honoured: [\n \"dereference\",\n \"errorOnExist\",\n \"force\",\n \"mode\",\n \"preserveTimestamps\",\n \"recursive\",\n \"verbatimSymlinks\"\n ],\n refused: [\"filter\"]\n },\n lstat: { argument: 1, honoured: [\"bigint\"], refused: [\"throwIfNoEntry\"] },\n mkdir: { argument: 1, honoured: [\"recursive\", \"mode\"], refused: [] },\n mkdtemp: { argument: 1, honoured: [\"encoding\"], refused: [] },\n readFile: { argument: 1, honoured: [\"encoding\", \"flag\"], refused: [\"signal\"] },\n readdir: { argument: 1, honoured: [\"encoding\", \"withFileTypes\", \"recursive\"], refused: [] },\n readlink: { argument: 1, honoured: [\"encoding\"], refused: [] },\n realpath: { argument: 1, honoured: [\"encoding\"], refused: [] },\n rm: { argument: 1, honoured: [\"force\", \"recursive\", \"maxRetries\", \"retryDelay\"], refused: [] },\n rmdir: { argument: 1, honoured: [\"recursive\", \"maxRetries\", \"retryDelay\"], refused: [] },\n stat: { argument: 1, honoured: [\"bigint\"], refused: [\"throwIfNoEntry\"] },\n writeFile: { argument: 2, honoured: [\"encoding\", \"mode\", \"flag\", \"flush\"], refused: [\"signal\"] }\n};\n\nconst STAT_NUMBER_FIELDS = [\n \"dev\",\n \"mode\",\n \"nlink\",\n \"uid\",\n \"gid\",\n \"rdev\",\n \"blksize\",\n \"ino\",\n \"size\",\n \"blocks\",\n \"atimeMs\",\n \"mtimeMs\",\n \"ctimeMs\",\n \"birthtimeMs\"\n] as const;\n\nconst FILE_TYPE_PREDICATES = [\n \"isFile\",\n \"isDirectory\",\n \"isSymbolicLink\",\n \"isBlockDevice\",\n \"isCharacterDevice\",\n \"isFIFO\",\n \"isSocket\"\n] as const;\n\n// node compares this encoding name case-sensitively; any other casing is an\n// invalid encoding node rejects on its own.\nconst BUFFER_ENCODING = \"buffer\";\n\n// The syscall node blames when each operation fails, read back from node itself:\n// several do not match the fs function name, so they cannot be derived from it.\nconst FS_SYSCALLS = {\n access: \"access\",\n appendFile: \"open\",\n chmod: \"chmod\",\n copyFile: \"copyfile\",\n // node's cp is its own JavaScript layer rather than a syscall wrapper, so it blames the\n // fs function by name: its ERR_FS_CP_* errors carry syscall 'cp'.\n cp: \"cp\",\n link: \"link\",\n lstat: \"lstat\",\n mkdir: \"mkdir\",\n mkdtemp: \"mkdtemp\",\n readFile: \"open\",\n readdir: \"scandir\",\n readlink: \"readlink\",\n realpath: \"realpath\",\n rename: \"rename\",\n rm: \"lstat\",\n rmdir: \"rmdir\",\n stat: \"stat\",\n symlink: \"symlink\",\n truncate: \"open\",\n utimes: \"utime\",\n writeFile: \"open\"\n} as const satisfies Record<FsOperationName, string>;\n\n// The name node blames when an operation's path argument is invalid, read back\n// from node itself: several do not match the fs function name \u2014 readlink blames\n// oldPath and mkdtemp blames prefix. Listed in node's own argument order, so the\n// length also says how many leading arguments are paths, and every one of them is\n// resolved against root and proven inside it.\n//\n// The two-path operations are the ones node reports with a dest field beside path,\n// cp excepted: it raises its own ERR_FS_CP_* errors, which carry a path alone. A\n// root denial for cp still names both paths, which is SafeJS's own shape rather\n// than an imitation of node's \u2014 the denial reports the call that was refused, and\n// node's cp has no error to copy here because it never refuses one for a root.\nconst FS_PATH_ARGUMENTS = {\n access: [\"path\"],\n appendFile: [\"path\"],\n chmod: [\"path\"],\n copyFile: [\"src\", \"dest\"],\n // node blames these by the same names it uses for copyFile's two paths.\n cp: [\"src\", \"dest\"],\n link: [\"existingPath\", \"newPath\"],\n lstat: [\"path\"],\n mkdir: [\"path\"],\n mkdtemp: [\"prefix\"],\n readFile: [\"path\"],\n readdir: [\"path\"],\n readlink: [\"oldPath\"],\n realpath: [\"path\"],\n rename: [\"oldPath\", \"newPath\"],\n rm: [\"path\"],\n rmdir: [\"path\"],\n stat: [\"path\"],\n symlink: [\"target\", \"path\"],\n truncate: [\"path\"],\n utimes: [\"path\"],\n writeFile: [\"path\"]\n} as const satisfies Record<FsOperationName, readonly string[]>;\n\nconst ACCESS_DENIED_CODE = \"EACCES\";\n\nconst INVALID_ARGUMENT_CODE = \"ERR_INVALID_ARG_VALUE\";\n\nconst INVALID_ARGUMENT_TYPE_CODE = \"ERR_INVALID_ARG_TYPE\";\n\nconst NULL_BYTE = \"\\u0000\";\n\n// libuv numbers errno differently per platform, so the errno and message paired\n// with EACCES come from node's own table rather than a hardcoded -13.\nconst [ACCESS_DENIED_ERRNO, ACCESS_DENIED_MESSAGE] = accessDeniedSystemError;\n\nexport type FsImplementation = Pick<typeof nodeFsPromises, FsOperationName>;\n\ntype FsHostOperation = (...args: readonly unknown[]) => unknown;\n\ntype FileTypePredicates = {\n readonly [Name in (typeof FILE_TYPE_PREDICATES)[number]]: () => boolean;\n};\n\nexport type SandboxStats = {\n readonly [Name in (typeof STAT_NUMBER_FIELDS)[number]]: number;\n} & FileTypePredicates;\n\nexport type SandboxDirent = {\n readonly name: string;\n readonly parentPath: string;\n} & FileTypePredicates;\n\ntype StringEncoding = FsBridgeEncoding;\n\ntype EncodingOptions = StringEncoding | { encoding: StringEncoding };\n\ntype ReadFileOptions = StringEncoding | { encoding: StringEncoding; flag?: string };\n\ntype ReaddirOptions = {\n encoding?: StringEncoding;\n recursive?: boolean;\n};\n\ntype StatOptions = {\n bigint?: false;\n};\n\nexport type FsModuleOptions = {\n hostReadMemoryLimit?: number;\n readFileMaxBytes?: number;\n} & (\n | {\n root?: string;\n fs?: FsImplementation;\n adapter?: never;\n cwd?: never;\n signal?: never;\n }\n | {\n adapter: FileSystem;\n root?: string;\n cwd?: string;\n signal?: AbortSignal;\n fs?: never;\n });\n\nexport type FsModule = Pick<FsImplementation, FsPassthroughName> & {\n readFile(path: PathLike, options: ReadFileOptions): Promise<string>;\n readlink(path: PathLike, options?: EncodingOptions): Promise<string>;\n realpath(path: PathLike, options?: EncodingOptions): Promise<string>;\n mkdtemp(prefix: string, options?: EncodingOptions): Promise<string>;\n readdir: {\n (path: PathLike, options: ReaddirOptions & { withFileTypes: true }): Promise<SandboxDirent[]>;\n (\n path: PathLike,\n options?: StringEncoding | (ReaddirOptions & { withFileTypes?: false })\n ): Promise<string[]>;\n };\n stat(path: PathLike, options?: StatOptions): Promise<SandboxStats>;\n lstat(path: PathLike, options?: StatOptions): Promise<SandboxStats>;\n constants: {\n F_OK: number;\n R_OK: number;\n W_OK: number;\n X_OK: number;\n COPYFILE_EXCL: number;\n };\n};\n\n\n\nexport function makeFsModule(options: FsModuleOptions = {}): FsModule & { default: FsModule; promises: FsModule } {\n assertSupportedPlatform();\n const hostReadMemoryLimit = options.hostReadMemoryLimit ?? Infinity;\n const readFileMaxBytes = options.readFileMaxBytes ?? Infinity;\n for (const limit of [hostReadMemoryLimit, readFileMaxBytes]) {\n if (limit !== Infinity && (!Number.isSafeInteger(limit) || limit < 0))\n throw new TypeError(\"Filesystem read limits must be non-negative safe integers or Infinity.\");\n }\n let reservedHostReadMemory = 0;\n\n if (options.fs && \"capabilities\" in options.fs) {\n throw new TypeError(\"Pass safe-fs FileSystem through the adapter option, not fs.\");\n }\n\n if (options.adapter !== undefined && options.fs !== undefined) {\n throw new TypeError(\"fs module accepts either adapter or fs, not both.\");\n }\n\n if (\n options.adapter === undefined &&\n (options.cwd !== undefined || options.signal !== undefined)\n ) {\n throw new TypeError(\"fs module cwd and signal require an adapter.\");\n }\n\n if (\n options.cwd !== undefined &&\n (typeof options.cwd !== \"string\" || !options.cwd.startsWith(\"/\") || options.cwd.includes(\"\\0\"))\n ) {\n throw new TypeError(\"fs module cwd must be an absolute virtual path without null bytes.\");\n }\n\n const implementation: FsImplementation =\n options.adapter === undefined\n ? (options.fs ?? nodeFsPromises)\n : (createFsBridge(options.adapter, {\n codec: fsCodec,\n cwd: options.root === undefined ? options.cwd : undefined,\n signal: options.signal\n }) as unknown as FsImplementation);\n const fs =\n options.root === undefined\n ? implementation\n : makeRootedFs(implementation, options.root, options.adapter, options.cwd, options.signal);\n\n let readFile = bindStringResult(fs, \"readFile\");\n if (options.adapter !== undefined) {\n // Ten bytes per input byte covers the backend result, bridge/codec copies,\n // worst-case hex UTF-16 output and guest admission. A configured host allowance\n // covers simultaneous runs and direct host calls using this module.\n const boundedRead = async (args: readonly unknown[], budget?: Budget): Promise<string> => {\n FS_PATH_ARGUMENTS.readFile.forEach((argument, index) => assertSupportedPath(\"readFile\", argument, args[index]));\n assertSupportedOptions(\"readFile\", args);\n assertNoBufferResult(\"readFile\", args[1]);\n const maxBytes = Math.max(0, Math.floor(Math.min(\n hostReadMemoryLimit / 40,\n readFileMaxBytes,\n (budget?.limits.stringLength ?? Infinity) / 2,\n ((budget?.limits.dataSize ?? Infinity) - (budget?.currentDataSize ?? 0)) / 4\n )));\n const reservation = Number.isFinite(hostReadMemoryLimit) ? maxBytes * 10 : 0;\n const bridge = createFsBridge(options.adapter!, {\n codec: fsCodec,\n cwd: options.root === undefined ? options.cwd : undefined,\n signal: options.signal,\n readFileMaxBytes: Number.isFinite(maxBytes) ? maxBytes : undefined,\n reserveReadFile() {\n if (reservedHostReadMemory + reservation > hostReadMemoryLimit) throw new Error(\"Filesystem read host memory budget exceeded\");\n reservedHostReadMemory += reservation;\n return () => { reservedHostReadMemory -= reservation; };\n }\n });\n const portable = bridge as unknown as FsImplementation;\n const boundedFs = options.root === undefined ? portable\n : makeRootedFs(portable, options.root, options.adapter, options.cwd, options.signal);\n return await invoke(boundedFs, \"readFile\", args) as string;\n };\n // Direct host calls must use the same reservation pool.\n const directRead = declare(\"readFile\", \"re-issue\", (...args: readonly unknown[]) => boundedRead(args)) as FsModule[\"readFile\"];\n declareBudgetedHostOperation(directRead, boundedRead);\n readFile = directRead;\n }\n const module: FsModule = {\n access: bind(fs, \"access\", \"re-issue\"),\n appendFile: bind(fs, \"appendFile\", \"read-side-effect\"),\n chmod: bind(fs, \"chmod\", \"read-side-effect\"),\n copyFile: bind(fs, \"copyFile\", \"read-side-effect\"),\n cp: bind(fs, \"cp\", \"read-side-effect\"),\n link: bind(fs, \"link\", \"read-side-effect\"),\n lstat: bindStat(fs, \"lstat\"),\n mkdir: bind(fs, \"mkdir\", \"read-side-effect\"),\n // Creates a directory, so it cannot be re-issued on resume like the other\n // string-result operations, but its name still crosses as a Buffer for a buffer\n // encoding and so goes through the same guard.\n mkdtemp: bindStringResult(fs, \"mkdtemp\", \"read-side-effect\"),\n readFile,\n readdir: bindReaddir(fs),\n readlink: bindStringResult(fs, \"readlink\"),\n realpath: bindStringResult(fs, \"realpath\"),\n rename: bind(fs, \"rename\", \"read-side-effect\"),\n rm: bind(fs, \"rm\", \"read-side-effect\"),\n rmdir: bind(fs, \"rmdir\", \"read-side-effect\"),\n stat: bindStat(fs, \"stat\"),\n symlink: bind(fs, \"symlink\", \"read-side-effect\"),\n truncate: bind(fs, \"truncate\", \"read-side-effect\"),\n utimes: bind(fs, \"utimes\", \"read-side-effect\"),\n writeFile: bind(fs, \"writeFile\", \"read-side-effect\"),\n constants: {\n F_OK: nodeFsConstants.F_OK,\n R_OK: nodeFsConstants.R_OK,\n W_OK: nodeFsConstants.W_OK,\n X_OK: nodeFsConstants.X_OK,\n COPYFILE_EXCL: nodeFsConstants.COPYFILE_EXCL\n }\n };\n return { ...module, default: module, promises: module };\n}\n\n// The module forwards node's error rather than translating it, which makes node's answer the\n// module's answer and node's answer the platform's. That holds across darwin and linux \u2014 the\n// errno differs, the code and the message do not \u2014 and stops holding on win32: node answers a\n// different code there, a path carries a drive letter root confinement has no rule for, and a\n// symlink needs a privilege a script cannot hold. Rather than half-support it, the module\n// refuses to build there, and refuses it here so an embedder is told before a script runs.\n//\n// Only win32 is named. Every other platform node runs on is POSIX and fails the way the\n// recorded two do, and a platform whose truth nobody has recorded is reported by the\n// conformance suite rather than guessed at by a guard here.\nfunction assertSupportedPlatform(): void {\n if (hostPlatform !== \"win32\") {\n return;\n }\n\n throw new Error(\n \"SafeJS's fs module does not support win32: node's fs answers a different code there (EPERM or UNKNOWN where darwin and linux answer EISDIR or ENOTEMPTY), a path carries a drive letter that root confinement has no rule for, and a symlink needs a privilege a script cannot hold. Run on darwin or linux, or build a host module for the surface you need.\"\n );\n}\n\nfunction bind<Name extends FsOperationName>(\n fs: FsImplementation,\n name: Name,\n policy: PendingHostCallPolicyMode\n): FsImplementation[Name] {\n return declare(name, policy, (...args: readonly unknown[]) =>\n invoke(fs, name, args)\n ) as FsImplementation[Name];\n}\n\nfunction bindStringResult<Name extends \"readFile\" | \"readlink\" | \"realpath\" | \"mkdtemp\">(\n fs: FsImplementation,\n name: Name,\n policy: PendingHostCallPolicyMode = \"re-issue\"\n): FsModule[Name] {\n return declare(name, policy, async (...args: readonly unknown[]) => {\n assertNoBufferResult(name, args[1]);\n return (await invoke(fs, name, args)) as string;\n }) as FsModule[Name];\n}\n\nfunction bindReaddir(fs: FsImplementation): FsModule[\"readdir\"] {\n return declare(\"readdir\", \"re-issue\", async (...args: readonly unknown[]) => {\n assertNoBufferResult(\"readdir\", args[1]);\n const entries = (await invoke(fs, \"readdir\", args)) as ReadonlyArray<string | Dirent>;\n return entries.map((entry) => (typeof entry === \"string\" ? entry : toSandboxDirent(entry)));\n }) as FsModule[\"readdir\"];\n}\n\nfunction bindStat<Name extends \"stat\" | \"lstat\">(fs: FsImplementation, name: Name): FsModule[Name] {\n return declare(name, \"re-issue\", async (...args: readonly unknown[]) => {\n assertNoBigIntResult(name, args[1]);\n return toSandboxStats((await invoke(fs, name, args)) as Stats);\n }) as FsModule[Name];\n}\n\n// Every exported operation is declared here, which makes this the one place that\n// can promise node's argument validation runs first: before an unsupported result\n// is refused, and before a root rewrites the path node would have blamed.\nfunction declare<TOperation extends FsHostOperation>(\n name: FsOperationName,\n policy: PendingHostCallPolicyMode,\n operation: TOperation\n): TOperation {\n // async so a refused argument rejects rather than throwing at the call site:\n // every node:fs/promises function answers with a promise either way.\n const validated = async (...args: readonly unknown[]): Promise<unknown> => {\n FS_PATH_ARGUMENTS[name].forEach((argument, index) =>\n assertSupportedPath(name, argument, args[index])\n );\n assertSupportedOptions(name, args);\n\n return await operation(...args);\n };\n\n Object.defineProperty(validated, \"name\", { value: name });\n declareHostOperation(validated, policy);\n return validated as TOperation;\n}\n\nfunction invoke(fs: FsImplementation, name: FsOperationName, args: readonly unknown[]): unknown {\n return Reflect.apply(fs[name] as (...operationArgs: readonly unknown[]) => unknown, fs, args);\n}\n\n// Wraps every operation so its path arguments resolve against root and are proven\n// to stay inside it. The wrapped operations keep node's own signatures and\n// results, so the bindings above are unaware a root is in play.\n// Share the queue across rooted modules using the same backend, including roots\n// that overlap. External host mutations still require backend-level confinement.\nconst rootedFsOperations = new WeakMap<object, Promise<void>>();\n\nfunction makeRootedFs(\n fs: FsImplementation,\n root: string,\n adapter?: FileSystem,\n cwd?: string,\n signal?: AbortSignal\n): FsImplementation {\n if (root.trim().length === 0) {\n throw new Error(\"fs module root must be a non-empty string.\");\n }\n\n const resolvedRoot = adapter === undefined ? root : resolve(\"/\", root);\n const rooted: Record<string, FsHostOperation> = {};\n const backend = adapter ?? fs;\n\n for (const name of Object.keys(FS_SYSCALLS) as FsOperationName[]) {\n rooted[name] = async (...args: readonly unknown[]) => {\n assertRootCanConfineOptions(name, args);\n const previous = rootedFsOperations.get(backend);\n let release!: () => void;\n const pending = new Promise<void>((resolve) => { release = resolve; });\n rootedFsOperations.set(backend, pending);\n await previous;\n try {\n // Hold the queue through the backend promise, not just path admission:\n // a relative symlink can change targets when another guest renames it.\n return await invoke(\n fs,\n name,\n await resolvePathArguments(fs, resolvedRoot, name, args, adapter, cwd, signal)\n );\n } finally {\n release();\n if (rootedFsOperations.get(backend) === pending) {\n rootedFsOperations.delete(backend);\n }\n }\n };\n }\n\n return rooted as unknown as FsImplementation;\n}\n\n// Refuses the one option a root cannot confine, before any path is resolved so a refused\n// call writes nothing. node reads dereference off its own defaults with a spread and\n// validates it as a boolean, so only `true` asks for the copy that escapes.\nfunction assertRootCanConfineOptions(name: FsOperationName, args: readonly unknown[]): void {\n if (name !== \"cp\") {\n return;\n }\n\n const options = args[FS_OPTION_SURFACE.cp.argument];\n\n if (isObjectLike(options) && (options as { dereference?: unknown }).dereference === true) {\n throw createUnsupportedOptionError(\"cp\", \"dereference\", ROOT_REFUSED_DEREFERENCE_REASON);\n }\n}\n\nasync function resolvePathArguments(\n fs: FsImplementation,\n root: string,\n name: FsOperationName,\n args: readonly unknown[],\n adapter?: FileSystem,\n cwd?: string,\n signal?: AbortSignal\n): Promise<readonly unknown[]> {\n const canonicalRoot = await resolveCanonicalPath(readCanonicalPathFs(fs), resolve(root));\n const base = cwd ?? canonicalRoot;\n const resolved = [...args];\n\n if (name === \"symlink\") {\n // node stores a symlink's target verbatim and resolves a relative target\n // against the link's own directory, so only the link path is rewritten while\n // the target is checked as the link's directory would see it.\n const linkPath = readPath(base, args[1]);\n const targetPath = readPath(dirname(linkPath), args[0]);\n resolved[1] = linkPath;\n if (adapter !== undefined && typeof args[0] === \"string\" && isAbsolute(args[0])) {\n signal?.throwIfAborted();\n if (!isPathWithin(canonicalRoot, targetPath) || !isPathWithin(canonicalRoot, linkPath)) {\n throw createAccessDeniedError(name, targetPath, linkPath);\n }\n throw new FsError(\"ENOTSUP\", {\n syscall: FS_SYSCALLS[name],\n path: targetPath,\n dest: linkPath,\n message:\n \"absolute symlink targets cannot be confined before creation; use a relative target\"\n });\n }\n const parent = await invoke(fs, \"realpath\", [dirname(linkPath)]);\n const checkedTarget = isAbsolute(args[0] as string)\n ? (args[0] as string)\n : `${parent as string}${sep}${args[0] as string}`;\n await assertInsideRoot(fs, canonicalRoot, name, [checkedTarget, linkPath], adapter, signal, [\n targetPath,\n linkPath\n ]);\n return resolved;\n }\n\n const paths = FS_PATH_ARGUMENTS[name].map((_, index) => {\n const path = readPath(base, args[index]);\n resolved[index] = path;\n return path;\n });\n\n await assertInsideRoot(fs, canonicalRoot, name, paths, adapter, signal);\n if (name === \"mkdtemp\") {\n const prefix = args[0] as string;\n const absolutePrefix = isAbsolute(prefix) ? prefix : `${base}${sep}${prefix}`;\n const parent = absolutePrefix.endsWith(sep) ? absolutePrefix : dirname(absolutePrefix);\n await assertInsideRoot(fs, canonicalRoot, name, [parent], adapter, signal, paths);\n resolved[0] = absolutePrefix;\n }\n if (adapter !== undefined && name === \"mkdir\") {\n const options = args[1];\n if (isObjectLike(options) && (options as { recursive?: unknown }).recursive === true) {\n signal?.throwIfAborted();\n try {\n await invoke(fs, \"realpath\", [dirname(canonicalRoot)]);\n } catch (error) {\n signal?.throwIfAborted();\n if (getOwnErrorCode(error) !== \"ENOENT\") throw error;\n throw createAccessDeniedError(name, paths[0]!);\n }\n }\n }\n return resolved;\n}\n\n// paths carries the operation's path arguments in node's order, so a denial names\n// the whole attempted call even when only one of them escapes.\nasync function assertInsideRoot(\n fs: FsImplementation,\n canonicalRoot: string,\n name: FsOperationName,\n paths: readonly string[],\n adapter?: FileSystem,\n signal?: AbortSignal,\n reportedPaths: readonly string[] = paths\n): Promise<void> {\n for (const path of paths) {\n if (await escapesRoot(fs, canonicalRoot, path, adapter, signal)) {\n throw createAccessDeniedError(name, reportedPaths[0]!, reportedPaths[1]);\n }\n }\n}\n\nasync function escapesRoot(\n fs: FsImplementation,\n canonicalRoot: string,\n path: string,\n adapter?: FileSystem,\n signal?: AbortSignal\n): Promise<boolean> {\n const canonicalPath = await resolveCanonicalPath(readCanonicalPathFs(fs), path);\n\n return !(await (adapter === undefined\n ? containsPath(readStat(fs), canonicalRoot, canonicalPath)\n : containsAdapterPath(adapter, canonicalRoot, canonicalPath, signal)));\n}\n\nasync function containsAdapterPath(\n adapter: FileSystem,\n canonicalRoot: string,\n canonicalPath: string,\n signal?: AbortSignal\n): Promise<boolean> {\n signal?.throwIfAborted();\n\n if (isPathWithin(canonicalRoot, canonicalPath)) {\n return true;\n }\n\n const compareEntry = adapter.compareEntry;\n if (compareEntry === undefined) {\n return false;\n }\n\n let current = canonicalPath;\n\n while (true) {\n try {\n const comparison = await awaitEntryComparison(\n () =>\n compareEntry.call(\n adapter,\n canonicalRoot,\n adapter,\n current,\n signal === undefined ? undefined : { signal }\n ),\n signal\n );\n if (comparison === \"same\") {\n return true;\n }\n if (comparison !== \"distinct\" && comparison !== \"unknown\") {\n throw new FsError(\"EIO\", { path: current, message: \"invalid filesystem entry comparison\" });\n }\n } catch (error) {\n signal?.throwIfAborted();\n const code = getOwnErrorCode(error);\n if (code !== \"ENOENT\" && code !== \"ENOTDIR\") {\n throw error;\n }\n }\n\n const parent = dirname(current);\n if (parent === current) {\n return false;\n }\n current = parent;\n }\n}\n\nasync function awaitEntryComparison(\n compare: () => Promise<EntryComparison>,\n signal?: AbortSignal\n): Promise<EntryComparison> {\n signal?.throwIfAborted();\n if (signal === undefined) {\n return compare();\n }\n\n let onAbort!: () => void;\n const aborted = new Promise<never>((_, reject) => {\n onAbort = () => reject(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n try {\n const comparison = await Promise.race([\n aborted,\n Promise.resolve().then(() => {\n signal.throwIfAborted();\n return compare();\n })\n ]);\n signal.throwIfAborted();\n return comparison;\n } finally {\n signal.removeEventListener(\"abort\", onAbort);\n }\n}\n\n// realpath and readlink are handed over as bound calls: the injected implementation\n// may keep them as methods that need their own receiver, and node's overloads widen\n// both results to Buffer, which only the no-encoding calls used here can never\n// return.\nfunction readCanonicalPathFs(fs: FsImplementation): CanonicalPathFs {\n return {\n realpath: async (path) => (await invoke(fs, \"realpath\", [path])) as string,\n readlink: async (path) => (await invoke(fs, \"readlink\", [path])) as string\n };\n}\n\n// Bound for the same reason as realpath above. Only dev and ino are read: they are\n// the filesystem's own answer for which file a path names.\nfunction readStat(fs: FsImplementation): Stat {\n return async (path) => (await invoke(fs, \"stat\", [path])) as Stats;\n}\n\n// node accepts a string, a Buffer, or a URL, and rejects everything else before it\n// touches the filesystem. The module has to raise these itself rather than leave\n// them to the injected implementation: a root rewrites the path first, and an\n// injected implementation is free to validate differently \u2014 memfs reads a\n// NUL-bearing path as a missing file and takes an integer as a descriptor.\nfunction assertSupportedPath(name: FsOperationName, argument: string, value: unknown): void {\n if (typeof value === \"string\") {\n if (value.includes(NULL_BYTE)) {\n throw createNullByteError(argument, value);\n }\n\n return;\n }\n\n const form = readUnsupportedPathForm(value);\n\n throw form === undefined\n ? createInvalidPathTypeError(argument, value)\n : createUnsupportedPathError(name, argument, form);\n}\n\n// The path forms node accepts and the sandbox cannot spell. An integer is not one\n// of them: fs/promises has no descriptor path form, so node blames an integer's\n// type like any other non-string and so does the module.\nfunction readUnsupportedPathForm(value: unknown): string | undefined {\n if (value instanceof Uint8Array) {\n return \"a Buffer or Uint8Array\";\n }\n\n return value instanceof URL ? \"a URL\" : undefined;\n}\n\n// Shaped exactly like node's own ERR_INVALID_ARG_VALUE for a NUL-bearing path,\n// down to inspecting the offending value the way node does.\nfunction createNullByteError(argument: string, value: string): TypeError {\n const error: SystemError = new TypeError(\n `The argument '${argument}' must be a string, Uint8Array, or URL without null bytes. Received ${inspect(value)}`\n );\n\n error.code = INVALID_ARGUMENT_CODE;\n return error;\n}\n\n// Shaped exactly like node's own ERR_INVALID_ARG_TYPE for a path it cannot read.\nfunction createInvalidPathTypeError(argument: string, value: unknown): TypeError {\n const error: SystemError = new TypeError(\n `The \"${argument}\" argument must be of type string or an instance of Buffer or URL. Received ${describeReceivedValue(value)}`\n );\n\n error.code = INVALID_ARGUMENT_TYPE_CODE;\n return error;\n}\n\nfunction createUnsupportedPathError(\n name: FsOperationName,\n argument: string,\n form: string\n): TypeError {\n return new TypeError(\n `fs.${name} cannot accept ${form} as the '${argument}' argument inside SafeJS; pass the path as a string.`\n );\n}\n\n// Ports node's own determineSpecificType (lib/internal/errors.js), which shapes the\n// \"Received ...\" tail of every ERR_INVALID_ARG_TYPE message. node spells out each\n// primitive case by hand; inspect already answers with the same text for all of\n// them, down to -0, NaN, and a bigint's n suffix.\nfunction describeReceivedValue(value: unknown): string {\n if (value === null || value === undefined) {\n return String(value);\n }\n\n if (typeof value === \"function\") {\n return `function ${value.name}`;\n }\n\n if (typeof value === \"object\") {\n const constructorName = value.constructor?.name;\n\n return constructorName === undefined\n ? inspect(value, { depth: -1 })\n : `an instance of ${constructorName}`;\n }\n\n return `type ${typeof value} (${inspect(value)})`;\n}\n\n// Every path argument reaches this already proven to be a NUL-free string: each\n// operation is validated as it is declared, before a root gets to rewrite it.\nfunction readPath(base: string, value: unknown): string {\n const path = value as string;\n\n return isAbsolute(path) ? resolve(path) : resolve(base, path);\n}\n\n// Shaped exactly like the system error node raises for a refused path, so a\n// script's `error.code` branch reads the same against SafeJS and against node.\nfunction createAccessDeniedError(\n name: FsOperationName,\n path: string,\n dest?: string\n): SystemError {\n const syscall = FS_SYSCALLS[name];\n const target = dest === undefined ? `'${path}'` : `'${path}' -> '${dest}'`;\n const error: SystemError & { dest?: string } = new Error(\n `${ACCESS_DENIED_CODE}: ${ACCESS_DENIED_MESSAGE}, ${syscall} ${target}`\n );\n\n error.code = ACCESS_DENIED_CODE;\n error.errno = ACCESS_DENIED_ERRNO;\n error.syscall = syscall;\n error.path = path;\n\n if (dest !== undefined) {\n error.dest = dest;\n }\n\n return error;\n}\n\n// node ignores an option key it does not know, which leaves a script unable to tell\n// an option it honoured from one it dropped. Every key is answered for here: refused\n// by name with the reason, or proven to be one node forwards.\nfunction assertSupportedOptions(name: FsOperationName, args: readonly unknown[]): void {\n // Widened to every operation for the lookup: the table only holds the ones node\n // gives an options bag.\n const surface: FsOptionSurface | undefined = (\n FS_OPTION_SURFACE as Partial<Record<FsOperationName, FsOptionSurface>>\n )[name];\n\n // An operation with no options bag, or an options argument node reads as an\n // encoding or a mode rather than a bag: node validates the value itself.\n if (surface === undefined || !isObjectLike(args[surface.argument])) {\n return;\n }\n\n const options = args[surface.argument] as object;\n\n // `in` rather than an enumeration: node reads an option by name, so a refused one\n // counts however it is spelled \u2014 own or inherited, enumerable or not. An\n // enumeration would answer for the keys a script wrote and miss the ones node\n // would still honour, which is the one way a refusal here could be bypassed.\n for (const option of surface.refused) {\n if (option in options) {\n throw createUnsupportedOptionError(name, option, REFUSED_OPTION_REASONS[option]);\n }\n }\n\n // Unknown keys are the ones node cannot be asked about, so they are enumerated\n // instead: for...in reads the own and inherited enumerable keys a script can\n // plausibly have written, which is where a typo for an option node does declare\n // shows up. Walking every own key of the whole chain would reach Object.prototype\n // and refuse `toString` on every options bag.\n for (const option in options) {\n if (!surface.honoured.includes(option)) {\n throw createUnsupportedOptionError(name, option, UNKNOWN_OPTION_REASON);\n }\n }\n}\n\nfunction assertNoBufferResult(operation: keyof typeof BUFFER_BY_DEFAULT, options: unknown): void {\n if (readsBuffer(options, BUFFER_BY_DEFAULT[operation])) {\n throw createUnsupportedCapabilityError(\n operation,\n \"return a Buffer\",\n 'pass a string encoding such as \"utf8\"'\n );\n }\n}\n\nfunction assertNoBigIntResult(operation: FsOperationName, options: unknown): void {\n if (isObjectLike(options) && (options as { bigint?: unknown }).bigint === true) {\n throw createUnsupportedCapabilityError(\n operation,\n \"return BigInt fields\",\n \"omit bigint and read the *Ms timestamps instead\"\n );\n }\n}\n\nfunction createUnsupportedOptionError(\n operation: FsOperationName,\n option: string,\n reason: string\n): TypeError {\n return createUnsupportedCapabilityError(operation, `honour the '${option}' option`, reason);\n}\n\n// The one shape every capability SafeJS cannot offer is refused with, so a script\n// reads the same sentence whichever option, encoding, or field it reached for.\nfunction createUnsupportedCapabilityError(\n operation: FsOperationName,\n capability: string,\n remedy: string\n): TypeError {\n return new TypeError(`fs.${operation} cannot ${capability} inside SafeJS; ${remedy}.`);\n}\n\n// Only reports the shapes node answers with a Buffer. Anything else \u2014 including\n// an unknown encoding or a malformed options argument \u2014 passes through so node's\n// own error surfaces instead of a SafeJS one.\nfunction readsBuffer(options: unknown, bufferByDefault: boolean): boolean {\n if (typeof options === \"string\") {\n return options === BUFFER_ENCODING;\n }\n\n if (options === undefined || options === null) {\n return bufferByDefault;\n }\n\n // node reads the encoding off anything it can hold a property on, so an array or\n // a function is an options object answering with a Buffer rather than a shape\n // node rejects. Everything else is left to node's own ERR_INVALID_ARG_TYPE.\n if (!isObjectLike(options)) {\n return false;\n }\n\n const { encoding } = options as { encoding?: unknown };\n\n if (encoding === BUFFER_ENCODING) {\n return true;\n }\n\n return (encoding === undefined || encoding === null) && bufferByDefault;\n}\n\nfunction toSandboxStats(stats: Stats): SandboxStats {\n const numbers: Record<string, number> = {};\n\n for (const field of STAT_NUMBER_FIELDS) {\n numbers[field] = stats[field];\n }\n\n return { ...numbers, ...toFileTypePredicates(stats) } as SandboxStats;\n}\n\nfunction toSandboxDirent(dirent: Dirent): SandboxDirent {\n return {\n name: dirent.name,\n parentPath: dirent.parentPath,\n ...toFileTypePredicates(dirent)\n };\n}\n\n// node's predicates read a mode the host object already resolved, so the answers\n// are captured here rather than keeping the host object alive behind a closure.\nfunction toFileTypePredicates(source: Stats | Dirent): FileTypePredicates {\n const predicates: Record<string, () => boolean> = {};\n\n for (const predicate of FILE_TYPE_PREDICATES) {\n const result = source[predicate]();\n predicates[predicate] = () => result;\n }\n\n return predicates as FileTypePredicates;\n}\n\nfunction isObjectLike(value: unknown): boolean {\n return (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n", "import { basename, dirname, isAbsolute, relative, resolve, sep } from \"./paths.js\";\n\nimport { getOwnErrorCode, type SystemError } from \"../error-codes.js\";\n\n// realpath answers ENOENT for a missing segment and ENOTDIR when a parent is a\n// file. Both mean the segment is not an existing directory, so both walk up.\nconst MISSING_PATH_CODES: readonly string[] = [\"ENOENT\", \"ENOTDIR\"];\n\n// What the filesystem answers for a path that has no link target to follow: EINVAL\n// for a path that exists and is not a link, and the missing-path codes for one that\n// is not there at all. Any other failure is the filesystem's own and is left to\n// surface rather than read as \"not a link\", which would canonicalize a link the\n// filesystem merely refused to read as though it named itself.\nconst NOT_A_SYMLINK_CODES: readonly string[] = [...MISSING_PATH_CODES, \"EINVAL\"];\n\n// A conforming realpath raises ELOOP for a cycle before the walk below can follow\n// one, so this cap is only reached by a filesystem that reports a cycle as a\n// missing path. Following one of those forever would hang the sandbox, so the walk\n// gives up the way the platform does \u2014 at SYMLOOP_MAX, which is 32 on darwin and\n// Linux alike.\nconst MAX_SYMLINK_FOLLOWS = 32;\n\ntype Realpath = (path: string) => Promise<string>;\n\n// A symlink's target exactly as stored, which is how node keeps it: relative\n// targets stay relative and resolve against the link's own directory.\ntype Readlink = (path: string) => Promise<string>;\n\n// The filesystem operations canonicalization needs: what a path resolves to, and\n// what a link it could not resolve names. Named as a whole because both are read\n// together, off the same filesystem, to canonicalize one path.\nexport type CanonicalPathFs = { realpath: Realpath; readlink: Readlink };\n\n// Which file a path names, as the filesystem itself answers it.\ntype PathIdentity = { dev: number; ino: number };\n\nexport type Stat = (path: string) => Promise<PathIdentity>;\n\n// Canonicalizes as much of the path as exists and re-appends the segments that do\n// not, so a path is checked after symlinks are followed rather than as written.\n// The missing segments go back through resolve(), which collapses any `..` among\n// them, so they cannot re-escape what realpath already pinned down.\n//\n// A dangling symlink is the case this cannot read off realpath alone: realpath\n// refuses one with the same ENOENT it gives a path that was never there, yet the two\n// are not the same place. node follows a dangling link and acts on its target \u2014 a\n// write through one creates the target \u2014 so a dangling link canonicalizes to what it\n// names, not to itself. Reading that ENOENT as \"nothing here\" would answer with the\n// link's own path and call a link out of a caller's root contained.\nexport async function resolveCanonicalPath(\n { realpath, readlink }: CanonicalPathFs,\n path: string\n): Promise<string> {\n const missingSegments: string[] = [];\n let current = path;\n let follows = 0;\n\n while (true) {\n try {\n const canonicalCurrent = await realpath(current);\n return resolve(canonicalCurrent, ...missingSegments.reverse());\n } catch (error) {\n if (!MISSING_PATH_CODES.includes(getOwnErrorCode(error) ?? \"\")) {\n throw error;\n }\n\n const target = await readSymlinkTarget(readlink, current);\n\n if (target !== undefined) {\n if (++follows > MAX_SYMLINK_FOLLOWS) {\n throw createLoopError(path);\n }\n\n // node resolves a relative target against the link's own directory. Any\n // segments already collected still hang off whatever the target resolves to,\n // so they stay on the list.\n current = isAbsolute(target) ? target : `${dirname(current)}${sep}${target}`;\n continue;\n }\n\n const parent = dirname(current);\n\n if (parent === current) {\n return resolve(path);\n }\n\n missingSegments.push(basename(current));\n current = parent;\n }\n }\n}\n\n// The target of a link realpath could not resolve, or undefined when the path is not\n// a link at all and the walk should climb past it instead.\nasync function readSymlinkTarget(readlink: Readlink, path: string): Promise<string | undefined> {\n try {\n return await readlink(path);\n } catch (error) {\n if (NOT_A_SYMLINK_CODES.includes(getOwnErrorCode(error) ?? \"\")) {\n return undefined;\n }\n\n throw error;\n }\n}\n\n// Shaped like the ELOOP a filesystem raises for a cycle it walked itself, so a\n// caller that branches on the code reads the cap and the filesystem's own answer the\n// same way.\nfunction createLoopError(path: string): SystemError {\n const error: SystemError = new Error(\n `ELOOP: too many symbolic links encountered, realpath '${path}'`\n );\n\n error.code = \"ELOOP\";\n return error;\n}\n\n// Whether root contains path, root itself included. Both arguments must already be\n// canonical: a `..` or a symlink left in either one would make the comparison lie.\n//\n// The rule: the filesystem has the deciding vote on containment, and comparing\n// the canonical spellings is only a fast path that is trusted when it answers\n// \"contained\". Two canonical paths can differ in spelling and still be the same\n// place \u2014 on a case-insensitive filesystem (darwin's default) `/repo` and `/REPO`\n// are one directory, and darwin's realpath echoes the spelling it was handed\n// rather than the on-disk one, so canonicalization does not fold the case away.\n// Comparing spellings can therefore only ever be wrong in one direction: it may\n// answer \"outside\" for a path that resolves inside root, never the reverse. So\n// \"outside\" is re-decided by walking the path's ancestors and asking the\n// filesystem for each one's identity, which no spelling can lie about. Folding\n// case here instead would be a hole: on a case-sensitive filesystem `/REPO/x` is\n// genuinely a different file from `/repo/x`.\nexport async function containsPath(\n stat: Stat,\n canonicalRoot: string,\n canonicalPath: string\n): Promise<boolean> {\n if (containsCanonicalSpelling(canonicalRoot, canonicalPath)) {\n return true;\n }\n\n return descendsFromRoot(stat, canonicalRoot, canonicalPath);\n}\n\n// Whether two canonical paths name the same place. Two spellings can name one\n// place on a case-insensitive filesystem, so identity decides here for the same\n// reason it decides containment above.\nexport async function isSamePath(\n stat: Stat,\n canonicalLeft: string,\n canonicalRight: string\n): Promise<boolean> {\n if (canonicalLeft === canonicalRight) {\n return true;\n }\n\n const [left, right] = await Promise.all([\n readIdentity(stat, canonicalLeft),\n readIdentity(stat, canonicalRight)\n ]);\n\n return (\n left !== undefined && right !== undefined && left.dev === right.dev && left.ino === right.ino\n );\n}\n\nfunction containsCanonicalSpelling(canonicalRoot: string, canonicalPath: string): boolean {\n const relativePath = relative(canonicalRoot, canonicalPath);\n\n // An empty relative path is root itself, which the root contains.\n return !(\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath)\n );\n}\n\n// Climbs the path's ancestors looking for root's own identity. A canonical path\n// carries no symlinks and no `..`, so every ancestor it names is a real ancestor:\n// finding root among them means the path descends from root whatever either one\n// is spelled like.\nasync function descendsFromRoot(\n stat: Stat,\n canonicalRoot: string,\n canonicalPath: string\n): Promise<boolean> {\n const root = await readIdentity(stat, canonicalRoot);\n\n if (root === undefined) {\n return false;\n }\n\n let current = canonicalPath;\n\n while (true) {\n const identity = await readIdentity(stat, current);\n\n if (identity !== undefined && identity.dev === root.dev && identity.ino === root.ino) {\n return true;\n }\n\n const parent = dirname(current);\n\n if (parent === current) {\n return false;\n }\n\n current = parent;\n }\n}\n\n// A path that is not there has no identity to match, so the walk climbs past it\n// rather than treating it as an answer. Any other failure is the filesystem's own\n// and is left to surface: swallowing it would report a refusal for what node\n// blames on something else.\nasync function readIdentity(stat: Stat, path: string): Promise<PathIdentity | undefined> {\n try {\n const { dev, ino } = await stat(path);\n return { dev, ino };\n } catch (error) {\n if (MISSING_PATH_CODES.includes(getOwnErrorCode(error) ?? \"\")) {\n return undefined;\n }\n\n throw error;\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["resolve"]
7
+ }
@@ -8,7 +8,7 @@ import {
8
8
  numericTypedArrayConstructors,
9
9
  parseModule,
10
10
  tokenize
11
- } from "./chunk-QKO4FATZ.js";
11
+ } from "./chunk-VQGYRKM4.js";
12
12
 
13
13
  // packages/safe-js/src/lint/rules/AS001.ts
14
14
  function AS001(source, options = {}) {
@@ -11177,4 +11177,4 @@ function hasOnlyRegexLiteralDiagnostics(diagnostics) {
11177
11177
  export {
11178
11178
  lint
11179
11179
  };
11180
- //# sourceMappingURL=chunk-RULU2F5J.js.map
11180
+ //# sourceMappingURL=chunk-762WTEEI.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isSandboxClosure
3
- } from "./chunk-MDIWQFYU.js";
3
+ } from "./chunk-SBFOCNNW.js";
4
4
 
5
5
  // packages/safe-js/src/lint/runtime-modules.ts
6
6
  var AsyncFunction = (async () => void 0).constructor;
@@ -34,4 +34,4 @@ function isAsyncRuntimeExport(value) {
34
34
  export {
35
35
  createLintModulesFromRuntimeRegistry
36
36
  };
37
- //# sourceMappingURL=chunk-E4XLBT7R.js.map
37
+ //# sourceMappingURL=chunk-7AHNAUR5.js.map
@@ -10,7 +10,7 @@ import {
10
10
  validateMigrationReconciliation,
11
11
  validateMigrationSemantics,
12
12
  validateSnapshotMigration
13
- } from "./chunk-PSVV3IG2.js";
13
+ } from "./chunk-IKRAX7Z5.js";
14
14
  import {
15
15
  DUMP_FORMAT_VERSION,
16
16
  EXECUTION_SEMANTICS,
@@ -20,10 +20,10 @@ import {
20
20
  serializeSafeJSSnapshot,
21
21
  validateDumpEnvelope,
22
22
  validateSnapshotData
23
- } from "./chunk-MDIWQFYU.js";
23
+ } from "./chunk-SBFOCNNW.js";
24
24
  import {
25
25
  parseModule
26
- } from "./chunk-QKO4FATZ.js";
26
+ } from "./chunk-VQGYRKM4.js";
27
27
  import {
28
28
  paths_default
29
29
  } from "./chunk-YUQFFRUF.js";
@@ -215,4 +215,4 @@ export {
215
215
  migrateSnapshot,
216
216
  migrateSnapshotFile
217
217
  };
218
- //# sourceMappingURL=chunk-W4SWUHCQ.js.map
218
+ //# sourceMappingURL=chunk-FUUG7UIZ.js.map
@@ -2,14 +2,14 @@ import {
2
2
  HostCallJournal,
3
3
  decodeReplayData,
4
4
  validateSnapshotData
5
- } from "./chunk-MDIWQFYU.js";
5
+ } from "./chunk-SBFOCNNW.js";
6
6
  import {
7
7
  CompileScope,
8
8
  SandboxError,
9
9
  functionSources,
10
10
  parse,
11
11
  parseModule
12
- } from "./chunk-QKO4FATZ.js";
12
+ } from "./chunk-VQGYRKM4.js";
13
13
 
14
14
  // packages/safe-js/src/parse/hash.ts
15
15
  var FNV_OFFSET_BASIS = 2166136261;
@@ -219,4 +219,4 @@ export {
219
219
  validateMigrationReconciliation,
220
220
  validateSnapshotMigration
221
221
  };
222
- //# sourceMappingURL=chunk-PSVV3IG2.js.map
222
+ //# sourceMappingURL=chunk-IKRAX7Z5.js.map
@@ -7,15 +7,15 @@ import {
7
7
  } from "./chunk-2GVBG23M.js";
8
8
  import {
9
9
  restore
10
- } from "./chunk-O4IDRXW7.js";
10
+ } from "./chunk-WDEOWDLS.js";
11
11
  import {
12
12
  hashParsedAst,
13
13
  hashSource
14
- } from "./chunk-PSVV3IG2.js";
14
+ } from "./chunk-IKRAX7Z5.js";
15
15
  import {
16
16
  attachDumpController,
17
17
  createDumpController
18
- } from "./chunk-X3CKAZQ4.js";
18
+ } from "./chunk-33AKDRQ4.js";
19
19
  import {
20
20
  DUMP_FORMAT_VERSION,
21
21
  EXECUTION_SEMANTICS,
@@ -93,6 +93,7 @@ import {
93
93
  runAsyncPrefix,
94
94
  runResources,
95
95
  sandboxGetProperty,
96
+ schedulesHostCallbacks,
96
97
  serializeSafeJSSnapshot,
97
98
  setSandboxPrototype,
98
99
  suspendJob,
@@ -102,7 +103,7 @@ import {
102
103
  withSandboxPromiseRejectionTracker,
103
104
  wrapCallerInjectedBindings,
104
105
  wrapCancelableBindings
105
- } from "./chunk-MDIWQFYU.js";
106
+ } from "./chunk-SBFOCNNW.js";
106
107
  import {
107
108
  Budget,
108
109
  CompileScope,
@@ -117,7 +118,7 @@ import {
117
118
  parseSourceModule,
118
119
  replaceErrorStack,
119
120
  safeAddEvent
120
- } from "./chunk-QKO4FATZ.js";
121
+ } from "./chunk-VQGYRKM4.js";
121
122
  import {
122
123
  dirname
123
124
  } from "./chunk-YUQFFRUF.js";
@@ -752,6 +753,8 @@ var RealmState = class {
752
753
  pendingWork = /* @__PURE__ */ new Set();
753
754
  releaseReconciliation;
754
755
  callbackCache = /* @__PURE__ */ new WeakMap();
756
+ queuedCallbackCache = /* @__PURE__ */ new WeakMap();
757
+ queuedCallbacks = /* @__PURE__ */ new WeakSet();
755
758
  hostObjects = /* @__PURE__ */ new Set();
756
759
  guestReferences = /* @__PURE__ */ new Map();
757
760
  retainedOperations = /* @__PURE__ */ new WeakMap();
@@ -789,6 +792,7 @@ var RealmState = class {
789
792
  return nativeRetainedArrayPrototype(roots, retainedArrayPrototype);
790
793
  };
791
794
  captureArguments = (operation, args, copy) => {
795
+ const queued = schedulesHostCallbacks(operation);
792
796
  const from = this.retainedOperations.get(operation)?.from ?? args.length;
793
797
  const owned = this.callbackOperations.has(operation) ? /* @__PURE__ */ new Map() : void 0;
794
798
  const captured = [];
@@ -803,10 +807,10 @@ var RealmState = class {
803
807
  }
804
808
  };
805
809
  try {
806
- const values = copy(args.slice(0, from), owned === void 0 ? void 0 : (closure) => {
810
+ const values = copy(args.slice(0, from), owned === void 0 ? queued ? (closure) => this.wrapCallback(closure, false, true) : void 0 : (closure) => {
807
811
  let callback = owned.get(closure);
808
812
  if (callback === void 0) {
809
- callback = this.wrapCallback(closure, true);
813
+ callback = this.wrapCallback(closure, true, queued);
810
814
  owned.set(closure, callback);
811
815
  }
812
816
  return callback;
@@ -1071,9 +1075,10 @@ var RealmState = class {
1071
1075
  }
1072
1076
  return object;
1073
1077
  };
1074
- wrapCallback = (closure, owned = false) => {
1078
+ wrapCallback = (closure, owned = false, queued = false) => {
1075
1079
  this.assertOpen();
1076
- const existing = owned ? void 0 : this.callbackCache.get(closure);
1080
+ const cache = queued ? this.queuedCallbackCache : this.callbackCache;
1081
+ const existing = owned ? void 0 : cache.get(closure);
1077
1082
  if (existing !== void 0 && this.callbacks.has(existing)) return existing;
1078
1083
  this.checkCollection(this.callbacks.size + 1, this.limits.callbacks, "callback");
1079
1084
  const invokeCallback = this.invokeCallback;
@@ -1081,7 +1086,8 @@ var RealmState = class {
1081
1086
  return invokeCallback(callback, { args, thisValue: this });
1082
1087
  };
1083
1088
  this.callbacks.set(callback, closure);
1084
- if (!owned) this.callbackCache.set(closure, callback);
1089
+ if (!owned) cache.set(closure, callback);
1090
+ if (queued) this.queuedCallbacks.add(callback);
1085
1091
  registerGuestCallback(callback, {
1086
1092
  owner: this,
1087
1093
  closure,
@@ -1139,6 +1145,10 @@ var RealmState = class {
1139
1145
  if (scheduled) this.releaseReconciliation ??= this.budget.deferReconciliation();
1140
1146
  const rejectionOwner = scheduled ? this.tracker.startOperation() : void 0;
1141
1147
  const invoke = async () => {
1148
+ if (this.queuedCallbacks.has(callback)) {
1149
+ this.options.signal?.throwIfAborted();
1150
+ this.controller.signal.throwIfAborted();
1151
+ }
1142
1152
  this.assertOpen();
1143
1153
  readGuestCallback(callback, this);
1144
1154
  const leave = enterRunningState(closure);
@@ -1187,7 +1197,7 @@ var RealmState = class {
1187
1197
  this.resources,
1188
1198
  () => withCancellationSignal(
1189
1199
  this.controller.signal,
1190
- () => active && this.phase.getStore()?.active ? runAsyncPrefix(invoke, completeSynchronous === void 0 && this.phase.getStore()?.extension !== void 0) : this.queue.run(invoke)
1200
+ () => !this.queuedCallbacks.has(callback) && active && this.phase.getStore()?.active ? runAsyncPrefix(invoke, completeSynchronous === void 0 && this.phase.getStore()?.extension !== void 0) : this.queue.run(invoke)
1191
1201
  )
1192
1202
  )
1193
1203
  )
@@ -2829,4 +2839,4 @@ export {
2829
2839
  UnhandledRejectionError,
2830
2840
  run
2831
2841
  };
2832
- //# sourceMappingURL=chunk-GNEORAQI.js.map
2842
+ //# sourceMappingURL=chunk-LELXBLG2.js.map