@@ -127,7 +127,11 @@ impl<'a> ConstructorStringParser<'a> {
127
127
}
128
128
129
129
// Ref: https://wicg.github.io/urlpattern/#change-state
130
- fn change_state ( & mut self , state : ConstructorStringParserState , skip : usize ) {
130
+ fn change_state (
131
+ & mut self ,
132
+ new_state : ConstructorStringParserState ,
133
+ skip : usize ,
134
+ ) {
131
135
match self . state {
132
136
ConstructorStringParserState :: Protocol => {
133
137
self . result . protocol = Some ( self . make_component_string ( ) )
@@ -153,10 +157,69 @@ impl<'a> ConstructorStringParser<'a> {
153
157
ConstructorStringParserState :: Hash => {
154
158
self . result . hash = Some ( self . make_component_string ( ) )
155
159
}
156
- _ => { }
160
+ ConstructorStringParserState :: Init
161
+ | ConstructorStringParserState :: Authority
162
+ | ConstructorStringParserState :: Done => { }
157
163
}
158
164
159
- self . state = state;
165
+ if self . state != ConstructorStringParserState :: Init
166
+ && new_state != ConstructorStringParserState :: Done
167
+ {
168
+ if matches ! (
169
+ self . state,
170
+ ConstructorStringParserState :: Protocol
171
+ | ConstructorStringParserState :: Authority
172
+ | ConstructorStringParserState :: Username
173
+ | ConstructorStringParserState :: Password
174
+ ) && matches ! (
175
+ new_state,
176
+ ConstructorStringParserState :: Port
177
+ | ConstructorStringParserState :: Pathname
178
+ | ConstructorStringParserState :: Search
179
+ | ConstructorStringParserState :: Hash
180
+ ) && self . result . hostname . is_none ( )
181
+ {
182
+ self . result . hostname = Some ( String :: new ( ) ) ;
183
+ }
184
+
185
+ if matches ! (
186
+ self . state,
187
+ ConstructorStringParserState :: Protocol
188
+ | ConstructorStringParserState :: Authority
189
+ | ConstructorStringParserState :: Username
190
+ | ConstructorStringParserState :: Password
191
+ | ConstructorStringParserState :: Hostname
192
+ | ConstructorStringParserState :: Port
193
+ ) && matches ! (
194
+ new_state,
195
+ ConstructorStringParserState :: Search
196
+ | ConstructorStringParserState :: Hash
197
+ ) && self . result . pathname . is_none ( )
198
+ {
199
+ if self . protocol_matches_special_scheme {
200
+ self . result . pathname = Some ( String :: from ( "/" ) ) ;
201
+ } else {
202
+ self . result . pathname = Some ( String :: new ( ) ) ;
203
+ }
204
+ }
205
+
206
+ if matches ! (
207
+ self . state,
208
+ ConstructorStringParserState :: Protocol
209
+ | ConstructorStringParserState :: Authority
210
+ | ConstructorStringParserState :: Username
211
+ | ConstructorStringParserState :: Password
212
+ | ConstructorStringParserState :: Hostname
213
+ | ConstructorStringParserState :: Port
214
+ | ConstructorStringParserState :: Pathname
215
+ ) && new_state == ConstructorStringParserState :: Hash
216
+ && self . result . search . is_none ( )
217
+ {
218
+ self . result . search = Some ( String :: new ( ) ) ;
219
+ }
220
+ }
221
+
222
+ self . state = new_state;
160
223
self . token_index += skip;
161
224
self . component_start = self . token_index ;
162
225
self . token_increment = 0 ;
@@ -273,11 +336,8 @@ pub(crate) fn parse_constructor_string<R: RegExp>(
273
336
parser. change_state ( ConstructorStringParserState :: Hash , 1 ) ;
274
337
} else if parser. is_search_prefix ( ) {
275
338
parser. change_state ( ConstructorStringParserState :: Search , 1 ) ;
276
- parser. result . hash = Some ( String :: new ( ) ) ;
277
339
} else {
278
340
parser. change_state ( ConstructorStringParserState :: Pathname , 0 ) ;
279
- parser. result . search = Some ( String :: new ( ) ) ;
280
- parser. result . hash = Some ( String :: new ( ) ) ;
281
341
}
282
342
parser. token_index += parser. token_increment ;
283
343
continue ;
@@ -306,22 +366,12 @@ pub(crate) fn parse_constructor_string<R: RegExp>(
306
366
match parser. state {
307
367
ConstructorStringParserState :: Init => {
308
368
if parser. is_protocol_suffix ( ) {
309
- parser. result . username = Some ( String :: new ( ) ) ;
310
- parser. result . password = Some ( String :: new ( ) ) ;
311
- parser. result . hostname = Some ( String :: new ( ) ) ;
312
- parser. result . port = Some ( String :: new ( ) ) ;
313
- parser. result . pathname = Some ( String :: new ( ) ) ;
314
- parser. result . search = Some ( String :: new ( ) ) ;
315
- parser. result . hash = Some ( String :: new ( ) ) ;
316
369
parser. rewind_and_set_state ( ConstructorStringParserState :: Protocol ) ;
317
370
}
318
371
}
319
372
ConstructorStringParserState :: Protocol => {
320
373
if parser. is_protocol_suffix ( ) {
321
374
parser. compute_protocol_matches_special_scheme :: < R > ( ) ?;
322
- if parser. protocol_matches_special_scheme {
323
- parser. result . pathname = Some ( String :: from ( "/" ) ) ;
324
- }
325
375
let mut next_state = ConstructorStringParserState :: Pathname ;
326
376
let mut skip = 1 ;
327
377
if parser. next_is_authority_slashes ( ) {
@@ -398,5 +448,10 @@ pub(crate) fn parse_constructor_string<R: RegExp>(
398
448
}
399
449
parser. token_index += parser. token_increment ;
400
450
}
451
+
452
+ if parser. result . hostname . is_some ( ) && parser. result . port . is_none ( ) {
453
+ parser. result . port = Some ( String :: new ( ) ) ;
454
+ }
455
+
401
456
Ok ( parser. result )
402
457
}
0 commit comments