Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4440571
url.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
url.js
View Options
import
{
test
,
testThrows
,
testDeep
,
summary
}
from
'./helpers.js'
;
console
.
log
(
'URL constructor\n'
);
const
url
=
new
URL
(
'https://user:pass@example.com:8080/path/to?query=value#hash'
);
test
(
'full URL href'
,
url
.
href
,
'https://user:pass@example.com:8080/path/to?query=value#hash'
);
const
url2
=
new
URL
(
'/other'
,
'https://example.com'
);
test
(
'URL with base'
,
url2
.
href
,
'https://example.com/other'
);
const
url2b
=
new
URL
(
'foo'
,
'https://example.com/bar/baz'
);
test
(
'URL with base resolves relative'
,
url2b
.
href
,
'https://example.com/bar/foo'
);
const
url2c
=
new
URL
(
'//other.com/path'
,
'https://example.com'
);
test
(
'URL with base protocol-relative'
,
url2c
.
href
,
'https://other.com/path'
);
testThrows
(
'requires new'
,
()
=>
URL
());
testThrows
(
'invalid URL throws TypeError'
,
()
=>
new
URL
(
'not a url'
));
testThrows
(
'invalid URL with base throws'
,
()
=>
new
URL
(
'http://%'
,
'https://example.com'
));
test
(
'toString() returns href'
,
url
.
toString
(),
url
.
href
);
test
(
'toJSON() returns href'
,
url
.
toJSON
(),
url
.
href
);
test
(
'URL.canParse valid'
,
URL
.
canParse
(
'https://example.com'
),
true
);
test
(
'URL.canParse invalid'
,
URL
.
canParse
(
'not a url'
),
false
);
test
(
'URL.canParse with base'
,
URL
.
canParse
(
'/path'
,
'https://example.com'
),
true
);
const
parsed
=
URL
.
parse
(
'https://example.com/test'
);
test
(
'URL.parse valid returns URL'
,
parsed
instanceof
URL
,
true
);
test
(
'URL.parse valid href'
,
parsed
.
href
,
'https://example.com/test'
);
test
(
'URL.parse invalid returns null'
,
URL
.
parse
(
'not a url'
),
null
);
const
parsedBase
=
URL
.
parse
(
'/path'
,
'https://example.com'
);
test
(
'URL.parse with base'
,
parsedBase
.
href
,
'https://example.com/path'
);
console
.
log
(
'\nURL properties (getters)\n'
);
test
(
'protocol'
,
url
.
protocol
,
'https:'
);
test
(
'username'
,
url
.
username
,
'user'
);
test
(
'password'
,
url
.
password
,
'pass'
);
test
(
'hostname'
,
url
.
hostname
,
'example.com'
);
test
(
'host (hostname:port)'
,
url
.
host
,
'example.com:8080'
);
test
(
'port'
,
url
.
port
,
'8080'
);
test
(
'pathname'
,
url
.
pathname
,
'/path/to'
);
test
(
'search'
,
url
.
search
,
'?query=value'
);
test
(
'hash'
,
url
.
hash
,
'#hash'
);
test
(
'origin'
,
url
.
origin
,
'https://example.com:8080'
);
const
urlNoSearch
=
new
URL
(
'https://example.com/path'
);
test
(
'search empty string when absent'
,
urlNoSearch
.
search
,
''
);
const
urlNoHash
=
new
URL
(
'https://example.com/path'
);
test
(
'hash empty string when absent'
,
urlNoHash
.
hash
,
''
);
const
urlDefaultHost
=
new
URL
(
'https://example.com/'
);
test
(
'host without port'
,
urlDefaultHost
.
host
,
'example.com'
);
const
urlNoUser
=
new
URL
(
'https://example.com/'
);
test
(
'username empty when absent'
,
urlNoUser
.
username
,
''
);
test
(
'password empty when absent'
,
urlNoUser
.
password
,
''
);
console
.
log
(
'\nURL property setters\n'
);
const
us1
=
new
URL
(
'https://example.com/old'
);
us1
.
href
=
'https://other.com/new?q=1'
;
test
(
'set href reparses'
,
us1
.
hostname
,
'other.com'
);
test
(
'set href pathname'
,
us1
.
pathname
,
'/new'
);
test
(
'set href search'
,
us1
.
search
,
'?q=1'
);
const
us2
=
new
URL
(
'https://example.com/path'
);
us2
.
protocol
=
'http:'
;
test
(
'set protocol'
,
us2
.
protocol
,
'http:'
);
const
us3
=
new
URL
(
'https://example.com/path'
);
us3
.
hostname
=
'other.com'
;
test
(
'set hostname'
,
us3
.
hostname
,
'other.com'
);
test
(
'set hostname updates host'
,
us3
.
host
,
'other.com'
);
const
us4
=
new
URL
(
'https://example.com/path'
);
us4
.
port
=
'9090'
;
test
(
'set port'
,
us4
.
port
,
'9090'
);
test
(
'set port updates host'
,
us4
.
host
,
'example.com:9090'
);
const
us4b
=
new
URL
(
'https://example.com:9090/path'
);
us4b
.
port
=
'443'
;
test
(
'set default port elides'
,
us4b
.
port
,
''
);
const
us5
=
new
URL
(
'https://example.com/old'
);
us5
.
pathname
=
'/new/path'
;
test
(
'set pathname'
,
us5
.
pathname
,
'/new/path'
);
const
us6
=
new
URL
(
'https://example.com/path'
);
us6
.
search
=
'?x=1&y=2'
;
test
(
'set search'
,
us6
.
search
,
'?x=1&y=2'
);
const
us6b
=
new
URL
(
'https://example.com/path?old=1'
);
us6b
.
search
=
''
;
test
(
'set search empty clears'
,
us6b
.
search
,
''
);
const
us7
=
new
URL
(
'https://example.com/path'
);
us7
.
hash
=
'#section'
;
test
(
'set hash'
,
us7
.
hash
,
'#section'
);
const
us7b
=
new
URL
(
'https://example.com/path#old'
);
us7b
.
hash
=
''
;
test
(
'set hash empty clears'
,
us7b
.
hash
,
''
);
const
us8
=
new
URL
(
'https://example.com/path'
);
us8
.
username
=
'alice'
;
test
(
'set username'
,
us8
.
username
,
'alice'
);
const
us9
=
new
URL
(
'https://example.com/path'
);
us9
.
password
=
'secret'
;
test
(
'set password'
,
us9
.
password
,
'secret'
);
console
.
log
(
'\ndefault port handling\n'
);
const
httpDefault
=
new
URL
(
'http://example.com:80/'
);
test
(
'http port 80 elided'
,
httpDefault
.
port
,
''
);
test
(
'http port 80 host omits port'
,
httpDefault
.
host
,
'example.com'
);
const
httpsDefault
=
new
URL
(
'https://example.com:443/'
);
test
(
'https port 443 elided'
,
httpsDefault
.
port
,
''
);
test
(
'https port 443 host omits port'
,
httpsDefault
.
host
,
'example.com'
);
const
httpNonDefault
=
new
URL
(
'http://example.com:3000/'
);
test
(
'http non-default port shown'
,
httpNonDefault
.
port
,
'3000'
);
test
(
'http non-default host includes port'
,
httpNonDefault
.
host
,
'example.com:3000'
);
const
httpsNonDefault
=
new
URL
(
'https://example.com:8443/'
);
test
(
'https non-default port shown'
,
httpsNonDefault
.
port
,
'8443'
);
console
.
log
(
'\nURLSearchParams constructor\n'
);
const
sp0
=
new
URLSearchParams
();
test
(
'empty constructor toString'
,
sp0
.
toString
(),
''
);
test
(
'empty constructor size'
,
sp0
.
size
,
0
);
const
sp1
=
new
URLSearchParams
(
'a=1&b=2'
);
test
(
'from string get a'
,
sp1
.
get
(
'a'
),
'1'
);
test
(
'from string get b'
,
sp1
.
get
(
'b'
),
'2'
);
test
(
'from string size'
,
sp1
.
size
,
2
);
const
sp1b
=
new
URLSearchParams
(
'?a=1&b=2'
);
test
(
'from string with leading ?'
,
sp1b
.
get
(
'a'
),
'1'
);
test
(
'from string with leading ? get b'
,
sp1b
.
get
(
'b'
),
'2'
);
const
sp2
=
new
URLSearchParams
([
[
'a'
,
'1'
],
[
'b'
,
'2'
]
]);
test
(
'from array get a'
,
sp2
.
get
(
'a'
),
'1'
);
test
(
'from array get b'
,
sp2
.
get
(
'b'
),
'2'
);
test
(
'from array size'
,
sp2
.
size
,
2
);
const
sp3
=
new
URLSearchParams
({
a
:
'1'
,
b
:
'2'
});
test
(
'from object get a'
,
sp3
.
get
(
'a'
),
'1'
);
test
(
'from object get b'
,
sp3
.
get
(
'b'
),
'2'
);
const
sp4
=
new
URLSearchParams
(
new
URLSearchParams
(
'x=9&y=8'
));
test
(
'from another URLSearchParams get x'
,
sp4
.
get
(
'x'
),
'9'
);
test
(
'from another URLSearchParams get y'
,
sp4
.
get
(
'y'
),
'8'
);
testThrows
(
'pair with 1 element throws'
,
()
=>
new
URLSearchParams
([[
'only_key'
]]));
testThrows
(
'pair with 3 elements throws'
,
()
=>
new
URLSearchParams
([[
'a'
,
'b'
,
'c'
]]));
console
.
log
(
'\nURLSearchParams methods\n'
);
const
sp
=
new
URLSearchParams
(
'a=1&b=2&a=3'
);
test
(
'get returns first value'
,
sp
.
get
(
'a'
),
'1'
);
test
(
'get missing returns null'
,
sp
.
get
(
'z'
),
null
);
testDeep
(
'getAll returns all values'
,
sp
.
getAll
(
'a'
),
[
'1'
,
'3'
]);
testDeep
(
'getAll missing returns empty'
,
sp
.
getAll
(
'z'
),
[]);
test
(
'has returns true'
,
sp
.
has
(
'a'
),
true
);
test
(
'has missing returns false'
,
sp
.
has
(
'z'
),
false
);
test
(
'has with matching value'
,
sp
.
has
(
'a'
,
'1'
),
true
);
test
(
'has with non-matching value'
,
sp
.
has
(
'a'
,
'999'
),
false
);
const
spSet
=
new
URLSearchParams
(
'a=1&b=2&a=3'
);
spSet
.
set
(
'a'
,
'99'
);
test
(
'set replaces all'
,
spSet
.
get
(
'a'
),
'99'
);
test
(
'set getAll length'
,
spSet
.
getAll
(
'a'
).
length
,
1
);
test
(
'set preserves others'
,
spSet
.
get
(
'b'
),
'2'
);
const
spApp
=
new
URLSearchParams
(
'a=1'
);
spApp
.
append
(
'a'
,
'2'
);
test
(
'append adds entry'
,
spApp
.
getAll
(
'a'
).
length
,
2
);
test
(
'append second value'
,
spApp
.
getAll
(
'a'
)[
1
],
'2'
);
const
spDel
=
new
URLSearchParams
(
'a=1&b=2&a=3'
);
spDel
.
delete
(
'a'
);
test
(
'delete removes all with name'
,
spDel
.
has
(
'a'
),
false
);
test
(
'delete preserves others'
,
spDel
.
has
(
'b'
),
true
);
const
spDelVal
=
new
URLSearchParams
(
'a=1&a=2&a=3'
);
spDelVal
.
delete
(
'a'
,
'2'
);
test
(
'delete with value removes specific'
,
spDelVal
.
getAll
(
'a'
).
length
,
2
);
test
(
'delete with value keeps others'
,
spDelVal
.
get
(
'a'
),
'1'
);
const
spSort
=
new
URLSearchParams
(
'c=3&a=1&b=2&a=4'
);
spSort
.
sort
();
test
(
'sort first key'
,
[...
spSort
.
keys
()][
0
],
'a'
);
test
(
'sort second key'
,
[...
spSort
.
keys
()][
1
],
'a'
);
test
(
'sort third key'
,
[...
spSort
.
keys
()][
2
],
'b'
);
test
(
'sort fourth key'
,
[...
spSort
.
keys
()][
3
],
'c'
);
test
(
'sort stable: first a value'
,
spSort
.
getAll
(
'a'
)[
0
],
'1'
);
test
(
'sort stable: second a value'
,
spSort
.
getAll
(
'a'
)[
1
],
'4'
);
test
(
'toString serializes'
,
new
URLSearchParams
(
'a=1&b=2'
).
toString
(),
'a=1&b=2'
);
test
(
'toString empty'
,
new
URLSearchParams
().
toString
(),
''
);
const
spFE
=
new
URLSearchParams
(
'a=1&b=2'
);
const
feResults
=
[];
spFE
.
forEach
((
value
,
name
)
=>
feResults
.
push
(
`
${
name
}
=
${
value
}
`
));
test
(
'forEach visits all'
,
feResults
.
length
,
2
);
test
(
'forEach first'
,
feResults
[
0
],
'a=1'
);
test
(
'forEach second'
,
feResults
[
1
],
'b=2'
);
test
(
'size getter'
,
new
URLSearchParams
(
'a=1&b=2&c=3'
).
size
,
3
);
test
(
'size after append'
,
(()
=>
{
const
s
=
new
URLSearchParams
(
'a=1'
);
s
.
append
(
'b'
,
'2'
);
return
s
.
size
;
})(),
2
);
console
.
log
(
'\nURLSearchParams encoding\n'
);
test
(
'space encoded as +'
,
new
URLSearchParams
([[
'k'
,
'hello world'
]]).
toString
(),
'k=hello+world'
);
test
(
'+ in value encoded as %2B'
,
new
URLSearchParams
([[
'k'
,
'a+b'
]]).
toString
(),
'k=a%2Bb'
);
test
(
'= in value encoded'
,
new
URLSearchParams
([[
'k'
,
'a=b'
]]).
toString
(),
'k=a%3Db'
);
test
(
'& in value encoded'
,
new
URLSearchParams
([[
'k'
,
'a&b'
]]).
toString
(),
'k=a%26b'
);
test
(
'* passes through'
,
new
URLSearchParams
([[
'k'
,
'*'
]]).
toString
(),
'k=*'
);
test
(
'- passes through'
,
new
URLSearchParams
([[
'k'
,
'-'
]]).
toString
(),
'k=-'
);
test
(
'. passes through'
,
new
URLSearchParams
([[
'k'
,
'.'
]]).
toString
(),
'k=.'
);
test
(
'_ passes through'
,
new
URLSearchParams
([[
'k'
,
'_'
]]).
toString
(),
'k=_'
);
test
(
'~ is percent-encoded'
,
new
URLSearchParams
([[
'k'
,
'~'
]]).
toString
(),
'k=%7E'
);
test
(
'parsing: + becomes space'
,
new
URLSearchParams
(
'k=hello+world'
).
get
(
'k'
),
'hello world'
);
test
(
'parsing: %20 becomes space'
,
new
URLSearchParams
(
'k=hello%20world'
).
get
(
'k'
),
'hello world'
);
test
(
'parsing: %2B becomes +'
,
new
URLSearchParams
(
'k=a%2Bb'
).
get
(
'k'
),
'a+b'
);
console
.
log
(
'\nURLSearchParams iterator protocol\n'
);
const
spi
=
new
URLSearchParams
(
'a=1&b=2'
);
const
entries
=
[...
spi
.
entries
()];
test
(
'entries length'
,
entries
.
length
,
2
);
test
(
'entries first'
,
entries
[
0
][
0
],
'a'
);
test
(
'entries first value'
,
entries
[
0
][
1
],
'1'
);
const
keys
=
[...
spi
.
keys
()];
test
(
'keys length'
,
keys
.
length
,
2
);
test
(
'keys first'
,
keys
[
0
],
'a'
);
test
(
'keys second'
,
keys
[
1
],
'b'
);
const
vals
=
[...
spi
.
values
()];
test
(
'values length'
,
vals
.
length
,
2
);
test
(
'values first'
,
vals
[
0
],
'1'
);
test
(
'values second'
,
vals
[
1
],
'2'
);
test
(
'Symbol.iterator is entries'
,
spi
[
Symbol
.
iterator
]
===
spi
.
entries
,
true
);
const
forOfResults
=
[];
for
(
const
[
name
,
value
]
of
new
URLSearchParams
(
'x=10&y=20'
))
{
forOfResults
.
push
(
`
${
name
}
=
${
value
}
`
);
}
test
(
'for...of first'
,
forOfResults
[
0
],
'x=10'
);
test
(
'for...of second'
,
forOfResults
[
1
],
'y=20'
);
const
spread
=
[...
new
URLSearchParams
(
'p=1&q=2'
)];
test
(
'spread length'
,
spread
.
length
,
2
);
test
(
'spread first pair'
,
spread
[
0
][
0
],
'p'
);
test
(
'spread first value'
,
spread
[
0
][
1
],
'1'
);
console
.
log
(
'\nURL-URLSearchParams bidirectional sync\n'
);
const
syncUrl
=
new
URL
(
'https://example.com/?a=1'
);
syncUrl
.
searchParams
.
set
(
'b'
,
'2'
);
test
(
'searchParams mutation updates search'
,
syncUrl
.
search
,
'?a=1&b=2'
);
syncUrl
.
searchParams
.
delete
(
'a'
);
test
(
'searchParams delete updates search'
,
syncUrl
.
search
,
'?b=2'
);
syncUrl
.
searchParams
.
append
(
'c'
,
'3'
);
test
(
'searchParams append updates search'
,
syncUrl
.
search
,
'?b=2&c=3'
);
const
syncUrl2
=
new
URL
(
'https://example.com/?x=1'
);
syncUrl2
.
search
=
'?y=2&z=3'
;
test
(
'set search updates searchParams get y'
,
syncUrl2
.
searchParams
.
get
(
'y'
),
'2'
);
test
(
'set search updates searchParams get z'
,
syncUrl2
.
searchParams
.
get
(
'z'
),
'3'
);
test
(
'set search removes old param'
,
syncUrl2
.
searchParams
.
has
(
'x'
),
false
);
const
syncUrl3
=
new
URL
(
'https://example.com/?a=1'
);
const
paramsRef1
=
syncUrl3
.
searchParams
;
syncUrl3
.
search
=
'?b=2'
;
const
paramsRef2
=
syncUrl3
.
searchParams
;
test
(
'searchParams identity preserved'
,
paramsRef1
===
paramsRef2
,
true
);
console
.
log
(
'\ntoStringTag\n'
);
test
(
'URL toStringTag'
,
Object
.
prototype
.
toString
.
call
(
new
URL
(
'https://example.com'
)),
'[object URL]'
);
test
(
'URLSearchParams toStringTag'
,
Object
.
prototype
.
toString
.
call
(
new
URLSearchParams
()),
'[object URLSearchParams]'
);
summary
();
File Metadata
Details
Attached
Mime Type
application/javascript
Expires
Sat, May 2, 8:40 AM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
539060
Default Alt Text
url.js (11 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment