1{ 2 "comment": [ 3 "## Tests for setters of https://url.spec.whatwg.org/#urlutils-members", 4 "", 5 "This file contains a JSON object.", 6 "Other than 'comment', each key is an attribute of the `URL` interface", 7 "defined in WHATWG’s URL Standard.", 8 "The values are arrays of test case objects for that attribute.", 9 "", 10 "To run a test case for the attribute `attr`:", 11 "", 12 "* Create a new `URL` object with the value for the 'href' key", 13 " the constructor single parameter. (Without a base URL.)", 14 " This must not throw.", 15 "* Set the attribute `attr` to (invoke its setter with)", 16 " with the value of for 'new_value' key.", 17 "* The value for the 'expected' key is another object.", 18 " For each `key` / `value` pair of that object,", 19 " get the attribute `key` (invoke its getter).", 20 " The returned string must be equal to `value`.", 21 "", 22 "Note: the 'href' setter is already covered by urltestdata.json." 23 ], 24 "protocol": [ 25 { 26 "comment": "The empty string is not a valid scheme. Setter leaves the URL unchanged.", 27 "href": "a://example.net", 28 "new_value": "", 29 "expected": { 30 "href": "a://example.net", 31 "protocol": "a:" 32 } 33 }, 34 { 35 "href": "a://example.net", 36 "new_value": "b", 37 "expected": { 38 "href": "b://example.net", 39 "protocol": "b:" 40 } 41 }, 42 { 43 "href": "javascript:alert(1)", 44 "new_value": "defuse", 45 "expected": { 46 "href": "defuse:alert(1)", 47 "protocol": "defuse:" 48 } 49 }, 50 { 51 "comment": "Upper-case ASCII is lower-cased", 52 "href": "a://example.net", 53 "new_value": "B", 54 "expected": { 55 "href": "b://example.net", 56 "protocol": "b:" 57 } 58 }, 59 { 60 "comment": "Non-ASCII is rejected", 61 "href": "a://example.net", 62 "new_value": "é", 63 "expected": { 64 "href": "a://example.net", 65 "protocol": "a:" 66 } 67 }, 68 { 69 "comment": "No leading digit", 70 "href": "a://example.net", 71 "new_value": "0b", 72 "expected": { 73 "href": "a://example.net", 74 "protocol": "a:" 75 } 76 }, 77 { 78 "comment": "No leading punctuation", 79 "href": "a://example.net", 80 "new_value": "+b", 81 "expected": { 82 "href": "a://example.net", 83 "protocol": "a:" 84 } 85 }, 86 { 87 "href": "a://example.net", 88 "new_value": "bC0+-.", 89 "expected": { 90 "href": "bc0+-.://example.net", 91 "protocol": "bc0+-.:" 92 } 93 }, 94 { 95 "comment": "Only some punctuation is acceptable", 96 "href": "a://example.net", 97 "new_value": "b,c", 98 "expected": { 99 "href": "a://example.net", 100 "protocol": "a:" 101 } 102 }, 103 { 104 "comment": "Non-ASCII is rejected", 105 "href": "a://example.net", 106 "new_value": "bé", 107 "expected": { 108 "href": "a://example.net", 109 "protocol": "a:" 110 } 111 }, 112 { 113 "comment": "Can’t switch from URL containing username/password/port to file", 114 "href": "http://test@example.net", 115 "new_value": "file", 116 "expected": { 117 "href": "http://test@example.net/", 118 "protocol": "http:" 119 } 120 }, 121 { 122 "href": "https://example.net:1234", 123 "new_value": "file", 124 "expected": { 125 "href": "https://example.net:1234/", 126 "protocol": "https:" 127 } 128 }, 129 { 130 "href": "wss://x:x@example.net:1234", 131 "new_value": "file", 132 "expected": { 133 "href": "wss://x:x@example.net:1234/", 134 "protocol": "wss:" 135 } 136 }, 137 { 138 "comment": "Can’t switch from file URL with no host", 139 "href": "file://localhost/", 140 "new_value": "http", 141 "expected": { 142 "href": "file:///", 143 "protocol": "file:" 144 } 145 }, 146 { 147 "href": "file:///test", 148 "new_value": "https", 149 "expected": { 150 "href": "file:///test", 151 "protocol": "file:" 152 } 153 }, 154 { 155 "href": "file:", 156 "new_value": "wss", 157 "expected": { 158 "href": "file:///", 159 "protocol": "file:" 160 } 161 }, 162 { 163 "comment": "Can’t switch from special scheme to non-special", 164 "href": "http://example.net", 165 "new_value": "b", 166 "expected": { 167 "href": "http://example.net/", 168 "protocol": "http:" 169 } 170 }, 171 { 172 "href": "file://hi/path", 173 "new_value": "s", 174 "expected": { 175 "href": "file://hi/path", 176 "protocol": "file:" 177 } 178 }, 179 { 180 "href": "https://example.net", 181 "new_value": "s", 182 "expected": { 183 "href": "https://example.net/", 184 "protocol": "https:" 185 } 186 }, 187 { 188 "href": "ftp://example.net", 189 "new_value": "test", 190 "expected": { 191 "href": "ftp://example.net/", 192 "protocol": "ftp:" 193 } 194 }, 195 { 196 "comment": "Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.", 197 "href": "mailto:me@example.net", 198 "new_value": "http", 199 "expected": { 200 "href": "mailto:me@example.net", 201 "protocol": "mailto:" 202 } 203 }, 204 { 205 "comment": "Can’t switch from non-special scheme to special", 206 "href": "ssh://me@example.net", 207 "new_value": "http", 208 "expected": { 209 "href": "ssh://me@example.net", 210 "protocol": "ssh:" 211 } 212 }, 213 { 214 "href": "ssh://me@example.net", 215 "new_value": "https", 216 "expected": { 217 "href": "ssh://me@example.net", 218 "protocol": "ssh:" 219 } 220 }, 221 { 222 "href": "ssh://me@example.net", 223 "new_value": "file", 224 "expected": { 225 "href": "ssh://me@example.net", 226 "protocol": "ssh:" 227 } 228 }, 229 { 230 "href": "ssh://example.net", 231 "new_value": "file", 232 "expected": { 233 "href": "ssh://example.net", 234 "protocol": "ssh:" 235 } 236 }, 237 { 238 "href": "nonsense:///test", 239 "new_value": "https", 240 "expected": { 241 "href": "nonsense:///test", 242 "protocol": "nonsense:" 243 } 244 }, 245 { 246 "comment": "Stuff after the first ':' is ignored", 247 "href": "http://example.net", 248 "new_value": "https:foo : bar", 249 "expected": { 250 "href": "https://example.net/", 251 "protocol": "https:" 252 } 253 }, 254 { 255 "comment": "Stuff after the first ':' is ignored", 256 "href": "data:text/html,<p>Test", 257 "new_value": "view-source+data:foo : bar", 258 "expected": { 259 "href": "view-source+data:text/html,<p>Test", 260 "protocol": "view-source+data:" 261 } 262 }, 263 { 264 "comment": "Port is set to null if it is the default for new scheme.", 265 "href": "http://foo.com:443/", 266 "new_value": "https", 267 "expected": { 268 "href": "https://foo.com/", 269 "protocol": "https:", 270 "port": "" 271 } 272 } 273 ], 274 "username": [ 275 { 276 "comment": "No host means no username", 277 "href": "file:///home/you/index.html", 278 "new_value": "me", 279 "expected": { 280 "href": "file:///home/you/index.html", 281 "username": "" 282 } 283 }, 284 { 285 "comment": "No host means no username", 286 "href": "unix:/run/foo.socket", 287 "new_value": "me", 288 "expected": { 289 "href": "unix:/run/foo.socket", 290 "username": "" 291 } 292 }, 293 { 294 "comment": "Cannot-be-a-base means no username", 295 "href": "mailto:you@example.net", 296 "new_value": "me", 297 "expected": { 298 "href": "mailto:you@example.net", 299 "username": "" 300 } 301 }, 302 { 303 "href": "javascript:alert(1)", 304 "new_value": "wario", 305 "expected": { 306 "href": "javascript:alert(1)", 307 "username": "" 308 } 309 }, 310 { 311 "href": "http://example.net", 312 "new_value": "me", 313 "expected": { 314 "href": "http://me@example.net/", 315 "username": "me" 316 } 317 }, 318 { 319 "href": "http://:secret@example.net", 320 "new_value": "me", 321 "expected": { 322 "href": "http://me:secret@example.net/", 323 "username": "me" 324 } 325 }, 326 { 327 "href": "http://me@example.net", 328 "new_value": "", 329 "expected": { 330 "href": "http://example.net/", 331 "username": "" 332 } 333 }, 334 { 335 "href": "http://me:secret@example.net", 336 "new_value": "", 337 "expected": { 338 "href": "http://:secret@example.net/", 339 "username": "" 340 } 341 }, 342 { 343 "comment": "UTF-8 percent encoding with the userinfo encode set.", 344 "href": "http://example.net", 345 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 346 "expected": { 347 "href": "http://%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9@example.net/", 348 "username": "%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9" 349 } 350 }, 351 { 352 "comment": "Bytes already percent-encoded are left as-is.", 353 "href": "http://example.net", 354 "new_value": "%c3%89té", 355 "expected": { 356 "href": "http://%c3%89t%C3%A9@example.net/", 357 "username": "%c3%89t%C3%A9" 358 } 359 }, 360 { 361 "href": "sc:///", 362 "new_value": "x", 363 "expected": { 364 "href": "sc:///", 365 "username": "" 366 } 367 }, 368 { 369 "href": "javascript://x/", 370 "new_value": "wario", 371 "expected": { 372 "href": "javascript://wario@x/", 373 "username": "wario" 374 } 375 }, 376 { 377 "href": "file://test/", 378 "new_value": "test", 379 "expected": { 380 "href": "file://test/", 381 "username": "" 382 } 383 } 384 ], 385 "password": [ 386 { 387 "comment": "No host means no password", 388 "href": "file:///home/me/index.html", 389 "new_value": "secret", 390 "expected": { 391 "href": "file:///home/me/index.html", 392 "password": "" 393 } 394 }, 395 { 396 "comment": "No host means no password", 397 "href": "unix:/run/foo.socket", 398 "new_value": "secret", 399 "expected": { 400 "href": "unix:/run/foo.socket", 401 "password": "" 402 } 403 }, 404 { 405 "comment": "Cannot-be-a-base means no password", 406 "href": "mailto:me@example.net", 407 "new_value": "secret", 408 "expected": { 409 "href": "mailto:me@example.net", 410 "password": "" 411 } 412 }, 413 { 414 "href": "http://example.net", 415 "new_value": "secret", 416 "expected": { 417 "href": "http://:secret@example.net/", 418 "password": "secret" 419 } 420 }, 421 { 422 "href": "http://me@example.net", 423 "new_value": "secret", 424 "expected": { 425 "href": "http://me:secret@example.net/", 426 "password": "secret" 427 } 428 }, 429 { 430 "href": "http://:secret@example.net", 431 "new_value": "", 432 "expected": { 433 "href": "http://example.net/", 434 "password": "" 435 } 436 }, 437 { 438 "href": "http://me:secret@example.net", 439 "new_value": "", 440 "expected": { 441 "href": "http://me@example.net/", 442 "password": "" 443 } 444 }, 445 { 446 "comment": "UTF-8 percent encoding with the userinfo encode set.", 447 "href": "http://example.net", 448 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 449 "expected": { 450 "href": "http://:%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9@example.net/", 451 "password": "%00%01%09%0A%0D%1F%20!%22%23$%&'()*+,-.%2F09%3A%3B%3C%3D%3E%3F%40AZ%5B%5C%5D%5E_%60az%7B%7C%7D~%7F%C2%80%C2%81%C3%89%C3%A9" 452 } 453 }, 454 { 455 "comment": "Bytes already percent-encoded are left as-is.", 456 "href": "http://example.net", 457 "new_value": "%c3%89té", 458 "expected": { 459 "href": "http://:%c3%89t%C3%A9@example.net/", 460 "password": "%c3%89t%C3%A9" 461 } 462 }, 463 { 464 "href": "sc:///", 465 "new_value": "x", 466 "expected": { 467 "href": "sc:///", 468 "password": "" 469 } 470 }, 471 { 472 "href": "javascript://x/", 473 "new_value": "bowser", 474 "expected": { 475 "href": "javascript://:bowser@x/", 476 "password": "bowser" 477 } 478 }, 479 { 480 "href": "file://test/", 481 "new_value": "test", 482 "expected": { 483 "href": "file://test/", 484 "password": "" 485 } 486 } 487 ], 488 "host": [ 489 { 490 "comment": "Non-special scheme", 491 "href": "sc://x/", 492 "new_value": "\u0000", 493 "expected": { 494 "href": "sc://x/", 495 "host": "x", 496 "hostname": "x" 497 } 498 }, 499 { 500 "href": "sc://x/", 501 "new_value": "\u0009", 502 "expected": { 503 "href": "sc:///", 504 "host": "", 505 "hostname": "" 506 } 507 }, 508 { 509 "href": "sc://x/", 510 "new_value": "\u000A", 511 "expected": { 512 "href": "sc:///", 513 "host": "", 514 "hostname": "" 515 } 516 }, 517 { 518 "href": "sc://x/", 519 "new_value": "\u000D", 520 "expected": { 521 "href": "sc:///", 522 "host": "", 523 "hostname": "" 524 } 525 }, 526 { 527 "href": "sc://x/", 528 "new_value": " ", 529 "expected": { 530 "href": "sc://x/", 531 "host": "x", 532 "hostname": "x" 533 } 534 }, 535 { 536 "href": "sc://x/", 537 "new_value": "#", 538 "expected": { 539 "href": "sc:///", 540 "host": "", 541 "hostname": "" 542 } 543 }, 544 { 545 "href": "sc://x/", 546 "new_value": "/", 547 "expected": { 548 "href": "sc:///", 549 "host": "", 550 "hostname": "" 551 } 552 }, 553 { 554 "href": "sc://x/", 555 "new_value": "?", 556 "expected": { 557 "href": "sc:///", 558 "host": "", 559 "hostname": "" 560 } 561 }, 562 { 563 "href": "sc://x/", 564 "new_value": "@", 565 "expected": { 566 "href": "sc://x/", 567 "host": "x", 568 "hostname": "x" 569 } 570 }, 571 { 572 "href": "sc://x/", 573 "new_value": "ß", 574 "expected": { 575 "href": "sc://%C3%9F/", 576 "host": "%C3%9F", 577 "hostname": "%C3%9F" 578 } 579 }, 580 { 581 "comment": "IDNA Nontransitional_Processing", 582 "href": "https://x/", 583 "new_value": "ß", 584 "expected": { 585 "href": "https://xn--zca/", 586 "host": "xn--zca", 587 "hostname": "xn--zca" 588 } 589 }, 590 { 591 "comment": "Cannot-be-a-base means no host", 592 "href": "mailto:me@example.net", 593 "new_value": "example.com", 594 "expected": { 595 "href": "mailto:me@example.net", 596 "host": "" 597 } 598 }, 599 { 600 "comment": "Cannot-be-a-base means no host", 601 "href": "data:text/plain,Stuff", 602 "new_value": "example.net", 603 "expected": { 604 "href": "data:text/plain,Stuff", 605 "host": "" 606 } 607 }, 608 { 609 "href": "http://example.net", 610 "new_value": "example.com:8080", 611 "expected": { 612 "href": "http://example.com:8080/", 613 "host": "example.com:8080", 614 "hostname": "example.com", 615 "port": "8080" 616 } 617 }, 618 { 619 "comment": "Port number is unchanged if not specified in the new value", 620 "href": "http://example.net:8080", 621 "new_value": "example.com", 622 "expected": { 623 "href": "http://example.com:8080/", 624 "host": "example.com:8080", 625 "hostname": "example.com", 626 "port": "8080" 627 } 628 }, 629 { 630 "comment": "Port number is unchanged if not specified", 631 "href": "http://example.net:8080", 632 "new_value": "example.com:", 633 "expected": { 634 "href": "http://example.com:8080/", 635 "host": "example.com:8080", 636 "hostname": "example.com", 637 "port": "8080" 638 } 639 }, 640 { 641 "comment": "The empty host is not valid for special schemes", 642 "href": "http://example.net", 643 "new_value": "", 644 "expected": { 645 "href": "http://example.net/", 646 "host": "example.net" 647 } 648 }, 649 { 650 "comment": "The empty host is OK for non-special schemes", 651 "href": "view-source+http://example.net/foo", 652 "new_value": "", 653 "expected": { 654 "href": "view-source+http:///foo", 655 "host": "" 656 } 657 }, 658 { 659 "comment": "Path-only URLs can gain a host", 660 "href": "a:/foo", 661 "new_value": "example.net", 662 "expected": { 663 "href": "a://example.net/foo", 664 "host": "example.net" 665 } 666 }, 667 { 668 "comment": "IPv4 address syntax is normalized", 669 "href": "http://example.net", 670 "new_value": "0x7F000001:8080", 671 "expected": { 672 "href": "http://127.0.0.1:8080/", 673 "host": "127.0.0.1:8080", 674 "hostname": "127.0.0.1", 675 "port": "8080" 676 } 677 }, 678 { 679 "comment": "IPv6 address syntax is normalized", 680 "href": "http://example.net", 681 "new_value": "[::0:01]:2", 682 "expected": { 683 "href": "http://[::1]:2/", 684 "host": "[::1]:2", 685 "hostname": "[::1]", 686 "port": "2" 687 } 688 }, 689 { 690 "comment": "IPv6 literal address with port, crbug.com/1012416", 691 "href": "http://example.net", 692 "new_value": "[2001:db8::2]:4002", 693 "expected": { 694 "href": "http://[2001:db8::2]:4002/", 695 "host": "[2001:db8::2]:4002", 696 "hostname": "[2001:db8::2]", 697 "port": "4002" 698 } 699 }, 700 { 701 "comment": "Default port number is removed", 702 "href": "http://example.net", 703 "new_value": "example.com:80", 704 "expected": { 705 "href": "http://example.com/", 706 "host": "example.com", 707 "hostname": "example.com", 708 "port": "" 709 } 710 }, 711 { 712 "comment": "Default port number is removed", 713 "href": "https://example.net", 714 "new_value": "example.com:443", 715 "expected": { 716 "href": "https://example.com/", 717 "host": "example.com", 718 "hostname": "example.com", 719 "port": "" 720 } 721 }, 722 { 723 "comment": "Default port number is only removed for the relevant scheme", 724 "href": "https://example.net", 725 "new_value": "example.com:80", 726 "expected": { 727 "href": "https://example.com:80/", 728 "host": "example.com:80", 729 "hostname": "example.com", 730 "port": "80" 731 } 732 }, 733 { 734 "comment": "Port number is removed if new port is scheme default and existing URL has a non-default port", 735 "href": "http://example.net:8080", 736 "new_value": "example.com:80", 737 "expected": { 738 "href": "http://example.com/", 739 "host": "example.com", 740 "hostname": "example.com", 741 "port": "" 742 } 743 }, 744 { 745 "comment": "Stuff after a / delimiter is ignored", 746 "href": "http://example.net/path", 747 "new_value": "example.com/stuff", 748 "expected": { 749 "href": "http://example.com/path", 750 "host": "example.com", 751 "hostname": "example.com", 752 "port": "" 753 } 754 }, 755 { 756 "comment": "Stuff after a / delimiter is ignored", 757 "href": "http://example.net/path", 758 "new_value": "example.com:8080/stuff", 759 "expected": { 760 "href": "http://example.com:8080/path", 761 "host": "example.com:8080", 762 "hostname": "example.com", 763 "port": "8080" 764 } 765 }, 766 { 767 "comment": "Stuff after a ? delimiter is ignored", 768 "href": "http://example.net/path", 769 "new_value": "example.com?stuff", 770 "expected": { 771 "href": "http://example.com/path", 772 "host": "example.com", 773 "hostname": "example.com", 774 "port": "" 775 } 776 }, 777 { 778 "comment": "Stuff after a ? delimiter is ignored", 779 "href": "http://example.net/path", 780 "new_value": "example.com:8080?stuff", 781 "expected": { 782 "href": "http://example.com:8080/path", 783 "host": "example.com:8080", 784 "hostname": "example.com", 785 "port": "8080" 786 } 787 }, 788 { 789 "comment": "Stuff after a # delimiter is ignored", 790 "href": "http://example.net/path", 791 "new_value": "example.com#stuff", 792 "expected": { 793 "href": "http://example.com/path", 794 "host": "example.com", 795 "hostname": "example.com", 796 "port": "" 797 } 798 }, 799 { 800 "comment": "Stuff after a # delimiter is ignored", 801 "href": "http://example.net/path", 802 "new_value": "example.com:8080#stuff", 803 "expected": { 804 "href": "http://example.com:8080/path", 805 "host": "example.com:8080", 806 "hostname": "example.com", 807 "port": "8080" 808 } 809 }, 810 { 811 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 812 "href": "http://example.net/path", 813 "new_value": "example.com\\stuff", 814 "expected": { 815 "href": "http://example.com/path", 816 "host": "example.com", 817 "hostname": "example.com", 818 "port": "" 819 } 820 }, 821 { 822 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 823 "href": "http://example.net/path", 824 "new_value": "example.com:8080\\stuff", 825 "expected": { 826 "href": "http://example.com:8080/path", 827 "host": "example.com:8080", 828 "hostname": "example.com", 829 "port": "8080" 830 } 831 }, 832 { 833 "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts", 834 "href": "view-source+http://example.net/path", 835 "new_value": "example.com\\stuff", 836 "expected": { 837 "href": "view-source+http://example.net/path", 838 "host": "example.net", 839 "hostname": "example.net", 840 "port": "" 841 } 842 }, 843 { 844 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 845 "href": "view-source+http://example.net/path", 846 "new_value": "example.com:8080stuff2", 847 "expected": { 848 "href": "view-source+http://example.com:8080/path", 849 "host": "example.com:8080", 850 "hostname": "example.com", 851 "port": "8080" 852 } 853 }, 854 { 855 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 856 "href": "http://example.net/path", 857 "new_value": "example.com:8080stuff2", 858 "expected": { 859 "href": "http://example.com:8080/path", 860 "host": "example.com:8080", 861 "hostname": "example.com", 862 "port": "8080" 863 } 864 }, 865 { 866 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 867 "href": "http://example.net/path", 868 "new_value": "example.com:8080+2", 869 "expected": { 870 "href": "http://example.com:8080/path", 871 "host": "example.com:8080", 872 "hostname": "example.com", 873 "port": "8080" 874 } 875 }, 876 { 877 "comment": "Port numbers are 16 bit integers", 878 "href": "http://example.net/path", 879 "new_value": "example.com:65535", 880 "expected": { 881 "href": "http://example.com:65535/path", 882 "host": "example.com:65535", 883 "hostname": "example.com", 884 "port": "65535" 885 } 886 }, 887 { 888 "comment": "Port numbers are 16 bit integers, overflowing is an error. Hostname is still set, though.", 889 "href": "http://example.net/path", 890 "new_value": "example.com:65536", 891 "expected": { 892 "href": "http://example.com/path", 893 "host": "example.com", 894 "hostname": "example.com", 895 "port": "" 896 } 897 }, 898 { 899 "comment": "Broken IPv6", 900 "href": "http://example.net/", 901 "new_value": "[google.com]", 902 "expected": { 903 "href": "http://example.net/", 904 "host": "example.net", 905 "hostname": "example.net" 906 } 907 }, 908 { 909 "href": "http://example.net/", 910 "new_value": "[::1.2.3.4x]", 911 "expected": { 912 "href": "http://example.net/", 913 "host": "example.net", 914 "hostname": "example.net" 915 } 916 }, 917 { 918 "href": "http://example.net/", 919 "new_value": "[::1.2.3.]", 920 "expected": { 921 "href": "http://example.net/", 922 "host": "example.net", 923 "hostname": "example.net" 924 } 925 }, 926 { 927 "href": "http://example.net/", 928 "new_value": "[::1.2.]", 929 "expected": { 930 "href": "http://example.net/", 931 "host": "example.net", 932 "hostname": "example.net" 933 } 934 }, 935 { 936 "href": "http://example.net/", 937 "new_value": "[::1.]", 938 "expected": { 939 "href": "http://example.net/", 940 "host": "example.net", 941 "hostname": "example.net" 942 } 943 }, 944 { 945 "href": "file://y/", 946 "new_value": "x:123", 947 "expected": { 948 "href": "file://y/", 949 "host": "y", 950 "hostname": "y", 951 "port": "" 952 } 953 }, 954 { 955 "href": "file://y/", 956 "new_value": "loc%41lhost", 957 "expected": { 958 "href": "file:///", 959 "host": "", 960 "hostname": "", 961 "port": "" 962 } 963 }, 964 { 965 "href": "file://hi/x", 966 "new_value": "", 967 "expected": { 968 "href": "file:///x", 969 "host": "", 970 "hostname": "", 971 "port": "" 972 } 973 }, 974 { 975 "href": "sc://test@test/", 976 "new_value": "", 977 "expected": { 978 "href": "sc://test@test/", 979 "host": "test", 980 "hostname": "test", 981 "username": "test" 982 } 983 }, 984 { 985 "href": "sc://test:12/", 986 "new_value": "", 987 "expected": { 988 "href": "sc://test:12/", 989 "host": "test:12", 990 "hostname": "test", 991 "port": "12" 992 } 993 }, 994 { 995 "comment": "Leading / is not stripped", 996 "href": "http://example.com/", 997 "new_value": "///bad.com", 998 "expected": { 999 "href": "http://example.com/", 1000 "host": "example.com", 1001 "hostname": "example.com" 1002 } 1003 }, 1004 { 1005 "comment": "Leading / is not stripped", 1006 "href": "sc://example.com/", 1007 "new_value": "///bad.com", 1008 "expected": { 1009 "href": "sc:///", 1010 "host": "", 1011 "hostname": "" 1012 } 1013 } 1014 ], 1015 "hostname": [ 1016 { 1017 "comment": "Non-special scheme", 1018 "href": "sc://x/", 1019 "new_value": "\u0000", 1020 "expected": { 1021 "href": "sc://x/", 1022 "host": "x", 1023 "hostname": "x" 1024 } 1025 }, 1026 { 1027 "href": "sc://x/", 1028 "new_value": "\u0009", 1029 "expected": { 1030 "href": "sc:///", 1031 "host": "", 1032 "hostname": "" 1033 } 1034 }, 1035 { 1036 "href": "sc://x/", 1037 "new_value": "\u000A", 1038 "expected": { 1039 "href": "sc:///", 1040 "host": "", 1041 "hostname": "" 1042 } 1043 }, 1044 { 1045 "href": "sc://x/", 1046 "new_value": "\u000D", 1047 "expected": { 1048 "href": "sc:///", 1049 "host": "", 1050 "hostname": "" 1051 } 1052 }, 1053 { 1054 "href": "sc://x/", 1055 "new_value": " ", 1056 "expected": { 1057 "href": "sc://x/", 1058 "host": "x", 1059 "hostname": "x" 1060 } 1061 }, 1062 { 1063 "href": "sc://x/", 1064 "new_value": "#", 1065 "expected": { 1066 "href": "sc:///", 1067 "host": "", 1068 "hostname": "" 1069 } 1070 }, 1071 { 1072 "href": "sc://x/", 1073 "new_value": "/", 1074 "expected": { 1075 "href": "sc:///", 1076 "host": "", 1077 "hostname": "" 1078 } 1079 }, 1080 { 1081 "href": "sc://x/", 1082 "new_value": "?", 1083 "expected": { 1084 "href": "sc:///", 1085 "host": "", 1086 "hostname": "" 1087 } 1088 }, 1089 { 1090 "href": "sc://x/", 1091 "new_value": "@", 1092 "expected": { 1093 "href": "sc://x/", 1094 "host": "x", 1095 "hostname": "x" 1096 } 1097 }, 1098 { 1099 "comment": "Cannot-be-a-base means no host", 1100 "href": "mailto:me@example.net", 1101 "new_value": "example.com", 1102 "expected": { 1103 "href": "mailto:me@example.net", 1104 "host": "" 1105 } 1106 }, 1107 { 1108 "comment": "Cannot-be-a-base means no host", 1109 "href": "data:text/plain,Stuff", 1110 "new_value": "example.net", 1111 "expected": { 1112 "href": "data:text/plain,Stuff", 1113 "host": "" 1114 } 1115 }, 1116 { 1117 "href": "http://example.net:8080", 1118 "new_value": "example.com", 1119 "expected": { 1120 "href": "http://example.com:8080/", 1121 "host": "example.com:8080", 1122 "hostname": "example.com", 1123 "port": "8080" 1124 } 1125 }, 1126 { 1127 "comment": "The empty host is not valid for special schemes", 1128 "href": "http://example.net", 1129 "new_value": "", 1130 "expected": { 1131 "href": "http://example.net/", 1132 "host": "example.net" 1133 } 1134 }, 1135 { 1136 "comment": "The empty host is OK for non-special schemes", 1137 "href": "view-source+http://example.net/foo", 1138 "new_value": "", 1139 "expected": { 1140 "href": "view-source+http:///foo", 1141 "host": "" 1142 } 1143 }, 1144 { 1145 "comment": "Path-only URLs can gain a host", 1146 "href": "a:/foo", 1147 "new_value": "example.net", 1148 "expected": { 1149 "href": "a://example.net/foo", 1150 "host": "example.net" 1151 } 1152 }, 1153 { 1154 "comment": "IPv4 address syntax is normalized", 1155 "href": "http://example.net:8080", 1156 "new_value": "0x7F000001", 1157 "expected": { 1158 "href": "http://127.0.0.1:8080/", 1159 "host": "127.0.0.1:8080", 1160 "hostname": "127.0.0.1", 1161 "port": "8080" 1162 } 1163 }, 1164 { 1165 "comment": "IPv6 address syntax is normalized", 1166 "href": "http://example.net", 1167 "new_value": "[::0:01]", 1168 "expected": { 1169 "href": "http://[::1]/", 1170 "host": "[::1]", 1171 "hostname": "[::1]", 1172 "port": "" 1173 } 1174 }, 1175 { 1176 "comment": ": delimiter invalidates entire value", 1177 "href": "http://example.net/path", 1178 "new_value": "example.com:8080", 1179 "expected": { 1180 "href": "http://example.net/path", 1181 "host": "example.net", 1182 "hostname": "example.net", 1183 "port": "" 1184 } 1185 }, 1186 { 1187 "comment": ": delimiter invalidates entire value", 1188 "href": "http://example.net:8080/path", 1189 "new_value": "example.com:", 1190 "expected": { 1191 "href": "http://example.net:8080/path", 1192 "host": "example.net:8080", 1193 "hostname": "example.net", 1194 "port": "8080" 1195 } 1196 }, 1197 { 1198 "comment": "Stuff after a / delimiter is ignored", 1199 "href": "http://example.net/path", 1200 "new_value": "example.com/stuff", 1201 "expected": { 1202 "href": "http://example.com/path", 1203 "host": "example.com", 1204 "hostname": "example.com", 1205 "port": "" 1206 } 1207 }, 1208 { 1209 "comment": "Stuff after a ? delimiter is ignored", 1210 "href": "http://example.net/path", 1211 "new_value": "example.com?stuff", 1212 "expected": { 1213 "href": "http://example.com/path", 1214 "host": "example.com", 1215 "hostname": "example.com", 1216 "port": "" 1217 } 1218 }, 1219 { 1220 "comment": "Stuff after a # delimiter is ignored", 1221 "href": "http://example.net/path", 1222 "new_value": "example.com#stuff", 1223 "expected": { 1224 "href": "http://example.com/path", 1225 "host": "example.com", 1226 "hostname": "example.com", 1227 "port": "" 1228 } 1229 }, 1230 { 1231 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 1232 "href": "http://example.net/path", 1233 "new_value": "example.com\\stuff", 1234 "expected": { 1235 "href": "http://example.com/path", 1236 "host": "example.com", 1237 "hostname": "example.com", 1238 "port": "" 1239 } 1240 }, 1241 { 1242 "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts", 1243 "href": "view-source+http://example.net/path", 1244 "new_value": "example.com\\stuff", 1245 "expected": { 1246 "href": "view-source+http://example.net/path", 1247 "host": "example.net", 1248 "hostname": "example.net", 1249 "port": "" 1250 } 1251 }, 1252 { 1253 "comment": "Broken IPv6", 1254 "href": "http://example.net/", 1255 "new_value": "[google.com]", 1256 "expected": { 1257 "href": "http://example.net/", 1258 "host": "example.net", 1259 "hostname": "example.net" 1260 } 1261 }, 1262 { 1263 "href": "http://example.net/", 1264 "new_value": "[::1.2.3.4x]", 1265 "expected": { 1266 "href": "http://example.net/", 1267 "host": "example.net", 1268 "hostname": "example.net" 1269 } 1270 }, 1271 { 1272 "href": "http://example.net/", 1273 "new_value": "[::1.2.3.]", 1274 "expected": { 1275 "href": "http://example.net/", 1276 "host": "example.net", 1277 "hostname": "example.net" 1278 } 1279 }, 1280 { 1281 "href": "http://example.net/", 1282 "new_value": "[::1.2.]", 1283 "expected": { 1284 "href": "http://example.net/", 1285 "host": "example.net", 1286 "hostname": "example.net" 1287 } 1288 }, 1289 { 1290 "href": "http://example.net/", 1291 "new_value": "[::1.]", 1292 "expected": { 1293 "href": "http://example.net/", 1294 "host": "example.net", 1295 "hostname": "example.net" 1296 } 1297 }, 1298 { 1299 "href": "file://y/", 1300 "new_value": "x:123", 1301 "expected": { 1302 "href": "file://y/", 1303 "host": "y", 1304 "hostname": "y", 1305 "port": "" 1306 } 1307 }, 1308 { 1309 "href": "file://y/", 1310 "new_value": "loc%41lhost", 1311 "expected": { 1312 "href": "file:///", 1313 "host": "", 1314 "hostname": "", 1315 "port": "" 1316 } 1317 }, 1318 { 1319 "href": "file://hi/x", 1320 "new_value": "", 1321 "expected": { 1322 "href": "file:///x", 1323 "host": "", 1324 "hostname": "", 1325 "port": "" 1326 } 1327 }, 1328 { 1329 "href": "sc://test@test/", 1330 "new_value": "", 1331 "expected": { 1332 "href": "sc://test@test/", 1333 "host": "test", 1334 "hostname": "test", 1335 "username": "test" 1336 } 1337 }, 1338 { 1339 "href": "sc://test:12/", 1340 "new_value": "", 1341 "expected": { 1342 "href": "sc://test:12/", 1343 "host": "test:12", 1344 "hostname": "test", 1345 "port": "12" 1346 } 1347 }, 1348 { 1349 "comment": "Drop /. from path", 1350 "href": "non-spec:/.//p", 1351 "new_value": "h", 1352 "expected": { 1353 "href": "non-spec://h//p", 1354 "host": "h", 1355 "hostname": "h", 1356 "pathname": "//p" 1357 } 1358 }, 1359 { 1360 "href": "non-spec:/.//p", 1361 "new_value": "", 1362 "expected": { 1363 "href": "non-spec:////p", 1364 "host": "", 1365 "hostname": "", 1366 "pathname": "//p" 1367 } 1368 }, 1369 { 1370 "comment": "Leading / is not stripped", 1371 "href": "http://example.com/", 1372 "new_value": "///bad.com", 1373 "expected": { 1374 "href": "http://example.com/", 1375 "host": "example.com", 1376 "hostname": "example.com" 1377 } 1378 }, 1379 { 1380 "comment": "Leading / is not stripped", 1381 "href": "sc://example.com/", 1382 "new_value": "///bad.com", 1383 "expected": { 1384 "href": "sc:///", 1385 "host": "", 1386 "hostname": "" 1387 } 1388 } 1389 ], 1390 "port": [ 1391 { 1392 "href": "http://example.net", 1393 "new_value": "8080", 1394 "expected": { 1395 "href": "http://example.net:8080/", 1396 "host": "example.net:8080", 1397 "hostname": "example.net", 1398 "port": "8080" 1399 } 1400 }, 1401 { 1402 "comment": "Port number is removed if empty is the new value", 1403 "href": "http://example.net:8080", 1404 "new_value": "", 1405 "expected": { 1406 "href": "http://example.net/", 1407 "host": "example.net", 1408 "hostname": "example.net", 1409 "port": "" 1410 } 1411 }, 1412 { 1413 "comment": "Default port number is removed", 1414 "href": "http://example.net:8080", 1415 "new_value": "80", 1416 "expected": { 1417 "href": "http://example.net/", 1418 "host": "example.net", 1419 "hostname": "example.net", 1420 "port": "" 1421 } 1422 }, 1423 { 1424 "comment": "Default port number is removed", 1425 "href": "https://example.net:4433", 1426 "new_value": "443", 1427 "expected": { 1428 "href": "https://example.net/", 1429 "host": "example.net", 1430 "hostname": "example.net", 1431 "port": "" 1432 } 1433 }, 1434 { 1435 "comment": "Default port number is only removed for the relevant scheme", 1436 "href": "https://example.net", 1437 "new_value": "80", 1438 "expected": { 1439 "href": "https://example.net:80/", 1440 "host": "example.net:80", 1441 "hostname": "example.net", 1442 "port": "80" 1443 } 1444 }, 1445 { 1446 "comment": "Stuff after a / delimiter is ignored", 1447 "href": "http://example.net/path", 1448 "new_value": "8080/stuff", 1449 "expected": { 1450 "href": "http://example.net:8080/path", 1451 "host": "example.net:8080", 1452 "hostname": "example.net", 1453 "port": "8080" 1454 } 1455 }, 1456 { 1457 "comment": "Stuff after a ? delimiter is ignored", 1458 "href": "http://example.net/path", 1459 "new_value": "8080?stuff", 1460 "expected": { 1461 "href": "http://example.net:8080/path", 1462 "host": "example.net:8080", 1463 "hostname": "example.net", 1464 "port": "8080" 1465 } 1466 }, 1467 { 1468 "comment": "Stuff after a # delimiter is ignored", 1469 "href": "http://example.net/path", 1470 "new_value": "8080#stuff", 1471 "expected": { 1472 "href": "http://example.net:8080/path", 1473 "host": "example.net:8080", 1474 "hostname": "example.net", 1475 "port": "8080" 1476 } 1477 }, 1478 { 1479 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 1480 "href": "http://example.net/path", 1481 "new_value": "8080\\stuff", 1482 "expected": { 1483 "href": "http://example.net:8080/path", 1484 "host": "example.net:8080", 1485 "hostname": "example.net", 1486 "port": "8080" 1487 } 1488 }, 1489 { 1490 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1491 "href": "view-source+http://example.net/path", 1492 "new_value": "8080stuff2", 1493 "expected": { 1494 "href": "view-source+http://example.net:8080/path", 1495 "host": "example.net:8080", 1496 "hostname": "example.net", 1497 "port": "8080" 1498 } 1499 }, 1500 { 1501 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1502 "href": "http://example.net/path", 1503 "new_value": "8080stuff2", 1504 "expected": { 1505 "href": "http://example.net:8080/path", 1506 "host": "example.net:8080", 1507 "hostname": "example.net", 1508 "port": "8080" 1509 } 1510 }, 1511 { 1512 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1513 "href": "http://example.net/path", 1514 "new_value": "8080+2", 1515 "expected": { 1516 "href": "http://example.net:8080/path", 1517 "host": "example.net:8080", 1518 "hostname": "example.net", 1519 "port": "8080" 1520 } 1521 }, 1522 { 1523 "comment": "Port numbers are 16 bit integers", 1524 "href": "http://example.net/path", 1525 "new_value": "65535", 1526 "expected": { 1527 "href": "http://example.net:65535/path", 1528 "host": "example.net:65535", 1529 "hostname": "example.net", 1530 "port": "65535" 1531 } 1532 }, 1533 { 1534 "comment": "Port numbers are 16 bit integers, overflowing is an error", 1535 "href": "http://example.net:8080/path", 1536 "new_value": "65536", 1537 "expected": { 1538 "href": "http://example.net:8080/path", 1539 "host": "example.net:8080", 1540 "hostname": "example.net", 1541 "port": "8080" 1542 } 1543 }, 1544 { 1545 "comment": "Port numbers are 16 bit integers, overflowing is an error", 1546 "href": "non-special://example.net:8080/path", 1547 "new_value": "65536", 1548 "expected": { 1549 "href": "non-special://example.net:8080/path", 1550 "host": "example.net:8080", 1551 "hostname": "example.net", 1552 "port": "8080" 1553 } 1554 }, 1555 { 1556 "href": "file://test/", 1557 "new_value": "12", 1558 "expected": { 1559 "href": "file://test/", 1560 "port": "" 1561 } 1562 }, 1563 { 1564 "href": "file://localhost/", 1565 "new_value": "12", 1566 "expected": { 1567 "href": "file:///", 1568 "port": "" 1569 } 1570 }, 1571 { 1572 "href": "non-base:value", 1573 "new_value": "12", 1574 "expected": { 1575 "href": "non-base:value", 1576 "port": "" 1577 } 1578 }, 1579 { 1580 "href": "sc:///", 1581 "new_value": "12", 1582 "expected": { 1583 "href": "sc:///", 1584 "port": "" 1585 } 1586 }, 1587 { 1588 "href": "sc://x/", 1589 "new_value": "12", 1590 "expected": { 1591 "href": "sc://x:12/", 1592 "port": "12" 1593 } 1594 }, 1595 { 1596 "href": "javascript://x/", 1597 "new_value": "12", 1598 "expected": { 1599 "href": "javascript://x:12/", 1600 "port": "12" 1601 } 1602 } 1603 ], 1604 "pathname": [ 1605 { 1606 "comment": "Cannot-be-a-base don’t have a path", 1607 "href": "mailto:me@example.net", 1608 "new_value": "/foo", 1609 "expected": { 1610 "href": "mailto:me@example.net", 1611 "pathname": "me@example.net" 1612 } 1613 }, 1614 { 1615 "comment": "Special URLs cannot have their paths erased", 1616 "href": "file:///some/path", 1617 "new_value": "", 1618 "expected": { 1619 "href": "file:///", 1620 "pathname": "/" 1621 } 1622 }, 1623 { 1624 "comment": "Non-special URLs can have their paths erased", 1625 "href": "foo://somehost/some/path", 1626 "new_value": "", 1627 "expected": { 1628 "href": "foo://somehost", 1629 "pathname": "" 1630 } 1631 }, 1632 { 1633 "comment": "Non-special URLs with an empty host can have their paths erased", 1634 "href": "foo:///some/path", 1635 "new_value": "", 1636 "expected": { 1637 "href": "foo://", 1638 "pathname": "" 1639 } 1640 }, 1641 { 1642 "comment": "Path-only URLs cannot have their paths erased", 1643 "href": "foo:/some/path", 1644 "new_value": "", 1645 "expected": { 1646 "href": "foo:/", 1647 "pathname": "/" 1648 } 1649 }, 1650 { 1651 "comment": "Path-only URLs always have an initial slash", 1652 "href": "foo:/some/path", 1653 "new_value": "test", 1654 "expected": { 1655 "href": "foo:/test", 1656 "pathname": "/test" 1657 } 1658 }, 1659 { 1660 "href": "unix:/run/foo.socket?timeout=10", 1661 "new_value": "/var/log/../run/bar.socket", 1662 "expected": { 1663 "href": "unix:/var/run/bar.socket?timeout=10", 1664 "pathname": "/var/run/bar.socket" 1665 } 1666 }, 1667 { 1668 "href": "https://example.net#nav", 1669 "new_value": "home", 1670 "expected": { 1671 "href": "https://example.net/home#nav", 1672 "pathname": "/home" 1673 } 1674 }, 1675 { 1676 "href": "https://example.net#nav", 1677 "new_value": "../home", 1678 "expected": { 1679 "href": "https://example.net/home#nav", 1680 "pathname": "/home" 1681 } 1682 }, 1683 { 1684 "comment": "\\ is a segment delimiter for 'special' URLs", 1685 "href": "http://example.net/home?lang=fr#nav", 1686 "new_value": "\\a\\%2E\\b\\%2e.\\c", 1687 "expected": { 1688 "href": "http://example.net/a/c?lang=fr#nav", 1689 "pathname": "/a/c" 1690 } 1691 }, 1692 { 1693 "comment": "\\ is *not* a segment delimiter for non-'special' URLs", 1694 "href": "view-source+http://example.net/home?lang=fr#nav", 1695 "new_value": "\\a\\%2E\\b\\%2e.\\c", 1696 "expected": { 1697 "href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav", 1698 "pathname": "/\\a\\%2E\\b\\%2e.\\c" 1699 } 1700 }, 1701 { 1702 "comment": "UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.", 1703 "href": "a:/", 1704 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 1705 "expected": { 1706 "href": "a:/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9", 1707 "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9" 1708 } 1709 }, 1710 { 1711 "comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.", 1712 "href": "http://example.net", 1713 "new_value": "%2e%2E%c3%89té", 1714 "expected": { 1715 "href": "http://example.net/%2e%2E%c3%89t%C3%A9", 1716 "pathname": "/%2e%2E%c3%89t%C3%A9" 1717 } 1718 }, 1719 { 1720 "comment": "? needs to be encoded", 1721 "href": "http://example.net", 1722 "new_value": "?", 1723 "expected": { 1724 "href": "http://example.net/%3F", 1725 "pathname": "/%3F" 1726 } 1727 }, 1728 { 1729 "comment": "# needs to be encoded", 1730 "href": "http://example.net", 1731 "new_value": "#", 1732 "expected": { 1733 "href": "http://example.net/%23", 1734 "pathname": "/%23" 1735 } 1736 }, 1737 { 1738 "comment": "? needs to be encoded, non-special scheme", 1739 "href": "sc://example.net", 1740 "new_value": "?", 1741 "expected": { 1742 "href": "sc://example.net/%3F", 1743 "pathname": "/%3F" 1744 } 1745 }, 1746 { 1747 "comment": "# needs to be encoded, non-special scheme", 1748 "href": "sc://example.net", 1749 "new_value": "#", 1750 "expected": { 1751 "href": "sc://example.net/%23", 1752 "pathname": "/%23" 1753 } 1754 }, 1755 { 1756 "comment": "? doesn't mess up encoding", 1757 "href": "http://example.net", 1758 "new_value": "/?é", 1759 "expected": { 1760 "href": "http://example.net/%3F%C3%A9", 1761 "pathname": "/%3F%C3%A9" 1762 } 1763 }, 1764 { 1765 "comment": "# doesn't mess up encoding", 1766 "href": "http://example.net", 1767 "new_value": "/#é", 1768 "expected": { 1769 "href": "http://example.net/%23%C3%A9", 1770 "pathname": "/%23%C3%A9" 1771 } 1772 }, 1773 { 1774 "comment": "File URLs and (back)slashes", 1775 "href": "file://monkey/", 1776 "new_value": "\\\\", 1777 "expected": { 1778 "href": "file://monkey//", 1779 "pathname": "//" 1780 } 1781 }, 1782 { 1783 "comment": "File URLs and (back)slashes", 1784 "href": "file:///unicorn", 1785 "new_value": "//\\/", 1786 "expected": { 1787 "href": "file://////", 1788 "pathname": "////" 1789 } 1790 }, 1791 { 1792 "comment": "File URLs and (back)slashes", 1793 "href": "file:///unicorn", 1794 "new_value": "//monkey/..//", 1795 "expected": { 1796 "href": "file://///", 1797 "pathname": "///" 1798 } 1799 }, 1800 { 1801 "comment": "Serialize /. in path", 1802 "href": "non-spec:/", 1803 "new_value": "/.//p", 1804 "expected": { 1805 "href": "non-spec:/.//p", 1806 "pathname": "//p" 1807 } 1808 }, 1809 { 1810 "href": "non-spec:/", 1811 "new_value": "/..//p", 1812 "expected": { 1813 "href": "non-spec:/.//p", 1814 "pathname": "//p" 1815 } 1816 }, 1817 { 1818 "href": "non-spec:/", 1819 "new_value": "//p", 1820 "expected": { 1821 "href": "non-spec:/.//p", 1822 "pathname": "//p" 1823 } 1824 }, 1825 { 1826 "comment": "Drop /. from path", 1827 "href": "non-spec:/.//", 1828 "new_value": "p", 1829 "expected": { 1830 "href": "non-spec:/p", 1831 "pathname": "/p" 1832 } 1833 } 1834 ], 1835 "search": [ 1836 { 1837 "href": "https://example.net#nav", 1838 "new_value": "lang=fr", 1839 "expected": { 1840 "href": "https://example.net/?lang=fr#nav", 1841 "search": "?lang=fr" 1842 } 1843 }, 1844 { 1845 "href": "https://example.net?lang=en-US#nav", 1846 "new_value": "lang=fr", 1847 "expected": { 1848 "href": "https://example.net/?lang=fr#nav", 1849 "search": "?lang=fr" 1850 } 1851 }, 1852 { 1853 "href": "https://example.net?lang=en-US#nav", 1854 "new_value": "?lang=fr", 1855 "expected": { 1856 "href": "https://example.net/?lang=fr#nav", 1857 "search": "?lang=fr" 1858 } 1859 }, 1860 { 1861 "href": "https://example.net?lang=en-US#nav", 1862 "new_value": "??lang=fr", 1863 "expected": { 1864 "href": "https://example.net/??lang=fr#nav", 1865 "search": "??lang=fr" 1866 } 1867 }, 1868 { 1869 "href": "https://example.net?lang=en-US#nav", 1870 "new_value": "?", 1871 "expected": { 1872 "href": "https://example.net/?#nav", 1873 "search": "" 1874 } 1875 }, 1876 { 1877 "href": "https://example.net?lang=en-US#nav", 1878 "new_value": "", 1879 "expected": { 1880 "href": "https://example.net/#nav", 1881 "search": "" 1882 } 1883 }, 1884 { 1885 "href": "https://example.net?lang=en-US", 1886 "new_value": "", 1887 "expected": { 1888 "href": "https://example.net/", 1889 "search": "" 1890 } 1891 }, 1892 { 1893 "href": "https://example.net", 1894 "new_value": "", 1895 "expected": { 1896 "href": "https://example.net/", 1897 "search": "" 1898 } 1899 }, 1900 { 1901 "comment": "UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.", 1902 "href": "a:/", 1903 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 1904 "expected": { 1905 "href": "a:/?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", 1906 "search": "?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" 1907 } 1908 }, 1909 { 1910 "comment": "Bytes already percent-encoded are left as-is", 1911 "href": "http://example.net", 1912 "new_value": "%c3%89té", 1913 "expected": { 1914 "href": "http://example.net/?%c3%89t%C3%A9", 1915 "search": "?%c3%89t%C3%A9" 1916 } 1917 } 1918 ], 1919 "hash": [ 1920 { 1921 "href": "https://example.net", 1922 "new_value": "main", 1923 "expected": { 1924 "href": "https://example.net/#main", 1925 "hash": "#main" 1926 } 1927 }, 1928 { 1929 "href": "https://example.net#nav", 1930 "new_value": "main", 1931 "expected": { 1932 "href": "https://example.net/#main", 1933 "hash": "#main" 1934 } 1935 }, 1936 { 1937 "href": "https://example.net?lang=en-US", 1938 "new_value": "##nav", 1939 "expected": { 1940 "href": "https://example.net/?lang=en-US##nav", 1941 "hash": "##nav" 1942 } 1943 }, 1944 { 1945 "href": "https://example.net?lang=en-US#nav", 1946 "new_value": "#main", 1947 "expected": { 1948 "href": "https://example.net/?lang=en-US#main", 1949 "hash": "#main" 1950 } 1951 }, 1952 { 1953 "href": "https://example.net?lang=en-US#nav", 1954 "new_value": "#", 1955 "expected": { 1956 "href": "https://example.net/?lang=en-US#", 1957 "hash": "" 1958 } 1959 }, 1960 { 1961 "href": "https://example.net?lang=en-US#nav", 1962 "new_value": "", 1963 "expected": { 1964 "href": "https://example.net/?lang=en-US", 1965 "hash": "" 1966 } 1967 }, 1968 { 1969 "href": "http://example.net", 1970 "new_value": "#foo bar", 1971 "expected": { 1972 "href": "http://example.net/#foo%20bar", 1973 "hash": "#foo%20bar" 1974 } 1975 }, 1976 { 1977 "href": "http://example.net", 1978 "new_value": "#foo\"bar", 1979 "expected": { 1980 "href": "http://example.net/#foo%22bar", 1981 "hash": "#foo%22bar" 1982 } 1983 }, 1984 { 1985 "href": "http://example.net", 1986 "new_value": "#foo<bar", 1987 "expected": { 1988 "href": "http://example.net/#foo%3Cbar", 1989 "hash": "#foo%3Cbar" 1990 } 1991 }, 1992 { 1993 "href": "http://example.net", 1994 "new_value": "#foo>bar", 1995 "expected": { 1996 "href": "http://example.net/#foo%3Ebar", 1997 "hash": "#foo%3Ebar" 1998 } 1999 }, 2000 { 2001 "href": "http://example.net", 2002 "new_value": "#foo`bar", 2003 "expected": { 2004 "href": "http://example.net/#foo%60bar", 2005 "hash": "#foo%60bar" 2006 } 2007 }, 2008 { 2009 "comment": "Simple percent-encoding; tabs and newlines are removed", 2010 "href": "a:/", 2011 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 2012 "expected": { 2013 "href": "a:/#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", 2014 "hash": "#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" 2015 } 2016 }, 2017 { 2018 "comment": "Percent-encode NULLs in fragment", 2019 "href": "http://example.net", 2020 "new_value": "a\u0000b", 2021 "expected": { 2022 "href": "http://example.net/#a%00b", 2023 "hash": "#a%00b" 2024 } 2025 }, 2026 { 2027 "comment": "Percent-encode NULLs in fragment", 2028 "href": "non-spec:/", 2029 "new_value": "a\u0000b", 2030 "expected": { 2031 "href": "non-spec:/#a%00b", 2032 "hash": "#a%00b" 2033 } 2034 }, 2035 { 2036 "comment": "Bytes already percent-encoded are left as-is", 2037 "href": "http://example.net", 2038 "new_value": "%c3%89té", 2039 "expected": { 2040 "href": "http://example.net/#%c3%89t%C3%A9", 2041 "hash": "#%c3%89t%C3%A9" 2042 } 2043 }, 2044 { 2045 "href": "javascript:alert(1)", 2046 "new_value": "castle", 2047 "expected": { 2048 "href": "javascript:alert(1)#castle", 2049 "hash": "#castle" 2050 } 2051 } 2052 ] 2053} 2054