Setting URL.pathname on non-special URL clears URL.searchParams
Categories
(Core :: DOM: Core & HTML, defect)
Tracking
()
People
(Reporter: flying-sheep, Unassigned)
Details
Attachments
(1 file)
(deleted),
text/html
|
Details |
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0
Steps to reproduce:
I have this function:
function broken(queryUrl) {
const url = new URL(queryUrl, 'x:/')
url.pathname = `${url.pathname}/stats`
for (const p of ['limit', 'offset', 'order', 'columns']) url.searchParams.delete(p)
return url.toString().substring(2) // 'x:/foo?...' -> '/foo?...'
}
And call it like this: broken('/foo?bar=baz&limit=100')
Actual results:
The function returns '/foo'
, unless I step into it with the devtools debugger and have a watch on url.toString()
, then it returns the expected result:
Expected results:
The function should have returned '/foo?bar=baz'
, just like the one below:
function works(queryUrl) {
const url = new URL(queryUrl, 'x:/')
const path = `${url.pathname}/stats`
const search = new URLSearchParams(url.search)
for (const p of ['limit', 'offset', 'order', 'columns']) search.delete(p)
return `${path}${search.toString().length > 0 ? `?${search}` : ''}`
}
Reporter | ||
Comment 1•3 years ago
|
||
Correction: It returns '/foo/stats'
and should have returned '/foo/stats?bar=baz'
, just like the second function does.
Comment 2•3 years ago
|
||
I turned the code here into a simple test case that alerts with the results of the two functions.
Comment 3•3 years ago
|
||
I tried this in Firefox Nightly, and the release versions of Chrome and Safari.
Firefox: "broken: /foo/stats; works: /foo/stats?bar=baz"
Chrome: "broken: /foo?bar=baz; works: /foo/stats?bar=baz"
Safari: "broken: /foo/stats?bar=baz; works: /foo/stats?bar=baz"
Note that Chrome also does not return the value expected by the reporter, but it returns a different value.
Anne, what should the behavior of this be? The fact that it apparently returns the expected value if the debugger is involved suggests this might be some weird bindings implementation issue, but it would be good to know what the behavior is expected to be.
Comment 4•3 years ago
|
||
The problem isn't URL.searchParams.delete
, it's that setting URL.pathname
on a URL that has 'x://' as the scheme clears the searchParams:
const http = new URL("http://a.com/foo?bar=baz&limit=100");
http.pathname = http.pathname;
console.log(Array.from(http.searchParams.keys()));
const x = new URL("x://foo?bar=baz&limit=100");
x.pathname = x.pathname;
console.log(Array.from(x.searchParams.keys()));
logs ["bar", "limit"]
and []
in Firefox.
Note that URL.searchParams
is cached in Firefox, so if you access it before setting pathname
then it'll have the right values, because we don't update the contents when setting pathname
(because that shouldn't affect the query).
Updated•3 years ago
|
Updated•3 years ago
|
Description
•