Skip to content

Commit

Permalink
url: improve invalid url performance
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Sep 17, 2023
1 parent 7e12d0e commit 79415ed
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 19 deletions.
23 changes: 23 additions & 0 deletions benchmark/url/whatwg-url-validity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict';
const common = require('../common.js');
const url = require('url');
const URL = url.URL;

const bench = common.createBenchmark(main, {
type: ['valid', 'invalid'],
e: [1e5],
});

// This benchmark is used to compare the `Invalid URL` path of the URL parser
function main({ type, e }) {
const url = type === 'valid' ? 'https://www.nodejs.org' : 'www.nodejs.org';
bench.start();
for (let i = 0; i < e; i++) {
try {
new URL(url);
} catch {
// do nothing
}
}
bench.end(e);
}
3 changes: 1 addition & 2 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1370,8 +1370,7 @@ E('ERR_INVALID_SYNC_FORK_INPUT',
E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError);
E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError);
E('ERR_INVALID_URI', 'URI malformed', URIError);
E('ERR_INVALID_URL', function(input) {
this.input = input;
E('ERR_INVALID_URL', function() {
// Don't include URL in message.
// (See https://github.com/nodejs/node/pull/38614)
return 'Invalid URL';
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/modules/esm/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async function getSource(url, context) {
} else if (protocol === 'data:') {
const match = RegExpPrototypeExec(DATA_URL_PATTERN, url.pathname);
if (!match) {
throw new ERR_INVALID_URL(responseURL);
throw new ERR_INVALID_URL();
}
const { 1: base64, 2: body } = match;
source = BufferFrom(decodeURIComponent(body), base64 ? 'base64' : 'utf8');
Expand Down Expand Up @@ -84,7 +84,7 @@ function getSourceSync(url, context) {
} else if (protocol === 'data:') {
const match = RegExpPrototypeExec(DATA_URL_PATTERN, url.pathname);
if (!match) {
throw new ERR_INVALID_URL(responseURL);
throw new ERR_INVALID_URL();
}
const { 1: base64, 2: body } = match;
source = BufferFrom(decodeURIComponent(body), base64 ? 'base64' : 'utf8');
Expand Down
10 changes: 2 additions & 8 deletions lib/internal/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -780,13 +780,7 @@ class URL {
base = `${base}`;
}

const href = bindingUrl.parse(input, base);

if (!href) {
throw new ERR_INVALID_URL(input);
}

this.#updateContext(href);
this.#updateContext(bindingUrl.parse(input, base));
}

[inspect.custom](depth, opts) {
Expand Down Expand Up @@ -861,7 +855,7 @@ class URL {
set href(value) {
value = `${value}`;
const href = bindingUrl.update(this.#context.href, updateActions.kHref, value);
if (!href) { throw ERR_INVALID_URL(value); }
if (!href) { throw ERR_INVALID_URL(); }
this.#updateContext(href);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
if (this.hostname !== '') {
if (ipv6Hostname) {
if (forbiddenHostCharsIpv6.test(this.hostname)) {
throw new ERR_INVALID_URL(url);
throw new ERR_INVALID_URL();
}
} else {
// IDNA Support: Returns a punycoded representation of "domain".
Expand All @@ -413,7 +413,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
// the pathname as we've done in getHostname, throw an exception to
// convey the severity of this issue.
if (this.hostname === '' || forbiddenHostChars.test(this.hostname)) {
throw new ERR_INVALID_URL(url);
throw new ERR_INVALID_URL();
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/node_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -243,15 +243,15 @@ void BindingData::Parse(const FunctionCallbackInfo<Value>& args) {
base =
ada::parse<ada::url_aggregator>(Utf8Value(isolate, args[1]).ToString());
if (!base) {
return args.GetReturnValue().Set(false);
return THROW_ERR_INVALID_URL(realm->env(), "Invalid URL");
}
base_pointer = &base.value();
}
auto out =
ada::parse<ada::url_aggregator>(input.ToStringView(), base_pointer);

if (!out) {
return args.GetReturnValue().Set(false);
return THROW_ERR_INVALID_URL(realm->env(), "Invalid URL");
}

binding_data->UpdateComponents(out->get_components(), out->type);
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-url-null-char.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ const assert = require('assert');

assert.throws(
() => { new URL('a\0b'); },
{ input: 'a\0b' }
{ code: 'ERR_INVALID_URL' }
);
2 changes: 1 addition & 1 deletion test/parallel/test-url-parse-invalid-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ assert.throws(() => { url.parse('http://%E0%A4%A@fail'); },
});

assert.throws(() => { url.parse('http://[127.0.0.1\x00c8763]:8000/'); },
{ code: 'ERR_INVALID_URL', input: 'http://[127.0.0.1\x00c8763]:8000/' }
{ code: 'ERR_INVALID_URL' }
);

if (common.hasIntl) {
Expand Down
2 changes: 1 addition & 1 deletion test/parallel/test-whatwg-url-custom-parsing.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ for (const test of failureTests) {
() => new URL(test.input, test.base),
(error) => {
assert.throws(() => { throw error; }, expectedError);
assert.strictEqual(`${error}`, 'TypeError [ERR_INVALID_URL]: Invalid URL');
assert.strictEqual(`${error}`, 'TypeError: Invalid URL');
assert.strictEqual(error.message, 'Invalid URL');
return true;
});
Expand Down

0 comments on commit 79415ed

Please sign in to comment.