Files
scriptc/tests/fixtures/npm/node_modules/fszoo/descriptors.js
Chris Tate 7d2d2116ec Expand Node 24 filesystem descriptor and FileHandle support (#625)
* Expand Node 24 filesystem descriptor and FileHandle support

* Preserve filesystem options getter evaluation and record fixture baselines

* Normalize the known Linux fiber warning in npm stderr comparisons
2026-10-03 00:41:02 -05:00

137 lines
8.4 KiB
JavaScript

import * as fs from "node:fs";
import * as fsp from "node:fs/promises";
import * as os from "node:os";
import * as path from "node:path";
import { pathToFileURL } from "node:url";
// Direct core-API evidence; the module boundary places these calls in the island.
export async function report() {
const lines = [];
const log = (...v) => lines.push(v.join("|"));
const root = fs.mkdtempSync(path.join(os.tmpdir(), "scr-node24-fd-"));
const file = path.join(root, "data");
const error = (label, action) => {
try { action(); log(label, "unexpected success"); }
catch (e) { log(label, e.name, e.code, e.message); }
};
const cbIO = (action) => new Promise((resolve, reject) => action((e, n, b) => e ? reject(e) : resolve([n, b])));
let fd;
try {
fd = fs.openSync(pathToFileURL(file), fs.constants.O_CREAT | fs.constants.O_RDWR | fs.constants.O_TRUNC, 0o600);
log("open", Number.isInteger(fd), fs.fstatSync(fd).isFile());
log("string", fs.writeSync(fd, "616263646566", 0, "hex"));
const buffer = Buffer.alloc(5, 46);
log("read options", fs.readSync(fd, buffer, { offset: 1, length: 3, position: 2n }), buffer.toString());
let getterOrder = "";
const getterOptions = () => ({
get buffer() { getterOrder += "b"; return buffer; },
get offset() { getterOrder += "o"; return 1; },
get length() { getterOrder += "l"; return 2; },
get position() { getterOrder += "p"; return 0; },
});
log("sync getters", fs.readSync(fd, buffer, getterOptions()), getterOrder);
const backing = new ArrayBuffer(8);
const view = new DataView(backing, 2, 3);
log("view read", fs.readSync(fd, view, { position: 1 }), Buffer.from(backing).toString("hex"));
const typed = new Uint16Array(backing, 2, 2);
log("typed write", fs.writeSync(fd, typed, { length: 3, position: 0 }));
log("buffer write", fs.writeSync(fd, Buffer.from("XYZ"), 1, 2, 3));
log("position preserved", fs.readSync(fd, Buffer.alloc(1)));
const vectors = [Buffer.alloc(2, 46), new Uint8Array(0), Buffer.alloc(6, 46)];
log("readv", fs.readvSync(fd, vectors, 0), vectors[0].toString(), vectors[2].toString());
log("writev", fs.writevSync(fd, [Buffer.from("12"), Buffer.from("34")], 0));
log("empty writev", fs.writevSync(-1, []));
error("empty readv", () => fs.readvSync(fd, []));
log("zero read", fs.readSync(-1, Buffer.alloc(0), { offset: 99, length: 0, position: -2 }));
error("offset", () => fs.readSync(fd, buffer, { offset: -1, length: 1 }));
error("length", () => fs.writeSync(fd, buffer, 0, 99));
error("fractional truncate", () => fs.ftruncateSync(fd, 0.5));
fs.fsyncSync(fd); fs.fdatasyncSync(fd); fs.ftruncateSync(fd, 4);
log("sync controls", fs.fstatSync(fd).size, fs.readFileSync(file, "utf8"));
fs.ftruncateSync(fd, -1); log("clamp", fs.fstatSync(fd).size);
fs.writeFileSync(fd, "abcd"); log("fd writeFile", fs.fstatSync(fd).size);
fs.closeSync(fd);
error("double close", () => fs.closeSync(fd));
error("closed read", () => fs.readSync(fd, buffer, 0, 1, 0));
error("closed zero vector", () => fs.readvSync(fd, [Buffer.alloc(0)]));
fd = undefined;
fd = (await cbIO((cb) => fs.open(file, "r+", cb)))[0];
let before = true;
const callbackBuffer = Buffer.alloc(2);
await new Promise((resolve, reject) => {
fs.read(fd, callbackBuffer, { position: 0 }, (e, n, b) => { if (e) return reject(e); log("callback read", before, n, b === callbackBuffer, b.toString()); resolve(); });
before = false;
});
const allocated = await cbIO((cb) => fs.read(fd, { length: 3, position: 1 }, cb));
log("callback allocated", allocated[0], allocated[1].length, allocated[1].subarray(0, allocated[0]).toString());
getterOrder = "";
const callbackGetters = await cbIO((cb) => fs.read(fd, getterOptions(), cb));
log("callback getters", callbackGetters[0], callbackGetters[1] === buffer, getterOrder);
const shorthand = await cbIO((cb) => fs.read(fd, cb));
log("callback default", shorthand[0], shorthand[1].length);
const cbWriteBuffer = Buffer.from("WX");
const cbWrite = await cbIO((cb) => fs.write(fd, cbWriteBuffer, { position: 0 }, cb));
log("callback write", cbWrite[0], cbWrite[1] === cbWriteBuffer);
const cbStr = await cbIO((cb) => fs.write(fd, "5a", 2, "hex", cb));
log("callback string", cbStr[0], cbStr[1]);
const cbVectors = [Buffer.alloc(2), Buffer.alloc(2)];
const cbReadv = await cbIO((cb) => fs.readv(fd, cbVectors, 0, cb));
log("callback readv", cbReadv[0], cbReadv[1] === cbVectors, cbVectors.map((b) => b.toString()).join(""));
const cbWritev = await cbIO((cb) => fs.writev(fd, cbVectors, 0, cb));
log("callback writev", cbWritev[0], cbWritev[1] === cbVectors);
await cbIO((cb) => fs.fsync(fd, cb)); await cbIO((cb) => fs.fdatasync(fd, cb));
await cbIO((cb) => fs.ftruncate(fd, 2, cb));
const cbStats = (await cbIO((cb) => fs.fstat(fd, cb)))[0]; log("callback stat", cbStats.size, cbStats.isFile());
await cbIO((cb) => fs.close(fd, cb)); fd = undefined;
let invoked = false;
error("sync validation", () => fs.read(-1, buffer, () => { invoked = true; }));
log("invalid callback not invoked", invoked);
await new Promise((resolve) => fs.open(path.join(root, "missing"), "r", (e) => { log("callback io error", e.name, e.code, e.syscall); resolve(); }));
const handle = await fsp.open(Buffer.from(file), "w+");
const alias = handle;
let closed = 0;
handle.on("close", () => { closed++; });
try {
const src = Buffer.from("hello");
const written = await handle.write(src, { position: 0 });
log("handle write", written.bytesWritten, written.buffer === src, Object.getPrototypeOf(written) === null);
const stringWritten = await handle.write("20776f726c64", 5, "hex"); log("handle string", stringWritten.bytesWritten, stringWritten.buffer);
const dst = new DataView(new ArrayBuffer(5));
const read = await handle.read({ buffer: dst, offset: 1, length: 3, position: 1 });
log("handle read", read.bytesRead, read.buffer === dst, Object.getPrototypeOf(read) === null, Buffer.from(dst.buffer).toString("hex"));
const defaultRead = await handle.read({ position: 0, length: 3 });
log("handle allocated", defaultRead.buffer.length, defaultRead.buffer.subarray(0, defaultRead.bytesRead).toString());
getterOrder = "";
const handleGetters = await handle.read(getterOptions());
log("handle getters", handleGetters.bytesRead, handleGetters.buffer === buffer, getterOrder);
const hv = [Buffer.alloc(3), Buffer.alloc(10, 46)];
const vr = await handle.readv(hv, 0); log("handle readv", vr.bytesRead, vr.buffers === hv, Object.getPrototypeOf(vr) === null, hv[0].toString(), hv[1].toString());
const vw = await handle.writev([Buffer.from("AB"), Buffer.from("CD")], 1); log("handle writev", vw.bytesWritten);
const empty = Buffer.alloc(0);
log("handle empty write", (await handle.write(empty, -1, -1, -2)).buffer === empty);
await handle.sync(); await handle.datasync();
if (process.platform !== "win32") await handle.chmod("600");
await handle.truncate(5); log("handle stat", (await handle.stat()).size);
log("handle readFile", await handle.readFile("utf8"));
await handle.truncate();
await handle.writeFile("good"); await handle.appendFile(Buffer.from("bye"));
const final = await handle.read({ position: 0 }); log("handle whole file", final.buffer.subarray(0, final.bytesRead).toString());
await handle.truncate(-1); log("handle clamp", (await handle.stat()).size);
try { await handle.truncate(0.5); } catch (e) { log("handle validation", e.name, e.code, e.message); }
} finally { await alias.close(); }
log("handle close", handle.fd, alias.fd, closed);
await handle.close(); log("handle close twice", closed);
for (const [name, action] of [ ["read", () => handle.read()], ["write", () => handle.write("")], ["readv", () => handle.readv([])], ["writev", () => handle.writev([])], ["fsync", () => handle.sync()], ["fdatasync", () => handle.datasync()], ["ftruncate", () => handle.truncate()] ]) {
let returned;
try { returned = action(); log("closed promise", name, returned instanceof Promise); await returned; }
catch (e) { log("closed error", name, e.name, e.code, e.message, e.syscall); }
}
} finally {
if (fd !== undefined) fs.closeSync(fd);
fs.rmSync(root, { recursive: true, force: true });
}
return lines.join("\n");
}