mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 15:24:46 -05:00
fix(cli/rt): Fix file URL to path conversion on Windows (#6920)
This commit is contained in:
parent
0da4779b17
commit
6e7208bec2
4 changed files with 62 additions and 40 deletions
|
@ -64,23 +64,18 @@
|
|||
}
|
||||
|
||||
function pathFromURLWin32(url) {
|
||||
const hostname = url.hostname;
|
||||
const pathname = decodeURIComponent(url.pathname.replace(/\//g, "\\"));
|
||||
|
||||
if (hostname !== "") {
|
||||
//TODO(actual-size) Node adds a punycode decoding step, we should consider adding this
|
||||
return `\\\\${hostname}${pathname}`;
|
||||
let path = decodeURIComponent(
|
||||
url.pathname
|
||||
.replace(/^\/*([A-Za-z]:)(\/|$)/, "$1/")
|
||||
.replace(/\//g, "\\"),
|
||||
);
|
||||
if (url.hostname != "") {
|
||||
// Note: The `URL` implementation guarantees that the drive letter and
|
||||
// hostname are mutually exclusive. Otherwise it would not have been valid
|
||||
// to append the hostname and path like this.
|
||||
path = `\\\\${url.hostname}${path}`;
|
||||
}
|
||||
|
||||
const validPath = /^\\(?<driveLetter>[A-Za-z]):\\/;
|
||||
const matches = validPath.exec(pathname);
|
||||
|
||||
if (!matches?.groups?.driveLetter) {
|
||||
throw new TypeError("A URL with the file schema must be absolute.");
|
||||
}
|
||||
|
||||
// we don't want a leading slash on an absolute path in Windows
|
||||
return pathname.slice(1);
|
||||
return path;
|
||||
}
|
||||
|
||||
function pathFromURLPosix(url) {
|
||||
|
|
|
@ -1,31 +1,49 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { posix, win32 } from "./mod.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { assertEquals, assertThrows } from "../testing/asserts.ts";
|
||||
|
||||
Deno.test("[path] fromFileUrl", function () {
|
||||
assertEquals(posix.fromFileUrl(new URL("file:///home/foo")), "/home/foo");
|
||||
assertEquals(posix.fromFileUrl("file:///"), "/");
|
||||
assertEquals(posix.fromFileUrl("file:///home/foo"), "/home/foo");
|
||||
assertEquals(posix.fromFileUrl("file:///home/foo%20bar"), "/home/foo bar");
|
||||
assertEquals(posix.fromFileUrl("https://example.com/foo"), "/foo");
|
||||
assertEquals(posix.fromFileUrl("file:///"), "/");
|
||||
// Drive letters are supported platform-independently to align with the WHATWG
|
||||
// URL specification.
|
||||
assertEquals(posix.fromFileUrl("file:///c:"), "c:/");
|
||||
assertEquals(posix.fromFileUrl("file:///c:/"), "c:/");
|
||||
assertEquals(posix.fromFileUrl("file:///C:/"), "C:/");
|
||||
assertEquals(posix.fromFileUrl("file:///C:/Users/"), "C:/Users/");
|
||||
assertEquals(posix.fromFileUrl("file://localhost/foo"), "/foo");
|
||||
assertEquals(posix.fromFileUrl("file:///C:"), "/C:");
|
||||
assertEquals(posix.fromFileUrl("file:///C:/"), "/C:/");
|
||||
assertEquals(posix.fromFileUrl("file:///C:/Users/"), "/C:/Users/");
|
||||
assertEquals(posix.fromFileUrl("file:///C:foo/bar"), "/C:foo/bar");
|
||||
assertThrows(
|
||||
() => posix.fromFileUrl("http://localhost/foo"),
|
||||
TypeError,
|
||||
"Must be a file URL.",
|
||||
);
|
||||
assertThrows(
|
||||
() => posix.fromFileUrl("abcd://localhost/foo"),
|
||||
TypeError,
|
||||
"Must be a file URL.",
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("[path] fromFileUrl (win32)", function () {
|
||||
assertEquals(win32.fromFileUrl(new URL("file:///home/foo")), "\\home\\foo");
|
||||
assertEquals(win32.fromFileUrl("file:///"), "\\");
|
||||
assertEquals(win32.fromFileUrl("file:///home/foo"), "\\home\\foo");
|
||||
assertEquals(win32.fromFileUrl("file:///home/foo%20bar"), "\\home\\foo bar");
|
||||
assertEquals(win32.fromFileUrl("https://example.com/foo"), "\\foo");
|
||||
assertEquals(win32.fromFileUrl("file:///"), "\\");
|
||||
assertEquals(win32.fromFileUrl("file:///c:"), "c:\\");
|
||||
assertEquals(win32.fromFileUrl("file:///c:/"), "c:\\");
|
||||
assertEquals(win32.fromFileUrl("file://localhost/foo"), "\\\\localhost\\foo");
|
||||
assertEquals(win32.fromFileUrl("file:///C:"), "C:\\");
|
||||
assertEquals(win32.fromFileUrl("file:///C:/"), "C:\\");
|
||||
// Drop the hostname if a drive letter is parsed.
|
||||
assertEquals(win32.fromFileUrl("file://localhost/C:/"), "C:\\");
|
||||
assertEquals(win32.fromFileUrl("file:///C:/Users/"), "C:\\Users\\");
|
||||
assertEquals(win32.fromFileUrl("file:///C:foo/bar"), "\\C:foo\\bar");
|
||||
assertThrows(
|
||||
() => win32.fromFileUrl("http://localhost/foo"),
|
||||
TypeError,
|
||||
"Must be a file URL.",
|
||||
);
|
||||
assertThrows(
|
||||
() => win32.fromFileUrl("abcd://localhost/foo"),
|
||||
TypeError,
|
||||
"Must be a file URL.",
|
||||
);
|
||||
});
|
||||
|
|
|
@ -430,11 +430,11 @@ export function parse(path: string): ParsedPath {
|
|||
/** Converts a file URL to a path string.
|
||||
*
|
||||
* fromFileUrl("file:///home/foo"); // "/home/foo"
|
||||
*
|
||||
* Note that non-file URLs are treated as file URLs and irrelevant components
|
||||
* are ignored.
|
||||
*/
|
||||
export function fromFileUrl(url: string | URL): string {
|
||||
return decodeURIComponent((url instanceof URL ? url : new URL(url)).pathname
|
||||
.replace(/^\/*([A-Za-z]:)(\/|$)/, "$1/"));
|
||||
url = url instanceof URL ? url : new URL(url);
|
||||
if (url.protocol != "file:") {
|
||||
throw new TypeError("Must be a file URL.");
|
||||
}
|
||||
return decodeURIComponent(url.pathname);
|
||||
}
|
||||
|
|
|
@ -907,16 +907,25 @@ export function parse(path: string): ParsedPath {
|
|||
|
||||
/** Converts a file URL to a path string.
|
||||
*
|
||||
* fromFileUrl("file:///C:/Users/foo"); // "C:\\Users\\foo"
|
||||
* fromFileUrl("file:///home/foo"); // "\\home\\foo"
|
||||
*
|
||||
* Note that non-file URLs are treated as file URLs and irrelevant components
|
||||
* are ignored.
|
||||
* fromFileUrl("file:///C:/Users/foo"); // "C:\\Users\\foo"
|
||||
* fromFileUrl("file://localhost/home/foo"); // "\\\\localhost\\home\\foo"
|
||||
*/
|
||||
export function fromFileUrl(url: string | URL): string {
|
||||
return decodeURIComponent(
|
||||
(url instanceof URL ? url : new URL(url)).pathname
|
||||
url = url instanceof URL ? url : new URL(url);
|
||||
if (url.protocol != "file:") {
|
||||
throw new TypeError("Must be a file URL.");
|
||||
}
|
||||
let path = decodeURIComponent(
|
||||
url.pathname
|
||||
.replace(/^\/*([A-Za-z]:)(\/|$)/, "$1/")
|
||||
.replace(/\//g, "\\"),
|
||||
);
|
||||
if (url.hostname != "") {
|
||||
// Note: The `URL` implementation guarantees that the drive letter and
|
||||
// hostname are mutually exclusive. Otherwise it would not have been valid
|
||||
// to append the hostname and path like this.
|
||||
path = `\\\\${url.hostname}${path}`;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue