Compare commits

...

4 Commits

Author SHA1 Message Date
Jarred Sumner
cb3ce26b1b fix url.fileURLToPath test 2025-08-11 14:29:28 -07:00
autofix-ci[bot]
50ec0ad46e [autofix.ci] apply automated fixes 2025-08-11 20:33:42 +00:00
Jarred Sumner
45362bfdd7 Merge branch 'main' into riskymh/18748 2025-08-11 13:32:24 -07:00
Jarred Sumner
676831ec7a fix "File URL path must be an absolute path" error on windows 2025-08-11 11:46:37 -07:00
3 changed files with 77 additions and 9 deletions

View File

@@ -27,11 +27,12 @@ ALWAYS_INLINE bool isAbsolutePath(WTF::String input)
if (len < 1)
return false;
const auto bytes = input.span8().data();
if (IS_SLASH(bytes[0]))
// On Windows, paths starting with / are not absolute paths
// They need to be resolved relative to the current drive
// Only paths with drive letters (C:\) or UNC paths (\\) are absolute
if (len >= 3 && IS_LETTER(bytes[0]) && bytes[1] == ':' && IS_SLASH(bytes[2]))
return true;
if (len < 2)
return false;
if (IS_LETTER(bytes[0]) && bytes[1] == ':' && IS_SLASH(bytes[2]))
if (len >= 2 && IS_SLASH(bytes[0]) && IS_SLASH(bytes[1]))
return true;
return false;
} else {
@@ -39,11 +40,12 @@ ALWAYS_INLINE bool isAbsolutePath(WTF::String input)
if (len < 1)
return false;
const auto bytes = input.span16().data();
if (IS_SLASH(bytes[0]))
// On Windows, paths starting with / are not absolute paths
// They need to be resolved relative to the current drive
// Only paths with drive letters (C:\) or UNC paths (\\) are absolute
if (len >= 3 && IS_LETTER(bytes[0]) && bytes[1] == ':' && IS_SLASH(bytes[2]))
return true;
if (len < 2)
return false;
if (IS_LETTER(bytes[0]) && bytes[1] == ':' && IS_SLASH(bytes[2]))
if (len >= 2 && IS_SLASH(bytes[0]) && IS_SLASH(bytes[1]))
return true;
return false;
}

View File

@@ -4,7 +4,12 @@ import { isWindows } from "harness";
describe("pathToFileURL", () => {
it("should convert a path to a file url", () => {
expect(pathToFileURL("/path/to/file.js").href).toBe("file:///path/to/file.js");
if (isWindows) {
const result = pathToFileURL("/path/to/file.js").href;
expect(result).toMatch(/^file:\/\/\/[A-Z]:\/path\/to\/file\.js$/);
} else {
expect(pathToFileURL("/path/to/file.js").href).toBe("file:///path/to/file.js");
}
});
});
@@ -12,7 +17,10 @@ describe("fileURLToPath", () => {
const absoluteErrorMessage = "File URL path must be an absolute";
it("should convert a file url to a path", () => {
if (isWindows) {
// This is still invalid on Windows because it lacks a drive letter
expect(() => fileURLToPath("file:///path/to/file.js")).toThrow(absoluteErrorMessage);
// But a properly formed Windows file URL should work
expect(fileURLToPath("file:///C:/path/to/file.js")).toBe("C:\\path\\to\\file.js");
} else {
expect(fileURLToPath("file:///path/to/file.js")).toBe("/path/to/file.js");
}
@@ -20,7 +28,10 @@ describe("fileURLToPath", () => {
it("should convert a URL to a path", () => {
if (isWindows) {
// This is still invalid on Windows because it lacks a drive letter
expect(() => fileURLToPath(new URL("file:///path/to/file.js"))).toThrow(absoluteErrorMessage);
// But a properly formed Windows file URL should work
expect(fileURLToPath(new URL("file:///C:/path/to/file.js"))).toBe("C:\\path\\to\\file.js");
} else {
expect(fileURLToPath(new URL("file:///path/to/file.js"))).toBe("/path/to/file.js");
}
@@ -49,4 +60,22 @@ describe("fileURLToPath", () => {
expect(fileURLToPath(url)).toBe(import.meta.path);
expect(fileURLToPath(import.meta.url)).toBe(import.meta.path);
});
it("should handle Windows paths starting with / correctly", () => {
if (isWindows) {
// Test the specific case that was failing with SolidStart
const testPaths = ["/test", "/@solid-refresh", "/node_modules/test"];
for (const testPath of testPaths) {
const url = pathToFileURL(testPath);
// Should include drive letter
expect(url.href).toMatch(/^file:\/\/\/[A-Z]:\//);
// Should roundtrip correctly
const result = fileURLToPath(url);
expect(result).toMatch(/^[A-Z]:\\/);
expect(result.toLowerCase()).toContain(testPath.replace(/\//g, "\\").toLowerCase());
}
}
});
});

View File

@@ -0,0 +1,37 @@
import { expect, test } from "bun:test";
import { isWindows } from "harness";
import { fileURLToPath, pathToFileURL } from "node:url";
test("fileURLToPath should handle paths starting with / correctly on all platforms", () => {
const testPaths = ["/test", "/@test", "/node_modules/test", "/@solid-refresh"];
for (const testPath of testPaths) {
const url = pathToFileURL(testPath);
if (isWindows) {
expect(url.href).toMatch(/^file:\/\/\/[A-Z]:\//);
} else {
expect(url.href).toBe(`file://${testPath}`);
}
const result = fileURLToPath(url);
if (isWindows) {
expect(result).toMatch(/^[A-Z]:\\/);
expect(result.toLowerCase()).toContain(testPath.replace(/\//g, "\\").toLowerCase());
} else {
expect(result).toBe(testPath);
}
}
});
test.if(isWindows)("Windows absolute paths should still work correctly", () => {
const absolutePaths = ["C:\\test", "C:\\Users\\test", "D:\\Projects\\myapp", "\\\\server\\share\\file"];
for (const absolutePath of absolutePaths) {
const url = pathToFileURL(absolutePath);
const result = fileURLToPath(url);
expect(result).toBe(absolutePath);
}
});