@@ -1046,16 +1046,17 @@ impl<'a> Parser<'a> {
1046
1046
let ( maybe_c, remaining) = input. split_first ( ) ;
1047
1047
// If url is special, then:
1048
1048
if scheme_type. is_special ( ) {
1049
- // If c is U+005C (\), validation error.
1050
- if maybe_c == Some ( '\\' ) {
1051
- self . log_violation ( SyntaxViolation :: Backslash ) ;
1052
- }
1053
- // If c is neither U+002F (/) nor U+005C (\), then decrease pointer by one.
1054
- if maybe_c == Some ( '/' ) || maybe_c == Some ( '\\' ) {
1055
- input = remaining;
1049
+ if let Some ( c) = maybe_c {
1050
+ if c == '\\' {
1051
+ // If c is U+005C (\), validation error.
1052
+ self . log_violation ( SyntaxViolation :: Backslash ) ;
1053
+ }
1054
+ // Set state to path state.
1055
+ return self . parse_path ( scheme_type, has_host, path_start, input) ;
1056
+ } else {
1057
+ // A special URL always has a non-empty path.
1058
+ self . serialization . push ( '/' ) ;
1056
1059
}
1057
- // Set state to path state.
1058
- return self . parse_path ( scheme_type, has_host, path_start, input) ;
1059
1060
} else if maybe_c == Some ( '?' ) {
1060
1061
// Otherwise, if state override is not given and c is U+003F (?),
1061
1062
// set url’s query to the empty string and state to query state.
@@ -1067,12 +1068,7 @@ impl<'a> Parser<'a> {
1067
1068
}
1068
1069
// Otherwise, if c is not the EOF code point:
1069
1070
if !remaining. is_empty ( ) {
1070
- if maybe_c == Some ( '/' ) {
1071
- return self . parse_path ( scheme_type, has_host, path_start, input) ;
1072
- } else {
1073
- // If c is not U+002F (/), then decrease pointer by one.
1074
- return self . parse_path ( scheme_type, has_host, path_start, remaining) ;
1075
- }
1071
+ return self . parse_path ( scheme_type, has_host, path_start, input) ;
1076
1072
}
1077
1073
input
1078
1074
}
@@ -1145,9 +1141,6 @@ impl<'a> Parser<'a> {
1145
1141
path_start : usize ,
1146
1142
mut input : Input < ' i > ,
1147
1143
) -> Input < ' i > {
1148
- if !self . serialization . ends_with ( '/' ) && scheme_type. is_special ( ) && !input. is_empty ( ) {
1149
- self . serialization . push ( '/' ) ;
1150
- }
1151
1144
// Relative path state
1152
1145
loop {
1153
1146
let segment_start = self . serialization . len ( ) ;
@@ -1169,7 +1162,7 @@ impl<'a> Parser<'a> {
1169
1162
&& scheme_type. is_special ( ) =>
1170
1163
{
1171
1164
self . log_violation ( SyntaxViolation :: Backslash ) ;
1172
- self . serialization . push ( c ) ;
1165
+ self . serialization . push ( '/' ) ;
1173
1166
ends_with_slash = true ;
1174
1167
break ;
1175
1168
}
@@ -1193,18 +1186,26 @@ impl<'a> Parser<'a> {
1193
1186
}
1194
1187
}
1195
1188
}
1189
+
1196
1190
match & self . serialization [ segment_start..] {
1191
+ // If buffer is a double-dot path segment, shorten url’s path,
1192
+ // 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.
1197
1193
".." | "%2e%2e" | "%2e%2E" | "%2E%2e" | "%2E%2E" | "%2e." | "%2E." | ".%2e"
1198
1194
| ".%2E" => {
1199
1195
debug_assert ! ( self . serialization. as_bytes( ) [ segment_start - 1 ] == b'/' ) ;
1200
1196
self . serialization . truncate ( segment_start - 1 ) ; // Truncate "/.."
1201
1197
self . pop_path ( scheme_type, path_start) ;
1202
- if !self . serialization [ path_start.. ] . ends_with ( '/' ) {
1203
- self . serialization . push ( '/' )
1198
+ if ends_with_slash && !self . serialization . ends_with ( "/" ) {
1199
+ self . serialization . push ( '/' ) ;
1204
1200
}
1205
1201
}
1202
+ // Otherwise, if buffer is a single-dot path segment and if neither c is U+002F (/),
1203
+ // nor url is special and c is U+005C (\), append the empty string to url’s path.
1206
1204
"." | "%2e" | "%2E" => {
1207
1205
self . serialization . truncate ( segment_start) ;
1206
+ if ends_with_slash && !self . serialization . ends_with ( "/" ) {
1207
+ self . serialization . push ( '/' ) ;
1208
+ }
1208
1209
}
1209
1210
_ => {
1210
1211
if scheme_type. is_file ( )
@@ -1219,9 +1220,6 @@ impl<'a> Parser<'a> {
1219
1220
* has_host = false ; // FIXME account for this in callers
1220
1221
}
1221
1222
}
1222
- if ends_with_slash {
1223
- self . serialization . push ( '/' )
1224
- }
1225
1223
}
1226
1224
}
1227
1225
if !ends_with_slash {
0 commit comments