setters_tests.json 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493
  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. "comment": "Upper-case ASCII is lower-cased",
  44. "href": "a://example.net",
  45. "new_value": "B",
  46. "expected": {
  47. "href": "b://example.net/",
  48. "protocol": "b:"
  49. }
  50. },
  51. {
  52. "comment": "Non-ASCII is rejected",
  53. "href": "a://example.net",
  54. "new_value": "é",
  55. "expected": {
  56. "href": "a://example.net/",
  57. "protocol": "a:"
  58. }
  59. },
  60. {
  61. "comment": "No leading digit",
  62. "href": "a://example.net",
  63. "new_value": "0b",
  64. "expected": {
  65. "href": "a://example.net/",
  66. "protocol": "a:"
  67. }
  68. },
  69. {
  70. "comment": "No leading punctuation",
  71. "href": "a://example.net",
  72. "new_value": "+b",
  73. "expected": {
  74. "href": "a://example.net/",
  75. "protocol": "a:"
  76. }
  77. },
  78. {
  79. "href": "a://example.net",
  80. "new_value": "bC0+-.",
  81. "expected": {
  82. "href": "bc0+-.://example.net/",
  83. "protocol": "bc0+-.:"
  84. }
  85. },
  86. {
  87. "comment": "Only some punctuation is acceptable",
  88. "href": "a://example.net",
  89. "new_value": "b,c",
  90. "expected": {
  91. "href": "a://example.net/",
  92. "protocol": "a:"
  93. }
  94. },
  95. {
  96. "comment": "Non-ASCII is rejected",
  97. "href": "a://example.net",
  98. "new_value": "bé",
  99. "expected": {
  100. "href": "a://example.net/",
  101. "protocol": "a:"
  102. }
  103. },
  104. {
  105. "comment": "Can’t switch from file URL with no host",
  106. "href": "file://localhost/",
  107. "new_value": "http",
  108. "expected": {
  109. "href": "file:///",
  110. "protocol": "file:"
  111. }
  112. },
  113. {
  114. "href": "file:///test",
  115. "new_value": "gopher",
  116. "expected": {
  117. "href": "file:///test",
  118. "protocol": "file:"
  119. }
  120. },
  121. {
  122. "href": "file:",
  123. "new_value": "wss",
  124. "expected": {
  125. "href": "file:///",
  126. "protocol": "file:"
  127. }
  128. },
  129. {
  130. "comment": "Spec deviation: from special scheme to not is not problematic. https://github.com/whatwg/url/issues/104",
  131. "href": "http://example.net",
  132. "new_value": "b",
  133. "expected": {
  134. "href": "b://example.net/",
  135. "protocol": "b:"
  136. }
  137. },
  138. {
  139. "comment": "Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.",
  140. "href": "mailto:me@example.net",
  141. "new_value": "http",
  142. "expected": {
  143. "href": "mailto:me@example.net",
  144. "protocol": "mailto:"
  145. }
  146. },
  147. {
  148. "comment": "Spec deviation: from non-special scheme with a host to special is not problematic. https://github.com/whatwg/url/issues/104",
  149. "href": "ssh://me@example.net",
  150. "new_value": "http",
  151. "expected": {
  152. "href": "http://me@example.net/",
  153. "protocol": "http:"
  154. }
  155. },
  156. {
  157. "comment": "Stuff after the first ':' is ignored",
  158. "href": "http://example.net",
  159. "new_value": "https:foo : bar",
  160. "expected": {
  161. "href": "https://example.net/",
  162. "protocol": "https:"
  163. }
  164. },
  165. {
  166. "comment": "Stuff after the first ':' is ignored",
  167. "href": "data:text/html,<p>Test",
  168. "new_value": "view-source+data:foo : bar",
  169. "expected": {
  170. "href": "view-source+data:text/html,<p>Test",
  171. "protocol": "view-source+data:"
  172. }
  173. }
  174. ],
  175. "username": [
  176. {
  177. "comment": "No host means no username",
  178. "href": "file:///home/you/index.html",
  179. "new_value": "me",
  180. "expected": {
  181. "href": "file:///home/you/index.html",
  182. "username": ""
  183. }
  184. },
  185. {
  186. "comment": "No host means no username",
  187. "href": "unix:/run/foo.socket",
  188. "new_value": "me",
  189. "expected": {
  190. "href": "unix:/run/foo.socket",
  191. "username": ""
  192. }
  193. },
  194. {
  195. "comment": "Cannot-be-a-base means no username",
  196. "href": "mailto:you@example.net",
  197. "new_value": "me",
  198. "expected": {
  199. "href": "mailto:you@example.net",
  200. "username": ""
  201. }
  202. },
  203. {
  204. "href": "javascript:alert(1)",
  205. "new_value": "wario",
  206. "expected": {
  207. "href": "javascript:alert(1)",
  208. "username": ""
  209. }
  210. },
  211. {
  212. "href": "http://example.net",
  213. "new_value": "me",
  214. "expected": {
  215. "href": "http://me@example.net/",
  216. "username": "me"
  217. }
  218. },
  219. {
  220. "href": "http://:secret@example.net",
  221. "new_value": "me",
  222. "expected": {
  223. "href": "http://me:secret@example.net/",
  224. "username": "me"
  225. }
  226. },
  227. {
  228. "href": "http://me@example.net",
  229. "new_value": "",
  230. "expected": {
  231. "href": "http://example.net/",
  232. "username": ""
  233. }
  234. },
  235. {
  236. "href": "http://me:secret@example.net",
  237. "new_value": "",
  238. "expected": {
  239. "href": "http://:secret@example.net/",
  240. "username": ""
  241. }
  242. },
  243. {
  244. "comment": "UTF-8 percent encoding with the userinfo encode set.",
  245. "href": "http://example.net",
  246. "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
  247. "expected": {
  248. "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/",
  249. "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"
  250. }
  251. },
  252. {
  253. "comment": "Bytes already percent-encoded are left as-is.",
  254. "href": "http://example.net",
  255. "new_value": "%c3%89té",
  256. "expected": {
  257. "href": "http://%c3%89t%C3%A9@example.net/",
  258. "username": "%c3%89t%C3%A9"
  259. }
  260. },
  261. {
  262. "href": "javascript://x/",
  263. "new_value": "wario",
  264. "expected": {
  265. "href": "javascript://wario@x/",
  266. "username": "wario"
  267. }
  268. }
  269. ],
  270. "password": [
  271. {
  272. "comment": "No host means no password",
  273. "href": "file:///home/me/index.html",
  274. "new_value": "secret",
  275. "expected": {
  276. "href": "file:///home/me/index.html",
  277. "password": ""
  278. }
  279. },
  280. {
  281. "comment": "No host means no password",
  282. "href": "unix:/run/foo.socket",
  283. "new_value": "secret",
  284. "expected": {
  285. "href": "unix:/run/foo.socket",
  286. "password": ""
  287. }
  288. },
  289. {
  290. "comment": "Cannot-be-a-base means no password",
  291. "href": "mailto:me@example.net",
  292. "new_value": "secret",
  293. "expected": {
  294. "href": "mailto:me@example.net",
  295. "password": ""
  296. }
  297. },
  298. {
  299. "href": "http://example.net",
  300. "new_value": "secret",
  301. "expected": {
  302. "href": "http://:secret@example.net/",
  303. "password": "secret"
  304. }
  305. },
  306. {
  307. "href": "http://me@example.net",
  308. "new_value": "secret",
  309. "expected": {
  310. "href": "http://me:secret@example.net/",
  311. "password": "secret"
  312. }
  313. },
  314. {
  315. "href": "http://:secret@example.net",
  316. "new_value": "",
  317. "expected": {
  318. "href": "http://example.net/",
  319. "password": ""
  320. }
  321. },
  322. {
  323. "href": "http://me:secret@example.net",
  324. "new_value": "",
  325. "expected": {
  326. "href": "http://me@example.net/",
  327. "password": ""
  328. }
  329. },
  330. {
  331. "comment": "UTF-8 percent encoding with the userinfo encode set.",
  332. "href": "http://example.net",
  333. "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
  334. "expected": {
  335. "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/",
  336. "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"
  337. }
  338. },
  339. {
  340. "comment": "Bytes already percent-encoded are left as-is.",
  341. "href": "http://example.net",
  342. "new_value": "%c3%89té",
  343. "expected": {
  344. "href": "http://:%c3%89t%C3%A9@example.net/",
  345. "password": "%c3%89t%C3%A9"
  346. }
  347. },
  348. {
  349. "href": "javascript://x/",
  350. "new_value": "bowser",
  351. "expected": {
  352. "href": "javascript://:bowser@x/",
  353. "password": "bowser"
  354. }
  355. }
  356. ],
  357. "host": [
  358. {
  359. "href": "sc://x/",
  360. "new_value": "\u0009",
  361. "expected": {
  362. "href": "sc:///",
  363. "host": "",
  364. "hostname": ""
  365. }
  366. },
  367. {
  368. "href": "sc://x/",
  369. "new_value": "\u000A",
  370. "expected": {
  371. "href": "sc:///",
  372. "host": "",
  373. "hostname": ""
  374. }
  375. },
  376. {
  377. "href": "sc://x/",
  378. "new_value": "\u000D",
  379. "expected": {
  380. "href": "sc:///",
  381. "host": "",
  382. "hostname": ""
  383. }
  384. },
  385. {
  386. "href": "sc://x/",
  387. "new_value": "#",
  388. "expected": {
  389. "href": "sc:///",
  390. "host": "",
  391. "hostname": ""
  392. }
  393. },
  394. {
  395. "href": "sc://x/",
  396. "new_value": "/",
  397. "expected": {
  398. "href": "sc:///",
  399. "host": "",
  400. "hostname": ""
  401. }
  402. },
  403. {
  404. "href": "sc://x/",
  405. "new_value": "?",
  406. "expected": {
  407. "href": "sc:///",
  408. "host": "",
  409. "hostname": ""
  410. }
  411. },
  412. {
  413. "href": "sc://x/",
  414. "new_value": "@",
  415. "expected": {
  416. "href": "sc://x/",
  417. "host": "x",
  418. "hostname": "x"
  419. }
  420. },
  421. {
  422. "href": "sc://x/",
  423. "new_value": "ß",
  424. "expected": {
  425. "href": "sc://%C3%9F/",
  426. "host": "%C3%9F",
  427. "hostname": "%C3%9F"
  428. }
  429. },
  430. {
  431. "comment": "Cannot-be-a-base means no host",
  432. "href": "mailto:me@example.net",
  433. "new_value": "example.com",
  434. "expected": {
  435. "href": "mailto:me@example.net",
  436. "host": ""
  437. }
  438. },
  439. {
  440. "comment": "Cannot-be-a-base means no password",
  441. "href": "data:text/plain,Stuff",
  442. "new_value": "example.net",
  443. "expected": {
  444. "href": "data:text/plain,Stuff",
  445. "host": ""
  446. }
  447. },
  448. {
  449. "href": "http://example.net",
  450. "new_value": "example.com:8080",
  451. "expected": {
  452. "href": "http://example.com:8080/",
  453. "host": "example.com:8080",
  454. "hostname": "example.com",
  455. "port": "8080"
  456. }
  457. },
  458. {
  459. "comment": "Port number is unchanged if not specified in the new value",
  460. "href": "http://example.net:8080",
  461. "new_value": "example.com",
  462. "expected": {
  463. "href": "http://example.com:8080/",
  464. "host": "example.com:8080",
  465. "hostname": "example.com",
  466. "port": "8080"
  467. }
  468. },
  469. {
  470. "comment": "Port number is removed if empty in the new value: https://github.com/whatwg/url/pull/113",
  471. "href": "http://example.net:8080",
  472. "new_value": "example.com:",
  473. "expected": {
  474. "href": "http://example.com/",
  475. "host": "example.com",
  476. "hostname": "example.com",
  477. "port": ""
  478. }
  479. },
  480. {
  481. "comment": "The empty host is not valid for special schemes",
  482. "href": "http://example.net",
  483. "new_value": "",
  484. "expected": {
  485. "href": "http://example.net/",
  486. "host": "example.net"
  487. }
  488. },
  489. {
  490. "comment": "The empty host is OK for non-special schemes",
  491. "href": "view-source+http://example.net/foo",
  492. "new_value": "",
  493. "expected": {
  494. "href": "view-source+http:///foo",
  495. "host": ""
  496. }
  497. },
  498. {
  499. "comment": "Path-only URLs can gain a host",
  500. "href": "a:/foo",
  501. "new_value": "example.net",
  502. "expected": {
  503. "href": "a://example.net/foo",
  504. "host": "example.net"
  505. }
  506. },
  507. {
  508. "comment": "IPv4 address syntax is normalized",
  509. "href": "http://example.net",
  510. "new_value": "0x7F000001:8080",
  511. "expected": {
  512. "href": "http://127.0.0.1:8080/",
  513. "host": "127.0.0.1:8080",
  514. "hostname": "127.0.0.1",
  515. "port": "8080"
  516. }
  517. },
  518. {
  519. "comment": "IPv6 address syntax is normalized",
  520. "href": "http://example.net",
  521. "new_value": "[::0:01]:2",
  522. "expected": {
  523. "href": "http://[::1]:2/",
  524. "host": "[::1]:2",
  525. "hostname": "[::1]",
  526. "port": "2"
  527. }
  528. },
  529. {
  530. "comment": "Default port number is removed",
  531. "href": "http://example.net",
  532. "new_value": "example.com:80",
  533. "expected": {
  534. "href": "http://example.com/",
  535. "host": "example.com",
  536. "hostname": "example.com",
  537. "port": ""
  538. }
  539. },
  540. {
  541. "comment": "Default port number is removed",
  542. "href": "https://example.net",
  543. "new_value": "example.com:443",
  544. "expected": {
  545. "href": "https://example.com/",
  546. "host": "example.com",
  547. "hostname": "example.com",
  548. "port": ""
  549. }
  550. },
  551. {
  552. "comment": "Default port number is only removed for the relevant scheme",
  553. "href": "https://example.net",
  554. "new_value": "example.com:80",
  555. "expected": {
  556. "href": "https://example.com:80/",
  557. "host": "example.com:80",
  558. "hostname": "example.com",
  559. "port": "80"
  560. }
  561. },
  562. {
  563. "comment": "Stuff after a / delimiter is ignored",
  564. "href": "http://example.net/path",
  565. "new_value": "example.com/stuff",
  566. "expected": {
  567. "href": "http://example.com/path",
  568. "host": "example.com",
  569. "hostname": "example.com",
  570. "port": ""
  571. }
  572. },
  573. {
  574. "comment": "Stuff after a / delimiter is ignored",
  575. "href": "http://example.net/path",
  576. "new_value": "example.com:8080/stuff",
  577. "expected": {
  578. "href": "http://example.com:8080/path",
  579. "host": "example.com:8080",
  580. "hostname": "example.com",
  581. "port": "8080"
  582. }
  583. },
  584. {
  585. "comment": "Stuff after a ? delimiter is ignored",
  586. "href": "http://example.net/path",
  587. "new_value": "example.com?stuff",
  588. "expected": {
  589. "href": "http://example.com/path",
  590. "host": "example.com",
  591. "hostname": "example.com",
  592. "port": ""
  593. }
  594. },
  595. {
  596. "comment": "Stuff after a ? delimiter is ignored",
  597. "href": "http://example.net/path",
  598. "new_value": "example.com:8080?stuff",
  599. "expected": {
  600. "href": "http://example.com:8080/path",
  601. "host": "example.com:8080",
  602. "hostname": "example.com",
  603. "port": "8080"
  604. }
  605. },
  606. {
  607. "comment": "Stuff after a # delimiter is ignored",
  608. "href": "http://example.net/path",
  609. "new_value": "example.com#stuff",
  610. "expected": {
  611. "href": "http://example.com/path",
  612. "host": "example.com",
  613. "hostname": "example.com",
  614. "port": ""
  615. }
  616. },
  617. {
  618. "comment": "Stuff after a # delimiter is ignored",
  619. "href": "http://example.net/path",
  620. "new_value": "example.com:8080#stuff",
  621. "expected": {
  622. "href": "http://example.com:8080/path",
  623. "host": "example.com:8080",
  624. "hostname": "example.com",
  625. "port": "8080"
  626. }
  627. },
  628. {
  629. "comment": "Stuff after a \\ delimiter is ignored for special schemes",
  630. "href": "http://example.net/path",
  631. "new_value": "example.com\\stuff",
  632. "expected": {
  633. "href": "http://example.com/path",
  634. "host": "example.com",
  635. "hostname": "example.com",
  636. "port": ""
  637. }
  638. },
  639. {
  640. "comment": "Stuff after a \\ delimiter is ignored for special schemes",
  641. "href": "http://example.net/path",
  642. "new_value": "example.com:8080\\stuff",
  643. "expected": {
  644. "href": "http://example.com:8080/path",
  645. "host": "example.com:8080",
  646. "hostname": "example.com",
  647. "port": "8080"
  648. }
  649. },
  650. {
  651. "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
  652. "href": "view-source+http://example.net/path",
  653. "new_value": "example.com\\stuff",
  654. "expected": {
  655. "href": "view-source+http://example.net/path",
  656. "host": "example.net",
  657. "hostname": "example.net",
  658. "port": ""
  659. }
  660. },
  661. {
  662. "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
  663. "href": "view-source+http://example.net/path",
  664. "new_value": "example.com:8080stuff2",
  665. "expected": {
  666. "href": "view-source+http://example.com:8080/path",
  667. "host": "example.com:8080",
  668. "hostname": "example.com",
  669. "port": "8080"
  670. }
  671. },
  672. {
  673. "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
  674. "href": "http://example.net/path",
  675. "new_value": "example.com:8080stuff2",
  676. "expected": {
  677. "href": "http://example.com:8080/path",
  678. "host": "example.com:8080",
  679. "hostname": "example.com",
  680. "port": "8080"
  681. }
  682. },
  683. {
  684. "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
  685. "href": "http://example.net/path",
  686. "new_value": "example.com:8080+2",
  687. "expected": {
  688. "href": "http://example.com:8080/path",
  689. "host": "example.com:8080",
  690. "hostname": "example.com",
  691. "port": "8080"
  692. }
  693. },
  694. {
  695. "comment": "Port numbers are 16 bit integers",
  696. "href": "http://example.net/path",
  697. "new_value": "example.com:65535",
  698. "expected": {
  699. "href": "http://example.com:65535/path",
  700. "host": "example.com:65535",
  701. "hostname": "example.com",
  702. "port": "65535"
  703. }
  704. },
  705. {
  706. "comment": "Port numbers are 16 bit integers, overflowing is an error. Hostname is still set, though.",
  707. "href": "http://example.net/path",
  708. "new_value": "example.com:65536",
  709. "expected": {
  710. "href": "http://example.com/path",
  711. "host": "example.com",
  712. "hostname": "example.com",
  713. "port": ""
  714. }
  715. },
  716. {
  717. "comment": "Broken IPv6",
  718. "href": "http://example.net/",
  719. "new_value": "[google.com]",
  720. "expected": {
  721. "href": "http://example.net/",
  722. "host": "example.net",
  723. "hostname": "example.net"
  724. }
  725. },
  726. {
  727. "href": "http://example.net/",
  728. "new_value": "[::1.2.3.4x]",
  729. "expected": {
  730. "href": "http://example.net/",
  731. "host": "example.net",
  732. "hostname": "example.net"
  733. }
  734. },
  735. {
  736. "href": "http://example.net/",
  737. "new_value": "[::1.2.3.]",
  738. "expected": {
  739. "href": "http://example.net/",
  740. "host": "example.net",
  741. "hostname": "example.net"
  742. }
  743. },
  744. {
  745. "href": "http://example.net/",
  746. "new_value": "[::1.2.]",
  747. "expected": {
  748. "href": "http://example.net/",
  749. "host": "example.net",
  750. "hostname": "example.net"
  751. }
  752. },
  753. {
  754. "href": "http://example.net/",
  755. "new_value": "[::1.]",
  756. "expected": {
  757. "href": "http://example.net/",
  758. "host": "example.net",
  759. "hostname": "example.net"
  760. }
  761. }
  762. ],
  763. "hostname": [
  764. {
  765. "href": "sc://x/",
  766. "new_value": "\u0009",
  767. "expected": {
  768. "href": "sc:///",
  769. "host": "",
  770. "hostname": ""
  771. }
  772. },
  773. {
  774. "href": "sc://x/",
  775. "new_value": "\u000A",
  776. "expected": {
  777. "href": "sc:///",
  778. "host": "",
  779. "hostname": ""
  780. }
  781. },
  782. {
  783. "href": "sc://x/",
  784. "new_value": "\u000D",
  785. "expected": {
  786. "href": "sc:///",
  787. "host": "",
  788. "hostname": ""
  789. }
  790. },
  791. {
  792. "href": "sc://x/",
  793. "new_value": "#",
  794. "expected": {
  795. "href": "sc:///",
  796. "host": "",
  797. "hostname": ""
  798. }
  799. },
  800. {
  801. "href": "sc://x/",
  802. "new_value": "/",
  803. "expected": {
  804. "href": "sc:///",
  805. "host": "",
  806. "hostname": ""
  807. }
  808. },
  809. {
  810. "href": "sc://x/",
  811. "new_value": "?",
  812. "expected": {
  813. "href": "sc:///",
  814. "host": "",
  815. "hostname": ""
  816. }
  817. },
  818. {
  819. "href": "sc://x/",
  820. "new_value": "@",
  821. "expected": {
  822. "href": "sc://x/",
  823. "host": "x",
  824. "hostname": "x"
  825. }
  826. },
  827. {
  828. "comment": "Cannot-be-a-base means no host",
  829. "href": "mailto:me@example.net",
  830. "new_value": "example.com",
  831. "expected": {
  832. "href": "mailto:me@example.net",
  833. "host": ""
  834. }
  835. },
  836. {
  837. "comment": "Cannot-be-a-base means no password",
  838. "href": "data:text/plain,Stuff",
  839. "new_value": "example.net",
  840. "expected": {
  841. "href": "data:text/plain,Stuff",
  842. "host": ""
  843. }
  844. },
  845. {
  846. "href": "http://example.net:8080",
  847. "new_value": "example.com",
  848. "expected": {
  849. "href": "http://example.com:8080/",
  850. "host": "example.com:8080",
  851. "hostname": "example.com",
  852. "port": "8080"
  853. }
  854. },
  855. {
  856. "comment": "The empty host is not valid for special schemes",
  857. "href": "http://example.net",
  858. "new_value": "",
  859. "expected": {
  860. "href": "http://example.net/",
  861. "host": "example.net"
  862. }
  863. },
  864. {
  865. "comment": "The empty host is OK for non-special schemes",
  866. "href": "view-source+http://example.net/foo",
  867. "new_value": "",
  868. "expected": {
  869. "href": "view-source+http:///foo",
  870. "host": ""
  871. }
  872. },
  873. {
  874. "comment": "Path-only URLs can gain a host",
  875. "href": "a:/foo",
  876. "new_value": "example.net",
  877. "expected": {
  878. "href": "a://example.net/foo",
  879. "host": "example.net"
  880. }
  881. },
  882. {
  883. "comment": "IPv4 address syntax is normalized",
  884. "href": "http://example.net:8080",
  885. "new_value": "0x7F000001",
  886. "expected": {
  887. "href": "http://127.0.0.1:8080/",
  888. "host": "127.0.0.1:8080",
  889. "hostname": "127.0.0.1",
  890. "port": "8080"
  891. }
  892. },
  893. {
  894. "comment": "IPv6 address syntax is normalized",
  895. "href": "http://example.net",
  896. "new_value": "[::0:01]",
  897. "expected": {
  898. "href": "http://[::1]/",
  899. "host": "[::1]",
  900. "hostname": "[::1]",
  901. "port": ""
  902. }
  903. },
  904. {
  905. "comment": "Stuff after a : delimiter is ignored",
  906. "href": "http://example.net/path",
  907. "new_value": "example.com:8080",
  908. "expected": {
  909. "href": "http://example.com/path",
  910. "host": "example.com",
  911. "hostname": "example.com",
  912. "port": ""
  913. }
  914. },
  915. {
  916. "comment": "Stuff after a : delimiter is ignored",
  917. "href": "http://example.net:8080/path",
  918. "new_value": "example.com:",
  919. "expected": {
  920. "href": "http://example.com:8080/path",
  921. "host": "example.com:8080",
  922. "hostname": "example.com",
  923. "port": "8080"
  924. }
  925. },
  926. {
  927. "comment": "Stuff after a / delimiter is ignored",
  928. "href": "http://example.net/path",
  929. "new_value": "example.com/stuff",
  930. "expected": {
  931. "href": "http://example.com/path",
  932. "host": "example.com",
  933. "hostname": "example.com",
  934. "port": ""
  935. }
  936. },
  937. {
  938. "comment": "Stuff after a ? delimiter is ignored",
  939. "href": "http://example.net/path",
  940. "new_value": "example.com?stuff",
  941. "expected": {
  942. "href": "http://example.com/path",
  943. "host": "example.com",
  944. "hostname": "example.com",
  945. "port": ""
  946. }
  947. },
  948. {
  949. "comment": "Stuff after a # delimiter is ignored",
  950. "href": "http://example.net/path",
  951. "new_value": "example.com#stuff",
  952. "expected": {
  953. "href": "http://example.com/path",
  954. "host": "example.com",
  955. "hostname": "example.com",
  956. "port": ""
  957. }
  958. },
  959. {
  960. "comment": "Stuff after a \\ delimiter is ignored for special schemes",
  961. "href": "http://example.net/path",
  962. "new_value": "example.com\\stuff",
  963. "expected": {
  964. "href": "http://example.com/path",
  965. "host": "example.com",
  966. "hostname": "example.com",
  967. "port": ""
  968. }
  969. },
  970. {
  971. "comment": "\\ is not a delimiter for non-special schemes, but still forbidden in hosts",
  972. "href": "view-source+http://example.net/path",
  973. "new_value": "example.com\\stuff",
  974. "expected": {
  975. "href": "view-source+http://example.net/path",
  976. "host": "example.net",
  977. "hostname": "example.net",
  978. "port": ""
  979. }
  980. },
  981. {
  982. "comment": "Broken IPv6",
  983. "href": "http://example.net/",
  984. "new_value": "[google.com]",
  985. "expected": {
  986. "href": "http://example.net/",
  987. "host": "example.net",
  988. "hostname": "example.net"
  989. }
  990. },
  991. {
  992. "href": "http://example.net/",
  993. "new_value": "[::1.2.3.4x]",
  994. "expected": {
  995. "href": "http://example.net/",
  996. "host": "example.net",
  997. "hostname": "example.net"
  998. }
  999. },
  1000. {
  1001. "href": "http://example.net/",
  1002. "new_value": "[::1.2.3.]",
  1003. "expected": {
  1004. "href": "http://example.net/",
  1005. "host": "example.net",
  1006. "hostname": "example.net"
  1007. }
  1008. },
  1009. {
  1010. "href": "http://example.net/",
  1011. "new_value": "[::1.2.]",
  1012. "expected": {
  1013. "href": "http://example.net/",
  1014. "host": "example.net",
  1015. "hostname": "example.net"
  1016. }
  1017. },
  1018. {
  1019. "href": "http://example.net/",
  1020. "new_value": "[::1.]",
  1021. "expected": {
  1022. "href": "http://example.net/",
  1023. "host": "example.net",
  1024. "hostname": "example.net"
  1025. }
  1026. }
  1027. ],
  1028. "port": [
  1029. {
  1030. "href": "http://example.net",
  1031. "new_value": "8080",
  1032. "expected": {
  1033. "href": "http://example.net:8080/",
  1034. "host": "example.net:8080",
  1035. "hostname": "example.net",
  1036. "port": "8080"
  1037. }
  1038. },
  1039. {
  1040. "comment": "Port number is removed if empty is the new value",
  1041. "href": "http://example.net:8080",
  1042. "new_value": "",
  1043. "expected": {
  1044. "href": "http://example.net/",
  1045. "host": "example.net",
  1046. "hostname": "example.net",
  1047. "port": ""
  1048. }
  1049. },
  1050. {
  1051. "comment": "Default port number is removed",
  1052. "href": "http://example.net:8080",
  1053. "new_value": "80",
  1054. "expected": {
  1055. "href": "http://example.net/",
  1056. "host": "example.net",
  1057. "hostname": "example.net",
  1058. "port": ""
  1059. }
  1060. },
  1061. {
  1062. "comment": "Default port number is removed",
  1063. "href": "https://example.net:4433",
  1064. "new_value": "443",
  1065. "expected": {
  1066. "href": "https://example.net/",
  1067. "host": "example.net",
  1068. "hostname": "example.net",
  1069. "port": ""
  1070. }
  1071. },
  1072. {
  1073. "comment": "Default port number is only removed for the relevant scheme",
  1074. "href": "https://example.net",
  1075. "new_value": "80",
  1076. "expected": {
  1077. "href": "https://example.net:80/",
  1078. "host": "example.net:80",
  1079. "hostname": "example.net",
  1080. "port": "80"
  1081. }
  1082. },
  1083. {
  1084. "comment": "Stuff after a / delimiter is ignored",
  1085. "href": "http://example.net/path",
  1086. "new_value": "8080/stuff",
  1087. "expected": {
  1088. "href": "http://example.net:8080/path",
  1089. "host": "example.net:8080",
  1090. "hostname": "example.net",
  1091. "port": "8080"
  1092. }
  1093. },
  1094. {
  1095. "comment": "Stuff after a ? delimiter is ignored",
  1096. "href": "http://example.net/path",
  1097. "new_value": "8080?stuff",
  1098. "expected": {
  1099. "href": "http://example.net:8080/path",
  1100. "host": "example.net:8080",
  1101. "hostname": "example.net",
  1102. "port": "8080"
  1103. }
  1104. },
  1105. {
  1106. "comment": "Stuff after a # delimiter is ignored",
  1107. "href": "http://example.net/path",
  1108. "new_value": "8080#stuff",
  1109. "expected": {
  1110. "href": "http://example.net:8080/path",
  1111. "host": "example.net:8080",
  1112. "hostname": "example.net",
  1113. "port": "8080"
  1114. }
  1115. },
  1116. {
  1117. "comment": "Stuff after a \\ delimiter is ignored for special schemes",
  1118. "href": "http://example.net/path",
  1119. "new_value": "8080\\stuff",
  1120. "expected": {
  1121. "href": "http://example.net:8080/path",
  1122. "host": "example.net:8080",
  1123. "hostname": "example.net",
  1124. "port": "8080"
  1125. }
  1126. },
  1127. {
  1128. "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
  1129. "href": "view-source+http://example.net/path",
  1130. "new_value": "8080stuff2",
  1131. "expected": {
  1132. "href": "view-source+http://example.net:8080/path",
  1133. "host": "example.net:8080",
  1134. "hostname": "example.net",
  1135. "port": "8080"
  1136. }
  1137. },
  1138. {
  1139. "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
  1140. "href": "http://example.net/path",
  1141. "new_value": "8080stuff2",
  1142. "expected": {
  1143. "href": "http://example.net:8080/path",
  1144. "host": "example.net:8080",
  1145. "hostname": "example.net",
  1146. "port": "8080"
  1147. }
  1148. },
  1149. {
  1150. "comment": "Anything other than ASCII digit stops the port parser in a setter but is not an error",
  1151. "href": "http://example.net/path",
  1152. "new_value": "8080+2",
  1153. "expected": {
  1154. "href": "http://example.net:8080/path",
  1155. "host": "example.net:8080",
  1156. "hostname": "example.net",
  1157. "port": "8080"
  1158. }
  1159. },
  1160. {
  1161. "comment": "Port numbers are 16 bit integers",
  1162. "href": "http://example.net/path",
  1163. "new_value": "65535",
  1164. "expected": {
  1165. "href": "http://example.net:65535/path",
  1166. "host": "example.net:65535",
  1167. "hostname": "example.net",
  1168. "port": "65535"
  1169. }
  1170. },
  1171. {
  1172. "comment": "Port numbers are 16 bit integers, overflowing is an error",
  1173. "href": "http://example.net:8080/path",
  1174. "new_value": "65536",
  1175. "expected": {
  1176. "href": "http://example.net:8080/path",
  1177. "host": "example.net:8080",
  1178. "hostname": "example.net",
  1179. "port": "8080"
  1180. }
  1181. },
  1182. {
  1183. "comment": "Port numbers are 16 bit integers, overflowing is an error",
  1184. "href": "non-special://example.net:8080/path",
  1185. "new_value": "65536",
  1186. "expected": {
  1187. "href": "non-special://example.net:8080/path",
  1188. "host": "example.net:8080",
  1189. "hostname": "example.net",
  1190. "port": "8080"
  1191. }
  1192. },
  1193. {
  1194. "href": "file://test/",
  1195. "new_value": "12",
  1196. "expected": {
  1197. "href": "file://test/",
  1198. "port": ""
  1199. }
  1200. },
  1201. {
  1202. "href": "file://localhost/",
  1203. "new_value": "12",
  1204. "expected": {
  1205. "href": "file:///",
  1206. "port": ""
  1207. }
  1208. },
  1209. {
  1210. "href": "non-base:value",
  1211. "new_value": "12",
  1212. "expected": {
  1213. "href": "non-base:value",
  1214. "port": ""
  1215. }
  1216. },
  1217. {
  1218. "href": "sc://x/",
  1219. "new_value": "12",
  1220. "expected": {
  1221. "href": "sc://x:12/",
  1222. "port": "12"
  1223. }
  1224. },
  1225. {
  1226. "href": "javascript://x/",
  1227. "new_value": "12",
  1228. "expected": {
  1229. "href": "javascript://x:12/",
  1230. "port": "12"
  1231. }
  1232. }
  1233. ],
  1234. "pathname": [
  1235. {
  1236. "comment": "Cannot-be-a-base don’t have a path",
  1237. "href": "mailto:me@example.net",
  1238. "new_value": "/foo",
  1239. "expected": {
  1240. "href": "mailto:me@example.net",
  1241. "pathname": "me@example.net"
  1242. }
  1243. },
  1244. {
  1245. "href": "unix:/run/foo.socket?timeout=10",
  1246. "new_value": "/var/log/../run/bar.socket",
  1247. "expected": {
  1248. "href": "unix:/var/run/bar.socket?timeout=10",
  1249. "pathname": "/var/run/bar.socket"
  1250. }
  1251. },
  1252. {
  1253. "href": "https://example.net#nav",
  1254. "new_value": "home",
  1255. "expected": {
  1256. "href": "https://example.net/home#nav",
  1257. "pathname": "/home"
  1258. }
  1259. },
  1260. {
  1261. "href": "https://example.net#nav",
  1262. "new_value": "../home",
  1263. "expected": {
  1264. "href": "https://example.net/home#nav",
  1265. "pathname": "/home"
  1266. }
  1267. },
  1268. {
  1269. "comment": "\\ is a segment delimiter for 'special' URLs",
  1270. "href": "http://example.net/home?lang=fr#nav",
  1271. "new_value": "\\a\\%2E\\b\\%2e.\\c",
  1272. "expected": {
  1273. "href": "http://example.net/a/c?lang=fr#nav",
  1274. "pathname": "/a/c"
  1275. }
  1276. },
  1277. {
  1278. "comment": "\\ is *not* a segment delimiter for non-'special' URLs",
  1279. "href": "view-source+http://example.net/home?lang=fr#nav",
  1280. "new_value": "\\a\\%2E\\b\\%2e.\\c",
  1281. "expected": {
  1282. "href": "view-source+http://example.net/\\a\\%2E\\b\\%2e.\\c?lang=fr#nav",
  1283. "pathname": "/\\a\\%2E\\b\\%2e.\\c"
  1284. }
  1285. },
  1286. {
  1287. "comment": "UTF-8 percent encoding with the default encode set. Tabs and newlines are removed. Leading or training C0 controls and space are removed.",
  1288. "href": "a:/",
  1289. "new_value": "\u0000\u0001\t\n\r\u001f !\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
  1290. "expected": {
  1291. "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",
  1292. "pathname": "/!%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E%3F@AZ[\\]^_%60az%7B|%7D~%7F%C2%80%C2%81%C3%89%C3%A9"
  1293. }
  1294. },
  1295. {
  1296. "comment": "Bytes already percent-encoded are left as-is, including %2E outside dotted segments.",
  1297. "href": "http://example.net",
  1298. "new_value": "%2e%2E%c3%89té",
  1299. "expected": {
  1300. "href": "http://example.net/%2e%2E%c3%89t%C3%A9",
  1301. "pathname": "/%2e%2E%c3%89t%C3%A9"
  1302. }
  1303. },
  1304. {
  1305. "comment": "? needs to be encoded",
  1306. "href": "http://example.net",
  1307. "new_value": "?",
  1308. "expected": {
  1309. "href": "http://example.net/%3F",
  1310. "pathname": "/%3F"
  1311. }
  1312. },
  1313. {
  1314. "comment": "# needs to be encoded",
  1315. "href": "http://example.net",
  1316. "new_value": "#",
  1317. "expected": {
  1318. "href": "http://example.net/%23",
  1319. "pathname": "/%23"
  1320. }
  1321. },
  1322. {
  1323. "comment": "? needs to be encoded, non-special scheme",
  1324. "href": "sc://example.net",
  1325. "new_value": "?",
  1326. "expected": {
  1327. "href": "sc://example.net/%3F",
  1328. "pathname": "/%3F"
  1329. }
  1330. },
  1331. {
  1332. "comment": "# needs to be encoded, non-special scheme",
  1333. "href": "sc://example.net",
  1334. "new_value": "#",
  1335. "expected": {
  1336. "href": "sc://example.net/%23",
  1337. "pathname": "/%23"
  1338. }
  1339. }
  1340. ],
  1341. "search": [
  1342. {
  1343. "href": "https://example.net#nav",
  1344. "new_value": "lang=fr",
  1345. "expected": {
  1346. "href": "https://example.net/?lang=fr#nav",
  1347. "search": "?lang=fr"
  1348. }
  1349. },
  1350. {
  1351. "href": "https://example.net?lang=en-US#nav",
  1352. "new_value": "lang=fr",
  1353. "expected": {
  1354. "href": "https://example.net/?lang=fr#nav",
  1355. "search": "?lang=fr"
  1356. }
  1357. },
  1358. {
  1359. "href": "https://example.net?lang=en-US#nav",
  1360. "new_value": "?lang=fr",
  1361. "expected": {
  1362. "href": "https://example.net/?lang=fr#nav",
  1363. "search": "?lang=fr"
  1364. }
  1365. },
  1366. {
  1367. "href": "https://example.net?lang=en-US#nav",
  1368. "new_value": "??lang=fr",
  1369. "expected": {
  1370. "href": "https://example.net/??lang=fr#nav",
  1371. "search": "??lang=fr"
  1372. }
  1373. },
  1374. {
  1375. "href": "https://example.net?lang=en-US#nav",
  1376. "new_value": "?",
  1377. "expected": {
  1378. "href": "https://example.net/?#nav",
  1379. "search": ""
  1380. }
  1381. },
  1382. {
  1383. "href": "https://example.net?lang=en-US#nav",
  1384. "new_value": "",
  1385. "expected": {
  1386. "href": "https://example.net/#nav",
  1387. "search": ""
  1388. }
  1389. },
  1390. {
  1391. "href": "https://example.net?lang=en-US",
  1392. "new_value": "",
  1393. "expected": {
  1394. "href": "https://example.net/",
  1395. "search": ""
  1396. }
  1397. },
  1398. {
  1399. "href": "https://example.net",
  1400. "new_value": "",
  1401. "expected": {
  1402. "href": "https://example.net/",
  1403. "search": ""
  1404. }
  1405. },
  1406. {
  1407. "comment": "UTF-8 percent encoding with the query encode set. Tabs and newlines are removed. Leading or training C0 controls and space are removed.",
  1408. "href": "a:/",
  1409. "new_value": "\u0000\u0001\t\n\r\u001f !\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
  1410. "expected": {
  1411. "href": "a:/?!%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
  1412. "search": "?!%00%01%1F%20!%22%23$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
  1413. }
  1414. },
  1415. {
  1416. "comment": "Bytes already percent-encoded are left as-is",
  1417. "href": "http://example.net",
  1418. "new_value": "%c3%89té",
  1419. "expected": {
  1420. "href": "http://example.net/?%c3%89t%C3%A9",
  1421. "search": "?%c3%89t%C3%A9"
  1422. }
  1423. }
  1424. ],
  1425. "hash": [
  1426. {
  1427. "href": "https://example.net",
  1428. "new_value": "main",
  1429. "expected": {
  1430. "href": "https://example.net/#main",
  1431. "hash": "#main"
  1432. }
  1433. },
  1434. {
  1435. "href": "https://example.net#nav",
  1436. "new_value": "main",
  1437. "expected": {
  1438. "href": "https://example.net/#main",
  1439. "hash": "#main"
  1440. }
  1441. },
  1442. {
  1443. "href": "https://example.net?lang=en-US",
  1444. "new_value": "##nav",
  1445. "expected": {
  1446. "href": "https://example.net/?lang=en-US##nav",
  1447. "hash": "##nav"
  1448. }
  1449. },
  1450. {
  1451. "href": "https://example.net?lang=en-US#nav",
  1452. "new_value": "#main",
  1453. "expected": {
  1454. "href": "https://example.net/?lang=en-US#main",
  1455. "hash": "#main"
  1456. }
  1457. },
  1458. {
  1459. "href": "https://example.net?lang=en-US#nav",
  1460. "new_value": "#",
  1461. "expected": {
  1462. "href": "https://example.net/?lang=en-US#",
  1463. "hash": ""
  1464. }
  1465. },
  1466. {
  1467. "href": "https://example.net?lang=en-US#nav",
  1468. "new_value": "",
  1469. "expected": {
  1470. "href": "https://example.net/?lang=en-US",
  1471. "hash": ""
  1472. }
  1473. },
  1474. {
  1475. "comment": "Simple percent-encoding; nuls, tabs, and newlines are removed",
  1476. "href": "a:/",
  1477. "new_value": "\u0000\u0001\t\n\r\u001f !\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé",
  1478. "expected": {
  1479. "href": "a:/#!%01%1F !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9",
  1480. "hash": "#!%01%1F !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9"
  1481. }
  1482. },
  1483. {
  1484. "comment": "Bytes already percent-encoded are left as-is",
  1485. "href": "http://example.net",
  1486. "new_value": "%c3%89té",
  1487. "expected": {
  1488. "href": "http://example.net/#%c3%89t%C3%A9",
  1489. "hash": "#%c3%89t%C3%A9"
  1490. }
  1491. }
  1492. ]
  1493. }