You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constu=newURL("https://user:pass@example.com:8080/p/q?k=v#frag");console.log("host:",u.host);console.log("hostname:",u.hostname);console.log("origin:",u.origin);console.log("password:",u.password);console.log("username:",u.username);console.log("toString:",u.toString());console.log("toJSON:",u.toJSON());constu2=newURL("https://example.com/");u2.pathname="/changed";u2.search="?x=1";u2.hash="#h";console.log("after mutation:",u2.href);console.log("URL.canParse('https://x'):",URL.canParse("https://x"));console.log("URL.parse('https://x'):",URL.parse("https://x")?.href);constsp=newURLSearchParams("a=1&b=2");console.log("sp.size:",sp.size);constsp2=newURLSearchParams([["a","1"],["b","2"]]);console.log("sp2 from iterable:",sp2.toString());
host: example.com:8080
hostname: example.com
origin: https://example.com:8080
password: pass
username: user
toString: https://user:pass@example.com:8080/p/q?k=v#frag
toJSON: https://user:pass@example.com:8080/p/q?k=v#frag
after mutation: https://example.com/changed?x=1#h
URL.canParse('https://x'): true
URL.parse('https://x'): https://x/
sp.size: 2
sp2 from iterable: a=1&b=2
Impact
The WHATWG URL class is foundational — every fetch(url), new URL(href), new URLSearchParams(), URL.canParse(s) call relies on it. Bugs here cascade into:
Authentication — code that does const u = new URL(authUrl); req.setHeader('Authorization', \Basic ${btoa(`${u.username}:${u.password}`)}`)` reads undefined for both fields.
Hostname-based routing — code that does if (u.hostname === 'api.example.com') matches the wrong string when userinfo is present.
URL serialization — JSON.stringify(url) produces "1970-01-01T00:00:00.000Z" instead of the URL string. Any object containing a URL field round-trips wrong.
Routing libraries — most web frameworks parse request.url via WHATWG URL; broken here means broken for hono, koa, etc.
The bugs cluster into a few categories that may share root causes:
WHATWG parser doesn't extract authority components — host, hostname, origin include the userinfo string; username/password come back undefined. Looks like the URL parser stops at :// and doesn't split out the user:pass@ before the host.
toString() returns [object Object] — the URL prototype's toString getter is unwired.
toJSON() returns 1970-01-01T00:00:00.000Z — the URL instance is being incorrectly classified as a Date by js_jsvalue_to_string's tag-based dispatch.
Setters are no-ops — u.pathname = "/x" doesn't update the underlying URL state; subsequent .href reads the original.
new URLSearchParams([['a','1']]) iterable form silently exits the process — earlier reported as a stand-alone bug; symptom is process exit 0 after the constructor call without printing anything further. Workaround: caller must construct via string or object literal form.
Acceptance
The 18-line repro above prints output byte-identical to Node.
Related
Test file: test-files/test_parity_url.ts (47 of 60 expected output lines today; 77 diff lines).
The [object Object] in toString() is a similar pattern — Perry's value-to-string falls through to a generic Object renderer instead of consulting the URL prototype's own toString.
Repro
Actual (Perry)
Expected (Node)
Impact
The WHATWG URL class is foundational — every
fetch(url),new URL(href),new URLSearchParams(),URL.canParse(s)call relies on it. Bugs here cascade into:const u = new URL(authUrl); req.setHeader('Authorization', \Basic ${btoa(`${u.username}:${u.password}`)}`)` reads undefined for both fields.if (u.hostname === 'api.example.com')matches the wrong string when userinfo is present.JSON.stringify(url)produces"1970-01-01T00:00:00.000Z"instead of the URL string. Any object containing a URL field round-trips wrong.request.urlvia WHATWG URL; broken here means broken for hono, koa, etc.The bugs cluster into a few categories that may share root causes:
host,hostname,origininclude the userinfo string;username/passwordcome back undefined. Looks like the URL parser stops at://and doesn't split out theuser:pass@before the host.toString()returns[object Object]— the URL prototype'stoStringgetter is unwired.toJSON()returns1970-01-01T00:00:00.000Z— the URL instance is being incorrectly classified as a Date byjs_jsvalue_to_string's tag-based dispatch.u.pathname = "/x"doesn't update the underlying URL state; subsequent.hrefreads the original.URL.canParse/URL.parsestatic methods missing entirely.URLSearchParams.sizegetter missing.new URLSearchParams([['a','1']])iterable form silently exits the process — earlier reported as a stand-alone bug; symptom isprocess exit 0after the constructor call without printing anything further. Workaround: caller must construct via string or object literal form.Acceptance
The 18-line repro above prints output byte-identical to Node.
Related
test-files/test_parity_url.ts(47 of 60 expected output lines today; 77 diff lines).toJSON: Datebug shares its root cause with typeof process returns "number" instead of "object" (default-import + global) #623 (NaN-box tag dispatch picking the wrong type for an unrecognized object kind).[object Object]intoString()is a similar pattern — Perry's value-to-string falls through to a generic Object renderer instead of consulting the URL prototype's own toString.