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": "gopher://example.net:1234", 123 "new_value": "file", 124 "expected": { 125 "href": "gopher://example.net:1234/", 126 "protocol": "gopher:" 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": "gopher", 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": "gopher", 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 password", 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": "Default port number is removed", 691 "href": "http://example.net", 692 "new_value": "example.com:80", 693 "expected": { 694 "href": "http://example.com/", 695 "host": "example.com", 696 "hostname": "example.com", 697 "port": "" 698 } 699 }, 700 { 701 "comment": "Default port number is removed", 702 "href": "https://example.net", 703 "new_value": "example.com:443", 704 "expected": { 705 "href": "https://example.com/", 706 "host": "example.com", 707 "hostname": "example.com", 708 "port": "" 709 } 710 }, 711 { 712 "comment": "Default port number is only removed for the relevant scheme", 713 "href": "https://example.net", 714 "new_value": "example.com:80", 715 "expected": { 716 "href": "https://example.com:80/", 717 "host": "example.com:80", 718 "hostname": "example.com", 719 "port": "80" 720 } 721 }, 722 { 723 "comment": "Port number is removed if new port is scheme default and existing URL has a non-default port", 724 "href": "http://example.net:8080", 725 "new_value": "example.com:80", 726 "expected": { 727 "href": "http://example.com/", 728 "host": "example.com", 729 "hostname": "example.com", 730 "port": "" 731 } 732 }, 733 { 734 "comment": "Stuff after a / delimiter is ignored", 735 "href": "http://example.net/path", 736 "new_value": "example.com/stuff", 737 "expected": { 738 "href": "http://example.com/path", 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:8080/stuff", 748 "expected": { 749 "href": "http://example.com:8080/path", 750 "host": "example.com:8080", 751 "hostname": "example.com", 752 "port": "8080" 753 } 754 }, 755 { 756 "comment": "Stuff after a ? delimiter is ignored", 757 "href": "http://example.net/path", 758 "new_value": "example.com?stuff", 759 "expected": { 760 "href": "http://example.com/path", 761 "host": "example.com", 762 "hostname": "example.com", 763 "port": "" 764 } 765 }, 766 { 767 "comment": "Stuff after a ? delimiter is ignored", 768 "href": "http://example.net/path", 769 "new_value": "example.com:8080?stuff", 770 "expected": { 771 "href": "http://example.com:8080/path", 772 "host": "example.com:8080", 773 "hostname": "example.com", 774 "port": "8080" 775 } 776 }, 777 { 778 "comment": "Stuff after a # delimiter is ignored", 779 "href": "http://example.net/path", 780 "new_value": "example.com#stuff", 781 "expected": { 782 "href": "http://example.com/path", 783 "host": "example.com", 784 "hostname": "example.com", 785 "port": "" 786 } 787 }, 788 { 789 "comment": "Stuff after a # delimiter is ignored", 790 "href": "http://example.net/path", 791 "new_value": "example.com:8080#stuff", 792 "expected": { 793 "href": "http://example.com:8080/path", 794 "host": "example.com:8080", 795 "hostname": "example.com", 796 "port": "8080" 797 } 798 }, 799 { 800 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 801 "href": "http://example.net/path", 802 "new_value": "example.com\\stuff", 803 "expected": { 804 "href": "http://example.com/path", 805 "host": "example.com", 806 "hostname": "example.com", 807 "port": "" 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:8080\\stuff", 814 "expected": { 815 "href": "http://example.com:8080/path", 816 "host": "example.com:8080", 817 "hostname": "example.com", 818 "port": "8080" 819 } 820 }, 821 { 822 "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts", 823 "href": "view-source+http://example.net/path", 824 "new_value": "example.com\\stuff", 825 "expected": { 826 "href": "view-source+http://example.net/path", 827 "host": "example.net", 828 "hostname": "example.net", 829 "port": "" 830 } 831 }, 832 { 833 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 834 "href": "view-source+http://example.net/path", 835 "new_value": "example.com:8080stuff2", 836 "expected": { 837 "href": "view-source+http://example.com:8080/path", 838 "host": "example.com:8080", 839 "hostname": "example.com", 840 "port": "8080" 841 } 842 }, 843 { 844 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 845 "href": "http://example.net/path", 846 "new_value": "example.com:8080stuff2", 847 "expected": { 848 "href": "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:8080+2", 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": "Port numbers are 16 bit integers", 867 "href": "http://example.net/path", 868 "new_value": "example.com:65535", 869 "expected": { 870 "href": "http://example.com:65535/path", 871 "host": "example.com:65535", 872 "hostname": "example.com", 873 "port": "65535" 874 } 875 }, 876 { 877 "comment": "Port numbers are 16 bit integers, overflowing is an error. Hostname is still set, though.", 878 "href": "http://example.net/path", 879 "new_value": "example.com:65536", 880 "expected": { 881 "href": "http://example.com/path", 882 "host": "example.com", 883 "hostname": "example.com", 884 "port": "" 885 } 886 }, 887 { 888 "comment": "Broken IPv6", 889 "href": "http://example.net/", 890 "new_value": "[google.com]", 891 "expected": { 892 "href": "http://example.net/", 893 "host": "example.net", 894 "hostname": "example.net" 895 } 896 }, 897 { 898 "href": "http://example.net/", 899 "new_value": "[::1.2.3.4x]", 900 "expected": { 901 "href": "http://example.net/", 902 "host": "example.net", 903 "hostname": "example.net" 904 } 905 }, 906 { 907 "href": "http://example.net/", 908 "new_value": "[::1.2.3.]", 909 "expected": { 910 "href": "http://example.net/", 911 "host": "example.net", 912 "hostname": "example.net" 913 } 914 }, 915 { 916 "href": "http://example.net/", 917 "new_value": "[::1.2.]", 918 "expected": { 919 "href": "http://example.net/", 920 "host": "example.net", 921 "hostname": "example.net" 922 } 923 }, 924 { 925 "href": "http://example.net/", 926 "new_value": "[::1.]", 927 "expected": { 928 "href": "http://example.net/", 929 "host": "example.net", 930 "hostname": "example.net" 931 } 932 }, 933 { 934 "href": "file://y/", 935 "new_value": "x:123", 936 "expected": { 937 "href": "file://y/", 938 "host": "y", 939 "hostname": "y", 940 "port": "" 941 } 942 }, 943 { 944 "href": "file://y/", 945 "new_value": "loc%41lhost", 946 "expected": { 947 "href": "file:///", 948 "host": "", 949 "hostname": "", 950 "port": "" 951 } 952 }, 953 { 954 "href": "file://hi/x", 955 "new_value": "", 956 "expected": { 957 "href": "file:///x", 958 "host": "", 959 "hostname": "", 960 "port": "" 961 } 962 }, 963 { 964 "href": "sc://test@test/", 965 "new_value": "", 966 "expected": { 967 "href": "sc://test@test/", 968 "host": "test", 969 "hostname": "test", 970 "username": "test" 971 } 972 }, 973 { 974 "href": "sc://test:12/", 975 "new_value": "", 976 "expected": { 977 "href": "sc://test:12/", 978 "host": "test:12", 979 "hostname": "test", 980 "port": "12" 981 } 982 } 983 ], 984 "hostname": [ 985 { 986 "comment": "Non-special scheme", 987 "href": "sc://x/", 988 "new_value": "\u0000", 989 "expected": { 990 "href": "sc://x/", 991 "host": "x", 992 "hostname": "x" 993 } 994 }, 995 { 996 "href": "sc://x/", 997 "new_value": "\u0009", 998 "expected": { 999 "href": "sc:///", 1000 "host": "", 1001 "hostname": "" 1002 } 1003 }, 1004 { 1005 "href": "sc://x/", 1006 "new_value": "\u000A", 1007 "expected": { 1008 "href": "sc:///", 1009 "host": "", 1010 "hostname": "" 1011 } 1012 }, 1013 { 1014 "href": "sc://x/", 1015 "new_value": "\u000D", 1016 "expected": { 1017 "href": "sc:///", 1018 "host": "", 1019 "hostname": "" 1020 } 1021 }, 1022 { 1023 "href": "sc://x/", 1024 "new_value": " ", 1025 "expected": { 1026 "href": "sc://x/", 1027 "host": "x", 1028 "hostname": "x" 1029 } 1030 }, 1031 { 1032 "href": "sc://x/", 1033 "new_value": "#", 1034 "expected": { 1035 "href": "sc:///", 1036 "host": "", 1037 "hostname": "" 1038 } 1039 }, 1040 { 1041 "href": "sc://x/", 1042 "new_value": "/", 1043 "expected": { 1044 "href": "sc:///", 1045 "host": "", 1046 "hostname": "" 1047 } 1048 }, 1049 { 1050 "href": "sc://x/", 1051 "new_value": "?", 1052 "expected": { 1053 "href": "sc:///", 1054 "host": "", 1055 "hostname": "" 1056 } 1057 }, 1058 { 1059 "href": "sc://x/", 1060 "new_value": "@", 1061 "expected": { 1062 "href": "sc://x/", 1063 "host": "x", 1064 "hostname": "x" 1065 } 1066 }, 1067 { 1068 "comment": "Cannot-be-a-base means no host", 1069 "href": "mailto:me@example.net", 1070 "new_value": "example.com", 1071 "expected": { 1072 "href": "mailto:me@example.net", 1073 "host": "" 1074 } 1075 }, 1076 { 1077 "comment": "Cannot-be-a-base means no password", 1078 "href": "data:text/plain,Stuff", 1079 "new_value": "example.net", 1080 "expected": { 1081 "href": "data:text/plain,Stuff", 1082 "host": "" 1083 } 1084 }, 1085 { 1086 "href": "http://example.net:8080", 1087 "new_value": "example.com", 1088 "expected": { 1089 "href": "http://example.com:8080/", 1090 "host": "example.com:8080", 1091 "hostname": "example.com", 1092 "port": "8080" 1093 } 1094 }, 1095 { 1096 "comment": "The empty host is not valid for special schemes", 1097 "href": "http://example.net", 1098 "new_value": "", 1099 "expected": { 1100 "href": "http://example.net/", 1101 "host": "example.net" 1102 } 1103 }, 1104 { 1105 "comment": "The empty host is OK for non-special schemes", 1106 "href": "view-source+http://example.net/foo", 1107 "new_value": "", 1108 "expected": { 1109 "href": "view-source+http:///foo", 1110 "host": "" 1111 } 1112 }, 1113 { 1114 "comment": "Path-only URLs can gain a host", 1115 "href": "a:/foo", 1116 "new_value": "example.net", 1117 "expected": { 1118 "href": "a://example.net/foo", 1119 "host": "example.net" 1120 } 1121 }, 1122 { 1123 "comment": "IPv4 address syntax is normalized", 1124 "href": "http://example.net:8080", 1125 "new_value": "0x7F000001", 1126 "expected": { 1127 "href": "http://127.0.0.1:8080/", 1128 "host": "127.0.0.1:8080", 1129 "hostname": "127.0.0.1", 1130 "port": "8080" 1131 } 1132 }, 1133 { 1134 "comment": "IPv6 address syntax is normalized", 1135 "href": "http://example.net", 1136 "new_value": "[::0:01]", 1137 "expected": { 1138 "href": "http://[::1]/", 1139 "host": "[::1]", 1140 "hostname": "[::1]", 1141 "port": "" 1142 } 1143 }, 1144 { 1145 "comment": "Stuff after a : delimiter is ignored", 1146 "href": "http://example.net/path", 1147 "new_value": "example.com:8080", 1148 "expected": { 1149 "href": "http://example.com/path", 1150 "host": "example.com", 1151 "hostname": "example.com", 1152 "port": "" 1153 } 1154 }, 1155 { 1156 "comment": "Stuff after a : delimiter is ignored", 1157 "href": "http://example.net:8080/path", 1158 "new_value": "example.com:", 1159 "expected": { 1160 "href": "http://example.com:8080/path", 1161 "host": "example.com:8080", 1162 "hostname": "example.com", 1163 "port": "8080" 1164 } 1165 }, 1166 { 1167 "comment": "Stuff after a / delimiter is ignored", 1168 "href": "http://example.net/path", 1169 "new_value": "example.com/stuff", 1170 "expected": { 1171 "href": "http://example.com/path", 1172 "host": "example.com", 1173 "hostname": "example.com", 1174 "port": "" 1175 } 1176 }, 1177 { 1178 "comment": "Stuff after a ? delimiter is ignored", 1179 "href": "http://example.net/path", 1180 "new_value": "example.com?stuff", 1181 "expected": { 1182 "href": "http://example.com/path", 1183 "host": "example.com", 1184 "hostname": "example.com", 1185 "port": "" 1186 } 1187 }, 1188 { 1189 "comment": "Stuff after a # delimiter is ignored", 1190 "href": "http://example.net/path", 1191 "new_value": "example.com#stuff", 1192 "expected": { 1193 "href": "http://example.com/path", 1194 "host": "example.com", 1195 "hostname": "example.com", 1196 "port": "" 1197 } 1198 }, 1199 { 1200 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 1201 "href": "http://example.net/path", 1202 "new_value": "example.com\\stuff", 1203 "expected": { 1204 "href": "http://example.com/path", 1205 "host": "example.com", 1206 "hostname": "example.com", 1207 "port": "" 1208 } 1209 }, 1210 { 1211 "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts", 1212 "href": "view-source+http://example.net/path", 1213 "new_value": "example.com\\stuff", 1214 "expected": { 1215 "href": "view-source+http://example.net/path", 1216 "host": "example.net", 1217 "hostname": "example.net", 1218 "port": "" 1219 } 1220 }, 1221 { 1222 "comment": "Broken IPv6", 1223 "href": "http://example.net/", 1224 "new_value": "[google.com]", 1225 "expected": { 1226 "href": "http://example.net/", 1227 "host": "example.net", 1228 "hostname": "example.net" 1229 } 1230 }, 1231 { 1232 "href": "http://example.net/", 1233 "new_value": "[::1.2.3.4x]", 1234 "expected": { 1235 "href": "http://example.net/", 1236 "host": "example.net", 1237 "hostname": "example.net" 1238 } 1239 }, 1240 { 1241 "href": "http://example.net/", 1242 "new_value": "[::1.2.3.]", 1243 "expected": { 1244 "href": "http://example.net/", 1245 "host": "example.net", 1246 "hostname": "example.net" 1247 } 1248 }, 1249 { 1250 "href": "http://example.net/", 1251 "new_value": "[::1.2.]", 1252 "expected": { 1253 "href": "http://example.net/", 1254 "host": "example.net", 1255 "hostname": "example.net" 1256 } 1257 }, 1258 { 1259 "href": "http://example.net/", 1260 "new_value": "[::1.]", 1261 "expected": { 1262 "href": "http://example.net/", 1263 "host": "example.net", 1264 "hostname": "example.net" 1265 } 1266 }, 1267 { 1268 "href": "file://y/", 1269 "new_value": "x:123", 1270 "expected": { 1271 "href": "file://y/", 1272 "host": "y", 1273 "hostname": "y", 1274 "port": "" 1275 } 1276 }, 1277 { 1278 "href": "file://y/", 1279 "new_value": "loc%41lhost", 1280 "expected": { 1281 "href": "file:///", 1282 "host": "", 1283 "hostname": "", 1284 "port": "" 1285 } 1286 }, 1287 { 1288 "href": "file://hi/x", 1289 "new_value": "", 1290 "expected": { 1291 "href": "file:///x", 1292 "host": "", 1293 "hostname": "", 1294 "port": "" 1295 } 1296 }, 1297 { 1298 "href": "sc://test@test/", 1299 "new_value": "", 1300 "expected": { 1301 "href": "sc://test@test/", 1302 "host": "test", 1303 "hostname": "test", 1304 "username": "test" 1305 } 1306 }, 1307 { 1308 "href": "sc://test:12/", 1309 "new_value": "", 1310 "expected": { 1311 "href": "sc://test:12/", 1312 "host": "test:12", 1313 "hostname": "test", 1314 "port": "12" 1315 } 1316 } 1317 ], 1318 "port": [ 1319 { 1320 "href": "http://example.net", 1321 "new_value": "8080", 1322 "expected": { 1323 "href": "http://example.net:8080/", 1324 "host": "example.net:8080", 1325 "hostname": "example.net", 1326 "port": "8080" 1327 } 1328 }, 1329 { 1330 "comment": "Port number is removed if empty is the new value", 1331 "href": "http://example.net:8080", 1332 "new_value": "", 1333 "expected": { 1334 "href": "http://example.net/", 1335 "host": "example.net", 1336 "hostname": "example.net", 1337 "port": "" 1338 } 1339 }, 1340 { 1341 "comment": "Default port number is removed", 1342 "href": "http://example.net:8080", 1343 "new_value": "80", 1344 "expected": { 1345 "href": "http://example.net/", 1346 "host": "example.net", 1347 "hostname": "example.net", 1348 "port": "" 1349 } 1350 }, 1351 { 1352 "comment": "Default port number is removed", 1353 "href": "https://example.net:4433", 1354 "new_value": "443", 1355 "expected": { 1356 "href": "https://example.net/", 1357 "host": "example.net", 1358 "hostname": "example.net", 1359 "port": "" 1360 } 1361 }, 1362 { 1363 "comment": "Default port number is only removed for the relevant scheme", 1364 "href": "https://example.net", 1365 "new_value": "80", 1366 "expected": { 1367 "href": "https://example.net:80/", 1368 "host": "example.net:80", 1369 "hostname": "example.net", 1370 "port": "80" 1371 } 1372 }, 1373 { 1374 "comment": "Stuff after a / delimiter is ignored", 1375 "href": "http://example.net/path", 1376 "new_value": "8080/stuff", 1377 "expected": { 1378 "href": "http://example.net:8080/path", 1379 "host": "example.net:8080", 1380 "hostname": "example.net", 1381 "port": "8080" 1382 } 1383 }, 1384 { 1385 "comment": "Stuff after a ? delimiter is ignored", 1386 "href": "http://example.net/path", 1387 "new_value": "8080?stuff", 1388 "expected": { 1389 "href": "http://example.net:8080/path", 1390 "host": "example.net:8080", 1391 "hostname": "example.net", 1392 "port": "8080" 1393 } 1394 }, 1395 { 1396 "comment": "Stuff after a # delimiter is ignored", 1397 "href": "http://example.net/path", 1398 "new_value": "8080#stuff", 1399 "expected": { 1400 "href": "http://example.net:8080/path", 1401 "host": "example.net:8080", 1402 "hostname": "example.net", 1403 "port": "8080" 1404 } 1405 }, 1406 { 1407 "comment": "Stuff after a \\ delimiter is ignored for special schemes", 1408 "href": "http://example.net/path", 1409 "new_value": "8080\\stuff", 1410 "expected": { 1411 "href": "http://example.net:8080/path", 1412 "host": "example.net:8080", 1413 "hostname": "example.net", 1414 "port": "8080" 1415 } 1416 }, 1417 { 1418 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1419 "href": "view-source+http://example.net/path", 1420 "new_value": "8080stuff2", 1421 "expected": { 1422 "href": "view-source+http://example.net:8080/path", 1423 "host": "example.net:8080", 1424 "hostname": "example.net", 1425 "port": "8080" 1426 } 1427 }, 1428 { 1429 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1430 "href": "http://example.net/path", 1431 "new_value": "8080stuff2", 1432 "expected": { 1433 "href": "http://example.net:8080/path", 1434 "host": "example.net:8080", 1435 "hostname": "example.net", 1436 "port": "8080" 1437 } 1438 }, 1439 { 1440 "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error", 1441 "href": "http://example.net/path", 1442 "new_value": "8080+2", 1443 "expected": { 1444 "href": "http://example.net:8080/path", 1445 "host": "example.net:8080", 1446 "hostname": "example.net", 1447 "port": "8080" 1448 } 1449 }, 1450 { 1451 "comment": "Port numbers are 16 bit integers", 1452 "href": "http://example.net/path", 1453 "new_value": "65535", 1454 "expected": { 1455 "href": "http://example.net:65535/path", 1456 "host": "example.net:65535", 1457 "hostname": "example.net", 1458 "port": "65535" 1459 } 1460 }, 1461 { 1462 "comment": "Port numbers are 16 bit integers, overflowing is an error", 1463 "href": "http://example.net:8080/path", 1464 "new_value": "65536", 1465 "expected": { 1466 "href": "http://example.net:8080/path", 1467 "host": "example.net:8080", 1468 "hostname": "example.net", 1469 "port": "8080" 1470 } 1471 }, 1472 { 1473 "comment": "Port numbers are 16 bit integers, overflowing is an error", 1474 "href": "non-special://example.net:8080/path", 1475 "new_value": "65536", 1476 "expected": { 1477 "href": "non-special://example.net:8080/path", 1478 "host": "example.net:8080", 1479 "hostname": "example.net", 1480 "port": "8080" 1481 } 1482 }, 1483 { 1484 "href": "file://test/", 1485 "new_value": "12", 1486 "expected": { 1487 "href": "file://test/", 1488 "port": "" 1489 } 1490 }, 1491 { 1492 "href": "file://localhost/", 1493 "new_value": "12", 1494 "expected": { 1495 "href": "file:///", 1496 "port": "" 1497 } 1498 }, 1499 { 1500 "href": "non-base:value", 1501 "new_value": "12", 1502 "expected": { 1503 "href": "non-base:value", 1504 "port": "" 1505 } 1506 }, 1507 { 1508 "href": "sc:///", 1509 "new_value": "12", 1510 "expected": { 1511 "href": "sc:///", 1512 "port": "" 1513 } 1514 }, 1515 { 1516 "href": "sc://x/", 1517 "new_value": "12", 1518 "expected": { 1519 "href": "sc://x:12/", 1520 "port": "12" 1521 } 1522 }, 1523 { 1524 "href": "javascript://x/", 1525 "new_value": "12", 1526 "expected": { 1527 "href": "javascript://x:12/", 1528 "port": "12" 1529 } 1530 } 1531 ], 1532 "pathname": [ 1533 { 1534 "comment": "Cannot-be-a-base don’t have a path", 1535 "href": "mailto:me@example.net", 1536 "new_value": "/foo", 1537 "expected": { 1538 "href": "mailto:me@example.net", 1539 "pathname": "me@example.net" 1540 } 1541 }, 1542 { 1543 "href": "unix:/run/foo.socket?timeout=10", 1544 "new_value": "/var/log/../run/bar.socket", 1545 "expected": { 1546 "href": "unix:/var/run/bar.socket?timeout=10", 1547 "pathname": "/var/run/bar.socket" 1548 } 1549 }, 1550 { 1551 "href": "https://example.net#nav", 1552 "new_value": "home", 1553 "expected": { 1554 "href": "https://example.net/home#nav", 1555 "pathname": "/home" 1556 } 1557 }, 1558 { 1559 "href": "https://example.net#nav", 1560 "new_value": "../home", 1561 "expected": { 1562 "href": "https://example.net/home#nav", 1563 "pathname": "/home" 1564 } 1565 }, 1566 { 1567 "comment": "\\ is a segment delimiter for 'special' URLs", 1568 "href": "http://example.net/home?lang=fr#nav", 1569 "new_value": "\\a\\%2E\\b\\%2e.\\c", 1570 "expected": { 1571 "href": "http://example.net/a/c?lang=fr#nav", 1572 "pathname": "/a/c" 1573 } 1574 }, 1575 { 1576 "comment": "\\ is *not* a segment delimiter for non-'special' URLs", 1577 "href": "view-source+http://example.net/home?lang=fr#nav", 1578 "new_value": "\\a\\%2E\\b\\%2e.\\c", 1579 "expected": { 1580 "href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav", 1581 "pathname": "/\\a\\%2E\\b\\%2e.\\c" 1582 } 1583 }, 1584 { 1585 "comment": "UTF-8 percent encoding with the default encode set. Tabs and newlines are removed.", 1586 "href": "a:/", 1587 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 1588 "expected": { 1589 "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", 1590 "pathname": "/%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9" 1591 } 1592 }, 1593 { 1594 "comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.", 1595 "href": "http://example.net", 1596 "new_value": "%2e%2E%c3%89té", 1597 "expected": { 1598 "href": "http://example.net/%2e%2E%c3%89t%C3%A9", 1599 "pathname": "/%2e%2E%c3%89t%C3%A9" 1600 } 1601 }, 1602 { 1603 "comment": "? needs to be encoded", 1604 "href": "http://example.net", 1605 "new_value": "?", 1606 "expected": { 1607 "href": "http://example.net/%3F", 1608 "pathname": "/%3F" 1609 } 1610 }, 1611 { 1612 "comment": "# needs to be encoded", 1613 "href": "http://example.net", 1614 "new_value": "#", 1615 "expected": { 1616 "href": "http://example.net/%23", 1617 "pathname": "/%23" 1618 } 1619 }, 1620 { 1621 "comment": "? needs to be encoded, non-special scheme", 1622 "href": "sc://example.net", 1623 "new_value": "?", 1624 "expected": { 1625 "href": "sc://example.net/%3F", 1626 "pathname": "/%3F" 1627 } 1628 }, 1629 { 1630 "comment": "# needs to be encoded, non-special scheme", 1631 "href": "sc://example.net", 1632 "new_value": "#", 1633 "expected": { 1634 "href": "sc://example.net/%23", 1635 "pathname": "/%23" 1636 } 1637 }, 1638 { 1639 "comment": "File URLs and (back)slashes", 1640 "href": "file://monkey/", 1641 "new_value": "\\\\", 1642 "expected": { 1643 "href": "file://monkey/", 1644 "pathname": "/" 1645 } 1646 }, 1647 { 1648 "comment": "File URLs and (back)slashes", 1649 "href": "file:///unicorn", 1650 "new_value": "//\\/", 1651 "expected": { 1652 "href": "file:///", 1653 "pathname": "/" 1654 } 1655 }, 1656 { 1657 "comment": "File URLs and (back)slashes", 1658 "href": "file:///unicorn", 1659 "new_value": "//monkey/..//", 1660 "expected": { 1661 "href": "file:///", 1662 "pathname": "/" 1663 } 1664 } 1665 ], 1666 "search": [ 1667 { 1668 "href": "https://example.net#nav", 1669 "new_value": "lang=fr", 1670 "expected": { 1671 "href": "https://example.net/?lang=fr#nav", 1672 "search": "?lang=fr" 1673 } 1674 }, 1675 { 1676 "href": "https://example.net?lang=en-US#nav", 1677 "new_value": "lang=fr", 1678 "expected": { 1679 "href": "https://example.net/?lang=fr#nav", 1680 "search": "?lang=fr" 1681 } 1682 }, 1683 { 1684 "href": "https://example.net?lang=en-US#nav", 1685 "new_value": "?lang=fr", 1686 "expected": { 1687 "href": "https://example.net/?lang=fr#nav", 1688 "search": "?lang=fr" 1689 } 1690 }, 1691 { 1692 "href": "https://example.net?lang=en-US#nav", 1693 "new_value": "??lang=fr", 1694 "expected": { 1695 "href": "https://example.net/??lang=fr#nav", 1696 "search": "??lang=fr" 1697 } 1698 }, 1699 { 1700 "href": "https://example.net?lang=en-US#nav", 1701 "new_value": "?", 1702 "expected": { 1703 "href": "https://example.net/?#nav", 1704 "search": "" 1705 } 1706 }, 1707 { 1708 "href": "https://example.net?lang=en-US#nav", 1709 "new_value": "", 1710 "expected": { 1711 "href": "https://example.net/#nav", 1712 "search": "" 1713 } 1714 }, 1715 { 1716 "href": "https://example.net?lang=en-US", 1717 "new_value": "", 1718 "expected": { 1719 "href": "https://example.net/", 1720 "search": "" 1721 } 1722 }, 1723 { 1724 "href": "https://example.net", 1725 "new_value": "", 1726 "expected": { 1727 "href": "https://example.net/", 1728 "search": "" 1729 } 1730 }, 1731 { 1732 "comment": "UTF-8 percent encoding with the query encode set. Tabs and newlines are removed.", 1733 "href": "a:/", 1734 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 1735 "expected": { 1736 "href": "a:/?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", 1737 "search": "?%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" 1738 } 1739 }, 1740 { 1741 "comment": "Bytes already percent-encoded are left as-is", 1742 "href": "http://example.net", 1743 "new_value": "%c3%89té", 1744 "expected": { 1745 "href": "http://example.net/?%c3%89t%C3%A9", 1746 "search": "?%c3%89t%C3%A9" 1747 } 1748 } 1749 ], 1750 "hash": [ 1751 { 1752 "href": "https://example.net", 1753 "new_value": "main", 1754 "expected": { 1755 "href": "https://example.net/#main", 1756 "hash": "#main" 1757 } 1758 }, 1759 { 1760 "href": "https://example.net#nav", 1761 "new_value": "main", 1762 "expected": { 1763 "href": "https://example.net/#main", 1764 "hash": "#main" 1765 } 1766 }, 1767 { 1768 "href": "https://example.net?lang=en-US", 1769 "new_value": "##nav", 1770 "expected": { 1771 "href": "https://example.net/?lang=en-US##nav", 1772 "hash": "##nav" 1773 } 1774 }, 1775 { 1776 "href": "https://example.net?lang=en-US#nav", 1777 "new_value": "#main", 1778 "expected": { 1779 "href": "https://example.net/?lang=en-US#main", 1780 "hash": "#main" 1781 } 1782 }, 1783 { 1784 "href": "https://example.net?lang=en-US#nav", 1785 "new_value": "#", 1786 "expected": { 1787 "href": "https://example.net/?lang=en-US#", 1788 "hash": "" 1789 } 1790 }, 1791 { 1792 "href": "https://example.net?lang=en-US#nav", 1793 "new_value": "", 1794 "expected": { 1795 "href": "https://example.net/?lang=en-US", 1796 "hash": "" 1797 } 1798 }, 1799 { 1800 "href": "http://example.net", 1801 "new_value": "#foo bar", 1802 "expected": { 1803 "href": "http://example.net/#foo%20bar", 1804 "hash": "#foo%20bar" 1805 } 1806 }, 1807 { 1808 "href": "http://example.net", 1809 "new_value": "#foo\"bar", 1810 "expected": { 1811 "href": "http://example.net/#foo%22bar", 1812 "hash": "#foo%22bar" 1813 } 1814 }, 1815 { 1816 "href": "http://example.net", 1817 "new_value": "#foo<bar", 1818 "expected": { 1819 "href": "http://example.net/#foo%3Cbar", 1820 "hash": "#foo%3Cbar" 1821 } 1822 }, 1823 { 1824 "href": "http://example.net", 1825 "new_value": "#foo>bar", 1826 "expected": { 1827 "href": "http://example.net/#foo%3Ebar", 1828 "hash": "#foo%3Ebar" 1829 } 1830 }, 1831 { 1832 "href": "http://example.net", 1833 "new_value": "#foo`bar", 1834 "expected": { 1835 "href": "http://example.net/#foo%60bar", 1836 "hash": "#foo%60bar" 1837 } 1838 }, 1839 { 1840 "comment": "Simple percent-encoding; nuls, tabs, and newlines are removed", 1841 "href": "a:/", 1842 "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", 1843 "expected": { 1844 "href": "a:/#%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", 1845 "hash": "#%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" 1846 } 1847 }, 1848 { 1849 "comment": "Bytes already percent-encoded are left as-is", 1850 "href": "http://example.net", 1851 "new_value": "%c3%89té", 1852 "expected": { 1853 "href": "http://example.net/#%c3%89t%C3%A9", 1854 "hash": "#%c3%89t%C3%A9" 1855 } 1856 }, 1857 { 1858 "href": "javascript:alert(1)", 1859 "new_value": "castle", 1860 "expected": { 1861 "href": "javascript:alert(1)#castle", 1862 "hash": "#castle" 1863 } 1864 } 1865 ] 1866} 1867