Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 11f48e0

Browse filesBrowse files
KhafraDevdanielleadams
authored andcommitted
url: implement URL.canParse
PR-URL: #47179 Backport-PR-URL: #48345 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Debadree Chatterjee <debadree333@gmail.com>
1 parent 1f2c91f commit 11f48e0
Copy full SHA for 11f48e0

File tree

Expand file treeCollapse file tree

7 files changed

+122
-2
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

7 files changed

+122
-2
lines changed
Open diff view settings
Collapse file
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
'use strict';
2+
const common = require('../common.js');
3+
4+
const bench = common.createBenchmark(main, {
5+
type: Object.keys(common.urls),
6+
n: [25e6],
7+
});
8+
9+
function main({ type, n }) {
10+
bench.start();
11+
for (let i = 0; i < n; i += 1)
12+
URL.canParse(common.urls[type]);
13+
bench.end(n);
14+
}
Collapse file

‎doc/api/url.md‎

Copy file name to clipboardExpand all lines: doc/api/url.md
+21Lines changed: 21 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,27 @@ added: v16.7.0
662662
Removes the stored {Blob} identified by the given ID. Attempting to revoke a
663663
ID that isn't registered will silently fail.
664664

665+
#### `URL.canParse(input[, base])`
666+
667+
<!-- YAML
668+
added: REPLACEME
669+
-->
670+
671+
* `input` {string} The absolute or relative input URL to parse. If `input`
672+
is relative, then `base` is required. If `input` is absolute, the `base`
673+
is ignored. If `input` is not a string, it is [converted to a string][] first.
674+
* `base` {string} The base URL to resolve against if the `input` is not
675+
absolute. If `base` is not a string, it is [converted to a string][] first.
676+
* Returns: {boolean}
677+
678+
Checks if an `input` relative to the `base` can be parsed to a `URL`.
679+
680+
```js
681+
const isValid = URL.canParse('/foo', 'https://example.org/'); // true
682+
683+
const isNotValid = URL.canParse('/foo'); // false
684+
```
685+
665686
### Class: `URLSearchParams`
666687

667688
<!-- YAML
Collapse file

‎lib/internal/url.js‎

Copy file name to clipboardExpand all lines: lib/internal/url.js
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const {
9191
domainToASCII: _domainToASCII,
9292
domainToUnicode: _domainToUnicode,
9393
parse,
94+
canParse: _canParse,
9495
updateUrl,
9596
} = internalBinding('url');
9697

@@ -793,6 +794,16 @@ class URL {
793794
return this[context].href;
794795
}
795796

