@@ -39,11 +39,12 @@ const backslashRegEx = /\\/g;
3939const newlineRegEx = / \n / g;
4040const carriageReturnRegEx = / \r / g;
4141const tabRegEx = / \t / g;
42+ const questionRegex = / \? / g;
43+ const hashRegex = / # / g;
4244// https://nodejs.org/api/url.html#urlpathtofileurlpath
4345export function pathToFileURL ( filepath : string ) : URL {
4446 // https://github.com/denoland/deno_std/blob/01a401c432fd5628efd3a4fafffdc14660efe9e2/node/url.ts#L1391
4547 // Thanks 🦖!
46- const outURL = new URL ( "file://" ) ;
4748 let resolved = path . resolve ( filepath ) ;
4849 // path.resolve strips trailing slashes so we must add them back
4950 const filePathLast = filepath . charCodeAt ( filepath . length - 1 ) ;
@@ -53,24 +54,34 @@ export function pathToFileURL(filepath: string): URL {
5354 ) {
5455 resolved += "/" ;
5556 }
56- outURL . pathname = encodePathChars ( resolved ) ;
57- return outURL ;
57+ resolved = encodePathChars ( resolved ) ;
58+ // Question and hash character should be included in pathname.
59+ // Therefore, encoding is required to eliminate parsing them in different states.
60+ // This is done as an optimization to not creating a URL instance and
61+ // later triggering pathname setter, which impacts performance
62+ if ( resolved . indexOf ( "?" ) !== - 1 ) {
63+ resolved = resolved . replace ( questionRegex , "%3F" ) ;
64+ }
65+ if ( resolved . indexOf ( "#" ) !== - 1 ) {
66+ resolved = resolved . replace ( hashRegex , "%23" ) ;
67+ }
68+ return new URL ( `file://${ resolved } ` ) ;
5869}
5970function encodePathChars ( filepath : string ) : string {
60- if ( filepath . includes ( "%" ) ) {
71+ if ( filepath . indexOf ( "%" ) !== - 1 ) {
6172 filepath = filepath . replace ( percentRegEx , "%25" ) ;
6273 }
6374 // In posix, backslash is a valid character in paths:
64- if ( filepath . includes ( "\\" ) ) {
75+ if ( filepath . indexOf ( "\\" ) !== - 1 ) {
6576 filepath = filepath . replace ( backslashRegEx , "%5C" ) ;
6677 }
67- if ( filepath . includes ( "\n" ) ) {
78+ if ( filepath . indexOf ( "\n" ) !== - 1 ) {
6879 filepath = filepath . replace ( newlineRegEx , "%0A" ) ;
6980 }
70- if ( filepath . includes ( "\r" ) ) {
81+ if ( filepath . indexOf ( "\r" ) !== - 1 ) {
7182 filepath = filepath . replace ( carriageReturnRegEx , "%0D" ) ;
7283 }
73- if ( filepath . includes ( "\t" ) ) {
84+ if ( filepath . indexOf ( "\t" ) !== - 1 ) {
7485 filepath = filepath . replace ( tabRegEx , "%09" ) ;
7586 }
7687 return filepath ;
0 commit comments