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 "comment": "Tab and newline are stripped", 275 "href": "http://test/", 276 "new_value": "h\u000D\u000Att\u0009ps", 277 "expected": { 278 "href": "https://test/", 279 "protocol": "https:", 280 "port": "" 281 } 282 }, 283 { 284 "href": "http://test/", 285 "new_value": "https\u000D", 286 "expected": { 287 "href": "https://test/", 288 "protocol": "https:" 289 } 290 }, 291 { 292 "comment": "Non-tab/newline C0 controls result in no-op", 293 "href": "http://test/", 294 "new_value": "https\u0000", 295 "expected": { 296 "href": "http://test/", 297 "protocol": "http:" 298 } 299 }, 300 { 301 "href": "http://test/", 302 "new_value": "https\u000C", 303 "expected": { 304 "href": "http://test/", 305 "protocol": "http:" 306 } 307 }, 308 { 309 "href": "http://test/", 310 "new_value": "https\u000E", 311 "expected": { 312 "href": "http://test/", 313 "protocol": "http:" 314 } 315 }, 316 { 317 "href": "http://test/", 318 "new_value": "https\u0020", 319 "expected": { 320 "href": "http://test/", 321 "protocol": "http:" 322 } 323 } 324 ], 325 "username": [ 326 { 327 "comment": "No host means no username", 328 "href": "file:///home/you/index.html", 329 "new_value": "me", 330 "expected": { 331 "href": "file:///home/you/index.html", 332 "username": "" 333 } 334 }, 335 { 336 "comment": "No host means no username", 337 "href": "unix:/run/foo.socket", 338 "new_value": "me", 339 "expected": { 340 "href": "unix:/run/foo.socket", 341 "username": "" 342 } 343 }, 344 { 345 "comment": "Cannot-be-a-base means no username", 346 "href": "mailto:you@example.net", 347 "new_value": "me", 348 "expected": { 349 "href": "mailto:you@example.net", 350 "username": "" 351 } 352 }, 353 { 354 "href": "javascript:alert(1)", 355 "new_value": "wario", 356 "expected": { 357 "href": "javascript:alert(1)", 358 "username": "" 359 } 360 }, 361 { 362 "href": "http://example.net", 363 "new_value": "me", 364 "expected": { 365 "href": "http://me@example.net/", 366 "username": "me" 367 } 368 }, 369 { 370 "href": "http://:secret@example.net", 371 "new_value": "me", 372 "expected": { 373 "href": "http://me:secret@example.net/", 374 "username": "me" 375 } 376 }, 377 { 378 "href": "http://me@example.net", 379 "new_value": "", 380 "expected": { 381 "href": "http://example.net/", 382 "username": "" 383 } 384 }, 385 { 386 "href": "http://me:secret@example.net", 387 "new_value": "", 388 "expected": { 389 "href": "http://:secret@example.net/", 390 "username": "" 391 } 392 }, 393 { 394 "comment": "UTF-8 percent encoding with the userinfo encode set.", 395 "href": "http://example.net", 396 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 397 "expected": { 398 "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/", 399 "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" 400 } 401 }, 402 { 403 "comment": "Bytes already percent-encoded are left as-is.", 404 "href": "http://example.net", 405 "new_value": "%c3%89té", 406 "expected": { 407 "href": "http://%c3%89t%C3%A9@example.net/", 408 "username": "%c3%89t%C3%A9" 409 } 410 }, 411 { 412 "href": "sc:///", 413 "new_value": "x", 414 "expected": { 415 "href": "sc:///", 416 "username": "" 417 } 418 }, 419 { 420 "href": "javascript://x/", 421 "new_value": "wario", 422 "expected": { 423 "href": "javascript://wario@x/", 424 "username": "wario" 425 } 426 }, 427 { 428 "href": "file://test/", 429 "new_value": "test", 430 "expected": { 431 "href": "file://test/", 432 "username": "" 433 } 434 } 435 ], 436 "password": [ 437 { 438 "comment": "No host means no password", 439 "href": "file:///home/me/index.html", 440 "new_value": "secret", 441 "expected": { 442 "href": "file:///home/me/index.html", 443 "password": "" 444 } 445 }, 446 { 447 "comment": "No host means no password", 448 "href": "unix:/run/foo.socket", 449 "new_value": "secret", 450 "expected": { 451 "href": "unix:/run/foo.socket", 452 "password": "" 453 } 454 }, 455 { 456 "comment": "Cannot-be-a-base means no password", 457 "href": "mailto:me@example.net", 458 "new_value": "secret", 459 "expected": { 460 "href": "mailto:me@example.net", 461 "password": "" 462 } 463 }, 464 { 465 "href": "http://example.net", 466 "new_value": "secret", 467 "expected": { 468 "href": "http://:secret@example.net/", 469 "password": "secret" 470 } 471 }, 472 { 473 "href": "http://me@example.net", 474 "new_value": "secret", 475 "expected": { 476 "href": "http://me:secret@example.net/", 477 "password": "secret" 478 } 479 }, 480 { 481 "href": "http://:secret@example.net", 482 "new_value": "", 483 "expected": { 484 "href": "http://example.net/", 485 "password": "" 486 } 487 }, 488 { 489 "href": "http://me:secret@example.net", 490 "new_value": "", 491 "expected": { 492 "href": "http://me@example.net/", 493 "password": "" 494 } 495 }, 496 { 497 "comment": "UTF-8 percent encoding with the userinfo encode set.", 498 "href": "http://example.net", 499 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 500 "expected": { 501 "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/", 502 "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" 503 } 504 }, 505 { 506 "comment": "Bytes already percent-encoded are left as-is.", 507 "href": "http://example.net", 508 "new_value": "%c3%89té", 509 "expected": { 510 "href": "http://:%c3%89t%C3%A9@example.net/", 511 "password": "%c3%89t%C3%A9" 512 } 513 }, 514 { 515 "href": "sc:///", 516 "new_value": "x", 517 "expected": { 518 "href": "sc:///", 519 "password": "" 520 } 521 }, 522 { 523 "href": "javascript://x/", 524 "new_value": "bowser", 525 "expected": { 526 "href": "javascript://:bowser@x/", 527 "password": "bowser" 528 } 529 }, 530 { 531 "href": "file://test/", 532 "new_value": "test", 533 "expected": { 534 "href": "file://test/", 535 "password": "" 536 } 537 } 538 ], 539 "host": [ 540 { 541 "comment": "Non-special scheme", 542 "href": "sc://x/", 543 "new_value": "\u0000", 544 "expected": { 545 "href": "sc://x/", 546 "host": "x", 547 "hostname": "x" 548 } 549 }, 550 { 551 "href": "sc://x/", 552 "new_value": "\u0009", 553 "expected": { 554 "href": "sc:///", 555 "host": "", 556 "hostname": "" 557 } 558 }, 559 { 560 "href": "sc://x/", 561 "new_value": "\u000A", 562 "expected": { 563 "href": "sc:///", 564 "host": "", 565 "hostname": "" 566 } 567 }, 568 { 569 "href": "sc://x/", 570 "new_value": "\u000D", 571 "expected": { 572 "href": "sc:///", 573 "host": "", 574 "hostname": "" 575 } 576 }, 577 { 578 "href": "sc://x/", 579 "new_value": " ", 580 "expected": { 581 "href": "sc://x/", 582 "host": "x", 583 "hostname": "x" 584 } 585 }, 586 { 587 "href": "sc://x/", 588 "new_value": "#", 589 "expected": { 590 "href": "sc:///", 591 "host": "", 592 "hostname": "" 593 } 594 }, 595 { 596 "href": "sc://x/", 597 "new_value": "/", 598 "expected": { 599 "href": "sc:///", 600 "host": "", 601 "hostname": "" 602 } 603 }, 604 { 605 "href": "sc://x/", 606 "new_value": "?", 607 "expected": { 608 "href": "sc:///", 609 "host": "", 610 "hostname": "" 611 } 612 }, 613 { 614 "href": "sc://x/", 615 "new_value": "@", 616 "expected": { 617 "href": "sc://x/", 618 "host": "x", 619 "hostname": "x" 620 } 621 }, 622 { 623 "href": "sc://x/", 624 "new_value": "ß", 625 "expected": { 626 "href": "sc://%C3%9F/", 627 "host": "%C3%9F", 628 "hostname": "%C3%9F" 629 } 630 }, 631 { 632 "comment": "IDNA Nontransitional_Processing", 633 "href": "https://x/", 634 "new_value": "ß", 635 "expected": { 636 "href": "https://xn--zca/", 637 "host": "xn--zca", 638 "hostname": "xn--zca" 639 } 640 }, 641 { 642 "comment": "Cannot-be-a-base means no host", 643 "href": "mailto:me@example.net", 644 "new_value": "example.com", 645 "expected": { 646 "href": "mailto:me@example.net", 647 "host": "" 648 } 649 }, 650 { 651 "comment": "Cannot-be-a-base means no host", 652 "href": "data:text/plain,Stuff", 653 "new_value": "example.net", 654 "expected": { 655 "href": "data:text/plain,Stuff", 656 "host": "" 657 } 658 }, 659 { 660 "href": "http://example.net", 661 "new_value": "example.com:8080", 662 "expected": { 663 "href": "http://example.com:8080/", 664 "host": "example.com:8080", 665 "hostname": "example.com", 666 "port": "8080" 667 } 668 }, 669 { 670 "comment": "Port number is unchanged if not specified in the new value", 671 "href": "http://example.net:8080", 672 "new_value": "example.com", 673 "expected": { 674 "href": "http://example.com:8080/", 675 "host": "example.com:8080", 676 "hostname": "example.com", 677 "port": "8080" 678 } 679 }, 680 { 681 "comment": "Port number is unchanged if not specified", 682 "href": "http://example.net:8080", 683 "new_value": "example.com:", 684 "expected": { 685 "href": "http://example.com:8080/", 686 "host": "example.com:8080", 687 "hostname": "example.com", 688 "port": "8080" 689 } 690 }, 691 { 692 "comment": "The empty host is not valid for special schemes", 693 "href": "http://example.net", 694 "new_value": "", 695 "expected": { 696 "href": "http://example.net/", 697 "host": "example.net" 698 } 699 }, 700 { 701 "comment": "The empty host is OK for non-special schemes", 702 "href": "view-source+http://example.net/foo", 703 "new_value": "", 704 "expected": { 705 "href": "view-source+http:///foo", 706 "host": "" 707 } 708 }, 709 { 710 "comment": "Path-only URLs can gain a host", 711 "href": "a:/foo", 712 "new_value": "example.net", 713 "expected": { 714 "href": "a://example.net/foo", 715 "host": "example.net" 716 } 717 }, 718 { 719 "comment": "IPv4 address syntax is normalized", 720 "href": "http://example.net", 721 "new_value": "0x7F000001:8080", 722 "expected": { 723 "href": "http://127.0.0.1:8080/", 724 "host": "127.0.0.1:8080", 725 "hostname": "127.0.0.1", 726 "port": "8080" 727 } 728 }, 729 { 730 "comment": "IPv6 address syntax is normalized", 731 "href": "http://example.net", 732 "new_value": "[::0:01]:2", 733 "expected": { 734 "href": "http://[::1]:2/", 735 "host": "[::1]:2", 736 "hostname": "[::1]", 737 "port": "2" 738 } 739 }, 740 { 741 "comment": "IPv6 literal address with port, crbug.com/1012416", 742 "href": "http://example.net", 743 "new_value": "[2001:db8::2]:4002", 744 "expected": { 745 "href": "http://[2001:db8::2]:4002/", 746 "host": "[2001:db8::2]:4002", 747 "hostname": "[2001:db8::2]", 748 "port": "4002" 749 } 750 }, 751 { 752 "comment": "Default port number is removed", 753 "href": "http://example.net", 754 "new_value": "example.com:80", 755 "expected": { 756 "href": "http://example.com/", 757 "host": "example.com", 758 "hostname": "example.com", 759 "port": "" 760 } 761 }, 762 { 763 "comment": "Default port number is removed", 764 "href": "https://example.net", 765 "new_value": "example.com:443", 766 "expected": { 767 "href": "https://example.com/", 768 "host": "example.com", 769 "hostname": "example.com", 770 "port": "" 771 } 772 }, 773 { 774 "comment": "Default port number is only removed for the relevant scheme", 775 "href": "https://example.net", 776 "new_value": "example.com:80", 777 "expected": { 778 "href": "https://example.com:80/", 779 "host": "example.com:80", 780 "hostname": "example.com", 781 "port": "80" 782 } 783 }, 784 { 785 "comment": "Port number is removed if new port is scheme default and existing URL has a non-default port", 786 "href": "http://example.net:8080", 787 "new_value": "example.com:80", 788 "expected": { 789 "href": "http://example.com/", 790 "host": "example.com", 791 "hostname": "example.com", 792 "port": "" 793 } 794 }, 795 { 796 "comment": "Stuff after a / delimiter is ignored", 797 "href": "http://example.net/path", 798 "new_value": "example.com/stuff", 799 "expected": { 800 "href": "http://example.com/path", 801 "host": "example.com", 802 "hostname": "example.com", 803 "port": "" 804 } 805 }, 806 { 807 "comment": "Stuff after a / delimiter is ignored", 808 "href": "http://example.net/path", 809 "new_value": "example.com:8080/stuff", 810 "expected": { 811 "href": "http://example.com:8080/path", 812 "host": "example.com:8080", 813 "hostname": "example.com", 814 "port": "8080" 815 } 816 }, 817 { 818 "comment": "Stuff after a ? delimiter is ignored", 819 "href": "http://example.net/path", 820 "new_value": "example.com?stuff", 821 "expected": { 822 "href": "http://example.com/path", 823 "host": "example.com", 824 "hostname": "example.com", 825 "port": "" 826 } 827 }, 828 { 829 "comment": "Stuff after a ? delimiter is ignored", 830 "href": "http://example.net/path", 831 "new_value": "example.com:8080?stuff", 832 "expected": { 833 "href": "http://example.com:8080/path", 834 "host": "example.com:8080", 835 "hostname": "example.com", 836 "port": "8080" 837 } 838 }, 839 { 840 "comment": "Stuff after a # delimiter is ignored", 841 "href": "http://example.net/path", 842 "new_value": "example.com#stuff", 843 "expected": { 844 "href": "http://example.com/path", 845 "host": "example.com", 846 "hostname": "example.com", 847 "port": "" 848 } 849 }, 850 { 851 "comment": "Stuff after a # delimiter is ignored", 852 "href": "http://example.net/path", 853 "new_value": "example.com:8080#stuff", 854 "expected": { 855 "href": "http://example.com:8080/path", 856 "host": "example.com:8080", 857 "hostname": "example.com", 858 "port": "8080" 859 } 860 }, 861 { 862 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 863 "href": "http://example.net/path", 864 "new_value": "example.com\\stuff", 865 "expected": { 866 "href": "http://example.com/path", 867 "host": "example.com", 868 "hostname": "example.com", 869 "port": "" 870 } 871 }, 872 { 873 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 874 "href": "http://example.net/path", 875 "new_value": "example.com:8080\\stuff", 876 "expected": { 877 "href": "http://example.com:8080/path", 878 "host": "example.com:8080", 879 "hostname": "example.com", 880 "port": "8080" 881 } 882 }, 883 { 884 "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts", 885 "href": "view-source+http://example.net/path", 886 "new_value": "example.com\\stuff", 887 "expected": { 888 "href": "view-source+http://example.net/path", 889 "host": "example.net", 890 "hostname": "example.net", 891 "port": "" 892 } 893 }, 894 { 895 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 896 "href": "view-source+http://example.net/path", 897 "new_value": "example.com:8080stuff2", 898 "expected": { 899 "href": "view-source+http://example.com:8080/path", 900 "host": "example.com:8080", 901 "hostname": "example.com", 902 "port": "8080" 903 } 904 }, 905 { 906 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 907 "href": "http://example.net/path", 908 "new_value": "example.com:8080stuff2", 909 "expected": { 910 "href": "http://example.com:8080/path", 911 "host": "example.com:8080", 912 "hostname": "example.com", 913 "port": "8080" 914 } 915 }, 916 { 917 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 918 "href": "http://example.net/path", 919 "new_value": "example.com:8080+2", 920 "expected": { 921 "href": "http://example.com:8080/path", 922 "host": "example.com:8080", 923 "hostname": "example.com", 924 "port": "8080" 925 } 926 }, 927 { 928 "comment": "Port numbers are 16 bit integers", 929 "href": "http://example.net/path", 930 "new_value": "example.com:65535", 931 "expected": { 932 "href": "http://example.com:65535/path", 933 "host": "example.com:65535", 934 "hostname": "example.com", 935 "port": "65535" 936 } 937 }, 938 { 939 "comment": "Port numbers are 16 bit integers, overflowing is an error. Hostname is still set, though.", 940 "href": "http://example.net/path", 941 "new_value": "example.com:65536", 942 "expected": { 943 "href": "http://example.com/path", 944 "host": "example.com", 945 "hostname": "example.com", 946 "port": "" 947 } 948 }, 949 { 950 "comment": "Broken IPv6", 951 "href": "http://example.net/", 952 "new_value": "[google.com]", 953 "expected": { 954 "href": "http://example.net/", 955 "host": "example.net", 956 "hostname": "example.net" 957 } 958 }, 959 { 960 "href": "http://example.net/", 961 "new_value": "[::1.2.3.4x]", 962 "expected": { 963 "href": "http://example.net/", 964 "host": "example.net", 965 "hostname": "example.net" 966 } 967 }, 968 { 969 "href": "http://example.net/", 970 "new_value": "[::1.2.3.]", 971 "expected": { 972 "href": "http://example.net/", 973 "host": "example.net", 974 "hostname": "example.net" 975 } 976 }, 977 { 978 "href": "http://example.net/", 979 "new_value": "[::1.2.]", 980 "expected": { 981 "href": "http://example.net/", 982 "host": "example.net", 983 "hostname": "example.net" 984 } 985 }, 986 { 987 "href": "http://example.net/", 988 "new_value": "[::1.]", 989 "expected": { 990 "href": "http://example.net/", 991 "host": "example.net", 992 "hostname": "example.net" 993 } 994 }, 995 { 996 "href": "file://y/", 997 "new_value": "x:123", 998 "expected": { 999 "href": "file://y/", 1000 "host": "y", 1001 "hostname": "y", 1002 "port": "" 1003 } 1004 }, 1005 { 1006 "href": "file://y/", 1007 "new_value": "loc%41lhost", 1008 "expected": { 1009 "href": "file:///", 1010 "host": "", 1011 "hostname": "", 1012 "port": "" 1013 } 1014 }, 1015 { 1016 "href": "file://hi/x", 1017 "new_value": "", 1018 "expected": { 1019 "href": "file:///x", 1020 "host": "", 1021 "hostname": "", 1022 "port": "" 1023 } 1024 }, 1025 { 1026 "href": "sc://test@test/", 1027 "new_value": "", 1028 "expected": { 1029 "href": "sc://test@test/", 1030 "host": "test", 1031 "hostname": "test", 1032 "username": "test" 1033 } 1034 }, 1035 { 1036 "href": "sc://test:12/", 1037 "new_value": "", 1038 "expected": { 1039 "href": "sc://test:12/", 1040 "host": "test:12", 1041 "hostname": "test", 1042 "port": "12" 1043 } 1044 }, 1045 { 1046 "comment": "Leading / is not stripped", 1047 "href": "http://example.com/", 1048 "new_value": "///bad.com", 1049 "expected": { 1050 "href": "http://example.com/", 1051 "host": "example.com", 1052 "hostname": "example.com" 1053 } 1054 }, 1055 { 1056 "comment": "Leading / is not stripped", 1057 "href": "sc://example.com/", 1058 "new_value": "///bad.com", 1059 "expected": { 1060 "href": "sc:///", 1061 "host": "", 1062 "hostname": "" 1063 } 1064 }, 1065 { 1066 "href": "https://example.com/", 1067 "new_value": "a%C2%ADb", 1068 "expected": { 1069 "href": "https://ab/", 1070 "host": "ab", 1071 "hostname": "ab" 1072 } 1073 }, 1074 { 1075 "href": "https://example.com/", 1076 "new_value": "\u00AD", 1077 "expected": { 1078 "href": "https://example.com/", 1079 "host": "example.com", 1080 "hostname": "example.com" 1081 } 1082 }, 1083 { 1084 "href": "https://example.com/", 1085 "new_value": "%C2%AD", 1086 "expected": { 1087 "href": "https://example.com/", 1088 "host": "example.com", 1089 "hostname": "example.com" 1090 } 1091 }, 1092 { 1093 "href": "https://example.com/", 1094 "new_value": "xn--", 1095 "expected": { 1096 "href": "https://example.com/", 1097 "host": "example.com", 1098 "hostname": "example.com" 1099 } 1100 } 1101 ], 1102 "hostname": [ 1103 { 1104 "comment": "Non-special scheme", 1105 "href": "sc://x/", 1106 "new_value": "\u0000", 1107 "expected": { 1108 "href": "sc://x/", 1109 "host": "x", 1110 "hostname": "x" 1111 } 1112 }, 1113 { 1114 "href": "sc://x/", 1115 "new_value": "\u0009", 1116 "expected": { 1117 "href": "sc:///", 1118 "host": "", 1119 "hostname": "" 1120 } 1121 }, 1122 { 1123 "href": "sc://x/", 1124 "new_value": "\u000A", 1125 "expected": { 1126 "href": "sc:///", 1127 "host": "", 1128 "hostname": "" 1129 } 1130 }, 1131 { 1132 "href": "sc://x/", 1133 "new_value": "\u000D", 1134 "expected": { 1135 "href": "sc:///", 1136 "host": "", 1137 "hostname": "" 1138 } 1139 }, 1140 { 1141 "href": "sc://x/", 1142 "new_value": " ", 1143 "expected": { 1144 "href": "sc://x/", 1145 "host": "x", 1146 "hostname": "x" 1147 } 1148 }, 1149 { 1150 "href": "sc://x/", 1151 "new_value": "#", 1152 "expected": { 1153 "href": "sc:///", 1154 "host": "", 1155 "hostname": "" 1156 } 1157 }, 1158 { 1159 "href": "sc://x/", 1160 "new_value": "/", 1161 "expected": { 1162 "href": "sc:///", 1163 "host": "", 1164 "hostname": "" 1165 } 1166 }, 1167 { 1168 "href": "sc://x/", 1169 "new_value": "?", 1170 "expected": { 1171 "href": "sc:///", 1172 "host": "", 1173 "hostname": "" 1174 } 1175 }, 1176 { 1177 "href": "sc://x/", 1178 "new_value": "@", 1179 "expected": { 1180 "href": "sc://x/", 1181 "host": "x", 1182 "hostname": "x" 1183 } 1184 }, 1185 { 1186 "comment": "Cannot-be-a-base means no host", 1187 "href": "mailto:me@example.net", 1188 "new_value": "example.com", 1189 "expected": { 1190 "href": "mailto:me@example.net", 1191 "host": "" 1192 } 1193 }, 1194 { 1195 "comment": "Cannot-be-a-base means no host", 1196 "href": "data:text/plain,Stuff", 1197 "new_value": "example.net", 1198 "expected": { 1199 "href": "data:text/plain,Stuff", 1200 "host": "" 1201 } 1202 }, 1203 { 1204 "href": "http://example.net:8080", 1205 "new_value": "example.com", 1206 "expected": { 1207 "href": "http://example.com:8080/", 1208 "host": "example.com:8080", 1209 "hostname": "example.com", 1210 "port": "8080" 1211 } 1212 }, 1213 { 1214 "comment": "The empty host is not valid for special schemes", 1215 "href": "http://example.net", 1216 "new_value": "", 1217 "expected": { 1218 "href": "http://example.net/", 1219 "host": "example.net" 1220 } 1221 }, 1222 { 1223 "comment": "The empty host is OK for non-special schemes", 1224 "href": "view-source+http://example.net/foo", 1225 "new_value": "", 1226 "expected": { 1227 "href": "view-source+http:///foo", 1228 "host": "" 1229 } 1230 }, 1231 { 1232 "comment": "Path-only URLs can gain a host", 1233 "href": "a:/foo", 1234 "new_value": "example.net", 1235 "expected": { 1236 "href": "a://example.net/foo", 1237 "host": "example.net" 1238 } 1239 }, 1240 { 1241 "comment": "IPv4 address syntax is normalized", 1242 "href": "http://example.net:8080", 1243 "new_value": "0x7F000001", 1244 "expected": { 1245 "href": "http://127.0.0.1:8080/", 1246 "host": "127.0.0.1:8080", 1247 "hostname": "127.0.0.1", 1248 "port": "8080" 1249 } 1250 }, 1251 { 1252 "comment": "IPv6 address syntax is normalized", 1253 "href": "http://example.net", 1254 "new_value": "[::0:01]", 1255 "expected": { 1256 "href": "http://[::1]/", 1257 "host": "[::1]", 1258 "hostname": "[::1]", 1259 "port": "" 1260 } 1261 }, 1262 { 1263 "comment": ": delimiter invalidates entire value", 1264 "href": "http://example.net/path", 1265 "new_value": "example.com:8080", 1266 "expected": { 1267 "href": "http://example.net/path", 1268 "host": "example.net", 1269 "hostname": "example.net", 1270 "port": "" 1271 } 1272 }, 1273 { 1274 "comment": ": delimiter invalidates entire value", 1275 "href": "http://example.net:8080/path", 1276 "new_value": "example.com:", 1277 "expected": { 1278 "href": "http://example.net:8080/path", 1279 "host": "example.net:8080", 1280 "hostname": "example.net", 1281 "port": "8080" 1282 } 1283 }, 1284 { 1285 "comment": "Stuff after a / delimiter is ignored", 1286 "href": "http://example.net/path", 1287 "new_value": "example.com/stuff", 1288 "expected": { 1289 "href": "http://example.com/path", 1290 "host": "example.com", 1291 "hostname": "example.com", 1292 "port": "" 1293 } 1294 }, 1295 { 1296 "comment": "Stuff after a ? delimiter is ignored", 1297 "href": "http://example.net/path", 1298 "new_value": "example.com?stuff", 1299 "expected": { 1300 "href": "http://example.com/path", 1301 "host": "example.com", 1302 "hostname": "example.com", 1303 "port": "" 1304 } 1305 }, 1306 { 1307 "comment": "Stuff after a # delimiter is ignored", 1308 "href": "http://example.net/path", 1309 "new_value": "example.com#stuff", 1310 "expected": { 1311 "href": "http://example.com/path", 1312 "host": "example.com", 1313 "hostname": "example.com", 1314 "port": "" 1315 } 1316 }, 1317 { 1318 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 1319 "href": "http://example.net/path", 1320 "new_value": "example.com\\stuff", 1321 "expected": { 1322 "href": "http://example.com/path", 1323 "host": "example.com", 1324 "hostname": "example.com", 1325 "port": "" 1326 } 1327 }, 1328 { 1329 "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts", 1330 "href": "view-source+http://example.net/path", 1331 "new_value": "example.com\\stuff", 1332 "expected": { 1333 "href": "view-source+http://example.net/path", 1334 "host": "example.net", 1335 "hostname": "example.net", 1336 "port": "" 1337 } 1338 }, 1339 { 1340 "comment": "Broken IPv6", 1341 "href": "http://example.net/", 1342 "new_value": "[google.com]", 1343 "expected": { 1344 "href": "http://example.net/", 1345 "host": "example.net", 1346 "hostname": "example.net" 1347 } 1348 }, 1349 { 1350 "href": "http://example.net/", 1351 "new_value": "[::1.2.3.4x]", 1352 "expected": { 1353 "href": "http://example.net/", 1354 "host": "example.net", 1355 "hostname": "example.net" 1356 } 1357 }, 1358 { 1359 "href": "http://example.net/", 1360 "new_value": "[::1.2.3.]", 1361 "expected": { 1362 "href": "http://example.net/", 1363 "host": "example.net", 1364 "hostname": "example.net" 1365 } 1366 }, 1367 { 1368 "href": "http://example.net/", 1369 "new_value": "[::1.2.]", 1370 "expected": { 1371 "href": "http://example.net/", 1372 "host": "example.net", 1373 "hostname": "example.net" 1374 } 1375 }, 1376 { 1377 "href": "http://example.net/", 1378 "new_value": "[::1.]", 1379 "expected": { 1380 "href": "http://example.net/", 1381 "host": "example.net", 1382 "hostname": "example.net" 1383 } 1384 }, 1385 { 1386 "href": "file://y/", 1387 "new_value": "x:123", 1388 "expected": { 1389 "href": "file://y/", 1390 "host": "y", 1391 "hostname": "y", 1392 "port": "" 1393 } 1394 }, 1395 { 1396 "href": "file://y/", 1397 "new_value": "loc%41lhost", 1398 "expected": { 1399 "href": "file:///", 1400 "host": "", 1401 "hostname": "", 1402 "port": "" 1403 } 1404 }, 1405 { 1406 "href": "file://hi/x", 1407 "new_value": "", 1408 "expected": { 1409 "href": "file:///x", 1410 "host": "", 1411 "hostname": "", 1412 "port": "" 1413 } 1414 }, 1415 { 1416 "href": "sc://test@test/", 1417 "new_value": "", 1418 "expected": { 1419 "href": "sc://test@test/", 1420 "host": "test", 1421 "hostname": "test", 1422 "username": "test" 1423 } 1424 }, 1425 { 1426 "href": "sc://test:12/", 1427 "new_value": "", 1428 "expected": { 1429 "href": "sc://test:12/", 1430 "host": "test:12", 1431 "hostname": "test", 1432 "port": "12" 1433 } 1434 }, 1435 { 1436 "comment": "Drop /. from path", 1437 "href": "non-spec:/.//p", 1438 "new_value": "h", 1439 "expected": { 1440 "href": "non-spec://h//p", 1441 "host": "h", 1442 "hostname": "h", 1443 "pathname": "//p" 1444 } 1445 }, 1446 { 1447 "href": "non-spec:/.//p", 1448 "new_value": "", 1449 "expected": { 1450 "href": "non-spec:////p", 1451 "host": "", 1452 "hostname": "", 1453 "pathname": "//p" 1454 } 1455 }, 1456 { 1457 "comment": "Leading / is not stripped", 1458 "href": "http://example.com/", 1459 "new_value": "///bad.com", 1460 "expected": { 1461 "href": "http://example.com/", 1462 "host": "example.com", 1463 "hostname": "example.com" 1464 } 1465 }, 1466 { 1467 "comment": "Leading / is not stripped", 1468 "href": "sc://example.com/", 1469 "new_value": "///bad.com", 1470 "expected": { 1471 "href": "sc:///", 1472 "host": "", 1473 "hostname": "" 1474 } 1475 }, 1476 { 1477 "href": "https://example.com/", 1478 "new_value": "a%C2%ADb", 1479 "expected": { 1480 "href": "https://ab/", 1481 "host": "ab", 1482 "hostname": "ab" 1483 } 1484 }, 1485 { 1486 "href": "https://example.com/", 1487 "new_value": "\u00AD", 1488 "expected": { 1489 "href": "https://example.com/", 1490 "host": "example.com", 1491 "hostname": "example.com" 1492 } 1493 }, 1494 { 1495 "href": "https://example.com/", 1496 "new_value": "%C2%AD", 1497 "expected": { 1498 "href": "https://example.com/", 1499 "host": "example.com", 1500 "hostname": "example.com" 1501 } 1502 }, 1503 { 1504 "href": "https://example.com/", 1505 "new_value": "xn--", 1506 "expected": { 1507 "href": "https://example.com/", 1508 "host": "example.com", 1509 "hostname": "example.com" 1510 } 1511 } 1512 ], 1513 "port": [ 1514 { 1515 "href": "http://example.net", 1516 "new_value": "8080", 1517 "expected": { 1518 "href": "http://example.net:8080/", 1519 "host": "example.net:8080", 1520 "hostname": "example.net", 1521 "port": "8080" 1522 } 1523 }, 1524 { 1525 "comment": "Port number is removed if empty is the new value", 1526 "href": "http://example.net:8080", 1527 "new_value": "", 1528 "expected": { 1529 "href": "http://example.net/", 1530 "host": "example.net", 1531 "hostname": "example.net", 1532 "port": "" 1533 } 1534 }, 1535 { 1536 "comment": "Default port number is removed", 1537 "href": "http://example.net:8080", 1538 "new_value": "80", 1539 "expected": { 1540 "href": "http://example.net/", 1541 "host": "example.net", 1542 "hostname": "example.net", 1543 "port": "" 1544 } 1545 }, 1546 { 1547 "comment": "Default port number is removed", 1548 "href": "https://example.net:4433", 1549 "new_value": "443", 1550 "expected": { 1551 "href": "https://example.net/", 1552 "host": "example.net", 1553 "hostname": "example.net", 1554 "port": "" 1555 } 1556 }, 1557 { 1558 "comment": "Default port number is only removed for the relevant scheme", 1559 "href": "https://example.net", 1560 "new_value": "80", 1561 "expected": { 1562 "href": "https://example.net:80/", 1563 "host": "example.net:80", 1564 "hostname": "example.net", 1565 "port": "80" 1566 } 1567 }, 1568 { 1569 "comment": "Stuff after a / delimiter is ignored", 1570 "href": "http://example.net/path", 1571 "new_value": "8080/stuff", 1572 "expected": { 1573 "href": "http://example.net:8080/path", 1574 "host": "example.net:8080", 1575 "hostname": "example.net", 1576 "port": "8080" 1577 } 1578 }, 1579 { 1580 "comment": "Stuff after a ? delimiter is ignored", 1581 "href": "http://example.net/path", 1582 "new_value": "8080?stuff", 1583 "expected": { 1584 "href": "http://example.net:8080/path", 1585 "host": "example.net:8080", 1586 "hostname": "example.net", 1587 "port": "8080" 1588 } 1589 }, 1590 { 1591 "comment": "Stuff after a # delimiter is ignored", 1592 "href": "http://example.net/path", 1593 "new_value": "8080#stuff", 1594 "expected": { 1595 "href": "http://example.net:8080/path", 1596 "host": "example.net:8080", 1597 "hostname": "example.net", 1598 "port": "8080" 1599 } 1600 }, 1601 { 1602 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 1603 "href": "http://example.net/path", 1604 "new_value": "8080\\stuff", 1605 "expected": { 1606 "href": "http://example.net:8080/path", 1607 "host": "example.net:8080", 1608 "hostname": "example.net", 1609 "port": "8080" 1610 } 1611 }, 1612 { 1613 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1614 "href": "view-source+http://example.net/path", 1615 "new_value": "8080stuff2", 1616 "expected": { 1617 "href": "view-source+http://example.net:8080/path", 1618 "host": "example.net:8080", 1619 "hostname": "example.net", 1620 "port": "8080" 1621 } 1622 }, 1623 { 1624 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1625 "href": "http://example.net/path", 1626 "new_value": "8080stuff2", 1627 "expected": { 1628 "href": "http://example.net:8080/path", 1629 "host": "example.net:8080", 1630 "hostname": "example.net", 1631 "port": "8080" 1632 } 1633 }, 1634 { 1635 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1636 "href": "http://example.net/path", 1637 "new_value": "8080+2", 1638 "expected": { 1639 "href": "http://example.net:8080/path", 1640 "host": "example.net:8080", 1641 "hostname": "example.net", 1642 "port": "8080" 1643 } 1644 }, 1645 { 1646 "comment": "Port numbers are 16 bit integers", 1647 "href": "http://example.net/path", 1648 "new_value": "65535", 1649 "expected": { 1650 "href": "http://example.net:65535/path", 1651 "host": "example.net:65535", 1652 "hostname": "example.net", 1653 "port": "65535" 1654 } 1655 }, 1656 { 1657 "comment": "Port numbers are 16 bit integers, overflowing is an error", 1658 "href": "http://example.net:8080/path", 1659 "new_value": "65536", 1660 "expected": { 1661 "href": "http://example.net:8080/path", 1662 "host": "example.net:8080", 1663 "hostname": "example.net", 1664 "port": "8080" 1665 } 1666 }, 1667 { 1668 "comment": "Setting port to a string that doesn't parse as a number", 1669 "href": "http://example.net:8080/path", 1670 "new_value": "randomstring", 1671 "expected": { 1672 "href": "http://example.net:8080/path", 1673 "host": "example.net:8080", 1674 "hostname": "example.net", 1675 "port": "8080" 1676 } 1677 }, 1678 { 1679 "comment": "Port numbers are 16 bit integers, overflowing is an error", 1680 "href": "non-special://example.net:8080/path", 1681 "new_value": "65536", 1682 "expected": { 1683 "href": "non-special://example.net:8080/path", 1684 "host": "example.net:8080", 1685 "hostname": "example.net", 1686 "port": "8080" 1687 } 1688 }, 1689 { 1690 "href": "file://test/", 1691 "new_value": "12", 1692 "expected": { 1693 "href": "file://test/", 1694 "port": "" 1695 } 1696 }, 1697 { 1698 "href": "file://localhost/", 1699 "new_value": "12", 1700 "expected": { 1701 "href": "file:///", 1702 "port": "" 1703 } 1704 }, 1705 { 1706 "href": "non-base:value", 1707 "new_value": "12", 1708 "expected": { 1709 "href": "non-base:value", 1710 "port": "" 1711 } 1712 }, 1713 { 1714 "href": "sc:///", 1715 "new_value": "12", 1716 "expected": { 1717 "href": "sc:///", 1718 "port": "" 1719 } 1720 }, 1721 { 1722 "href": "sc://x/", 1723 "new_value": "12", 1724 "expected": { 1725 "href": "sc://x:12/", 1726 "port": "12" 1727 } 1728 }, 1729 { 1730 "href": "javascript://x/", 1731 "new_value": "12", 1732 "expected": { 1733 "href": "javascript://x:12/", 1734 "port": "12" 1735 } 1736 }, 1737 { 1738 "comment": "Leading u0009 on special scheme", 1739 "href": "https://domain.com:443", 1740 "new_value": "\u00098080", 1741 "expected": { 1742 "port": "8080" 1743 } 1744 }, 1745 { 1746 "comment": "Leading u0009 on non-special scheme", 1747 "href": "wpt++://domain.com:443", 1748 "new_value": "\u00098080", 1749 "expected": { 1750 "port": "8080" 1751 } 1752 }, 1753 { 1754 "comment": "Should use all ascii prefixed characters as port", 1755 "href": "https://www.google.com:4343", 1756 "new_value": "4wpt", 1757 "expected": { 1758 "port": "4" 1759 } 1760 } 1761 ], 1762 "pathname": [ 1763 { 1764 "comment": "Opaque paths cannot be set", 1765 "href": "mailto:me@example.net", 1766 "new_value": "/foo", 1767 "expected": { 1768 "href": "mailto:me@example.net", 1769 "pathname": "me@example.net" 1770 } 1771 }, 1772 { 1773 "href": "data:original", 1774 "new_value": "new value", 1775 "expected": { 1776 "href": "data:original", 1777 "pathname": "original" 1778 } 1779 }, 1780 { 1781 "href": "sc:original", 1782 "new_value": "new value", 1783 "expected": { 1784 "href": "sc:original", 1785 "pathname": "original" 1786 } 1787 }, 1788 { 1789 "comment": "Special URLs cannot have their paths erased", 1790 "href": "file:///some/path", 1791 "new_value": "", 1792 "expected": { 1793 "href": "file:///", 1794 "pathname": "/" 1795 } 1796 }, 1797 { 1798 "comment": "Non-special URLs can have their paths erased", 1799 "href": "foo://somehost/some/path", 1800 "new_value": "", 1801 "expected": { 1802 "href": "foo://somehost", 1803 "pathname": "" 1804 } 1805 }, 1806 { 1807 "comment": "Non-special URLs with an empty host can have their paths erased", 1808 "href": "foo:///some/path", 1809 "new_value": "", 1810 "expected": { 1811 "href": "foo://", 1812 "pathname": "" 1813 } 1814 }, 1815 { 1816 "comment": "Path-only URLs cannot have their paths erased", 1817 "href": "foo:/some/path", 1818 "new_value": "", 1819 "expected": { 1820 "href": "foo:/", 1821 "pathname": "/" 1822 } 1823 }, 1824 { 1825 "comment": "Path-only URLs always have an initial slash", 1826 "href": "foo:/some/path", 1827 "new_value": "test", 1828 "expected": { 1829 "href": "foo:/test", 1830 "pathname": "/test" 1831 } 1832 }, 1833 { 1834 "href": "unix:/run/foo.socket?timeout=10", 1835 "new_value": "/var/log/../run/bar.socket", 1836 "expected": { 1837 "href": "unix:/var/run/bar.socket?timeout=10", 1838 "pathname": "/var/run/bar.socket" 1839 } 1840 }, 1841 { 1842 "href": "https://example.net#nav", 1843 "new_value": "home", 1844 "expected": { 1845 "href": "https://example.net/home#nav", 1846 "pathname": "/home" 1847 } 1848 }, 1849 { 1850 "href": "https://example.net#nav", 1851 "new_value": "../home", 1852 "expected": { 1853 "href": "https://example.net/home#nav", 1854 "pathname": "/home" 1855 } 1856 }, 1857 { 1858 "comment": "\\ is a segment delimiter for 'special' URLs", 1859 "href": "http://example.net/home?lang=fr#nav", 1860 "new_value": "\\a\\%2E\\b\\%2e.\\c", 1861 "expected": { 1862 "href": "http://example.net/a/c?lang=fr#nav", 1863 "pathname": "/a/c" 1864 } 1865 }, 1866 { 1867 "comment": "\\ is *not* a segment delimiter for non-'special' URLs", 1868 "href": "view-source+http://example.net/home?lang=fr#nav", 1869 "new_value": "\\a\\%2E\\b\\%2e.\\c", 1870 "expected": { 1871 "href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav", 1872 "pathname": "/\\a\\%2E\\b\\%2e.\\c" 1873 } 1874 }, 1875 { 1876 "comment": "UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.", 1877 "href": "a:/", 1878 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 1879 "expected": { 1880 "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", 1881 "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9" 1882 } 1883 }, 1884 { 1885 "comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.", 1886 "href": "http://example.net", 1887 "new_value": "%2e%2E%c3%89té", 1888 "expected": { 1889 "href": "http://example.net/%2e%2E%c3%89t%C3%A9", 1890 "pathname": "/%2e%2E%c3%89t%C3%A9" 1891 } 1892 }, 1893 { 1894 "comment": "? needs to be encoded", 1895 "href": "http://example.net", 1896 "new_value": "?", 1897 "expected": { 1898 "href": "http://example.net/%3F", 1899 "pathname": "/%3F" 1900 } 1901 }, 1902 { 1903 "comment": "# needs to be encoded", 1904 "href": "http://example.net", 1905 "new_value": "#", 1906 "expected": { 1907 "href": "http://example.net/%23", 1908 "pathname": "/%23" 1909 } 1910 }, 1911 { 1912 "comment": "? needs to be encoded, non-special scheme", 1913 "href": "sc://example.net", 1914 "new_value": "?", 1915 "expected": { 1916 "href": "sc://example.net/%3F", 1917 "pathname": "/%3F" 1918 } 1919 }, 1920 { 1921 "comment": "# needs to be encoded, non-special scheme", 1922 "href": "sc://example.net", 1923 "new_value": "#", 1924 "expected": { 1925 "href": "sc://example.net/%23", 1926 "pathname": "/%23" 1927 } 1928 }, 1929 { 1930 "comment": "? doesn't mess up encoding", 1931 "href": "http://example.net", 1932 "new_value": "/?é", 1933 "expected": { 1934 "href": "http://example.net/%3F%C3%A9", 1935 "pathname": "/%3F%C3%A9" 1936 } 1937 }, 1938 { 1939 "comment": "# doesn't mess up encoding", 1940 "href": "http://example.net", 1941 "new_value": "/#é", 1942 "expected": { 1943 "href": "http://example.net/%23%C3%A9", 1944 "pathname": "/%23%C3%A9" 1945 } 1946 }, 1947 { 1948 "comment": "File URLs and (back)slashes", 1949 "href": "file://monkey/", 1950 "new_value": "\\\\", 1951 "expected": { 1952 "href": "file://monkey//", 1953 "pathname": "//" 1954 } 1955 }, 1956 { 1957 "comment": "File URLs and (back)slashes", 1958 "href": "file:///unicorn", 1959 "new_value": "//\\/", 1960 "expected": { 1961 "href": "file://////", 1962 "pathname": "////" 1963 } 1964 }, 1965 { 1966 "comment": "File URLs and (back)slashes", 1967 "href": "file:///unicorn", 1968 "new_value": "//monkey/..//", 1969 "expected": { 1970 "href": "file://///", 1971 "pathname": "///" 1972 } 1973 }, 1974 { 1975 "comment": "Serialize /. in path", 1976 "href": "non-spec:/", 1977 "new_value": "/.//p", 1978 "expected": { 1979 "href": "non-spec:/.//p", 1980 "pathname": "//p" 1981 } 1982 }, 1983 { 1984 "href": "non-spec:/", 1985 "new_value": "/..//p", 1986 "expected": { 1987 "href": "non-spec:/.//p", 1988 "pathname": "//p" 1989 } 1990 }, 1991 { 1992 "href": "non-spec:/", 1993 "new_value": "//p", 1994 "expected": { 1995 "href": "non-spec:/.//p", 1996 "pathname": "//p" 1997 } 1998 }, 1999 { 2000 "comment": "Drop /. from path", 2001 "href": "non-spec:/.//", 2002 "new_value": "p", 2003 "expected": { 2004 "href": "non-spec:/p", 2005 "pathname": "/p" 2006 } 2007 }, 2008 { 2009 "comment": "Non-special URLs with non-opaque paths percent-encode U+0020", 2010 "href": "data:/nospace", 2011 "new_value": "space ", 2012 "expected": { 2013 "href": "data:/space%20", 2014 "pathname": "/space%20" 2015 } 2016 }, 2017 { 2018 "href": "sc:/nospace", 2019 "new_value": "space ", 2020 "expected": { 2021 "href": "sc:/space%20", 2022 "pathname": "/space%20" 2023 } 2024 } 2025 ], 2026 "search": [ 2027 { 2028 "href": "https://example.net#nav", 2029 "new_value": "lang=fr", 2030 "expected": { 2031 "href": "https://example.net/?lang=fr#nav", 2032 "search": "?lang=fr" 2033 } 2034 }, 2035 { 2036 "href": "https://example.net?lang=en-US#nav", 2037 "new_value": "lang=fr", 2038 "expected": { 2039 "href": "https://example.net/?lang=fr#nav", 2040 "search": "?lang=fr" 2041 } 2042 }, 2043 { 2044 "href": "https://example.net?lang=en-US#nav", 2045 "new_value": "?lang=fr", 2046 "expected": { 2047 "href": "https://example.net/?lang=fr#nav", 2048 "search": "?lang=fr" 2049 } 2050 }, 2051 { 2052 "href": "https://example.net?lang=en-US#nav", 2053 "new_value": "??lang=fr", 2054 "expected": { 2055 "href": "https://example.net/??lang=fr#nav", 2056 "search": "??lang=fr" 2057 } 2058 }, 2059 { 2060 "href": "https://example.net?lang=en-US#nav", 2061 "new_value": "?", 2062 "expected": { 2063 "href": "https://example.net/?#nav", 2064 "search": "" 2065 } 2066 }, 2067 { 2068 "href": "https://example.net?lang=en-US#nav", 2069 "new_value": "", 2070 "expected": { 2071 "href": "https://example.net/#nav", 2072 "search": "" 2073 } 2074 }, 2075 { 2076 "href": "https://example.net?lang=en-US", 2077 "new_value": "", 2078 "expected": { 2079 "href": "https://example.net/", 2080 "search": "" 2081 } 2082 }, 2083 { 2084 "href": "https://example.net", 2085 "new_value": "", 2086 "expected": { 2087 "href": "https://example.net/", 2088 "search": "" 2089 } 2090 }, 2091 { 2092 "comment": "UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.", 2093 "href": "a:/", 2094 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 2095 "expected": { 2096 "href": "a:/?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", 2097 "search": "?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" 2098 } 2099 }, 2100 { 2101 "comment": "Bytes already percent-encoded are left as-is", 2102 "href": "http://example.net", 2103 "new_value": "%c3%89té", 2104 "expected": { 2105 "href": "http://example.net/?%c3%89t%C3%A9", 2106 "search": "?%c3%89t%C3%A9" 2107 } 2108 }, 2109 { 2110 "comment": "Drop trailing spaces from trailing opaque paths", 2111 "href": "data:space ?query", 2112 "new_value": "", 2113 "expected": { 2114 "href": "data:space", 2115 "pathname": "space", 2116 "search": "" 2117 } 2118 }, 2119 { 2120 "href": "sc:space ?query", 2121 "new_value": "", 2122 "expected": { 2123 "href": "sc:space", 2124 "pathname": "space", 2125 "search": "" 2126 } 2127 }, 2128 { 2129 "comment": "Do not drop trailing spaces from non-trailing opaque paths", 2130 "href": "data:space ?query#fragment", 2131 "new_value": "", 2132 "expected": { 2133 "href": "data:space #fragment", 2134 "search": "" 2135 } 2136 }, 2137 { 2138 "href": "sc:space ?query#fragment", 2139 "new_value": "", 2140 "expected": { 2141 "href": "sc:space #fragment", 2142 "search": "" 2143 } 2144 } 2145 ], 2146 "hash": [ 2147 { 2148 "href": "https://example.net", 2149 "new_value": "main", 2150 "expected": { 2151 "href": "https://example.net/#main", 2152 "hash": "#main" 2153 } 2154 }, 2155 { 2156 "href": "https://example.net#nav", 2157 "new_value": "main", 2158 "expected": { 2159 "href": "https://example.net/#main", 2160 "hash": "#main" 2161 } 2162 }, 2163 { 2164 "href": "https://example.net?lang=en-US", 2165 "new_value": "##nav", 2166 "expected": { 2167 "href": "https://example.net/?lang=en-US##nav", 2168 "hash": "##nav" 2169 } 2170 }, 2171 { 2172 "href": "https://example.net?lang=en-US#nav", 2173 "new_value": "#main", 2174 "expected": { 2175 "href": "https://example.net/?lang=en-US#main", 2176 "hash": "#main" 2177 } 2178 }, 2179 { 2180 "href": "https://example.net?lang=en-US#nav", 2181 "new_value": "#", 2182 "expected": { 2183 "href": "https://example.net/?lang=en-US#", 2184 "hash": "" 2185 } 2186 }, 2187 { 2188 "href": "https://example.net?lang=en-US#nav", 2189 "new_value": "", 2190 "expected": { 2191 "href": "https://example.net/?lang=en-US", 2192 "hash": "" 2193 } 2194 }, 2195 { 2196 "href": "http://example.net", 2197 "new_value": "#foo bar", 2198 "expected": { 2199 "href": "http://example.net/#foo%20bar", 2200 "hash": "#foo%20bar" 2201 } 2202 }, 2203 { 2204 "href": "http://example.net", 2205 "new_value": "#foo\"bar", 2206 "expected": { 2207 "href": "http://example.net/#foo%22bar", 2208 "hash": "#foo%22bar" 2209 } 2210 }, 2211 { 2212 "href": "http://example.net", 2213 "new_value": "#foo<bar", 2214 "expected": { 2215 "href": "http://example.net/#foo%3Cbar", 2216 "hash": "#foo%3Cbar" 2217 } 2218 }, 2219 { 2220 "href": "http://example.net", 2221 "new_value": "#foo>bar", 2222 "expected": { 2223 "href": "http://example.net/#foo%3Ebar", 2224 "hash": "#foo%3Ebar" 2225 } 2226 }, 2227 { 2228 "href": "http://example.net", 2229 "new_value": "#foo`bar", 2230 "expected": { 2231 "href": "http://example.net/#foo%60bar", 2232 "hash": "#foo%60bar" 2233 } 2234 }, 2235 { 2236 "comment": "Simple percent-encoding; tabs and newlines are removed", 2237 "href": "a:/", 2238 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 2239 "expected": { 2240 "href": "a:/#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", 2241 "hash": "#%00%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" 2242 } 2243 }, 2244 { 2245 "comment": "Percent-encode NULLs in fragment", 2246 "href": "http://example.net", 2247 "new_value": "a\u0000b", 2248 "expected": { 2249 "href": "http://example.net/#a%00b", 2250 "hash": "#a%00b" 2251 } 2252 }, 2253 { 2254 "comment": "Percent-encode NULLs in fragment", 2255 "href": "non-spec:/", 2256 "new_value": "a\u0000b", 2257 "expected": { 2258 "href": "non-spec:/#a%00b", 2259 "hash": "#a%00b" 2260 } 2261 }, 2262 { 2263 "comment": "Bytes already percent-encoded are left as-is", 2264 "href": "http://example.net", 2265 "new_value": "%c3%89té", 2266 "expected": { 2267 "href": "http://example.net/#%c3%89t%C3%A9", 2268 "hash": "#%c3%89t%C3%A9" 2269 } 2270 }, 2271 { 2272 "href": "javascript:alert(1)", 2273 "new_value": "castle", 2274 "expected": { 2275 "href": "javascript:alert(1)#castle", 2276 "hash": "#castle" 2277 } 2278 }, 2279 { 2280 "comment": "Drop trailing spaces from trailing opaque paths", 2281 "href": "data:space #fragment", 2282 "new_value": "", 2283 "expected": { 2284 "href": "data:space", 2285 "pathname": "space", 2286 "hash": "" 2287 } 2288 }, 2289 { 2290 "href": "sc:space #fragment", 2291 "new_value": "", 2292 "expected": { 2293 "href": "sc:space", 2294 "pathname": "space", 2295 "hash": "" 2296 } 2297 }, 2298 { 2299 "comment": "Do not drop trailing spaces from non-trailing opaque paths", 2300 "href": "data:space ?query#fragment", 2301 "new_value": "", 2302 "expected": { 2303 "href": "data:space ?query", 2304 "hash": "" 2305 } 2306 }, 2307 { 2308 "href": "sc:space ?query#fragment", 2309 "new_value": "", 2310 "expected": { 2311 "href": "sc:space ?query", 2312 "hash": "" 2313 } 2314 } 2315 ], 2316 "href": [ 2317 { 2318 "href": "file:///var/log/system.log", 2319 "new_value": "http://0300.168.0xF0", 2320 "expected": { 2321 "href": "http://192.168.0.240/", 2322 "protocol": "http:" 2323 } 2324 } 2325 ] 2326} 2327