1212
1313package java .net
1414
15- import scala .scalajs .js .RegExp
16- import scala .scalajs .js
17-
1815import scala .annotation .tailrec
1916
20- import java .lang .Utils ._
2117import java .nio ._
2218import java .nio .charset .{CodingErrorAction , StandardCharsets }
19+ import java .{util => ju }
20+ import java .util .ScalaOps ._
21+ import java .util .regex .RegExpImpl
2322
2423final class URI (origStr : String ) extends Serializable with Comparable [URI ] {
2524
@@ -32,14 +31,14 @@ final class URI(origStr: String) extends Serializable with Comparable[URI] {
3231 * This is a local val for the primary constructor. It is a val,
3332 * since we'll set it to null after initializing all fields.
3433 */
35- private [this ] var _fld : RegExp . ExecResult = URI .uriRe .exec(origStr)
36- if (_fld == null )
34+ private [this ] var _fld = RegExpImpl .impl .exec(URI .uriRe, origStr)
35+ if (! RegExpImpl .impl.matches( _fld) )
3736 throw new URISyntaxException (origStr, " Malformed URI" )
3837
39- private val _isAbsolute = undefOrIsDefined (_fld( AbsScheme ) )
40- private val _isOpaque = undefOrIsDefined (_fld( AbsOpaquePart ) )
38+ private val _isAbsolute = RegExpImpl .impl.exists (_fld, AbsScheme )
39+ private val _isOpaque = RegExpImpl .impl.exists (_fld, AbsOpaquePart )
4140
42- @ inline private def fld (idx : Int ): String = undefOrGetOrNull (_fld( idx) )
41+ @ inline private def fld (idx : Int ): String = RegExpImpl .impl.getOrElse (_fld, idx, null )
4342
4443 @ inline private def fld (absIdx : Int , relIdx : Int ): String =
4544 if (_isAbsolute) fld(absIdx) else fld(relIdx)
@@ -93,7 +92,7 @@ final class URI(origStr: String) extends Serializable with Comparable[URI] {
9392 private val _fragment = fld(Fragment )
9493
9594 // End of default ctor. Unset helper field
96- _fld = null
95+ _fld = null . asInstanceOf [ RegExpImpl .impl. Repr ]
9796
9897 def this (scheme : String , ssp : String , fragment : String ) =
9998 this (URI .uriStr(scheme, ssp, fragment))
@@ -217,11 +216,9 @@ final class URI(origStr: String) extends Serializable with Comparable[URI] {
217216
218217 def normalize (): URI = if (_isOpaque || _path == null ) this
219218 else {
220- import js .JSStringOps ._
221-
222219 val origPath = _path
223220
224- val segments = origPath.jsSplit (" /" )
221+ val segments = origPath.split (" /" , - 1 )
225222
226223 // Step 1: Remove all "." segments
227224 // Step 2: Remove ".." segments preceded by non ".." segment until no
@@ -279,17 +276,13 @@ final class URI(origStr: String) extends Serializable with Comparable[URI] {
279276 }
280277 }
281278
282- // Truncate `segments` at `outIdx`
283- segments.length = outIdx
284-
285279 // Step 3: If path is relative and first segment contains ":", prepend "."
286280 // segment (according to JavaDoc). If the path is absolute, the first
287281 // segment is "" so the `contains(':')` returns false.
288- if (outIdx != 0 && segments(0 ).contains(" :" ))
289- segments.unshift(" ." )
290-
291- // Now add all the segments from step 1, 2 and 3
292- val newPath = segments.join(" /" )
282+ val prependDot = outIdx != 0 && segments(0 ).contains(" :" )
283+ val normalized =
284+ ju.Arrays .asList(segments).subList(0 , outIdx).scalaOps.mkString(" " , " /" , " " )
285+ val newPath = if (prependDot) " ./" + normalized else normalized
293286
294287 // Only create new instance if anything changed
295288 if (newPath == origPath)
@@ -437,7 +430,8 @@ object URI {
437430 // (25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]) # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 (IPv4-Embedded IPv6 Address)
438431 }
439432
440- private val ipv6Re = new RegExp (" ^" + ipv6address + " $" , " i" )
433+ private val ipv6Re =
434+ RegExpImpl .impl.compile(" ^" + ipv6address + " $" , RegExpImpl .Flags .CaseInsensitive )
441435
442436 // URI syntax parser. Based on RFC2396, RFC2732 and adaptations according to
443437 // JavaDoc.
@@ -586,7 +580,7 @@ object URI {
586580 // URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
587581 val uriRef = " ^(?:" + absoluteURI + " |" + relativeURI + " )(?:#" + fragment + " )?$"
588582
589- new RegExp (uriRef, " i " )
583+ RegExpImpl .impl.compile (uriRef, RegExpImpl . Flags . CaseInsensitive )
590584 }
591585
592586 private object Fields {
@@ -643,7 +637,7 @@ object URI {
643637 resStr += quoteUserInfo(userInfo) + " @"
644638
645639 if (host != null ) {
646- if (URI .ipv6Re.test( host))
640+ if (RegExpImpl .impl.matches( RegExpImpl .impl.exec( URI .ipv6Re, host) ))
647641 resStr += " [" + host + " ]"
648642 else
649643 resStr += host
@@ -753,7 +747,8 @@ object URI {
753747 }
754748 }
755749
756- private val quoteStr : js.Function1 [String , String ] = { (str : String ) =>
750+ /** Encode a matched string as percent-encoded UTF-8 bytes. */
751+ private def quoteStrFn (str : String ): String = {
757752 val buf = StandardCharsets .UTF_8 .encode(str)
758753
759754 var res = " "
@@ -765,39 +760,41 @@ object URI {
765760 res
766761 }
767762
763+ private object QuoteStrMapper extends ju.function.Function [String , String ] {
764+ def apply (t : String ): String = quoteStrFn(t)
765+ }
766+
768767 /** matches any character not in unreserved, punct, escaped or other */
769- private val userInfoQuoteRe = new RegExp (
770- // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
771- // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=%]
772- " [\u0000 - \" #/<>?@\\ [-\\ ^`{-}" +
773- " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
774- " %(?![0-9a-f]{2})" ,
775- " ig" )
768+ private val userInfoQuoteRe = RegExpImpl .impl.compile(
769+ // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
770+ // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=%]
771+ " [\u0000 - \" #/<>?@\\ [-\\ ^`{-}" +
772+ " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
773+ " %(?![0-9a-f]{2})" ,
774+ RegExpImpl .Flags .Global | RegExpImpl .Flags .CaseInsensitive
775+ )
776776
777777 /** Quote any character not in unreserved, punct, escaped or other */
778- private def quoteUserInfo (str : String ) = {
779- import js .JSStringOps ._
780- str.jsReplace(userInfoQuoteRe, quoteStr)
781- }
778+ private def quoteUserInfo (str : String ): String =
779+ RegExpImpl .impl.replaceAll(userInfoQuoteRe, str, QuoteStrMapper )
782780
783781 /** matches any character not in unreserved, punct, escaped, other or equal
784782 * to '/' or '@'
785783 */
786- private val pathQuoteRe = new RegExp (
787- // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
788- // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=%@/]
789- " [\u0000 - \" #<>?\\ [-\\ ^`{-}" +
790- " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
791- " %(?![0-9a-f]{2})" ,
792- " ig" )
784+ private val pathQuoteRe = RegExpImpl .impl.compile(
785+ // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
786+ // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=%@/]
787+ " [\u0000 - \" #<>?\\ [-\\ ^`{-}" +
788+ " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
789+ " %(?![0-9a-f]{2})" ,
790+ RegExpImpl .Flags .Global | RegExpImpl .Flags .CaseInsensitive
791+ )
793792
794793 /** Quote any character not in unreserved, punct, escaped, other or equal
795794 * to '/' or '@'
796795 */
797- private def quotePath (str : String ) = {
798- import js .JSStringOps ._
799- str.jsReplace(pathQuoteRe, quoteStr)
800- }
796+ private def quotePath (str : String ): String =
797+ RegExpImpl .impl.replaceAll(pathQuoteRe, str, QuoteStrMapper )
801798
802799 /** matches any character not in unreserved, punct, escaped, other or equal
803800 * to '@', '[' or ']'
@@ -806,48 +803,45 @@ object URI {
806803 * in IPv6 addresses, but technically speaking they are in reserved
807804 * due to RFC2732).
808805 */
809- private val authorityQuoteRe = new RegExp (
810- // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
811- // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=%@\[\]]
812- " [\u0000 - \" #/<>?\\ ^`{-}" +
813- " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
814- " %(?![0-9a-f]{2})" ,
815- " ig" )
806+ private [this ] lazy val authorityQuoteRe = RegExpImpl .impl.compile(
807+ // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
808+ // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=%@\[\]]
809+ " [\u0000 - \" #/<>?\\ ^`{-}" +
810+ " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
811+ " %(?![0-9a-f]{2})" ,
812+ RegExpImpl .Flags .Global | RegExpImpl .Flags .CaseInsensitive
813+ )
816814
817815 /** Quote any character not in unreserved, punct, escaped, other or equal
818816 * to '@'
819817 */
820- private def quoteAuthority (str : String ) = {
821- import js .JSStringOps ._
822- str.jsReplace(authorityQuoteRe, quoteStr)
823- }
818+ private def quoteAuthority (str : String ): String =
819+ RegExpImpl .impl.replaceAll(authorityQuoteRe, str, QuoteStrMapper )
824820
825821 /** matches any character not in unreserved, reserved, escaped or other */
826- private val illegalQuoteRe = new RegExp (
827- // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
828- // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=?/\\[\\]%]
829- " [\u0000 - \" #<>@\\ ^`{-}" +
830- " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
831- " %(?![0-9a-f]{2})" ,
832- " ig" )
822+ private val illegalQuoteRe = RegExpImpl .impl.compile(
823+ // !other = [\u0000-\u00a0\u1680\u2000-\u200a\u202f\u205f\u3000\u2028\u2029]
824+ // Char class is: [:!other:^a-z0-9-_.!~*'(),;:$&+=?/\\[\\]%]
825+ " [\u0000 - \" #<>@\\ ^`{-}" +
826+ " \u007f -\u00a0\u1680\u2000 -\u200a\u202f\u205f\u3000\u2028\u2029 ]|" +
827+ " %(?![0-9a-f]{2})" ,
828+ RegExpImpl .Flags .Global | RegExpImpl .Flags .CaseInsensitive
829+ )
833830
834831 /** Quote any character not in unreserved, reserved, escaped or other */
835- private def quoteIllegal (str : String ) = {
836- import js .JSStringOps ._
837- str.jsReplace(illegalQuoteRe, quoteStr)
838- }
832+ private def quoteIllegal (str : String ): String =
833+ RegExpImpl .impl.replaceAll(illegalQuoteRe, str, QuoteStrMapper )
839834
840835 /** matches characters not in ASCII
841836 *
842837 * Note: It is important that the match is maximal, since we might encounter
843838 * surrogates that need to be encoded in one shot.
844839 */
845- private val nonASCIIQuoteRe = new RegExp (" [^\u0000 -\u007F ]+" , " g" )
840+ private val nonASCIIQuoteRe =
841+ RegExpImpl .impl.compile(" [^\u0000 -\u007F ]+" , RegExpImpl .Flags .Global )
846842
847- private def quoteNonASCII (str : String ) = {
848- import js .JSStringOps ._
849- str.jsReplace(nonASCIIQuoteRe, quoteStr)
850- }
843+ private def quoteNonASCII (str : String ): String =
844+ RegExpImpl .impl.replaceAll(nonASCIIQuoteRe, str, QuoteStrMapper )
851845
852846 /** Case-insensitive comparison that accepts `null` values.
853847 *
0 commit comments