diff --git a/std/node/module.ts b/std/node/module.ts index e73eb4d5d7..4e0c55c1d8 100644 --- a/std/node/module.ts +++ b/std/node/module.ts @@ -31,6 +31,7 @@ import * as nodeQueryString from "./querystring.ts"; import * as path from "../path/mod.ts"; import { assert } from "../testing/asserts.ts"; +import { pathToFileURL, fileURLToPath } from "./url.ts"; const CHAR_FORWARD_SLASH = "/".charCodeAt(0); const CHAR_BACKWARD_SLASH = "\\".charCodeAt(0); @@ -1162,103 +1163,6 @@ function stripBOM(content: string): string { return content; } -const forwardSlashRegEx = /\//g; -const CHAR_LOWERCASE_A = "a".charCodeAt(0); -const CHAR_LOWERCASE_Z = "z".charCodeAt(0); - -function getPathFromURLWin32(url: URL): string { - // const hostname = url.hostname; - let pathname = url.pathname; - for (let n = 0; n < pathname.length; n++) { - if (pathname[n] === "%") { - const third = pathname.codePointAt(n + 2)! | 0x20; - if ( - (pathname[n + 1] === "2" && third === 102) || // 2f 2F / - (pathname[n + 1] === "5" && third === 99) - ) { - // 5c 5C \ - throw new Error( - "Invalid file url path: must not include encoded \\ or / characters" - ); - } - } - } - pathname = pathname.replace(forwardSlashRegEx, "\\"); - pathname = decodeURIComponent(pathname); - // TODO: handle windows hostname case (needs bindings) - const letter = pathname.codePointAt(1)! | 0x20; - const sep = pathname[2]; - if ( - letter < CHAR_LOWERCASE_A || - letter > CHAR_LOWERCASE_Z || // a..z A..Z - sep !== ":" - ) { - throw new Error("Invalid file URL path: must be absolute"); - } - return pathname.slice(1); -} - -function getPathFromURLPosix(url: URL): string { - if (url.hostname !== "") { - throw new Error("Invalid file URL host"); - } - const pathname = url.pathname; - for (let n = 0; n < pathname.length; n++) { - if (pathname[n] === "%") { - const third = pathname.codePointAt(n + 2)! | 0x20; - if (pathname[n + 1] === "2" && third === 102) { - throw new Error( - "Invalid file URL path: must not include encoded / characters" - ); - } - } - } - return decodeURIComponent(pathname); -} - -function fileURLToPath(path: string | URL): string { - if (typeof path === "string") { - path = new URL(path); - } - if (path.protocol !== "file:") { - throw new Error("Protocol has to be file://"); - } - return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path); -} - -const percentRegEx = /%/g; -const backslashRegEx = /\\/g; -const newlineRegEx = /\n/g; -const carriageReturnRegEx = /\r/g; -const tabRegEx = /\t/g; -function pathToFileURL(filepath: string): URL { - let resolved = path.resolve(filepath); - // path.resolve strips trailing slashes so we must add them back - const filePathLast = filepath.charCodeAt(filepath.length - 1); - if ( - (filePathLast === CHAR_FORWARD_SLASH || - (isWindows && filePathLast === CHAR_BACKWARD_SLASH)) && - resolved[resolved.length - 1] !== path.sep - ) { - resolved += "/"; - } - const outURL = new URL("file://"); - if (resolved.includes("%")) resolved = resolved.replace(percentRegEx, "%25"); - // In posix, "/" is a valid character in paths - if (!isWindows && resolved.includes("\\")) { - resolved = resolved.replace(backslashRegEx, "%5C"); - } - if (resolved.includes("\n")) { - resolved = resolved.replace(newlineRegEx, "%0A"); - } - if (resolved.includes("\r")) { - resolved = resolved.replace(carriageReturnRegEx, "%0D"); - } - if (resolved.includes("\t")) resolved = resolved.replace(tabRegEx, "%09"); - outURL.pathname = resolved; - return outURL; -} - export const builtinModules = Module.builtinModules; export const createRequire = Module.createRequire; export default Module; diff --git a/std/node/url.ts b/std/node/url.ts index bbf0ff5d00..b0034d02d2 100644 --- a/std/node/url.ts +++ b/std/node/url.ts @@ -72,7 +72,7 @@ function getPathFromURLWin(url: URL): string { return `\\\\${hostname}${pathname}`; } else { // Otherwise, it's a local path that requires a drive letter - const letter = pathname.codePointAt(1) || 0x20; + const letter = pathname.codePointAt(1)! | 0x20; const sep = pathname[2]; if ( letter < CHAR_LOWERCASE_A ||