@@ -489,25 +489,25 @@ export function findLast<T>(
489489 return undefined
490490}
491491
492- const DECODE_IGNORE_LIST = [
493- '%' ,
494- '\\' ,
495- '/' ,
496- ';' ,
497- ':' ,
498- '@' ,
499- '&' ,
500- '=' ,
501- '+' ,
502- '$' ,
503- ',' ,
504- ] . map ( ( c ) => encodeURIComponent ( c ) )
492+ const DECODE_IGNORE_LIST = new Map ( [
493+ [ '%' , '%25' ] ,
494+ [ '\\' , '%5C' ] ,
495+ [ '/' , '%2F' ] ,
496+ [ ';' , '%3B' ] ,
497+ [ ':' , '%3A' ] ,
498+ [ '@' , '%40' ] ,
499+ [ '&' , '%26' ] ,
500+ [ '=' , '%3D' ] ,
501+ [ '+' , '%2B' ] ,
502+ [ '$' , '%24' ] ,
503+ [ ',' , '%2C' ] ,
504+ ] )
505505
506506export function decodePathSegment (
507507 part : string ,
508- decodeIgnore : Array < string > = DECODE_IGNORE_LIST ,
508+ decodeIgnore : Array < string > = Array . from ( DECODE_IGNORE_LIST . values ( ) ) ,
509509 startIndex = 0 ,
510- ) {
510+ ) : string {
511511 function decode ( part : string ) {
512512 try {
513513 return decodeURIComponent ( part )
@@ -523,22 +523,36 @@ export function decodePathSegment(
523523 }
524524 }
525525
526- if ( part === '' || ! part . match ( / % ../ g) ) return part
526+ // if the path segment does not contain any encoded uri components return the path as is
527+ if ( part === '' || ! part . match ( / % [ 0 - 9 A - F a - f ] { 2 } / g) ) return part
527528
529+ // decode the path / path segment by splitting it into parts defined by the ignore list.
530+ // once these pieces have been decoded, join them back together to form the final decoded path segment with the ignored character in place.
531+ // we walk through the ignore list linearly, breaking the segment up into pieces and decoding each piece individually.
532+ // use index traversal to avoid making unnecessary copies of the array.
528533 for ( let i = startIndex ; i < decodeIgnore . length ; i ++ ) {
529534 const char = decodeIgnore [ i ]
530535
536+ // check if the part includes the current ignore character
537+ // if it doesn't continue to the next ignore character
531538 if ( char && part . includes ( char ) ) {
539+ // split the part into pieces that needs to be checked and decoded
532540 const partsToDecode = part . split ( char )
533541 const partsToJoin : Array < string > = [ ]
534542
543+ // now check and decode each piece individually taking into consideration the remaining ignored characters.
544+ // since we are walking through the list linearly, we only need to consider ignore items not yet traversed.
535545 for ( const partToDecode of partsToDecode ) {
546+ // once we have traversed the entire ignore list, each decoded part is returned.
536547 partsToJoin . push ( decodePathSegment ( partToDecode , decodeIgnore , i + 1 ) )
537548 }
538549
550+ // and join them back together to form the final decoded path segment with the ignored character in place.
539551 return partsToJoin . join ( char )
540552 }
541553 }
542554
555+ // once we have reached the end of the ignore list, we start walking back returning each decoded part.
556+ // should there be no matching characters, the path segment as a whole will be decoded.
543557 return decode ( part )
544558}
0 commit comments