@poe-platform/safe-js 0.1.730 → 0.1.732
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/safe-js/chunks/{chunk-SJZWSPWD.js → chunk-2GVBG23M.js} +1 -1
- package/dist/safe-js/chunks/{chunk-SJZWSPWD.js.map → chunk-2GVBG23M.js.map} +1 -1
- package/dist/safe-js/chunks/{chunk-MW2QLYVN.js → chunk-3ITVV2R6.js} +77 -66
- package/dist/safe-js/chunks/chunk-3ITVV2R6.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-VIMROAQA.js → chunk-E4XLBT7R.js} +2 -2
- package/dist/safe-js/chunks/chunk-F6CV74HU.js +114 -0
- package/dist/safe-js/chunks/chunk-F6CV74HU.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-OZLTLIHX.js → chunk-G6WTEIJJ.js} +2 -2
- package/dist/safe-js/chunks/{chunk-XX57YCGZ.js → chunk-GNEORAQI.js} +55 -50
- package/dist/safe-js/chunks/chunk-GNEORAQI.js.map +7 -0
- package/dist/safe-js/chunks/chunk-GVKXZW53.js +76 -0
- package/dist/safe-js/chunks/chunk-GVKXZW53.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-MRULOD5J.js → chunk-K4T4EBED.js} +59 -38
- package/dist/safe-js/chunks/chunk-K4T4EBED.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-MFCEBCGV.js → chunk-KETIFEA7.js} +17 -8
- package/dist/safe-js/chunks/chunk-KETIFEA7.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-S5YDMMM3.js → chunk-MDIWQFYU.js} +95 -169
- package/dist/safe-js/chunks/{chunk-S5YDMMM3.js.map → chunk-MDIWQFYU.js.map} +4 -4
- package/dist/safe-js/chunks/{chunk-EN724VH3.js → chunk-O4IDRXW7.js} +4 -4
- package/dist/safe-js/chunks/{chunk-3LSNBW5N.js → chunk-P64CQIUA.js} +4 -4
- package/dist/safe-js/chunks/{chunk-EA7AHM2X.js → chunk-PSVV3IG2.js} +3 -3
- package/dist/safe-js/chunks/{chunk-Y5EZYHU6.js → chunk-QKO4FATZ.js} +33 -5
- package/dist/safe-js/chunks/chunk-QKO4FATZ.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-EG3QWREA.js → chunk-RULU2F5J.js} +2 -2
- package/dist/safe-js/chunks/chunk-UQPYTZOZ.js +72 -0
- package/dist/safe-js/chunks/chunk-UQPYTZOZ.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-LRSWTDIV.js → chunk-W4SWUHCQ.js} +58 -23
- package/dist/safe-js/chunks/chunk-W4SWUHCQ.js.map +7 -0
- package/dist/safe-js/chunks/{chunk-W3IY6FKO.js → chunk-WS2FJBH6.js} +2 -2
- package/dist/safe-js/chunks/{chunk-MVLDRXWS.js → chunk-X3CKAZQ4.js} +3 -3
- package/dist/safe-js/chunks/chunk-YUQFFRUF.js +26 -0
- package/dist/safe-js/chunks/chunk-YUQFFRUF.js.map +7 -0
- package/dist/safe-js/chunks/{cli-runtime-WSVW5DNT.js → cli-runtime-ZSOTNIVC.js} +51 -30
- package/dist/safe-js/chunks/cli-runtime-ZSOTNIVC.js.map +7 -0
- package/dist/safe-js/chunks/{dump-UNYK24YS.js → dump-RGRC3CG3.js} +5 -4
- package/dist/safe-js/chunks/harness-UMOMFXDT.js +11 -0
- package/dist/safe-js/chunks/mcp-2Z4XWHKW.js +12 -0
- package/dist/safe-js/chunks/migration-file-KRXQYI3Q.js +15 -0
- package/dist/safe-js/chunks/restore-GEO7VN2R.js +14 -0
- package/dist/safe-js/chunks/run-ZSFX66RN.js +20 -0
- package/dist/safe-js/chunks/runtime-modules-A3U2DKFL.js +11 -0
- package/dist/safe-js/chunks/source-files-L3SGK63Z.js +10 -0
- package/dist/safe-js/cli-runtime.d.ts +2 -0
- package/dist/safe-js/cli.js +4 -4
- package/dist/safe-js/core.d.ts +1 -0
- package/dist/safe-js/core.js +15 -8
- package/dist/safe-js/error/shape.js +170 -0
- package/dist/safe-js/index.js +42 -33
- package/dist/safe-js/index.js.map +2 -2
- package/dist/safe-js/interp/budget.js +600 -0
- package/dist/safe-js/interp/internal-symbols.js +1 -0
- package/dist/safe-js/interp/promise-replay.d.ts +1 -1
- package/dist/safe-js/interp/template-cache.js +7 -0
- package/dist/safe-js/migration-file.d.ts +2 -0
- package/dist/safe-js/modules/fs-config.d.ts +3 -1
- package/dist/safe-js/modules/fs.d.ts +8 -4
- package/dist/safe-js/modules/fs.js +16 -0
- package/dist/safe-js/modules/source-files.d.ts +3 -2
- package/dist/safe-js/platform/context.js +58 -0
- package/dist/safe-js/platform/node.js +64 -0
- package/dist/safe-js/platform/types.js +63 -0
- package/dist/safe-js/platform/workerd.js +39 -0
- package/dist/safe-js/runner/run-harness.d.ts +2 -0
- package/dist/safe-js/snapshot/backend.d.ts +2 -0
- package/package.json +9 -2
- package/dist/safe-js/chunks/chunk-FCCA27RC.js +0 -69
- package/dist/safe-js/chunks/chunk-FCCA27RC.js.map +0 -7
- package/dist/safe-js/chunks/chunk-LRSWTDIV.js.map +0 -7
- package/dist/safe-js/chunks/chunk-MFCEBCGV.js.map +0 -7
- package/dist/safe-js/chunks/chunk-MRULOD5J.js.map +0 -7
- package/dist/safe-js/chunks/chunk-MW2QLYVN.js.map +0 -7
- package/dist/safe-js/chunks/chunk-XX57YCGZ.js.map +0 -7
- package/dist/safe-js/chunks/chunk-Y5EZYHU6.js.map +0 -7
- package/dist/safe-js/chunks/cli-runtime-WSVW5DNT.js.map +0 -7
- package/dist/safe-js/chunks/fs-AOV77RQC.js +0 -13
- package/dist/safe-js/chunks/harness-ZIEO7NAV.js +0 -10
- package/dist/safe-js/chunks/mcp-E2AJXEQM.js +0 -11
- package/dist/safe-js/chunks/migration-file-3SWGNDS2.js +0 -12
- package/dist/safe-js/chunks/restore-FCTWPLU3.js +0 -13
- package/dist/safe-js/chunks/run-ESJHEXCE.js +0 -17
- package/dist/safe-js/chunks/runtime-modules-7V6BWCRK.js +0 -10
- package/dist/safe-js/chunks/source-files-73OHLNGH.js +0 -8
- /package/dist/safe-js/chunks/{chunk-VIMROAQA.js.map → chunk-E4XLBT7R.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-OZLTLIHX.js.map → chunk-G6WTEIJJ.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-EN724VH3.js.map → chunk-O4IDRXW7.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-3LSNBW5N.js.map → chunk-P64CQIUA.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-EA7AHM2X.js.map → chunk-PSVV3IG2.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-EG3QWREA.js.map → chunk-RULU2F5J.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-W3IY6FKO.js.map → chunk-WS2FJBH6.js.map} +0 -0
- /package/dist/safe-js/chunks/{chunk-MVLDRXWS.js.map → chunk-X3CKAZQ4.js.map} +0 -0
- /package/dist/safe-js/chunks/{dump-UNYK24YS.js.map → dump-RGRC3CG3.js.map} +0 -0
- /package/dist/safe-js/chunks/{fs-AOV77RQC.js.map → harness-UMOMFXDT.js.map} +0 -0
- /package/dist/safe-js/chunks/{harness-ZIEO7NAV.js.map → mcp-2Z4XWHKW.js.map} +0 -0
- /package/dist/safe-js/chunks/{mcp-E2AJXEQM.js.map → migration-file-KRXQYI3Q.js.map} +0 -0
- /package/dist/safe-js/chunks/{migration-file-3SWGNDS2.js.map → restore-GEO7VN2R.js.map} +0 -0
- /package/dist/safe-js/chunks/{restore-FCTWPLU3.js.map → run-ZSFX66RN.js.map} +0 -0
- /package/dist/safe-js/chunks/{run-ESJHEXCE.js.map → runtime-modules-A3U2DKFL.js.map} +0 -0
- /package/dist/safe-js/chunks/{runtime-modules-7V6BWCRK.js.map → source-files-L3SGK63Z.js.map} +0 -0
- /package/dist/safe-js/{chunks/source-files-73OHLNGH.js.map → modules/fs.js.map} +0 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// packages/safe-js/src/modules/fs-codec.ts
|
|
2
|
+
var encodings = /* @__PURE__ */ new Set(["ascii", "utf8", "utf-8", "utf16le", "utf-16le", "ucs2", "ucs-2", "base64", "base64url", "latin1", "binary", "hex"]);
|
|
3
|
+
var utf8 = new TextEncoder();
|
|
4
|
+
var fsCodec = {
|
|
5
|
+
isEncoding: (encoding) => encodings.has(encoding.toLowerCase()),
|
|
6
|
+
encode(text, encoding) {
|
|
7
|
+
const name = encoding.toLowerCase();
|
|
8
|
+
if (name === "utf8" || name === "utf-8") return utf8.encode(text);
|
|
9
|
+
if (name === "hex") {
|
|
10
|
+
const bytes = [];
|
|
11
|
+
const digits = "0123456789abcdef";
|
|
12
|
+
for (let i = 0; i + 1 < text.length; i += 2) {
|
|
13
|
+
const high = digits.indexOf(text[i].toLowerCase());
|
|
14
|
+
const low = digits.indexOf(text[i + 1].toLowerCase());
|
|
15
|
+
if (high < 0 || low < 0) break;
|
|
16
|
+
bytes.push(high * 16 + low);
|
|
17
|
+
}
|
|
18
|
+
return Uint8Array.from(bytes);
|
|
19
|
+
}
|
|
20
|
+
if (name === "base64" || name === "base64url") {
|
|
21
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
22
|
+
const bytes = [];
|
|
23
|
+
let bits = 0, count = 0;
|
|
24
|
+
for (const char of text) {
|
|
25
|
+
if (char === "=") break;
|
|
26
|
+
const digit = alphabet.indexOf(char === "-" ? "+" : char === "_" ? "/" : char);
|
|
27
|
+
if (digit < 0) continue;
|
|
28
|
+
bits = bits << 6 | digit;
|
|
29
|
+
count += 6;
|
|
30
|
+
if (count >= 8) {
|
|
31
|
+
count -= 8;
|
|
32
|
+
bytes.push(bits >>> count & 255);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return Uint8Array.from(bytes);
|
|
36
|
+
}
|
|
37
|
+
if (["utf16le", "utf-16le", "ucs2", "ucs-2"].includes(name)) {
|
|
38
|
+
const bytes = new Uint8Array(text.length * 2);
|
|
39
|
+
for (let i = 0; i < text.length; i++) {
|
|
40
|
+
const code = text.charCodeAt(i);
|
|
41
|
+
bytes[i * 2] = code & 255;
|
|
42
|
+
bytes[i * 2 + 1] = code >>> 8;
|
|
43
|
+
}
|
|
44
|
+
return bytes;
|
|
45
|
+
}
|
|
46
|
+
if (["ascii", "latin1", "binary"].includes(name)) return Uint8Array.from(text.split(""), (char) => char.charCodeAt(0) & 255);
|
|
47
|
+
throw new TypeError("Invalid encoding");
|
|
48
|
+
},
|
|
49
|
+
decode(bytes, encoding) {
|
|
50
|
+
const name = encoding.toLowerCase();
|
|
51
|
+
if (name === "utf8" || name === "utf-8") return new TextDecoder("utf-8", { ignoreBOM: true }).decode(bytes);
|
|
52
|
+
if (name === "hex") return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
53
|
+
if (name === "base64" || name === "base64url") {
|
|
54
|
+
const alphabet = name === "base64" ? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
55
|
+
let result2 = "";
|
|
56
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
57
|
+
const a = bytes[i], b = bytes[i + 1], c = bytes[i + 2];
|
|
58
|
+
result2 += alphabet[a >>> 2] + alphabet[(a & 3) << 4 | (b ?? 0) >>> 4];
|
|
59
|
+
result2 += b === void 0 ? name === "base64" ? "==" : "" : alphabet[(b & 15) << 2 | (c ?? 0) >>> 6] + (c === void 0 ? name === "base64" ? "=" : "" : alphabet[c & 63]);
|
|
60
|
+
}
|
|
61
|
+
return result2;
|
|
62
|
+
}
|
|
63
|
+
let result = "";
|
|
64
|
+
if (["utf16le", "utf-16le", "ucs2", "ucs-2"].includes(name)) {
|
|
65
|
+
for (let i = 0; i + 1 < bytes.length; i += 2) result += String.fromCharCode(bytes[i] | bytes[i + 1] << 8);
|
|
66
|
+
} else if (["ascii", "latin1", "binary"].includes(name)) {
|
|
67
|
+
for (const byte of bytes) result += String.fromCharCode(name === "ascii" ? byte & 127 : byte);
|
|
68
|
+
} else throw new TypeError("Invalid encoding");
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
fsCodec
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-GVKXZW53.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/modules/fs-codec.ts"],
|
|
4
|
+
"sourcesContent": ["import type { FsBridgeCodec } from \"@poe-code/safe-fs/core\";\n\nconst encodings = new Set([\"ascii\", \"utf8\", \"utf-8\", \"utf16le\", \"utf-16le\", \"ucs2\", \"ucs-2\", \"base64\", \"base64url\", \"latin1\", \"binary\", \"hex\"]);\nconst utf8 = new TextEncoder();\nexport const fsCodec: FsBridgeCodec = {\n isEncoding: encoding => encodings.has(encoding.toLowerCase()),\n encode(text, encoding) {\n const name = encoding.toLowerCase();\n if (name === \"utf8\" || name === \"utf-8\") return utf8.encode(text);\n if (name === \"hex\") {\n const bytes: number[] = [];\n const digits = \"0123456789abcdef\";\n for (let i = 0; i + 1 < text.length; i += 2) {\n const high = digits.indexOf(text[i]!.toLowerCase());\n const low = digits.indexOf(text[i + 1]!.toLowerCase());\n if (high < 0 || low < 0) break;\n bytes.push(high * 16 + low);\n }\n return Uint8Array.from(bytes);\n }\n if (name === \"base64\" || name === \"base64url\") {\n const alphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n const bytes: number[] = [];\n let bits = 0, count = 0;\n for (const char of text) {\n if (char === \"=\") break;\n const digit = alphabet.indexOf(char === \"-\" ? \"+\" : char === \"_\" ? \"/\" : char);\n if (digit < 0) continue;\n bits = (bits << 6) | digit; count += 6;\n if (count >= 8) { count -= 8; bytes.push((bits >>> count) & 255); }\n }\n return Uint8Array.from(bytes);\n }\n if ([\"utf16le\", \"utf-16le\", \"ucs2\", \"ucs-2\"].includes(name)) {\n const bytes = new Uint8Array(text.length * 2);\n for (let i = 0; i < text.length; i++) {\n const code = text.charCodeAt(i); bytes[i * 2] = code & 255; bytes[i * 2 + 1] = code >>> 8;\n }\n return bytes;\n }\n if ([\"ascii\", \"latin1\", \"binary\"].includes(name)) return Uint8Array.from(text.split(\"\"), char => char.charCodeAt(0) & 255);\n throw new TypeError(\"Invalid encoding\");\n },\n decode(bytes, encoding) {\n const name = encoding.toLowerCase();\n if (name === \"utf8\" || name === \"utf-8\") return new TextDecoder(\"utf-8\", { ignoreBOM: true }).decode(bytes);\n if (name === \"hex\") return Array.from(bytes, byte => byte.toString(16).padStart(2, \"0\")).join(\"\");\n if (name === \"base64\" || name === \"base64url\") {\n const alphabet = name === \"base64\" ? \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\" : \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n let result = \"\";\n for (let i = 0; i < bytes.length; i += 3) {\n const a = bytes[i]!, b = bytes[i + 1], c = bytes[i + 2];\n result += alphabet[a >>> 2]! + alphabet[((a & 3) << 4) | ((b ?? 0) >>> 4)]!;\n result += b === undefined ? (name === \"base64\" ? \"==\" : \"\") : alphabet[((b & 15) << 2) | ((c ?? 0) >>> 6)]! + (c === undefined ? (name === \"base64\" ? \"=\" : \"\") : alphabet[c & 63]!);\n }\n return result;\n }\n let result = \"\";\n if ([\"utf16le\", \"utf-16le\", \"ucs2\", \"ucs-2\"].includes(name)) {\n for (let i = 0; i + 1 < bytes.length; i += 2) result += String.fromCharCode(bytes[i]! | bytes[i + 1]! << 8);\n } else if ([\"ascii\", \"latin1\", \"binary\"].includes(name)) {\n for (const byte of bytes) result += String.fromCharCode(name === \"ascii\" ? byte & 127 : byte);\n } else throw new TypeError(\"Invalid encoding\");\n return result;\n }\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["result"]
|
|
7
|
+
}
|
|
@@ -1,25 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fsCodec
|
|
3
|
+
} from "./chunk-GVKXZW53.js";
|
|
1
4
|
import {
|
|
2
5
|
getOwnErrorCode
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2GVBG23M.js";
|
|
4
7
|
import {
|
|
5
|
-
accessDeniedSystemError,
|
|
6
8
|
declareBudgetedHostOperation,
|
|
7
9
|
declareHostOperation
|
|
8
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-MDIWQFYU.js";
|
|
11
|
+
import {
|
|
12
|
+
basename,
|
|
13
|
+
dirname,
|
|
14
|
+
isAbsolutePath,
|
|
15
|
+
relative,
|
|
16
|
+
resolve,
|
|
17
|
+
sep
|
|
18
|
+
} from "./chunk-YUQFFRUF.js";
|
|
19
|
+
import {
|
|
20
|
+
accessDeniedSystemError,
|
|
21
|
+
constants,
|
|
22
|
+
hostFs,
|
|
23
|
+
hostPlatform,
|
|
24
|
+
inspect
|
|
25
|
+
} from "./chunk-UQPYTZOZ.js";
|
|
9
26
|
|
|
10
27
|
// packages/safe-js/src/modules/fs.ts
|
|
11
|
-
import {
|
|
12
|
-
import * as nodeFsPromises from "node:fs/promises";
|
|
13
|
-
import { dirname as dirname2, isAbsolute as isAbsolute2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
14
|
-
import { inspect } from "node:util";
|
|
15
|
-
import { createNodeFsBridge } from "@poe-platform/safe-fs/node/filesystem";
|
|
28
|
+
import { createFsBridge } from "@poe-platform/safe-fs/core";
|
|
16
29
|
import {
|
|
17
30
|
FsError,
|
|
18
31
|
isPathWithin
|
|
19
32
|
} from "@poe-platform/safe-fs/core";
|
|
20
33
|
|
|
21
34
|
// packages/safe-js/src/modules/canonical-path.ts
|
|
22
|
-
import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
23
35
|
var MISSING_PATH_CODES = ["ENOENT", "ENOTDIR"];
|
|
24
36
|
var NOT_A_SYMLINK_CODES = [...MISSING_PATH_CODES, "EINVAL"];
|
|
25
37
|
var MAX_SYMLINK_FOLLOWS = 32;
|
|
@@ -40,7 +52,7 @@ async function resolveCanonicalPath({ realpath, readlink }, path) {
|
|
|
40
52
|
if (++follows > MAX_SYMLINK_FOLLOWS) {
|
|
41
53
|
throw createLoopError(path);
|
|
42
54
|
}
|
|
43
|
-
current =
|
|
55
|
+
current = isAbsolutePath(target) ? target : `${dirname(current)}${sep}${target}`;
|
|
44
56
|
continue;
|
|
45
57
|
}
|
|
46
58
|
const parent = dirname(current);
|
|
@@ -77,7 +89,7 @@ async function containsPath(stat, canonicalRoot, canonicalPath) {
|
|
|
77
89
|
}
|
|
78
90
|
function containsCanonicalSpelling(canonicalRoot, canonicalPath) {
|
|
79
91
|
const relativePath = relative(canonicalRoot, canonicalPath);
|
|
80
|
-
return !(relativePath === ".." || relativePath.startsWith(`..${sep}`) ||
|
|
92
|
+
return !(relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolutePath(relativePath));
|
|
81
93
|
}
|
|
82
94
|
async function descendsFromRoot(stat, canonicalRoot, canonicalPath) {
|
|
83
95
|
const root = await readIdentity(stat, canonicalRoot);
|
|
@@ -250,10 +262,15 @@ var INVALID_ARGUMENT_CODE = "ERR_INVALID_ARG_VALUE";
|
|
|
250
262
|
var INVALID_ARGUMENT_TYPE_CODE = "ERR_INVALID_ARG_TYPE";
|
|
251
263
|
var NULL_BYTE = "\0";
|
|
252
264
|
var [ACCESS_DENIED_ERRNO, ACCESS_DENIED_MESSAGE] = accessDeniedSystemError;
|
|
253
|
-
var hostReadMemoryLimit = 16 * 1024 * 1024;
|
|
254
|
-
var reservedHostReadMemory = 0;
|
|
255
265
|
function makeFsModule(options = {}) {
|
|
256
266
|
assertSupportedPlatform();
|
|
267
|
+
const hostReadMemoryLimit = options.hostReadMemoryLimit ?? Infinity;
|
|
268
|
+
const readFileMaxBytes = options.readFileMaxBytes ?? Infinity;
|
|
269
|
+
for (const limit of [hostReadMemoryLimit, readFileMaxBytes]) {
|
|
270
|
+
if (limit !== Infinity && (!Number.isSafeInteger(limit) || limit < 0))
|
|
271
|
+
throw new TypeError("Filesystem read limits must be non-negative safe integers or Infinity.");
|
|
272
|
+
}
|
|
273
|
+
let reservedHostReadMemory = 0;
|
|
257
274
|
if (options.adapter !== void 0 && options.fs !== void 0) {
|
|
258
275
|
throw new TypeError("fs module accepts either adapter or fs, not both.");
|
|
259
276
|
}
|
|
@@ -263,7 +280,8 @@ function makeFsModule(options = {}) {
|
|
|
263
280
|
if (options.cwd !== void 0 && (typeof options.cwd !== "string" || !options.cwd.startsWith("/") || options.cwd.includes("\0"))) {
|
|
264
281
|
throw new TypeError("fs module cwd must be an absolute virtual path without null bytes.");
|
|
265
282
|
}
|
|
266
|
-
const implementation = options.adapter === void 0 ? options.fs ??
|
|
283
|
+
const implementation = options.adapter === void 0 ? options.fs ?? hostFs : createFsBridge(options.adapter, {
|
|
284
|
+
codec: fsCodec,
|
|
267
285
|
cwd: options.root === void 0 ? options.cwd : void 0,
|
|
268
286
|
signal: options.signal
|
|
269
287
|
});
|
|
@@ -276,14 +294,16 @@ function makeFsModule(options = {}) {
|
|
|
276
294
|
assertNoBufferResult("readFile", args[1]);
|
|
277
295
|
const maxBytes = Math.max(0, Math.floor(Math.min(
|
|
278
296
|
hostReadMemoryLimit / 40,
|
|
297
|
+
readFileMaxBytes,
|
|
279
298
|
(budget?.limits.stringLength ?? Infinity) / 2,
|
|
280
299
|
((budget?.limits.dataSize ?? Infinity) - (budget?.currentDataSize ?? 0)) / 4
|
|
281
300
|
)));
|
|
282
|
-
const reservation = maxBytes * 10;
|
|
283
|
-
const bridge =
|
|
301
|
+
const reservation = Number.isFinite(hostReadMemoryLimit) ? maxBytes * 10 : 0;
|
|
302
|
+
const bridge = createFsBridge(options.adapter, {
|
|
303
|
+
codec: fsCodec,
|
|
284
304
|
cwd: options.root === void 0 ? options.cwd : void 0,
|
|
285
305
|
signal: options.signal,
|
|
286
|
-
readFileMaxBytes: maxBytes,
|
|
306
|
+
readFileMaxBytes: Number.isFinite(maxBytes) ? maxBytes : void 0,
|
|
287
307
|
reserveReadFile() {
|
|
288
308
|
if (reservedHostReadMemory + reservation > hostReadMemoryLimit) throw new Error("Filesystem read host memory budget exceeded");
|
|
289
309
|
reservedHostReadMemory += reservation;
|
|
@@ -292,7 +312,8 @@ function makeFsModule(options = {}) {
|
|
|
292
312
|
};
|
|
293
313
|
}
|
|
294
314
|
});
|
|
295
|
-
const
|
|
315
|
+
const portable = bridge;
|
|
316
|
+
const boundedFs = options.root === void 0 ? portable : makeRootedFs(portable, options.root, options.adapter, options.cwd, options.signal);
|
|
296
317
|
return await invoke(boundedFs, "readFile", args);
|
|
297
318
|
};
|
|
298
319
|
const directRead = declare("readFile", "re-issue", (...args) => boundedRead(args));
|
|
@@ -325,16 +346,16 @@ function makeFsModule(options = {}) {
|
|
|
325
346
|
utimes: bind(fs, "utimes", "read-side-effect"),
|
|
326
347
|
writeFile: bind(fs, "writeFile", "read-side-effect"),
|
|
327
348
|
constants: {
|
|
328
|
-
F_OK:
|
|
329
|
-
R_OK:
|
|
330
|
-
W_OK:
|
|
331
|
-
X_OK:
|
|
332
|
-
COPYFILE_EXCL:
|
|
349
|
+
F_OK: constants.F_OK,
|
|
350
|
+
R_OK: constants.R_OK,
|
|
351
|
+
W_OK: constants.W_OK,
|
|
352
|
+
X_OK: constants.X_OK,
|
|
353
|
+
COPYFILE_EXCL: constants.COPYFILE_EXCL
|
|
333
354
|
}
|
|
334
355
|
};
|
|
335
356
|
}
|
|
336
357
|
function assertSupportedPlatform() {
|
|
337
|
-
if (
|
|
358
|
+
if (hostPlatform !== "win32") {
|
|
338
359
|
return;
|
|
339
360
|
}
|
|
340
361
|
throw new Error(
|
|
@@ -387,7 +408,7 @@ function makeRootedFs(fs, root, adapter, cwd, signal) {
|
|
|
387
408
|
if (root.trim().length === 0) {
|
|
388
409
|
throw new Error("fs module root must be a non-empty string.");
|
|
389
410
|
}
|
|
390
|
-
const resolvedRoot = adapter === void 0 ? root :
|
|
411
|
+
const resolvedRoot = adapter === void 0 ? root : resolve("/", root);
|
|
391
412
|
const rooted = {};
|
|
392
413
|
const backend = adapter ?? fs;
|
|
393
414
|
for (const name of Object.keys(FS_SYSCALLS)) {
|
|
@@ -395,8 +416,8 @@ function makeRootedFs(fs, root, adapter, cwd, signal) {
|
|
|
395
416
|
assertRootCanConfineOptions(name, args);
|
|
396
417
|
const previous = rootedFsOperations.get(backend);
|
|
397
418
|
let release;
|
|
398
|
-
const pending = new Promise((
|
|
399
|
-
release =
|
|
419
|
+
const pending = new Promise((resolve2) => {
|
|
420
|
+
release = resolve2;
|
|
400
421
|
});
|
|
401
422
|
rootedFsOperations.set(backend, pending);
|
|
402
423
|
await previous;
|
|
@@ -426,14 +447,14 @@ function assertRootCanConfineOptions(name, args) {
|
|
|
426
447
|
}
|
|
427
448
|
}
|
|
428
449
|
async function resolvePathArguments(fs, root, name, args, adapter, cwd, signal) {
|
|
429
|
-
const canonicalRoot = await resolveCanonicalPath(readCanonicalPathFs(fs),
|
|
450
|
+
const canonicalRoot = await resolveCanonicalPath(readCanonicalPathFs(fs), resolve(root));
|
|
430
451
|
const base = cwd ?? canonicalRoot;
|
|
431
452
|
const resolved = [...args];
|
|
432
453
|
if (name === "symlink") {
|
|
433
454
|
const linkPath = readPath(base, args[1]);
|
|
434
|
-
const targetPath = readPath(
|
|
455
|
+
const targetPath = readPath(dirname(linkPath), args[0]);
|
|
435
456
|
resolved[1] = linkPath;
|
|
436
|
-
if (adapter !== void 0 && typeof args[0] === "string" &&
|
|
457
|
+
if (adapter !== void 0 && typeof args[0] === "string" && isAbsolutePath(args[0])) {
|
|
437
458
|
signal?.throwIfAborted();
|
|
438
459
|
if (!isPathWithin(canonicalRoot, targetPath) || !isPathWithin(canonicalRoot, linkPath)) {
|
|
439
460
|
throw createAccessDeniedError(name, targetPath, linkPath);
|
|
@@ -445,8 +466,8 @@ async function resolvePathArguments(fs, root, name, args, adapter, cwd, signal)
|
|
|
445
466
|
message: "absolute symlink targets cannot be confined before creation; use a relative target"
|
|
446
467
|
});
|
|
447
468
|
}
|
|
448
|
-
const parent = await invoke(fs, "realpath", [
|
|
449
|
-
const checkedTarget =
|
|
469
|
+
const parent = await invoke(fs, "realpath", [dirname(linkPath)]);
|
|
470
|
+
const checkedTarget = isAbsolutePath(args[0]) ? args[0] : `${parent}${sep}${args[0]}`;
|
|
450
471
|
await assertInsideRoot(fs, canonicalRoot, name, [checkedTarget, linkPath], adapter, signal, [
|
|
451
472
|
targetPath,
|
|
452
473
|
linkPath
|
|
@@ -461,8 +482,8 @@ async function resolvePathArguments(fs, root, name, args, adapter, cwd, signal)
|
|
|
461
482
|
await assertInsideRoot(fs, canonicalRoot, name, paths, adapter, signal);
|
|
462
483
|
if (name === "mkdtemp") {
|
|
463
484
|
const prefix = args[0];
|
|
464
|
-
const absolutePrefix =
|
|
465
|
-
const parent = absolutePrefix.endsWith(
|
|
485
|
+
const absolutePrefix = isAbsolutePath(prefix) ? prefix : `${base}${sep}${prefix}`;
|
|
486
|
+
const parent = absolutePrefix.endsWith(sep) ? absolutePrefix : dirname(absolutePrefix);
|
|
466
487
|
await assertInsideRoot(fs, canonicalRoot, name, [parent], adapter, signal, paths);
|
|
467
488
|
resolved[0] = absolutePrefix;
|
|
468
489
|
}
|
|
@@ -471,7 +492,7 @@ async function resolvePathArguments(fs, root, name, args, adapter, cwd, signal)
|
|
|
471
492
|
if (isObjectLike(options) && options.recursive === true) {
|
|
472
493
|
signal?.throwIfAborted();
|
|
473
494
|
try {
|
|
474
|
-
await invoke(fs, "realpath", [
|
|
495
|
+
await invoke(fs, "realpath", [dirname(canonicalRoot)]);
|
|
475
496
|
} catch (error) {
|
|
476
497
|
signal?.throwIfAborted();
|
|
477
498
|
if (getOwnErrorCode(error) !== "ENOENT") throw error;
|
|
@@ -527,7 +548,7 @@ async function containsAdapterPath(adapter, canonicalRoot, canonicalPath, signal
|
|
|
527
548
|
throw error;
|
|
528
549
|
}
|
|
529
550
|
}
|
|
530
|
-
const parent =
|
|
551
|
+
const parent = dirname(current);
|
|
531
552
|
if (parent === current) {
|
|
532
553
|
return false;
|
|
533
554
|
}
|
|
@@ -617,7 +638,7 @@ function describeReceivedValue(value) {
|
|
|
617
638
|
}
|
|
618
639
|
function readPath(base, value) {
|
|
619
640
|
const path = value;
|
|
620
|
-
return
|
|
641
|
+
return isAbsolutePath(path) ? resolve(path) : resolve(base, path);
|
|
621
642
|
}
|
|
622
643
|
function createAccessDeniedError(name, path, dest) {
|
|
623
644
|
const syscall = FS_SYSCALLS[name];
|
|
@@ -721,4 +742,4 @@ export {
|
|
|
721
742
|
FS_OPTION_SURFACE,
|
|
722
743
|
makeFsModule
|
|
723
744
|
};
|
|
724
|
-
//# sourceMappingURL=chunk-
|
|
745
|
+
//# sourceMappingURL=chunk-K4T4EBED.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 {\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.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 return {\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}\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
|
+
}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
addBrokenPipeListener,
|
|
3
3
|
createBrokenPipeState,
|
|
4
4
|
createSafeOutputStream
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-G6WTEIJJ.js";
|
|
6
6
|
import {
|
|
7
7
|
SandboxError,
|
|
8
8
|
activateOtelSpan,
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
safeRecordException,
|
|
15
15
|
safeStartSpan,
|
|
16
16
|
splitSourceLines
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QKO4FATZ.js";
|
|
18
|
+
import {
|
|
19
|
+
AsyncLocalStorage
|
|
20
|
+
} from "./chunk-UQPYTZOZ.js";
|
|
18
21
|
|
|
19
22
|
// packages/safe-js/src/error/format.ts
|
|
20
23
|
var DEFAULT_MAX_MESSAGE_LENGTH = 1e4;
|
|
@@ -800,9 +803,6 @@ function countLines(value) {
|
|
|
800
803
|
return count;
|
|
801
804
|
}
|
|
802
805
|
|
|
803
|
-
// packages/safe-js/src/modules/agent.ts
|
|
804
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
805
|
-
|
|
806
806
|
// packages/agent-defs/src/agents/claude-code.ts
|
|
807
807
|
var claudeCodeAgent = {
|
|
808
808
|
id: "claude-code",
|
|
@@ -2640,7 +2640,7 @@ import {
|
|
|
2640
2640
|
validateFileSystemConfig
|
|
2641
2641
|
} from "@poe-platform/safe-fs";
|
|
2642
2642
|
function validateFsConfig(value) {
|
|
2643
|
-
const config = readConfigRecord(value, "fs config", ["adapter", "root", "cwd"]);
|
|
2643
|
+
const config = readConfigRecord(value, "fs config", ["adapter", "root", "cwd", "readFileMaxBytes", "hostReadMemoryLimit"]);
|
|
2644
2644
|
const paths = {};
|
|
2645
2645
|
for (const key of ["root", "cwd"]) {
|
|
2646
2646
|
const path = config[key];
|
|
@@ -2650,9 +2650,18 @@ function validateFsConfig(value) {
|
|
|
2650
2650
|
}
|
|
2651
2651
|
paths[key] = path;
|
|
2652
2652
|
}
|
|
2653
|
+
const limits = {};
|
|
2654
|
+
for (const key of ["readFileMaxBytes", "hostReadMemoryLimit"]) {
|
|
2655
|
+
const value2 = config[key];
|
|
2656
|
+
if (value2 === void 0) continue;
|
|
2657
|
+
if (value2 !== Infinity && (typeof value2 !== "number" || !Number.isSafeInteger(value2) || value2 < 0))
|
|
2658
|
+
throw new TypeError(`${key} must be a non-negative safe integer or Infinity`);
|
|
2659
|
+
Object.assign(limits, { [key]: value2 });
|
|
2660
|
+
}
|
|
2653
2661
|
return {
|
|
2654
2662
|
adapter: validateFileSystemConfig(config.adapter),
|
|
2655
|
-
...paths
|
|
2663
|
+
...paths,
|
|
2664
|
+
...limits
|
|
2656
2665
|
};
|
|
2657
2666
|
}
|
|
2658
2667
|
function parseFsConfig(json) {
|
|
@@ -2841,4 +2850,4 @@ export {
|
|
|
2841
2850
|
makeLogModule,
|
|
2842
2851
|
makeMetricModule
|
|
2843
2852
|
};
|
|
2844
|
-
//# sourceMappingURL=chunk-
|
|
2853
|
+
//# sourceMappingURL=chunk-KETIFEA7.js.map
|