797+
static canParse(url, base = undefined) {
798+
url = `${url}`;
799+
800+
if (base !== undefined) {
801+
base = `${base}`;
802+
}
803+
804+
return _canParse(url, base);
805+
}
806+
796807
static createObjectURL(obj) {
797808
const cryptoRandom = lazyCryptoRandom();
798809
if (cryptoRandom === undefined)
@@ -842,6 +853,12 @@ ObjectDefineProperties(URL.prototype, {
842853
});
843854

844855
ObjectDefineProperties(URL, {
856+
canParse: {
857+
__proto__: null,
858+
configurable: true,
859+
writable: true,
860+
enumerable: true,
861+
},
845862
createObjectURL: kEnumerableProperty,
846863
revokeObjectURL: kEnumerableProperty,
847864
});
Collapse file

‎src/node_url.cc‎

Copy file name to clipboardExpand all lines: src/node_url.cc
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,30 @@ void Parse(const FunctionCallbackInfo<Value>& args) {
9393
args.GetReturnValue().Set(true);
9494
}
9595

96+
void CanParse(const FunctionCallbackInfo<Value>& args) {
97+
CHECK_GE(args.Length(), 2);
98+
CHECK(args[0]->IsString()); // input
99+
// args[1] // base url
100+
101+
Environment* env = Environment::GetCurrent(args);
102+
HandleScope handle_scope(env->isolate());
103+
Context::Scope context_scope(env->context());
104+
105+
Utf8Value input(env->isolate(), args[0]);
106+
ada::result base;
107+
ada::url* base_pointer = nullptr;
108+
if (args[1]->IsString()) {
109+
base = ada::parse(Utf8Value(env->isolate(), args[1]).ToString());
110+
if (!base) {
111+
return args.GetReturnValue().Set(false);
112+
}
113+
base_pointer = &base.value();
114+
}
115+
ada::result out = ada::parse(input.ToStringView(), base_pointer);
116+
117+
args.GetReturnValue().Set(out.has_value());
118+
}
119+
96120
void DomainToASCII(const FunctionCallbackInfo<Value>& args) {
97121
Environment* env = Environment::GetCurrent(args);
98122
CHECK_GE(args.Length(), 1);
@@ -285,6 +309,7 @@ void Initialize(Local<Object> target,
285309
void* priv) {
286310
SetMethod(context, target, "parse", Parse);
287311
SetMethod(context, target, "updateUrl", UpdateUrl);
312+
SetMethodNoSideEffect(context, target, "canParse", CanParse);
288313
SetMethodNoSideEffect(context, target, "formatUrl", FormatUrl);
289314

290315
SetMethodNoSideEffect(context, target, "domainToASCII", DomainToASCII);
@@ -294,6 +319,7 @@ void Initialize(Local<Object> target,
294319

295320
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
296321
registry->Register(Parse);
322+
registry->Register(CanParse);
297323
registry->Register(UpdateUrl);
298324
registry->Register(FormatUrl);
299325

Collapse file

‎test/fixtures/wpt/README.md‎

Copy file name to clipboardExpand all lines: test/fixtures/wpt/README.md
+1-1Lines changed: 1 addition & 1 deletion
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Last update:
2727
- performance-timeline: https://github.com/web-platform-tests/wpt/tree/17ebc3aea0/performance-timeline
2828
- resources: https://github.com/web-platform-tests/wpt/tree/fbf1e7d247/resources
2929
- streams: https://github.com/web-platform-tests/wpt/tree/9e5ef42bd3/streams
30-
- url: https://github.com/web-platform-tests/wpt/tree/84caeb6fbd/url
30+
- url: https://github.com/web-platform-tests/wpt/tree/7c5c3cc125/url
3131
- user-timing: https://github.com/web-platform-tests/wpt/tree/df24fb604e/user-timing
3232
- wasm/jsapi: https://github.com/web-platform-tests/wpt/tree/cde25e7e3c/wasm/jsapi
3333
- wasm/webapi: https://github.com/web-platform-tests/wpt/tree/fd1b23eeaa/wasm/webapi
Collapse file
+42Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// This intentionally does not use resources/urltestdata.json to preserve resources.
2+
[
3+
{
4+
"url": undefined,
5+
"base": undefined,
6+
"expected": false
7+
},
8+
{
9+
"url": "a:b",
10+
"base": undefined,
11+
"expected": true
12+
},
13+
{
14+
"url": undefined,
15+
"base": "a:b",
16+
"expected": false
17+
},
18+
{
19+
"url": "a:/b",
20+
"base": undefined,
21+
"expected": true
22+
},
23+
{
24+
"url": undefined,
25+
"base": "a:/b",
26+
"expected": true
27+
},
28+
{
29+
"url": "https://test:test",
30+
"base": undefined,
31+
"expected": false
32+
},
33+
{
34+
"url": "a",
35+
"base": "https://b/",
36+
"expected": true
37+
}
38+
].forEach(({ url, base, expected }) => {
39+
test(() => {
40+
assert_equals(URL.canParse(url, base), expected);
41+
}, `URL.canParse(${url}, ${base})`);
42+
});
Collapse file

‎test/fixtures/wpt/versions.json‎

Copy file name to clipboardExpand all lines: test/fixtures/wpt/versions.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
"path": "streams"
6969
},
7070
"url": {
71-
"commit": "84caeb6fbdf45129f57c67448e6113ee1ced9fb3",
71+
"commit": "7c5c3cc125979b4768d414471e6ab655b473aae8",
7272
"path": "url"
7373
},
7474
"user-timing": {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.