authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-02-03 20:51:29 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-02-03 20:51:29 -08:00
logd4423c228d4eb0a749fec2db387df8b5bf522d3e
tree8d2fd2480a5230c84f1ec73310ce46a395ae6422
parent7895771e940a0d38141203bb110c40349c2bd9d0

pass parsePass with base


3 files changed, 428 insertions(+), 62 deletions(-)

generate.ts-2
......@@ -130,8 +130,6 @@ for (const c of cases) {
130130}
131131
132132w.write(`\n`);
133// prettier-ignore
134if (false)
135133for (const c of cases) {
136134 if (c.base === null) continue;
137135 if (c.failure) continue;
url.zig+160-60
......@@ -16,6 +16,7 @@ pub const URL = struct {
1616 pathname: []const u8,
1717 search: []const u8,
1818 hash: []const u8,
19 has_opaque_path: bool,
1920
2021 pub const HostKind = enum {
2122 unset,
......@@ -36,13 +37,13 @@ pub const URL = struct {
3637 if (base) |b| {
3738 const b_url = try parseBasic(alloc, b, null, null);
3839 defer alloc.free(b_url.href);
39 return parseBasic(alloc, input, b_url, null);
40 return parseBasic(alloc, input, &b_url, null);
4041 }
41 return parseBasic(alloc, input, if (base) |b| try parseBasic(alloc, b, null, null) else null, null);
42 return parseBasic(alloc, input, null, null);
4243 }
4344
4445 /// https://url.spec.whatwg.org/#concept-basic-url-parser
45 fn parseBasic(alloc: std.mem.Allocator, input: []const u8, base: ?URL, state_override: ?BasicParserState) error{ InvalidURL, OutOfMemory }!URL {
46 fn parseBasic(alloc: std.mem.Allocator, input: []const u8, base: ?*const URL, state_override: ?BasicParserState) error{ InvalidURL, OutOfMemory }!URL {
4647 // input is a scalar value string
4748 if (!std.unicode.utf8ValidateSlice(input)) return error.InvalidURL;
4849
......@@ -93,6 +94,7 @@ pub const URL = struct {
9394 var href = ManyArrayList(8 + 7, u8).init(alloc);
9495 defer href.deinit();
9596 var hostname_kind: HostKind = .unset;
97 var has_opaque_path = false;
9698 // scheme
9799 // :
98100 // //
......@@ -164,9 +166,11 @@ pub const URL = struct {
164166 }
165167 // 6. Otherwise, if url is special, base is non-null, and base’s scheme is url’s scheme:
166168 else if (isSchemeSpecial(href.items(0)) and base != null and std.mem.eql(u8, base.?.scheme(), href.items(0))) {
167 @panic("TODO");
168169 // 1. Assert: base is special (and therefore does not have an opaque path).
170 std.debug.assert(base.?.isSpecial());
171 std.debug.assert(!base.?.has_opaque_path);
169172 // 2. Set state to special relative or authority state.
173 state = .special_relative_or_authority;
170174 }
171175 // 7. Otherwise, if url is special, set state to special authority slashes state.
172176 else if (isSchemeSpecial(href.items(0))) {
......@@ -182,6 +186,7 @@ pub const URL = struct {
182186 // 9. Otherwise, set url’s path to the empty string and set state to opaque path state.
183187 else {
184188 href.clear(10);
189 has_opaque_path = true;
185190 state = .opaque_path;
186191 }
187192 }
......@@ -192,6 +197,7 @@ pub const URL = struct {
192197 pointer = 0;
193198 i = 0;
194199 c = inputl.items[i];
200 continue;
195201 }
196202 // 4. Otherwise, return failure.
197203 else {
......@@ -200,11 +206,38 @@ pub const URL = struct {
200206 },
201207 .no_scheme => {
202208 // 1. If base is null, or base has an opaque path and c is not U+0023 (#), missing-scheme-non-relative-URL validation error, return failure.
203 if (base == null) return error.InvalidURL;
209 if (base == null or (base != null and base.?.has_opaque_path and c != '#')) {
210 return error.InvalidURL;
211 }
204212 // 2. Otherwise, if base has an opaque path and c is U+0023 (#), set url’s scheme to base’s scheme, url’s path to base’s path, url’s query to base’s query, url’s fragment to the empty string, and set state to fragment state.
213 else if (base.?.has_opaque_path and c == '#') {
214 try href.set(0, base.?.scheme());
215 try href.set(1, ":");
216 try href.set(7, base.?.hostname);
217 hostname_kind = base.?.hostname_kind;
218 try href.set(10, base.?.pathname);
219 has_opaque_path = base.?.has_opaque_path;
220 try href.set(12, base.?.query());
221 try href.set(13, "#");
222 try href.set(14, "");
223 state = .fragment;
224 }
205225 // 3. Otherwise, if base’s scheme is not "file", set state to relative state and decrease pointer by 1.
226 else if (!std.mem.eql(u8, base.?.scheme(), "file")) {
227 state = .relative;
228 if (pointer == 0) continue; // pointer goes to -1 then +1'd
229 pointer -= 1;
230 i = lastcpi(inputl.items[0..i]);
231 c = inputl.items[i];
232 }
206233 // 4. Otherwise, set state to file state and decrease pointer by 1.
207 return error.InvalidURL;
234 else {
235 state = .file;
236 if (pointer == 0) continue; // pointer goes to -1 then +1'd
237 pointer -= 1;
238 i = lastcpi(inputl.items[0..i]);
239 c = inputl.items[i];
240 }
208241 },
209242 .special_relative_or_authority => {
210243 // 1. If c is U+002F (/) and remaining starts with U+002F (/), then set state to special authority ignore slashes state and increase pointer by 1.
......@@ -217,7 +250,9 @@ pub const URL = struct {
217250 // 2. Otherwise, special-scheme-missing-following-solidus validation error, set state to relative state and decrease pointer by 1.
218251 else {
219252 state = .relative;
220 @panic("TODO");
253 pointer -= 1;
254 i = lastcpi(inputl.items[0..i]);
255 c = inputl.items[i];
221256 }
222257 },
223258 .path_or_authority => {
......@@ -231,7 +266,6 @@ pub const URL = struct {
231266 pointer -= 1;
232267 i = lastcpi(inputl.items[0..i]);
233268 c = inputl.items[i];
234 try href.appendSlice(10, "/");
235269 }
236270 },
237271 .relative => {
......@@ -251,12 +285,14 @@ pub const URL = struct {
251285 // 5. Otherwise:
252286 else {
253287 // 1. Set url’s username to base’s username, url’s password to base’s password, url’s host to base’s host, url’s port to base’s port, url’s path to a clone of base’s path, and url’s query to base’s query.
254 // try username.appendSlice(base.?.username);
255 // try password.appendSlice(base.?.password);
256 // host = base.?.host;
257 // try port.writer().print("{d}", .{base.?.port.?});
258 // try path.appendSlice(base.?.path);
259 // try query.appendSlice(base.?.query.?);
288 try href.set(3, base.?.username);
289 try href.set(5, base.?.password);
290 try href.set(7, base.?.hostname);
291 hostname_kind = base.?.hostname_kind;
292 try href.set(9, base.?.port);
293 try href.set(10, base.?.pathname);
294 has_opaque_path = base.?.has_opaque_path;
295 try href.set(12, base.?.query());
260296 // 2. If c is U+003F (?), then set url’s query to the empty string, and state to query state.
261297 if (c == '?') {
262298 href.clear(12);
......@@ -274,12 +310,13 @@ pub const URL = struct {
274310 // 1. Set url’s query to null.
275311 href.clear(12);
276312 // 2. Shorten url’s path.
277 @panic("TODO");
313 shortenUrlPath(&href, has_opaque_path);
278314 // 3. Set state to path state and decrease pointer by 1.
279 // state = .path;
280 // pointer -= 1;
281 // i = lastcpi(inputl.items[0..i]);
282 // c = inputl.items[i];
315 state = .path;
316 if (pointer == 0) continue; // pointer goes to -1 then +1'd
317 pointer -= 1;
318 i = lastcpi(inputl.items[0..i]);
319 c = inputl.items[i];
283320 }
284321 }
285322 },
......@@ -296,15 +333,16 @@ pub const URL = struct {
296333 }
297334 // 3. Otherwise, set url’s username to base’s username, url’s password to base’s password, url’s host to base’s host, url’s port to base’s port, state to path state, and then, decrease pointer by 1.
298335 else {
299 // try username.appendSlice(base.?.username);
300 // try password.appendSlice(base.?.password);
301 // host = base.?.host;
302 // try port.writer().print("{d}", .{base.?.port.?});
336 try href.set(3, base.?.username);
337 try href.set(5, base.?.password);
338 try href.set(7, base.?.hostname);
339 hostname_kind = base.?.hostname_kind;
340 try href.set(9, base.?.port);
303341 state = .path;
342 if (pointer == 0) continue; // pointer goes to -1 then +1'd
304343 pointer -= 1;
305344 i = lastcpi(inputl.items[0..i]);
306345 c = inputl.items[i];
307 @panic("TODO");
308346 }
309347 },
310348 .special_authority_slashes => {
......@@ -340,6 +378,7 @@ pub const URL = struct {
340378 // 1. If c is U+0040 (@), then:
341379 if (c == '@') {
342380 // 1. Invalid-credentials validation error.
381 {}
343382 // 2. If atSignSeen is true, then prepend "%40" to buffer.
344383 if (atSignSeen) try buffer.insertSlice(0, "%40");
345384 // 3. Set atSignSeen to true.
......@@ -496,9 +535,11 @@ pub const URL = struct {
496535 // 4. Otherwise, if base is non-null and base’s scheme is "file":
497536 else if (base != null and std.mem.eql(u8, base.?.scheme(), "file")) {
498537 // 1. Set url’s host to base’s host, url’s path to a clone of base’s path, and url’s query to base’s query.
499 // host = base.?.host;
500 // try path.appendSlice(base.?.path.?);
501 // try query.appendSlice(base.?.query.?);
538 try href.set(7, base.?.hostname);
539 hostname_kind = base.?.hostname_kind;
540 try href.set(10, base.?.pathname);
541 has_opaque_path = base.?.has_opaque_path;
542 try href.set(12, base.?.query());
502543 // 2. If c is U+003F (?), then set url’s query to the empty string and state to query state.
503544 if (c == '?') {
504545 href.clear(12);
......@@ -516,15 +557,20 @@ pub const URL = struct {
516557 // 1. Set url’s query to null.
517558 href.clear(12);
518559 // 2. If the code point substring from pointer to the end of input does not start with a Windows drive letter, then shorten url’s path.
560 if (!startsWithWindowsDriveLetter(inputl.items[i..])) {
561 shortenUrlPath(&href, has_opaque_path);
562 }
519563 // 3. Otherwise:
520564 // This is a (platform-independent) Windows drive letter quirk.
521 if (builtin.target.os.tag == .windows) @compileError("TODO");
522 {
565 else {
523566 // 1. File-invalid-Windows-drive-letter validation error.
567 {}
524568 // 2. Set url’s path to « ».
569 href.clear(10);
525570 }
526571 // 4. Set state to path state and decrease pointer by 1.
527572 state = .path;
573 if (pointer == 0) continue; // pointer goes to -1 then +1'd
528574 pointer -= 1;
529575 i = lastcpi(inputl.items[0..i]);
530576 c = inputl.items[i];
......@@ -536,7 +582,6 @@ pub const URL = struct {
536582 pointer -= 1;
537583 i = lastcpi(inputl.items[0..i]);
538584 c = inputl.items[i];
539 try href.appendSlice(10, "/");
540585 }
541586 },
542587 .file_slash => {
......@@ -552,17 +597,24 @@ pub const URL = struct {
552597 // 1. If base is non-null and base’s scheme is "file", then:
553598 if (base != null and std.mem.eql(u8, base.?.scheme(), "file")) {
554599 // 1. Set url’s host to base’s host.
555 // host = base.?.host;
600 try href.set(7, base.?.hostname);
601 hostname_kind = base.?.hostname_kind;
556602 // 2. If the code point substring from pointer to the end of input does not start with a Windows drive letter and base’s path[0] is a normalized Windows drive letter, then append base’s path[0] to url’s path.
557603 // > This is a (platform-independent) Windows drive letter quirk.
558 if (builtin.target.os.tag == .windows) @compileError("TODO");
604 if (!startsWithWindowsDriveLetter(inputl.items[i..])) {
605 const base_path0 = nthScalarItem(u8, base.?.pathname, '/', 1);
606 if (isNormalizedWindowsDriveLetter(base_path0)) {
607 try href.appendSlice(10, "/");
608 try href.appendSlice(10, base_path0);
609 }
610 }
559611 }
560612 // 2. Set state to path state, and decrease pointer by 1.
561613 state = .path;
614 if (pointer == 0) continue; // pointer goes to -1 then +1'd
562615 pointer -= 1;
563616 i = lastcpi(inputl.items[0..i]);
564617 c = inputl.items[i];
565 try href.appendSlice(10, "/");
566618 }
567619 },
568620 .file_host => {
......@@ -575,7 +627,6 @@ pub const URL = struct {
575627 // > This is a (platform-independent) Windows drive letter quirk. buffer is not reset here and instead used in the path state.
576628 if (state_override == null and isWindowsDriveLetter(buffer.items)) {
577629 state = .path;
578 try href.appendSlice(10, "/");
579630 }
580631 // 2. Otherwise, if buffer is the empty string, then:
581632 else if (buffer.items.len == 0) {
......@@ -626,7 +677,6 @@ pub const URL = struct {
626677 i = lastcpi(inputl.items[0..i]);
627678 c = inputl.items[i];
628679 }
629 try href.appendSlice(10, "/");
630680 }
631681 // 2. Otherwise, if state override is not given and c is U+003F (?), set url’s query to the empty string and state to query state.
632682 else if (state_override == null and c == '?') {
......@@ -649,8 +699,6 @@ pub const URL = struct {
649699 pointer -= 1;
650700 i = lastcpi(inputl.items[0..i]);
651701 c = inputl.items[i];
652 } else {
653 try href.appendSlice(10, &.{c});
654702 }
655703 }
656704 // 5. Otherwise, if state override is given and url’s host is null, append the empty string to url’s path.
......@@ -671,29 +719,28 @@ pub const URL = struct {
671719 {}
672720 // 2. If buffer is a double-dot URL path segment, then:
673721 if (isDoubleDotPathSeg(buffer.items)) {
674 const olen = href.lengths[10];
675 const idx = std.mem.lastIndexOfScalar(u8, href.items(10)[0 .. olen - 1], '/') orelse 0;
676 try href.replace(10, idx + 1, olen - idx - 1, "");
677722 // 1. Shorten url’s path.
723 shortenUrlPath(&href, has_opaque_path);
678724 // 2. If neither c is U+002F (/), nor url is special and c is U+005C (\), append the empty string to url’s path.
679725 // > This means that for input /usr/.. the result is / and not a lack of a path.
726 if (!is_lsep and !is_rsep) {
727 try href.appendSlice(10, "/");
728 }
680729 }
681730 // 3. Otherwise, if buffer is a single-dot URL path segment and if neither c is U+002F (/), nor url is special and c is U+005C (\), append the empty string to url’s path.
682 else if (isSingleDotPathSeg(buffer.items) and (c != '/' or !(is_rsep))) {
683 // =no action needed
731 else if (isSingleDotPathSeg(buffer.items) and !is_lsep and !is_rsep) {
732 try href.appendSlice(10, "/");
684733 }
685734 // 4. Otherwise, if buffer is not a single-dot URL path segment, then:
686735 else if (!isSingleDotPathSeg(buffer.items)) {
687736 // 1. If url’s scheme is "file", url’s path is empty, and buffer is a Windows drive letter, then replace the second code point in buffer with U+003A (:).
688737 // > This is a (platform-independent) Windows drive letter quirk.
689 if (std.mem.eql(u8, href.items(0), "file") and href.lengths[10] <= 1 and isWindowsDriveLetter(buffer.items)) {
738 if (std.mem.eql(u8, href.items(0), "file") and href.lengths[10] == 0 and isWindowsDriveLetter(buffer.items)) {
690739 buffer.items[1] = ':';
691740 }
692741 // 2. Append buffer to url’s path.
693 // if (!std.mem.endsWith(u8, href.items(10), "/")) try href.appendSlice(10, "/");
742 try href.appendSlice(10, "/");
694743 try href.appendSlice(10, buffer.items);
695 if (is_lsep) try href.appendSlice(10, "/");
696 if (is_rsep) try href.appendSlice(10, "/");
697744 }
698745 // 5. Set buffer to the empty string.
699746 buffer.clearRetainingCapacity();
......@@ -766,6 +813,7 @@ pub const URL = struct {
766813 // - url is not special
767814 // - url’s scheme is "ws" or "wss"
768815 // then set encoding to UTF-8.
816 {}
769817 // 2. If one of the following is true:
770818 // - state override is not given and c is U+0023 (#)
771819 // - c is the EOF code point
......@@ -812,14 +860,10 @@ pub const URL = struct {
812860 }
813861
814862 // If after a run pointer points to the EOF code point, go to the next step. Otherwise, increase pointer by 1 and continue with the state machine.
815 if (i == length) {
816 if (state == .fragment) break;
817 state = @enumFromInt(@intFromEnum(state) + 1);
818 } else {
819 i += l(c);
820 c = if (i < length) inputl.items[i] else 0;
821 pointer += 1;
822 }
863 if (i == length) break;
864 i += l(c);
865 c = if (i < length) inputl.items[i] else 0;
866 pointer += 1;
823867 }
824868
825869 if (hostname_kind != .unset) {
......@@ -834,6 +878,12 @@ pub const URL = struct {
834878 if (href.lengths[9] > 0) {
835879 try href.set(8, ":");
836880 }
881 if (href.lengths[12] > 0) {
882 try href.set(11, "?");
883 }
884 if (href.lengths[14] > 0) {
885 try href.set(13, "#");
886 }
837887
838888 var path_offset: usize = 0;
839889 if (hostname_kind == .unset and std.mem.startsWith(u8, href.items(10), "//")) {
......@@ -855,6 +905,7 @@ pub const URL = struct {
855905 .pathname = _href[extras.sum(usize, href.lengths[0..10])..][0..href.lengths[10]][path_offset..],
856906 .search = if (href.lengths[12] == 0) "" else _href[extras.sum(usize, href.lengths[0..11])..][0..extras.sum(usize, href.lengths[11..][0..2])],
857907 .hash = if (href.lengths[14] == 0) "" else _href[extras.sum(usize, href.lengths[0..13])..][0..extras.sum(usize, href.lengths[13..][0..2])],
908 .has_opaque_path = has_opaque_path,
858909 };
859910 return url;
860911 }
......@@ -890,6 +941,16 @@ pub const URL = struct {
890941 pub fn scheme(u: *const URL) []const u8 {
891942 return u.protocol[0 .. u.protocol.len - 1];
892943 }
944
945 pub fn query(u: *const URL) []const u8 {
946 if (u.search.len == 0) return "";
947 return u.search[1..]; // search includes '?'
948 }
949
950 pub fn fragment(u: *const URL) []const u8 {
951 if (u.hash.len == 0) return "";
952 return u.hash[1..]; // hash includes '#'
953 }
893954};
894955
895956/// https://url.spec.whatwg.org/#special-scheme
......@@ -938,6 +999,24 @@ fn isWindowsDriveLetter(buffer: []const u8) bool {
938999 return true;
9391000}
9401001
1002/// https://url.spec.whatwg.org/#normalized-windows-drive-letter
1003fn isNormalizedWindowsDriveLetter(buffer: []const u8) bool {
1004 if (buffer.len != 2) return false;
1005 if (!std.ascii.isAlphabetic(buffer[0])) return false;
1006 if (!(buffer[1] == ':')) return false;
1007 return true;
1008}
1009
1010/// https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
1011fn startsWithWindowsDriveLetter(buffer: []const u8) bool {
1012 if (buffer.len < 2) return false;
1013 if (!std.ascii.isAlphabetic(buffer[0])) return false;
1014 if (!(buffer[1] == ':' or buffer[1] == '|')) return false;
1015 if (buffer.len == 2) return true;
1016 if (!(buffer[2] == '/' or buffer[2] == '\\' or buffer[2] == '?' or buffer[2] == '#')) return false;
1017 return true;
1018}
1019
9411020/// https://url.spec.whatwg.org/#concept-host-parser
9421021fn parseHost(allocator: std.mem.Allocator, input: []u8, isOpaque: bool) !URL.Host {
9431022 // 1. If input starts with U+005B ([), then:
......@@ -963,7 +1042,7 @@ fn parseHost(allocator: std.mem.Allocator, input: []u8, isOpaque: bool) !URL.Hos
9631042 // 7. If asciiDomain ends in a number, then return the result of IPv4 parsing asciiDomain.
9641043 if (endsInANumber(asciidomain)) {
9651044 defer allocator.free(asciidomain);
966 const adr = try parseIPv4(input);
1045 const adr = try parseIPv4(asciidomain);
9671046 return .{ .ipv4 = adr };
9681047 }
9691048 // 8. Return asciiDomain.
......@@ -1031,7 +1110,7 @@ fn parseIPv6(input: []const u8) !u128 {
10311110 // 4. Let numbersSeen be 0.
10321111 var numbersSeen: usize = 0;
10331112 // 5. While c is not the EOF code point:
1034 if (pointer < input.len) {
1113 while (pointer < input.len) {
10351114 // 1. Let ipv4Piece be null.
10361115 var ipv4Piece: ?u16 = null;
10371116 // 2. If numbersSeen is greater than 0, then:
......@@ -1046,9 +1125,9 @@ fn parseIPv6(input: []const u8) !u128 {
10461125 }
10471126 }
10481127 // 3. If c is not an ASCII digit, IPv4-in-IPv6-invalid-code-point validation error, return failure.
1049 if (!std.ascii.isDigit(input[pointer])) return error.InvalidURL;
1128 if (pointer == input.len or !std.ascii.isDigit(input[pointer])) return error.InvalidURL;
10501129 // 4. While c is an ASCII digit:
1051 while (std.ascii.isDigit(input[pointer])) {
1130 while (pointer < input.len and std.ascii.isDigit(input[pointer])) {
10521131 // 1. Let number be c interpreted as decimal number.
10531132 const dec_alpha = "0123456789";
10541133 const number: u8 = @intCast(std.mem.indexOfScalar(u8, dec_alpha, input[pointer]).?);
......@@ -1196,7 +1275,7 @@ fn endsInANumber(input: []const u8) bool {
11961275 var end = input.len;
11971276 var start: usize = if (std.mem.lastIndexOfScalar(u8, input[0..end], '.')) |i| i + 1 else 0;
11981277 if (end - start == 0) {
1199 if (std.mem.count(u8, input, ".") == 0) return false;
1278 if (extras.countScalar(u8, input, '.') == 0) return false;
12001279 end = start - 1;
12011280 start = if (std.mem.lastIndexOfScalar(u8, input[0..end], '.')) |i| i + 1 else 0;
12021281 }
......@@ -1210,7 +1289,7 @@ fn endsInANumber(input: []const u8) bool {
12101289fn parseIPv4(input: []const u8) !u32 {
12111290 // 1. Let parts be the result of strictly splitting input on U+002E (.).
12121291 var end = input.len;
1213 var parts_size = std.mem.count(u8, input[0..end], ".") + 1;
1292 var parts_size = extras.countScalar(u8, input[0..end], '.') + 1;
12141293 // 2. If the last item in parts is the empty string, then:
12151294 if (std.mem.endsWith(u8, input, ".")) {
12161295 // 1. IPv4-empty-part validation error.
......@@ -1305,6 +1384,21 @@ fn parseIPv4Number(input_: []const u8, T: type) !T {
13051384 return output;
13061385}
13071386
1387/// https://url.spec.whatwg.org/#shorten-a-urls-path
1388fn shortenUrlPath(url: *ManyArrayList(15, u8), has_opaque_path: bool) void {
1389 // 1. Assert: url does not have an opaque path.
1390 std.debug.assert(!has_opaque_path);
1391 // 2. Let path be url’s path.
1392 const path = url.items(10);
1393 // 3. If url’s scheme is "file", path’s size is 1, and path[0] is a normalized Windows drive letter, then return.
1394 if (std.mem.eql(u8, url.items(0), "file") and extras.countScalar(u8, path, '/') == 1 and isNormalizedWindowsDriveLetter(nthScalarItem(u8, path, '/', 1))) {
1395 return;
1396 }
1397 // 4. Remove path’s last item, if any.
1398 const new_len = std.mem.lastIndexOfScalar(u8, path, '/') orelse return;
1399 url.replace(10, new_len, path.len - new_len, "") catch unreachable;
1400}
1401
13081402//
13091403//
13101404//
......@@ -1562,6 +1656,12 @@ pub fn replaceInPlace(comptime T: type, input: []T, needle: []const T, replaceme
15621656 }
15631657 return replacements;
15641658}
1659fn nthScalarItem(T: type, haystack: []const u8, needle: T, index: usize) []const T {
1660 var it = std.mem.splitScalar(T, haystack, needle);
1661 var idx: usize = 0;
1662 while (idx < index) : (idx += 1) _ = it.next().?;
1663 return it.next().?;
1664}
15651665
15661666pub fn ManyArrayList(N: usize, T: type) type {
15671667 return struct {
zig-out/test.zig+268
......@@ -658,6 +658,274 @@ test { try parsePass("non-special:\\/opaque", null, "non-special:\\/opaque", "nu
658658test { try parsePass("non-special:/\\path", null, "non-special:/\\path", "null", "non-special:", "", "", "", "", "", "/\\path", "", ""); }
659659test { try parsePass("non-special://host/a\\b", null, "non-special://host/a\\b", "null", "non-special:", "", "", "host", "host", "", "/a\\b", "", ""); }
660660
661test { try parsePass("http://example\t.\norg", "http://example.org/foo/bar", "http://example.org/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/", "", ""); }
662test { try parsePass("http://user:pass@foo:21/bar;par?b#c", "http://example.org/foo/bar", "http://user:pass@foo:21/bar;par?b#c", "http://foo:21", "http:", "user", "pass", "foo:21", "foo", "21", "/bar;par", "?b", "#c"); }
663test { try parsePass("http:foo.com", "http://example.org/foo/bar", "http://example.org/foo/foo.com", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/foo.com", "", ""); }
664test { try parsePass("\t :foo.com \n", "http://example.org/foo/bar", "http://example.org/foo/:foo.com", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:foo.com", "", ""); }
665test { try parsePass(" foo.com ", "http://example.org/foo/bar", "http://example.org/foo/foo.com", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/foo.com", "", ""); }
666test { try parsePass("a:\t foo.com", "http://example.org/foo/bar", "a: foo.com", "null", "a:", "", "", "", "", "", " foo.com", "", ""); }
667test { try parsePass("http://f:21/ b ? d # e ", "http://example.org/foo/bar", "http://f:21/%20b%20?%20d%20#%20e", "http://f:21", "http:", "", "", "f:21", "f", "21", "/%20b%20", "?%20d%20", "#%20e"); }
668test { try parsePass("http://f:/c", "http://example.org/foo/bar", "http://f/c", "http://f", "http:", "", "", "f", "f", "", "/c", "", ""); }
669test { try parsePass("http://f:0/c", "http://example.org/foo/bar", "http://f:0/c", "http://f:0", "http:", "", "", "f:0", "f", "0", "/c", "", ""); }
670test { try parsePass("http://f:00000000000000/c", "http://example.org/foo/bar", "http://f:0/c", "http://f:0", "http:", "", "", "f:0", "f", "0", "/c", "", ""); }
671test { try parsePass("http://f:00000000000000000000080/c", "http://example.org/foo/bar", "http://f/c", "http://f", "http:", "", "", "f", "f", "", "/c", "", ""); }
672test { try parsePass("http://f:\n/c", "http://example.org/foo/bar", "http://f/c", "http://f", "http:", "", "", "f", "f", "", "/c", "", ""); }
673test { try parsePass("", "http://example.org/foo/bar", "http://example.org/foo/bar", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", ""); }
674test { try parsePass(" \t", "http://example.org/foo/bar", "http://example.org/foo/bar", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", ""); }
675test { try parsePass(":foo.com/", "http://example.org/foo/bar", "http://example.org/foo/:foo.com/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:foo.com/", "", ""); }
676test { try parsePass(":foo.com\\", "http://example.org/foo/bar", "http://example.org/foo/:foo.com/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:foo.com/", "", ""); }
677test { try parsePass(":", "http://example.org/foo/bar", "http://example.org/foo/:", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:", "", ""); }
678test { try parsePass(":a", "http://example.org/foo/bar", "http://example.org/foo/:a", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:a", "", ""); }
679test { try parsePass(":/", "http://example.org/foo/bar", "http://example.org/foo/:/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:/", "", ""); }
680test { try parsePass(":\\", "http://example.org/foo/bar", "http://example.org/foo/:/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:/", "", ""); }
681test { try parsePass(":#", "http://example.org/foo/bar", "http://example.org/foo/:#", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:", "", ""); }
682test { try parsePass("#", "http://example.org/foo/bar", "http://example.org/foo/bar#", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", ""); }
683test { try parsePass("#/", "http://example.org/foo/bar", "http://example.org/foo/bar#/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", "#/"); }
684test { try parsePass("#\\", "http://example.org/foo/bar", "http://example.org/foo/bar#\\", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", "#\\"); }
685test { try parsePass("#;?", "http://example.org/foo/bar", "http://example.org/foo/bar#;?", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", "#;?"); }
686test { try parsePass("?", "http://example.org/foo/bar", "http://example.org/foo/bar?", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", ""); }
687test { try parsePass("/", "http://example.org/foo/bar", "http://example.org/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/", "", ""); }
688test { try parsePass(":23", "http://example.org/foo/bar", "http://example.org/foo/:23", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:23", "", ""); }
689test { try parsePass("/:23", "http://example.org/foo/bar", "http://example.org/:23", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/:23", "", ""); }
690test { try parsePass("\\x", "http://example.org/foo/bar", "http://example.org/x", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/x", "", ""); }
691test { try parsePass("\\\\x\\hello", "http://example.org/foo/bar", "http://x/hello", "http://x", "http:", "", "", "x", "x", "", "/hello", "", ""); }
692test { try parsePass("::", "http://example.org/foo/bar", "http://example.org/foo/::", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/::", "", ""); }
693test { try parsePass("::23", "http://example.org/foo/bar", "http://example.org/foo/::23", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/::23", "", ""); }
694test { try parsePass("foo://", "http://example.org/foo/bar", "foo://", "null", "foo:", "", "", "", "", "", "", "", ""); }
695test { try parsePass("http://a:b@c:29/d", "http://example.org/foo/bar", "http://a:b@c:29/d", "http://c:29", "http:", "a", "b", "c:29", "c", "29", "/d", "", ""); }
696test { try parsePass("http::@c:29", "http://example.org/foo/bar", "http://example.org/foo/:@c:29", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/:@c:29", "", ""); }
697test { try parsePass("http://&a:foo(b]c@d:2/", "http://example.org/foo/bar", "http://&a:foo(b%5Dc@d:2/", "http://d:2", "http:", "&a", "foo(b%5Dc", "d:2", "d", "2", "/", "", ""); }
698test { try parsePass("http://::@c@d:2", "http://example.org/foo/bar", "http://:%3A%40c@d:2/", "http://d:2", "http:", "", "%3A%40c", "d:2", "d", "2", "/", "", ""); }
699test { try parsePass("http://foo.com:b@d/", "http://example.org/foo/bar", "http://foo.com:b@d/", "http://d", "http:", "foo.com", "b", "d", "d", "", "/", "", ""); }
700test { try parsePass("http://foo.com/\\@", "http://example.org/foo/bar", "http://foo.com//@", "http://foo.com", "http:", "", "", "foo.com", "foo.com", "", "//@", "", ""); }
701test { try parsePass("http:\\\\foo.com\\", "http://example.org/foo/bar", "http://foo.com/", "http://foo.com", "http:", "", "", "foo.com", "foo.com", "", "/", "", ""); }
702test { try parsePass("http:\\\\a\\b:c\\d@foo.com\\", "http://example.org/foo/bar", "http://a/b:c/d@foo.com/", "http://a", "http:", "", "", "a", "a", "", "/b:c/d@foo.com/", "", ""); }
703test { try parsePass("foo:/", "http://example.org/foo/bar", "foo:/", "null", "foo:", "", "", "", "", "", "/", "", ""); }
704test { try parsePass("foo:/bar.com/", "http://example.org/foo/bar", "foo:/bar.com/", "null", "foo:", "", "", "", "", "", "/bar.com/", "", ""); }
705test { try parsePass("foo://///////", "http://example.org/foo/bar", "foo://///////", "null", "foo:", "", "", "", "", "", "///////", "", ""); }
706test { try parsePass("foo://///////bar.com/", "http://example.org/foo/bar", "foo://///////bar.com/", "null", "foo:", "", "", "", "", "", "///////bar.com/", "", ""); }
707test { try parsePass("foo:////://///", "http://example.org/foo/bar", "foo:////://///", "null", "foo:", "", "", "", "", "", "//://///", "", ""); }
708test { try parsePass("c:/foo", "http://example.org/foo/bar", "c:/foo", "null", "c:", "", "", "", "", "", "/foo", "", ""); }
709test { try parsePass("//foo/bar", "http://example.org/foo/bar", "http://foo/bar", "http://foo", "http:", "", "", "foo", "foo", "", "/bar", "", ""); }
710test { try parsePass("http://foo/path;a??e#f#g", "http://example.org/foo/bar", "http://foo/path;a??e#f#g", "http://foo", "http:", "", "", "foo", "foo", "", "/path;a", "??e", "#f#g"); }
711test { try parsePass("http://foo/abcd?efgh?ijkl", "http://example.org/foo/bar", "http://foo/abcd?efgh?ijkl", "http://foo", "http:", "", "", "foo", "foo", "", "/abcd", "?efgh?ijkl", ""); }
712test { try parsePass("http://foo/abcd#foo?bar", "http://example.org/foo/bar", "http://foo/abcd#foo?bar", "http://foo", "http:", "", "", "foo", "foo", "", "/abcd", "", "#foo?bar"); }
713test { try parsePass("[61:24:74]:98", "http://example.org/foo/bar", "http://example.org/foo/[61:24:74]:98", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/[61:24:74]:98", "", ""); }
714test { try parsePass("http:[61:27]/:foo", "http://example.org/foo/bar", "http://example.org/foo/[61:27]/:foo", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/[61:27]/:foo", "", ""); }
715test { try parsePass("http://[2001::1]", "http://example.org/foo/bar", "http://[2001::1]/", "http://[2001::1]", "http:", "", "", "[2001::1]", "[2001::1]", "", "/", "", ""); }
716test { try parsePass("http://[::127.0.0.1]", "http://example.org/foo/bar", "http://[::7f00:1]/", "http://[::7f00:1]", "http:", "", "", "[::7f00:1]", "[::7f00:1]", "", "/", "", ""); }
717test { try parsePass("http://[0:0:0:0:0:0:13.1.68.3]", "http://example.org/foo/bar", "http://[::d01:4403]/", "http://[::d01:4403]", "http:", "", "", "[::d01:4403]", "[::d01:4403]", "", "/", "", ""); }
718test { try parsePass("http://[2001::1]:80", "http://example.org/foo/bar", "http://[2001::1]/", "http://[2001::1]", "http:", "", "", "[2001::1]", "[2001::1]", "", "/", "", ""); }
719test { try parsePass("http:/example.com/", "http://example.org/foo/bar", "http://example.org/example.com/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/example.com/", "", ""); }
720test { try parsePass("ftp:/example.com/", "http://example.org/foo/bar", "ftp://example.com/", "ftp://example.com", "ftp:", "", "", "example.com", "example.com", "", "/", "", ""); }
721test { try parsePass("https:/example.com/", "http://example.org/foo/bar", "https://example.com/", "https://example.com", "https:", "", "", "example.com", "example.com", "", "/", "", ""); }
722test { try parsePass("madeupscheme:/example.com/", "http://example.org/foo/bar", "madeupscheme:/example.com/", "null", "madeupscheme:", "", "", "", "", "", "/example.com/", "", ""); }
723test { try parsePass("file:/example.com/", "http://example.org/foo/bar", "file:///example.com/", "", "file:", "", "", "", "", "", "/example.com/", "", ""); }
724test { try parsePass("ftps:/example.com/", "http://example.org/foo/bar", "ftps:/example.com/", "null", "ftps:", "", "", "", "", "", "/example.com/", "", ""); }
725test { try parsePass("gopher:/example.com/", "http://example.org/foo/bar", "gopher:/example.com/", "null", "gopher:", "", "", "", "", "", "/example.com/", "", ""); }
726test { try parsePass("ws:/example.com/", "http://example.org/foo/bar", "ws://example.com/", "ws://example.com", "ws:", "", "", "example.com", "example.com", "", "/", "", ""); }
727test { try parsePass("wss:/example.com/", "http://example.org/foo/bar", "wss://example.com/", "wss://example.com", "wss:", "", "", "example.com", "example.com", "", "/", "", ""); }
728test { try parsePass("data:/example.com/", "http://example.org/foo/bar", "data:/example.com/", "null", "data:", "", "", "", "", "", "/example.com/", "", ""); }
729test { try parsePass("javascript:/example.com/", "http://example.org/foo/bar", "javascript:/example.com/", "null", "javascript:", "", "", "", "", "", "/example.com/", "", ""); }
730test { try parsePass("mailto:/example.com/", "http://example.org/foo/bar", "mailto:/example.com/", "null", "mailto:", "", "", "", "", "", "/example.com/", "", ""); }
731test { try parsePass("http:example.com/", "http://example.org/foo/bar", "http://example.org/foo/example.com/", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/example.com/", "", ""); }
732test { try parsePass("ftp:example.com/", "http://example.org/foo/bar", "ftp://example.com/", "ftp://example.com", "ftp:", "", "", "example.com", "example.com", "", "/", "", ""); }
733test { try parsePass("https:example.com/", "http://example.org/foo/bar", "https://example.com/", "https://example.com", "https:", "", "", "example.com", "example.com", "", "/", "", ""); }
734test { try parsePass("madeupscheme:example.com/", "http://example.org/foo/bar", "madeupscheme:example.com/", "null", "madeupscheme:", "", "", "", "", "", "example.com/", "", ""); }
735test { try parsePass("ftps:example.com/", "http://example.org/foo/bar", "ftps:example.com/", "null", "ftps:", "", "", "", "", "", "example.com/", "", ""); }
736test { try parsePass("gopher:example.com/", "http://example.org/foo/bar", "gopher:example.com/", "null", "gopher:", "", "", "", "", "", "example.com/", "", ""); }
737test { try parsePass("ws:example.com/", "http://example.org/foo/bar", "ws://example.com/", "ws://example.com", "ws:", "", "", "example.com", "example.com", "", "/", "", ""); }
738test { try parsePass("wss:example.com/", "http://example.org/foo/bar", "wss://example.com/", "wss://example.com", "wss:", "", "", "example.com", "example.com", "", "/", "", ""); }
739test { try parsePass("data:example.com/", "http://example.org/foo/bar", "data:example.com/", "null", "data:", "", "", "", "", "", "example.com/", "", ""); }
740test { try parsePass("javascript:example.com/", "http://example.org/foo/bar", "javascript:example.com/", "null", "javascript:", "", "", "", "", "", "example.com/", "", ""); }
741test { try parsePass("mailto:example.com/", "http://example.org/foo/bar", "mailto:example.com/", "null", "mailto:", "", "", "", "", "", "example.com/", "", ""); }
742test { try parsePass("/a/b/c", "http://example.org/foo/bar", "http://example.org/a/b/c", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/a/b/c", "", ""); }
743test { try parsePass("/a/ /c", "http://example.org/foo/bar", "http://example.org/a/%20/c", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/a/%20/c", "", ""); }
744test { try parsePass("/a%2fc", "http://example.org/foo/bar", "http://example.org/a%2fc", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/a%2fc", "", ""); }
745test { try parsePass("/a/%2f/c", "http://example.org/foo/bar", "http://example.org/a/%2f/c", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/a/%2f/c", "", ""); }
746test { try parsePass("#\xce\xb2", "http://example.org/foo/bar", "http://example.org/foo/bar#%CE%B2", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", "#%CE%B2"); }
747test { try parsePass("data:text/html,test#test", "http://example.org/foo/bar", "data:text/html,test#test", "null", "data:", "", "", "", "", "", "text/html,test", "", "#test"); }
748test { try parsePass("tel:1234567890", "http://example.org/foo/bar", "tel:1234567890", "null", "tel:", "", "", "", "", "", "1234567890", "", ""); }
749test { try parsePass("ssh://example.com/foo/bar.git", "http://example.org/", "ssh://example.com/foo/bar.git", "null", "ssh:", "", "", "example.com", "example.com", "", "/foo/bar.git", "", ""); }
750test { try parsePass("file:c:\\foo\\bar.html", "file:///tmp/mock/path", "file:///c:/foo/bar.html", "", "file:", "", "", "", "", "", "/c:/foo/bar.html", "", ""); }
751test { try parsePass(" File:c|////foo\\bar.html", "file:///tmp/mock/path", "file:///c:////foo/bar.html", "", "file:", "", "", "", "", "", "/c:////foo/bar.html", "", ""); }
752test { try parsePass("C|/foo/bar", "file:///tmp/mock/path", "file:///C:/foo/bar", "", "file:", "", "", "", "", "", "/C:/foo/bar", "", ""); }
753test { try parsePass("/C|\\foo\\bar", "file:///tmp/mock/path", "file:///C:/foo/bar", "", "file:", "", "", "", "", "", "/C:/foo/bar", "", ""); }
754test { try parsePass("//C|/foo/bar", "file:///tmp/mock/path", "file:///C:/foo/bar", "", "file:", "", "", "", "", "", "/C:/foo/bar", "", ""); }
755test { try parsePass("//server/file", "file:///tmp/mock/path", "file://server/file", "", "file:", "", "", "server", "server", "", "/file", "", ""); }
756test { try parsePass("\\\\server\\file", "file:///tmp/mock/path", "file://server/file", "", "file:", "", "", "server", "server", "", "/file", "", ""); }
757test { try parsePass("/\\server/file", "file:///tmp/mock/path", "file://server/file", "", "file:", "", "", "server", "server", "", "/file", "", ""); }
758test { try parsePass("file:///foo/bar.txt", "file:///tmp/mock/path", "file:///foo/bar.txt", "", "file:", "", "", "", "", "", "/foo/bar.txt", "", ""); }
759test { try parsePass("file:///home/me", "file:///tmp/mock/path", "file:///home/me", "", "file:", "", "", "", "", "", "/home/me", "", ""); }
760test { try parsePass("//", "file:///tmp/mock/path", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
761test { try parsePass("///", "file:///tmp/mock/path", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
762test { try parsePass("///test", "file:///tmp/mock/path", "file:///test", "", "file:", "", "", "", "", "", "/test", "", ""); }
763test { try parsePass("file://test", "file:///tmp/mock/path", "file://test/", "", "file:", "", "", "test", "test", "", "/", "", ""); }
764test { try parsePass("file://localhost", "file:///tmp/mock/path", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
765test { try parsePass("file://localhost/", "file:///tmp/mock/path", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
766test { try parsePass("file://localhost/test", "file:///tmp/mock/path", "file:///test", "", "file:", "", "", "", "", "", "/test", "", ""); }
767test { try parsePass("test", "file:///tmp/mock/path", "file:///tmp/mock/test", "", "file:", "", "", "", "", "", "/tmp/mock/test", "", ""); }
768test { try parsePass("file:test", "file:///tmp/mock/path", "file:///tmp/mock/test", "", "file:", "", "", "", "", "", "/tmp/mock/test", "", ""); }
769test { try parsePass("/", "http://www.example.com/test", "http://www.example.com/", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/", "", ""); }
770test { try parsePass("/test.txt", "http://www.example.com/test", "http://www.example.com/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/test.txt", "", ""); }
771test { try parsePass(".", "http://www.example.com/test", "http://www.example.com/", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/", "", ""); }
772test { try parsePass("..", "http://www.example.com/test", "http://www.example.com/", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/", "", ""); }
773test { try parsePass("test.txt", "http://www.example.com/test", "http://www.example.com/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/test.txt", "", ""); }
774test { try parsePass("./test.txt", "http://www.example.com/test", "http://www.example.com/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/test.txt", "", ""); }
775test { try parsePass("../test.txt", "http://www.example.com/test", "http://www.example.com/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/test.txt", "", ""); }
776test { try parsePass("../aaa/test.txt", "http://www.example.com/test", "http://www.example.com/aaa/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/aaa/test.txt", "", ""); }
777test { try parsePass("../../test.txt", "http://www.example.com/test", "http://www.example.com/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/test.txt", "", ""); }
778test { try parsePass("\xe4\xb8\xad/test.txt", "http://www.example.com/test", "http://www.example.com/%E4%B8%AD/test.txt", "http://www.example.com", "http:", "", "", "www.example.com", "www.example.com", "", "/%E4%B8%AD/test.txt", "", ""); }
779test { try parsePass("http://www.example2.com", "http://www.example.com/test", "http://www.example2.com/", "http://www.example2.com", "http:", "", "", "www.example2.com", "www.example2.com", "", "/", "", ""); }
780test { try parsePass("//www.example2.com", "http://www.example.com/test", "http://www.example2.com/", "http://www.example2.com", "http:", "", "", "www.example2.com", "www.example2.com", "", "/", "", ""); }
781test { try parsePass("file:...", "http://www.example.com/test", "file:///...", "", "file:", "", "", "", "", "", "/...", "", ""); }
782test { try parsePass("file:..", "http://www.example.com/test", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
783test { try parsePass("file:a", "http://www.example.com/test", "file:///a", "", "file:", "", "", "", "", "", "/a", "", ""); }
784test { try parsePass("file:.", "http://www.example.com/test", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
785test { try parsePass("http://ExAmPlE.CoM", "http://other.com/", "http://example.com/", "http://example.com", "http:", "", "", "example.com", "example.com", "", "/", "", ""); }
786test { try parsePass("http://GOO\xe2\x80\x8b\xe2\x81\xa0\xef\xbb\xbfgoo.com", "http://other.com/", "http://googoo.com/", "http://googoo.com", "http:", "", "", "googoo.com", "googoo.com", "", "/", "", ""); }
787test { try parsePass("http://www.foo\xe3\x80\x82bar.com", "http://other.com/", "http://www.foo.bar.com/", "http://www.foo.bar.com", "http:", "", "", "www.foo.bar.com", "www.foo.bar.com", "", "/", "", ""); }
788test { try parsePass("http://\xef\xbc\xa7\xef\xbd\x8f.com", "http://other.com/", "http://go.com/", "http://go.com", "http:", "", "", "go.com", "go.com", "", "/", "", ""); }
789test { try parsePass("http://\xe4\xbd\xa0\xe5\xa5\xbd\xe4\xbd\xa0\xe5\xa5\xbd", "http://other.com/", "http://xn--6qqa088eba/", "http://xn--6qqa088eba", "http:", "", "", "xn--6qqa088eba", "xn--6qqa088eba", "", "/", "", ""); }
790test { try parsePass("http://%30%78%63%30%2e%30%32%35%30.01", "http://other.com/", "http://192.168.0.1/", "http://192.168.0.1", "http:", "", "", "192.168.0.1", "192.168.0.1", "", "/", "", ""); }
791test { try parsePass("http://%30%78%63%30%2e%30%32%35%30.01%2e", "http://other.com/", "http://192.168.0.1/", "http://192.168.0.1", "http:", "", "", "192.168.0.1", "192.168.0.1", "", "/", "", ""); }
792test { try parsePass("http://\xef\xbc\x90\xef\xbc\xb8\xef\xbd\x83\xef\xbc\x90\xef\xbc\x8e\xef\xbc\x90\xef\xbc\x92\xef\xbc\x95\xef\xbc\x90\xef\xbc\x8e\xef\xbc\x90\xef\xbc\x91", "http://other.com/", "http://192.168.0.1/", "http://192.168.0.1", "http:", "", "", "192.168.0.1", "192.168.0.1", "", "/", "", ""); }
793test { try parsePass("http://foo:\xf0\x9f\x92\xa9@example.com/bar", "http://other.com/", "http://foo:%F0%9F%92%A9@example.com/bar", "http://example.com", "http:", "foo", "%F0%9F%92%A9", "example.com", "example.com", "", "/bar", "", ""); }
794test { try parsePass("#", "test:test", "test:test#", "null", "test:", "", "", "", "", "", "test", "", ""); }
795test { try parsePass("#x", "mailto:x@x.com", "mailto:x@x.com#x", "null", "mailto:", "", "", "", "", "", "x@x.com", "", "#x"); }
796test { try parsePass("#x", "data:,", "data:,#x", "null", "data:", "", "", "", "", "", ",", "", "#x"); }
797test { try parsePass("#x", "about:blank", "about:blank#x", "null", "about:", "", "", "", "", "", "blank", "", "#x"); }
798test { try parsePass("#x:y", "about:blank", "about:blank#x:y", "null", "about:", "", "", "", "", "", "blank", "", "#x:y"); }
799test { try parsePass("#", "test:test?test", "test:test?test#", "null", "test:", "", "", "", "", "", "test", "?test", ""); }
800test { try parsePass("https://@test@test@example:800/", "http://doesnotmatter/", "https://%40test%40test@example:800/", "https://example:800", "https:", "%40test%40test", "", "example:800", "example", "800", "/", "", ""); }
801test { try parsePass("https://@@@example", "http://doesnotmatter/", "https://%40%40@example/", "https://example", "https:", "%40%40", "", "example", "example", "", "/", "", ""); }
802test { try parsePass("http://`{}:`{}@h/`{}?`{}", "http://doesnotmatter/", "http://%60%7B%7D:%60%7B%7D@h/%60%7B%7D?`{}", "http://h", "http:", "%60%7B%7D", "%60%7B%7D", "h", "h", "", "/%60%7B%7D", "?`{}", ""); }
803test { try parsePass("/some/path", "http://user@example.org/smth", "http://user@example.org/some/path", "http://example.org", "http:", "user", "", "example.org", "example.org", "", "/some/path", "", ""); }
804test { try parsePass("", "http://user:pass@example.org:21/smth", "http://user:pass@example.org:21/smth", "http://example.org:21", "http:", "user", "pass", "example.org:21", "example.org", "21", "/smth", "", ""); }
805test { try parsePass("/some/path", "http://user:pass@example.org:21/smth", "http://user:pass@example.org:21/some/path", "http://example.org:21", "http:", "user", "pass", "example.org:21", "example.org", "21", "/some/path", "", ""); }
806test { try parsePass("i", "sc:/pa/pa", "sc:/pa/i", "null", "sc:", "", "", "", "", "", "/pa/i", "", ""); }
807test { try parsePass("i", "sc://ho/pa", "sc://ho/i", "null", "sc:", "", "", "ho", "ho", "", "/i", "", ""); }
808test { try parsePass("i", "sc:///pa/pa", "sc:///pa/i", "null", "sc:", "", "", "", "", "", "/pa/i", "", ""); }
809test { try parsePass("../i", "sc:/pa/pa", "sc:/i", "null", "sc:", "", "", "", "", "", "/i", "", ""); }
810test { try parsePass("../i", "sc://ho/pa", "sc://ho/i", "null", "sc:", "", "", "ho", "ho", "", "/i", "", ""); }
811test { try parsePass("../i", "sc:///pa/pa", "sc:///i", "null", "sc:", "", "", "", "", "", "/i", "", ""); }
812test { try parsePass("/i", "sc:/pa/pa", "sc:/i", "null", "sc:", "", "", "", "", "", "/i", "", ""); }
813test { try parsePass("/i", "sc://ho/pa", "sc://ho/i", "null", "sc:", "", "", "ho", "ho", "", "/i", "", ""); }
814test { try parsePass("/i", "sc:///pa/pa", "sc:///i", "null", "sc:", "", "", "", "", "", "/i", "", ""); }
815test { try parsePass("?i", "sc:/pa/pa", "sc:/pa/pa?i", "null", "sc:", "", "", "", "", "", "/pa/pa", "?i", ""); }
816test { try parsePass("?i", "sc://ho/pa", "sc://ho/pa?i", "null", "sc:", "", "", "ho", "ho", "", "/pa", "?i", ""); }
817test { try parsePass("?i", "sc:///pa/pa", "sc:///pa/pa?i", "null", "sc:", "", "", "", "", "", "/pa/pa", "?i", ""); }
818test { try parsePass("#i", "sc:sd", "sc:sd#i", "null", "sc:", "", "", "", "", "", "sd", "", "#i"); }
819test { try parsePass("#i", "sc:sd/sd", "sc:sd/sd#i", "null", "sc:", "", "", "", "", "", "sd/sd", "", "#i"); }
820test { try parsePass("#i", "sc:/pa/pa", "sc:/pa/pa#i", "null", "sc:", "", "", "", "", "", "/pa/pa", "", "#i"); }
821test { try parsePass("#i", "sc://ho/pa", "sc://ho/pa#i", "null", "sc:", "", "", "ho", "ho", "", "/pa", "", "#i"); }
822test { try parsePass("#i", "sc:///pa/pa", "sc:///pa/pa#i", "null", "sc:", "", "", "", "", "", "/pa/pa", "", "#i"); }
823test { try parsePass("x", "sc://\xc3\xb1", "sc://%C3%B1/x", "null", "sc:", "", "", "%C3%B1", "%C3%B1", "", "/x", "", ""); }
824test { try parsePass("?a=b&c=d", "http://example.org/foo/bar", "http://example.org/foo/bar?a=b&c=d", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "?a=b&c=d", ""); }
825test { try parsePass("??a=b&c=d", "http://example.org/foo/bar", "http://example.org/foo/bar??a=b&c=d", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "??a=b&c=d", ""); }
826test { try parsePass("http:", "http://example.org/foo/bar", "http://example.org/foo/bar", "http://example.org", "http:", "", "", "example.org", "example.org", "", "/foo/bar", "", ""); }
827test { try parsePass("sc:", "https://example.org/foo/bar", "sc:", "null", "sc:", "", "", "", "", "", "", "", ""); }
828test { try parsePass("http://1.2.3.4/", "http://other.com/", "http://1.2.3.4/", "http://1.2.3.4", "http:", "", "", "1.2.3.4", "1.2.3.4", "", "/", "", ""); }
829test { try parsePass("http://1.2.3.4./", "http://other.com/", "http://1.2.3.4/", "http://1.2.3.4", "http:", "", "", "1.2.3.4", "1.2.3.4", "", "/", "", ""); }
830test { try parsePass("http://192.168.257", "http://other.com/", "http://192.168.1.1/", "http://192.168.1.1", "http:", "", "", "192.168.1.1", "192.168.1.1", "", "/", "", ""); }
831test { try parsePass("http://192.168.257.", "http://other.com/", "http://192.168.1.1/", "http://192.168.1.1", "http:", "", "", "192.168.1.1", "192.168.1.1", "", "/", "", ""); }
832test { try parsePass("http://192.168.257.com", "http://other.com/", "http://192.168.257.com/", "http://192.168.257.com", "http:", "", "", "192.168.257.com", "192.168.257.com", "", "/", "", ""); }
833test { try parsePass("http://256", "http://other.com/", "http://0.0.1.0/", "http://0.0.1.0", "http:", "", "", "0.0.1.0", "0.0.1.0", "", "/", "", ""); }
834test { try parsePass("http://256.com", "http://other.com/", "http://256.com/", "http://256.com", "http:", "", "", "256.com", "256.com", "", "/", "", ""); }
835test { try parsePass("http://999999999", "http://other.com/", "http://59.154.201.255/", "http://59.154.201.255", "http:", "", "", "59.154.201.255", "59.154.201.255", "", "/", "", ""); }
836test { try parsePass("http://999999999.", "http://other.com/", "http://59.154.201.255/", "http://59.154.201.255", "http:", "", "", "59.154.201.255", "59.154.201.255", "", "/", "", ""); }
837test { try parsePass("http://999999999.com", "http://other.com/", "http://999999999.com/", "http://999999999.com", "http:", "", "", "999999999.com", "999999999.com", "", "/", "", ""); }
838test { try parsePass("http://10000000000.com", "http://other.com/", "http://10000000000.com/", "http://10000000000.com", "http:", "", "", "10000000000.com", "10000000000.com", "", "/", "", ""); }
839test { try parsePass("http://4294967295", "http://other.com/", "http://255.255.255.255/", "http://255.255.255.255", "http:", "", "", "255.255.255.255", "255.255.255.255", "", "/", "", ""); }
840test { try parsePass("http://0xffffffff", "http://other.com/", "http://255.255.255.255/", "http://255.255.255.255", "http:", "", "", "255.255.255.255", "255.255.255.255", "", "/", "", ""); }
841test { try parsePass("pix/submit.gif", "file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/anchor.html", "file:///C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/pix/submit.gif", "", "file:", "", "", "", "", "", "/C:/Users/Domenic/Dropbox/GitHub/tmpvar/jsdom/test/level2/html/files/pix/submit.gif", "", ""); }
842test { try parsePass("..", "file:///C:/", "file:///C:/", "", "file:", "", "", "", "", "", "/C:/", "", ""); }
843test { try parsePass("..", "file:///", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
844test { try parsePass("/", "file:///C:/a/b", "file:///C:/", "", "file:", "", "", "", "", "", "/C:/", "", ""); }
845test { try parsePass("/", "file://h/C:/a/b", "file://h/C:/", "", "file:", "", "", "h", "h", "", "/C:/", "", ""); }
846test { try parsePass("/", "file://h/a/b", "file://h/", "", "file:", "", "", "h", "h", "", "/", "", ""); }
847test { try parsePass("//d:", "file:///C:/a/b", "file:///d:", "", "file:", "", "", "", "", "", "/d:", "", ""); }
848test { try parsePass("//d:/..", "file:///C:/a/b", "file:///d:/", "", "file:", "", "", "", "", "", "/d:/", "", ""); }
849test { try parsePass("..", "file:///ab:/", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
850test { try parsePass("..", "file:///1:/", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
851test { try parsePass("", "file:///test?test#test", "file:///test?test", "", "file:", "", "", "", "", "", "/test", "?test", ""); }
852test { try parsePass("file:", "file:///test?test#test", "file:///test?test", "", "file:", "", "", "", "", "", "/test", "?test", ""); }
853test { try parsePass("?x", "file:///test?test#test", "file:///test?x", "", "file:", "", "", "", "", "", "/test", "?x", ""); }
854test { try parsePass("file:?x", "file:///test?test#test", "file:///test?x", "", "file:", "", "", "", "", "", "/test", "?x", ""); }
855test { try parsePass("#x", "file:///test?test#test", "file:///test?test#x", "", "file:", "", "", "", "", "", "/test", "?test", "#x"); }
856test { try parsePass("file:#x", "file:///test?test#test", "file:///test?test#x", "", "file:", "", "", "", "", "", "/test", "?test", "#x"); }
857test { try parsePass("/////mouse", "file:///elephant", "file://///mouse", "", "file:", "", "", "", "", "", "///mouse", "", ""); }
858test { try parsePass("\\//pig", "file://lion/", "file:///pig", "", "file:", "", "", "", "", "", "/pig", "", ""); }
859test { try parsePass("\\/localhost//pig", "file://lion/", "file:////pig", "", "file:", "", "", "", "", "", "//pig", "", ""); }
860test { try parsePass("//localhost//pig", "file://lion/", "file:////pig", "", "file:", "", "", "", "", "", "//pig", "", ""); }
861test { try parsePass("/..//localhost//pig", "file://lion/", "file://lion//localhost//pig", "", "file:", "", "", "lion", "lion", "", "//localhost//pig", "", ""); }
862test { try parsePass("file://", "file://ape/", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
863test { try parsePass("/rooibos", "file://tea/", "file://tea/rooibos", "", "file:", "", "", "tea", "tea", "", "/rooibos", "", ""); }
864test { try parsePass("/?chai", "file://tea/", "file://tea/?chai", "", "file:", "", "", "tea", "tea", "", "/", "?chai", ""); }
865test { try parsePass("C|", "file://host/dir/file", "file://host/C:", "", "file:", "", "", "host", "host", "", "/C:", "", ""); }
866test { try parsePass("C|", "file://host/D:/dir1/dir2/file", "file://host/C:", "", "file:", "", "", "host", "host", "", "/C:", "", ""); }
867test { try parsePass("C|#", "file://host/dir/file", "file://host/C:#", "", "file:", "", "", "host", "host", "", "/C:", "", ""); }
868test { try parsePass("C|?", "file://host/dir/file", "file://host/C:?", "", "file:", "", "", "host", "host", "", "/C:", "", ""); }
869test { try parsePass("C|/", "file://host/dir/file", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
870test { try parsePass("C|\n/", "file://host/dir/file", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
871test { try parsePass("C|\\", "file://host/dir/file", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
872test { try parsePass("C", "file://host/dir/file", "file://host/dir/C", "", "file:", "", "", "host", "host", "", "/dir/C", "", ""); }
873test { try parsePass("C|a", "file://host/dir/file", "file://host/dir/C|a", "", "file:", "", "", "host", "host", "", "/dir/C|a", "", ""); }
874test { try parsePass("/c:/foo/bar", "file:///c:/baz/qux", "file:///c:/foo/bar", "", "file:", "", "", "", "", "", "/c:/foo/bar", "", ""); }
875test { try parsePass("/c|/foo/bar", "file:///c:/baz/qux", "file:///c:/foo/bar", "", "file:", "", "", "", "", "", "/c:/foo/bar", "", ""); }
876test { try parsePass("file:\\c:\\foo\\bar", "file:///c:/baz/qux", "file:///c:/foo/bar", "", "file:", "", "", "", "", "", "/c:/foo/bar", "", ""); }
877test { try parsePass("/c:/foo/bar", "file://host/path", "file://host/c:/foo/bar", "", "file:", "", "", "host", "host", "", "/c:/foo/bar", "", ""); }
878test { try parsePass("C|/", "file://host/", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
879test { try parsePass("/C:/", "file://host/", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
880test { try parsePass("file:C:/", "file://host/", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
881test { try parsePass("file:/C:/", "file://host/", "file://host/C:/", "", "file:", "", "", "host", "host", "", "/C:/", "", ""); }
882test { try parsePass("//C:/", "file://host/", "file:///C:/", "", "file:", "", "", "", "", "", "/C:/", "", ""); }
883test { try parsePass("file://C:/", "file://host/", "file:///C:/", "", "file:", "", "", "", "", "", "/C:/", "", ""); }
884test { try parsePass("///C:/", "file://host/", "file:///C:/", "", "file:", "", "", "", "", "", "/C:/", "", ""); }
885test { try parsePass("file:///C:/", "file://host/", "file:///C:/", "", "file:", "", "", "", "", "", "/C:/", "", ""); }
886test { try parsePass("file:///one/two", "file:///", "file:///one/two", "", "file:", "", "", "", "", "", "/one/two", "", ""); }
887test { try parsePass("file:////one/two", "file:///", "file:////one/two", "", "file:", "", "", "", "", "", "//one/two", "", ""); }
888test { try parsePass("//one/two", "file:///", "file://one/two", "", "file:", "", "", "one", "one", "", "/two", "", ""); }
889test { try parsePass("///one/two", "file:///", "file:///one/two", "", "file:", "", "", "", "", "", "/one/two", "", ""); }
890test { try parsePass("////one/two", "file:///", "file:////one/two", "", "file:", "", "", "", "", "", "//one/two", "", ""); }
891test { try parsePass("file:///.//", "file:////", "file:////", "", "file:", "", "", "", "", "", "//", "", ""); }
892test { try parsePass("http://[1:0::]", "http://example.net/", "http://[1::]/", "http://[1::]", "http:", "", "", "[1::]", "[1::]", "", "/", "", ""); }
893test { try parsePass("#x", "sc://\xc3\xb1", "sc://%C3%B1#x", "null", "sc:", "", "", "%C3%B1", "%C3%B1", "", "", "", "#x"); }
894test { try parsePass("?x", "sc://\xc3\xb1", "sc://%C3%B1?x", "null", "sc:", "", "", "%C3%B1", "%C3%B1", "", "", "?x", ""); }
895test { try parsePass("///", "sc://x/", "sc:///", "", "sc:", "", "", "", "", "", "/", "", ""); }
896test { try parsePass("////", "sc://x/", "sc:////", "", "sc:", "", "", "", "", "", "//", "", ""); }
897test { try parsePass("////x/", "sc://x/", "sc:////x/", "", "sc:", "", "", "", "", "", "//x/", "", ""); }
898test { try parsePass("/.//path", "non-spec:/p", "non-spec:/.//path", "", "non-spec:", "", "", "", "", "", "//path", "", ""); }
899test { try parsePass("/..//path", "non-spec:/p", "non-spec:/.//path", "", "non-spec:", "", "", "", "", "", "//path", "", ""); }
900test { try parsePass("..//path", "non-spec:/p", "non-spec:/.//path", "", "non-spec:", "", "", "", "", "", "//path", "", ""); }
901test { try parsePass("a/..//path", "non-spec:/p", "non-spec:/.//path", "", "non-spec:", "", "", "", "", "", "//path", "", ""); }
902test { try parsePass("", "non-spec:/..//p", "non-spec:/.//p", "", "non-spec:", "", "", "", "", "", "//p", "", ""); }
903test { try parsePass("path", "non-spec:/..//p", "non-spec:/.//path", "", "non-spec:", "", "", "", "", "", "//path", "", ""); }
904test { try parsePass("../path", "non-spec:/.//p", "non-spec:/path", "", "non-spec:", "", "", "", "", "", "/path", "", ""); }
905test { try parsePass("test-a-colon-slash.html", "a:/", "a:/test-a-colon-slash.html", "", "a:", "", "", "", "", "", "/test-a-colon-slash.html", "", ""); }
906test { try parsePass("test-a-colon-slash-slash.html", "a://", "a:///test-a-colon-slash-slash.html", "", "a:", "", "", "", "", "", "/test-a-colon-slash-slash.html", "", ""); }
907test { try parsePass("test-a-colon-slash-b.html", "a:/b", "a:/test-a-colon-slash-b.html", "", "a:", "", "", "", "", "", "/test-a-colon-slash-b.html", "", ""); }
908test { try parsePass("test-a-colon-slash-slash-b.html", "a://b", "a://b/test-a-colon-slash-slash-b.html", "", "a:", "", "", "b", "b", "", "/test-a-colon-slash-slash-b.html", "", ""); }
909test { try parsePass("10.0.0.7:8080/foo.html", "file:///some/dir/bar.html", "file:///some/dir/10.0.0.7:8080/foo.html", "", "file:", "", "", "", "", "", "/some/dir/10.0.0.7:8080/foo.html", "", ""); }
910test { try parsePass("a!@$*=/foo.html", "file:///some/dir/bar.html", "file:///some/dir/a!@$*=/foo.html", "", "file:", "", "", "", "", "", "/some/dir/a!@$*=/foo.html", "", ""); }
911test { try parsePass("a1234567890-+.:foo/bar", "http://example.com/dir/file", "a1234567890-+.:foo/bar", "", "a1234567890-+.:", "", "", "", "", "", "foo/bar", "", ""); }
912test { try parsePass("#link", "https://example.org/##link", "https://example.org/#link", "", "https:", "", "", "example.org", "example.org", "", "/", "", "#link"); }
913test { try parsePass("https://user:pass[\x7f@foo/bar", "http://example.org", "https://user:pass%5B%7F@foo/bar", "https://foo", "https:", "user", "pass%5B%7F", "foo", "foo", "", "/bar", "", ""); }
914test { try parsePass("abc:rootless", "abc://host/path", "abc:rootless", "", "abc:", "", "", "", "", "", "rootless", "", ""); }
915test { try parsePass("abc:rootless", "abc:/path", "abc:rootless", "", "abc:", "", "", "", "", "", "rootless", "", ""); }
916test { try parsePass("abc:rootless", "abc:path", "abc:rootless", "", "abc:", "", "", "", "", "", "rootless", "", ""); }
917test { try parsePass("abc:/rooted", "abc://host/path", "abc:/rooted", "", "abc:", "", "", "", "", "", "/rooted", "", ""); }
918test { try parsePass("///test", "http://example.org/", "http://test/", "", "http:", "", "", "test", "test", "", "/", "", ""); }
919test { try parsePass("///\\//\\//test", "http://example.org/", "http://test/", "", "http:", "", "", "test", "test", "", "/", "", ""); }
920test { try parsePass("///example.org/path", "http://example.org/", "http://example.org/path", "", "http:", "", "", "example.org", "example.org", "", "/path", "", ""); }
921test { try parsePass("///example.org/../path", "http://example.org/", "http://example.org/path", "", "http:", "", "", "example.org", "example.org", "", "/path", "", ""); }
922test { try parsePass("///example.org/../../", "http://example.org/", "http://example.org/", "", "http:", "", "", "example.org", "example.org", "", "/", "", ""); }
923test { try parsePass("///example.org/../path/../../", "http://example.org/", "http://example.org/", "", "http:", "", "", "example.org", "example.org", "", "/", "", ""); }
924test { try parsePass("///example.org/../path/../../path", "http://example.org/", "http://example.org/path", "", "http:", "", "", "example.org", "example.org", "", "/path", "", ""); }
925test { try parsePass("/\\/\\//example.org/../path", "http://example.org/", "http://example.org/path", "", "http:", "", "", "example.org", "example.org", "", "/path", "", ""); }
926test { try parsePass("///abcdef/../", "file:///", "file:///", "", "file:", "", "", "", "", "", "/", "", ""); }
927test { try parsePass("/\\//\\/a/../", "file:///", "file://////", "", "file:", "", "", "", "", "", "////", "", ""); }
928test { try parsePass("//a/../", "file:///", "file://a/", "", "file:", "", "", "a", "a", "", "/", "", ""); }
661929
662930test { try parseIDNAFail("a\xe2\x80\x8cb"); }
663931test { try parseIDNAFail("A\xe2\x80\x8cB"); }