@@ -1028,16 +1028,17 @@ impl<'a> Parser<'a> {
1028
1028
let ( maybe_c, remaining) = input. split_first ( ) ;
1029
1029
// If url is special, then:
1030
1030
if scheme_type. is_special ( ) {
1031
- // If c is U+005C (\), validation error.
1032
- if maybe_c == Some ( '\\' ) {
1033
- self . log_violation ( SyntaxViolation :: Backslash ) ;
1034
- }
1035
- // If c is neither U+002F (/) nor U+005C (\), then decrease pointer by one.
1036
- if maybe_c == Some ( '/' ) || maybe_c == Some ( '\\' ) {
1037
- input = remaining;
1031
+ if let Some ( c) = maybe_c {
1032
+ if c == '\\' {
1033
+ // If c is U+005C (\), validation error.
1034
+ self . log_violation ( SyntaxViolation :: Backslash ) ;
1035
+ }
1036
+ // Set state to path state.
1037
+ return self . parse_path ( scheme_type, has_host, path_start, input) ;
1038
+ } else {
1039
+ // A special URL always has a non-empty path.
1040
+ self . serialization . push ( '/' ) ;
1038
1041
}
1039
- // Set state to path state.
1040
- return self . parse_path ( scheme_type, has_host, path_start, input) ;
1041
1042
} else if maybe_c == Some ( '?' ) {
1042
1043
// Otherwise, if state override is not given and c is U+003F (?),
1043
1044
// set url’s query to the empty string and state to query state.
@@ -1049,12 +1050,7 @@ impl<'a> Parser<'a> {
1049
1050
}
1050
1051
// Otherwise, if c is not the EOF code point:
1051
1052
if !remaining. is_empty ( ) {
1052
- if maybe_c == Some ( '/' ) {
1053
- return self . parse_path ( scheme_type, has_host, path_start, input) ;
1054
- } else {
1055
- // If c is not U+002F (/), then decrease pointer by one.
1056
- return self . parse_path ( scheme_type, has_host, path_start, remaining) ;
1057
- }
1053
+ return self . parse_path ( scheme_type, has_host, path_start, input) ;
1058
1054
}
1059
1055
input
1060
1056
}
@@ -1127,9 +1123,6 @@ impl<'a> Parser<'a> {
1127
1123
path_start : usize ,
1128
1124
mut input : Input < ' i > ,
1129
1125
) -> Input < ' i > {
1130
- if !self . serialization . ends_with ( '/' ) && scheme_type. is_special ( ) && !input. is_empty ( ) {
1131
- self . serialization . push ( '/' ) ;
1132
- }
1133
1126
// Relative path state
1134
1127
loop {
1135
1128
let segment_start = self . serialization . len ( ) ;
@@ -1151,7 +1144,7 @@ impl<'a> Parser<'a> {
1151
1144
&& scheme_type. is_special ( ) =>
1152
1145
{
1153
1146
self . log_violation ( SyntaxViolation :: Backslash ) ;
1154
- self . serialization . push ( c ) ;
1147
+ self . serialization . push ( '/' ) ;
1155
1148
ends_with_slash = true ;
1156
1149
break ;
1157
1150
}
@@ -1175,18 +1168,26 @@ impl<'a> Parser<'a> {
1175
1168
}
1176
1169
}
1177
1170
}
1171
+
1178
1172
match & self . serialization [ segment_start..] {
1173
+ // If buffer is a double-dot path segment, shorten url’s path,
1174
+ // and then if neither c is U+002F (/), nor url is special and c is U+005C (\), append the empty string to url’s path.
1179
1175
".." | "%2e%2e" | "%2e%2E" | "%2E%2e" | "%2E%2E" | "%2e." | "%2E." | ".%2e"
1180
1176
| ".%2E" => {
1181
1177
debug_assert ! ( self . serialization. as_bytes( ) [ segment_start - 1 ] == b'/' ) ;
1182
1178
self . serialization . truncate ( segment_start - 1 ) ; // Truncate "/.."
1183
1179
self . pop_path ( scheme_type, path_start) ;
1184
- if !self . serialization [ path_start.. ] . ends_with ( '/' ) {
1185
- self . serialization . push ( '/' )
1180
+ if ends_with_slash && !self . serialization . ends_with ( "/" ) {
1181
+ self . serialization . push ( '/' ) ;
1186
1182
}
1187
1183
}
1184
+ // Otherwise, if buffer is a single-dot path segment and if neither c is U+002F (/),
1185
+ // nor url is special and c is U+005C (\), append the empty string to url’s path.
1188
1186
"." | "%2e" | "%2E" => {
1189
1187
self . serialization . truncate ( segment_start) ;
1188
+ if ends_with_slash && !self . serialization . ends_with ( "/" ) {
1189
+ self . serialization . push ( '/' ) ;
1190
+ }
1190
1191
}
1191
1192
_ => {
1192
1193
if scheme_type. is_file ( )
@@ -1201,9 +1202,6 @@ impl<'a> Parser<'a> {
1201
1202
* has_host = false ; // FIXME account for this in callers
1202
1203
}
1203
1204
}
1204
- if ends_with_slash {
1205
- self . serialization . push ( '/' )
1206
- }
1207
1205
}
1208
1206
}
1209
1207
if !ends_with_slash {
0 commit comments