mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-02 08:35:07 +08:00
106 lines
2.7 KiB
TypeScript
106 lines
2.7 KiB
TypeScript
// fs failures are CATCHABLE — the payoff of the exceptions phase: a try
|
|
// around each failing call recovers and execution continues after the
|
|
// catch, exactly like Node. The message text itself cannot be observed here
|
|
// (the supported catch form is bindingless); its Node-matching format
|
|
// ("ENOENT: no such file or directory, open 'x'") is asserted by the
|
|
// runtime C tests instead.
|
|
import {
|
|
existsSync,
|
|
mkdirSync,
|
|
readdirSync,
|
|
readFileSync,
|
|
rmdirSync,
|
|
rmSync,
|
|
writeFileSync,
|
|
} from "node:fs";
|
|
|
|
function tail(path: string): string {
|
|
let i = path.length - 1;
|
|
while (i >= 0 && path.charAt(i) !== "/" && path.charAt(i) !== "\\") {
|
|
i = i - 1;
|
|
}
|
|
return path.slice(i + 1);
|
|
}
|
|
function freshDir(dir: string): void {
|
|
if (existsSync(dir)) {
|
|
for (const name of readdirSync(dir)) {
|
|
rmSync(dir + "/" + name);
|
|
}
|
|
rmdirSync(dir);
|
|
}
|
|
mkdirSync(dir);
|
|
}
|
|
const scratch = "tmp-994-" + tail(process.argv[1]);
|
|
freshDir(scratch);
|
|
|
|
let caught = 0;
|
|
try {
|
|
const text = readFileSync(scratch + "/missing.txt", "utf8");
|
|
console.log("unreachable", text);
|
|
} catch {
|
|
caught = caught + 1;
|
|
console.log("caught: read of a missing file");
|
|
}
|
|
try {
|
|
mkdirSync(scratch); // already exists → EEXIST
|
|
} catch {
|
|
caught = caught + 1;
|
|
console.log("caught: mkdir of an existing path");
|
|
}
|
|
try {
|
|
mkdirSync(scratch + "/nope/deep"); // missing parent → ENOENT
|
|
} catch {
|
|
caught = caught + 1;
|
|
console.log("caught: mkdir under a missing parent");
|
|
}
|
|
try {
|
|
rmSync(scratch + "/missing.txt");
|
|
} catch {
|
|
caught = caught + 1;
|
|
console.log("caught: rm of a missing path");
|
|
}
|
|
try {
|
|
rmdirSync(scratch + "/missing");
|
|
} catch {
|
|
caught = caught + 1;
|
|
console.log("caught: rmdir of a missing path");
|
|
}
|
|
try {
|
|
const names = readdirSync(scratch + "/missing");
|
|
console.log("unreachable", names.length);
|
|
} catch {
|
|
caught = caught + 1;
|
|
console.log("caught: readdir of a missing path");
|
|
}
|
|
console.log("total caught:", caught);
|
|
|
|
// existsSync never throws — a missing path is simply false.
|
|
console.log(existsSync(scratch + "/missing.txt"));
|
|
|
|
// Errors propagate through call chains to the nearest catch, like any throw.
|
|
function readOrDefault(path: string, fallback: string): string {
|
|
try {
|
|
return readFileSync(path, "utf8");
|
|
} catch {
|
|
return fallback;
|
|
}
|
|
}
|
|
console.log(readOrDefault(scratch + "/missing.txt", "the default"));
|
|
writeFileSync(scratch + "/real.txt", "the real content");
|
|
console.log(readOrDefault(scratch + "/real.txt", "the default"));
|
|
|
|
// finally runs on the exception path of a failing fs call.
|
|
try {
|
|
try {
|
|
readFileSync(scratch + "/also-missing.txt", "utf8");
|
|
} finally {
|
|
console.log("finally ran");
|
|
}
|
|
} catch {
|
|
console.log("caught after finally");
|
|
}
|
|
|
|
rmSync(scratch + "/real.txt");
|
|
rmdirSync(scratch);
|
|
console.log(existsSync(scratch));
|