diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-03-05 18:46:37 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-05 22:46:37 +0000 |
commit | 76b173b60c975fe7540d04aac5b7a40be67fe466 (patch) | |
tree | 0d1a58abce1b336e1e20ceeeeb7319030a3142b5 /ext/web/00_infra.js | |
parent | 1ab16e2426819af2c534e8a99b98f244626de512 (diff) |
refactor: move "pathFromURL" to deno_web extension (#18037)
This API is required by several extensions like "ext/node", "ext/ffi"
and also FS APIs that we want to move to a separate crate. Because
of that "pathFromURL" API was moved to "deno_web" extension so
other extension crates can rely on it.
Diffstat (limited to 'ext/web/00_infra.js')
-rw-r--r-- | ext/web/00_infra.js | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/ext/web/00_infra.js b/ext/web/00_infra.js index cff0f66d8..0c062f89c 100644 --- a/ext/web/00_infra.js +++ b/ext/web/00_infra.js @@ -7,14 +7,17 @@ /// <reference path="../web/lib.deno_web.d.ts" /> const core = globalThis.Deno.core; +const internals = globalThis.__bootstrap.internals; const ops = core.ops; const primordials = globalThis.__bootstrap.primordials; const { ArrayPrototypeJoin, ArrayPrototypeMap, + decodeURIComponent, Error, JSONStringify, NumberPrototypeToString, + ObjectPrototypeIsPrototypeOf, SafeArrayIterator, SafeRegExp, String, @@ -29,6 +32,7 @@ const { StringPrototypeToUpperCase, TypeError, } = primordials; +import { URLPrototype } from "internal:deno_url/00_url.js"; const ASCII_DIGIT = ["\u0030-\u0039"]; const ASCII_UPPER_ALPHA = ["\u0041-\u005A"]; @@ -362,6 +366,77 @@ function serializeJSValueToJSONString(value) { return result; } +const PATHNAME_WIN_RE = new SafeRegExp(/^\/*([A-Za-z]:)(\/|$)/); +const SLASH_WIN_RE = new SafeRegExp(/\//g); +const PERCENT_RE = new SafeRegExp(/%(?![0-9A-Fa-f]{2})/g); + +// Keep in sync with `fromFileUrl()` in `std/path/win32.ts`. +/** + * @param {URL} url + * @returns {string} + */ +function pathFromURLWin32(url) { + let p = StringPrototypeReplace( + url.pathname, + PATHNAME_WIN_RE, + "$1/", + ); + p = StringPrototypeReplace( + p, + SLASH_WIN_RE, + "\\", + ); + p = StringPrototypeReplace( + p, + PERCENT_RE, + "%25", + ); + let path = decodeURIComponent(p); + 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; +} + +// Keep in sync with `fromFileUrl()` in `std/path/posix.ts`. +/** + * @param {URL} url + * @returns {string} + */ +function pathFromURLPosix(url) { + if (url.hostname !== "") { + throw new TypeError(`Host must be empty.`); + } + + return decodeURIComponent( + StringPrototypeReplace( + url.pathname, + PERCENT_RE, + "%25", + ), + ); +} + +function pathFromURL(pathOrUrl) { + if (ObjectPrototypeIsPrototypeOf(URLPrototype, pathOrUrl)) { + if (pathOrUrl.protocol != "file:") { + throw new TypeError("Must be a file URL."); + } + + return core.build.os == "windows" + ? pathFromURLWin32(pathOrUrl) + : pathFromURLPosix(pathOrUrl); + } + return pathOrUrl; +} + +// NOTE(bartlomieju): this is exposed on `internals` so we can test +// it in unit tests +internals.pathFromURL = pathFromURL; + export { ASCII_ALPHA, ASCII_ALPHANUMERIC, @@ -389,6 +464,7 @@ export { HTTP_WHITESPACE_PREFIX_RE, HTTP_WHITESPACE_SUFFIX_RE, httpTrim, + pathFromURL, regexMatcher, serializeJSValueToJSONString, }; |