Files
scriptc/tests/fixtures/npm/node_modules/node24-url-fixture/file-conversion.js
Chris Tate bc7c9f6bf6 Support Node 24 file URL buffers and platform options (#645)
* Support Node 24 file URL bytes and runtime platform options

* Record preflight baselines for file URL conversion fixtures
2026-10-03 17:33:04 -05:00

81 lines
5.0 KiB
JavaScript

import { URL, fileURLToPath, fileURLToPathBuffer, pathToFileURL } from "node:url";
import { Buffer } from "node:buffer";
export function reportFileUrls() {
function report(label, convert, input, options) {
try {
const value = convert(input, options);
console.log(label, value instanceof URL ? value.href : typeof value === "string" ? JSON.stringify(value) : value.toString("hex"));
} catch (error) { console.log(label, error.name, error.code ?? "", error.message); }
}
for (const tail of ["ascii", "é-水-😀", "%00", "%20", "%FF", "%80", "%C0%AF", "%ED%A0%80", "%", "%0", "%GG", "%2F", "%5C", "%252F", "%E0/%2F"]) {
const href = "file:///C:/work/" + tail + "?ignored#ignored";
for (const windows of [false, true]) {
const options = { windows };
const bytes = fileURLToPathBuffer(href, options);
console.log("buffer", windows, tail, Buffer.isBuffer(bytes), bytes.toString("hex"), bytes.equals(fileURLToPathBuffer(new URL(href), options)));
report("string", fileURLToPath, href, options);
}
}
for (const input of ["file://server/share/a%FF%2F%5C", "file://localhost/C:/a", "file:///%43%3A/path", "file:///%2FC:/path", "file:///no-drive", "invalid", "https://example.com/a"]) {
for (const convert of [fileURLToPath, fileURLToPathBuffer]) {
report("posix", convert, input, { windows: false });
report("windows", convert, input, { windows: true });
}
}
for (const convert of [fileURLToPath, fileURLToPathBuffer]) {
for (const input of [undefined, null, 7, true, {}, { href: "file:///C:/fake" }, Object.create(URL.prototype)]) report("input", convert, input, {});
for (const windows of [false, true, null, undefined, 0, 1, "", "yes", {}]) report("truthiness", convert, "file:///C:/a", { windows });
for (const options of [null, undefined, false, 7, "ignored"]) report("options", convert, "file:///C:/a", options);
}
for (const path of ["C:\\work\\a b#é.txt", "\\\\server\\share\\a b", "/posix/a\\b", "/control/\t\n\r", "/percent/%2F", "relative"]) {
for (const windows of [false, true]) {
const options = { windows, extra: "ignored" };
const url = pathToFileURL(path, options);
console.log("roundtrip", windows, url.href);
report("roundtrip-string", fileURLToPath, url, options);
report("roundtrip-buffer", fileURLToPathBuffer, url, options);
}
}
for (const input of [undefined, null, 7, true, {}]) report("path-input", pathToFileURL, input, { windows: false });
for (const path of ["\\\\server", "\\\\\\share"]) report("unc-error", pathToFileURL, path, { windows: true });
for (const windows of [false, true, null, undefined, 0, 1, "", "yes", {}]) report("path-truthiness", pathToFileURL, "C:\\work\\a", { windows });
for (const options of [null, undefined, {}, { windows: undefined }, { windows: null }]) {
console.log("defaults", pathToFileURL("relative", options).href === pathToFileURL("relative").href,
fileURLToPathBuffer("file:///C:/default", options).equals(fileURLToPathBuffer("file:///C:/default")));
}
const failure = new Error("option failed");
for (const convert of [fileURLToPath, fileURLToPathBuffer, pathToFileURL]) {
let order = "";
const input = () => { order += "input;"; return null; };
const options = () => { order += "options;"; return { get windows() { order += "get;"; throw failure; } }; };
try { convert(input(), options()); }
catch (error) { console.log("option-first", error === failure, order); }
}
let order = "";
const options = new Proxy({}, { get(target, key) { order += String(key) + ";"; return true; } });
console.log("proxy", fileURLToPath("file:///C:/a", options), fileURLToPathBuffer("file:///C:/a", options).toString("hex"), pathToFileURL("C:\\a", options).href, order);
let calls = 0;
const coercible = { toString() { calls++; return "file:///C:/fake"; } };
for (const convert of [fileURLToPath, fileURLToPathBuffer, pathToFileURL]) report("no-coercion", convert, coercible, {});
console.log("coercions", calls);
order = "";
const urlLike = {
get href() { order += "href;"; return "unused"; },
get protocol() { order += "protocol;"; return "file:"; },
get auth() { order += "auth;"; return undefined; },
get path() { order += "path;"; return undefined; },
get hostname() { order += "hostname;"; return ""; },
get pathname() { order += "pathname;"; return "/C:/like%FF"; },
};
console.log("url-like", fileURLToPathBuffer(urlLike, { get windows() { order += "windows;"; return true; } }).toString("hex"), order);
class FileURL extends URL {}
for (const url of [new FileURL("file:///C:/subclass"), URL.parse("file:///C:/parsed")]) {
console.log("branded", fileURLToPath(url, { windows: true }), fileURLToPathBuffer(url, { windows: true }).toString("hex"));
}
const first = fileURLToPathBuffer("file:///C:/copy"), second = fileURLToPathBuffer("file:///C:/copy");
first[0] = 120;
console.log("unshared", first !== second, first.equals(second));
console.log("recovery", fileURLToPathBuffer("file:///C:/after", { windows: true }).toString("hex"));
}