diff --git a/benchmark/querystring/querystring-parse.js b/benchmark/querystring/querystring-parse.js index fe14d95a53f0a0..2e2ec1417bcd35 100644 --- a/benchmark/querystring/querystring-parse.js +++ b/benchmark/querystring/querystring-parse.js @@ -3,17 +3,7 @@ var common = require('../common.js'); var querystring = require('querystring'); var v8 = require('v8'); -var inputs = { - noencode: 'foo=bar&baz=quux&xyzzy=thud', - multicharsep: 'foo=bar&&&&&&&&&&baz=quux&&&&&&&&&&xyzzy=thud', - encodefake: 'foo=%©ar&baz=%A©uux&xyzzy=%©ud', - encodemany: '%66%6F%6F=bar&%62%61%7A=quux&xyzzy=%74h%75d', - encodelast: 'foo=bar&baz=quux&xyzzy=thu%64', - multivalue: 'foo=bar&foo=baz&foo=quux&quuy=quuz', - multivaluemany: 'foo=bar&foo=baz&foo=quux&quuy=quuz&foo=abc&foo=def&' + - 'foo=ghi&foo=jkl&foo=mno&foo=pqr&foo=stu&foo=vwxyz', - manypairs: 'a&b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z' -}; +var inputs = require('../fixtures/url-inputs.js').searchParams; var bench = common.createBenchmark(main, { type: Object.keys(inputs), diff --git a/benchmark/url/url-format.js b/benchmark/url/url-format.js index 3f7df8a0bc4536..886958406b91c5 100644 --- a/benchmark/url/url-format.js +++ b/benchmark/url/url-format.js @@ -3,8 +3,13 @@ const common = require('../common.js'); const url = require('url'); const v8 = require('v8'); +const inputs = { + slashes: {slashes: true, host: 'localhost'}, + file: {protocol: 'file:', pathname: '/foo'}, +}; + const bench = common.createBenchmark(main, { - type: 'one two'.split(' '), + type: Object.keys(inputs), n: [25e6] }); @@ -12,10 +17,6 @@ function main(conf) { const type = conf.type; const n = conf.n | 0; - const inputs = { - one: {slashes: true, host: 'localhost'}, - two: {protocol: 'file:', pathname: '/foo'}, - }; const input = inputs[type] || ''; // Force-optimize url.format() so that the benchmark doesn't get diff --git a/benchmark/url/url-parse.js b/benchmark/url/url-parse.js deleted file mode 100644 index 89679548b8f193..00000000000000 --- a/benchmark/url/url-parse.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict'; -var common = require('../common.js'); -var url = require('url'); -var v8 = require('v8'); - -var bench = common.createBenchmark(main, { - type: 'one two three four five six'.split(' '), - n: [25e4] -}); - -function main(conf) { - var type = conf.type; - var n = conf.n | 0; - - var inputs = { - one: 'http://nodejs.org/docs/latest/api/url.html#url_url_format_urlobj', - two: 'http://blog.nodejs.org/', - three: 'https://encrypted.google.com/search?q=url&q=site:npmjs.org&hl=en', - four: 'javascript:alert("node is awesome");', - five: 'some.ran/dom/url.thing?oh=yes#whoo', - six: 'https://user:pass@example.com/', - }; - var input = inputs[type] || ''; - - // Force-optimize url.parse() so that the benchmark doesn't get - // disrupted by the optimizer kicking in halfway through. - for (var name in inputs) - url.parse(inputs[name]); - - v8.setFlagsFromString('--allow_natives_syntax'); - eval('%OptimizeFunctionOnNextCall(url.parse)'); - - bench.start(); - for (var i = 0; i < n; i += 1) - url.parse(input); - bench.end(n); -} diff --git a/benchmark/url/url-resolve.js b/benchmark/url/url-resolve.js index 8372132e4d269e..4335511ca6d2df 100644 --- a/benchmark/url/url-resolve.js +++ b/benchmark/url/url-resolve.js @@ -1,36 +1,28 @@ 'use strict'; -var common = require('../common.js'); -var url = require('url'); -var v8 = require('v8'); +const common = require('../common.js'); +const url = require('url'); +const v8 = require('v8'); +const hrefs = require('../fixtures/url-inputs.js').urls; +hrefs.noscheme = 'some.ran/dom/url.thing?oh=yes#whoo'; -var hrefs = [ - 'http://example.com/', - 'http://nodejs.org/docs/latest/api/url.html#url_url_format_urlobj', - 'http://blog.nodejs.org/', - 'https://encrypted.google.com/search?q=url&q=site:npmjs.org&hl=en', - 'javascript:alert("node is awesome");', - 'some.ran/dom/url.thing?oh=yes#whoo' -]; +const paths = { + 'up': '../../../../../etc/passwd', + 'sibling': '../foo/bar?baz=boom', + 'foo/bar': 'foo/bar', + 'withscheme': 'http://nodejs.org', + 'down': './foo/bar?baz' +}; - -var paths = [ - '../../../../../etc/passwd', - '../foo/bar?baz=boom', - 'foo/bar', - 'http://nodejs.org', - './foo/bar?baz' -]; - -var bench = common.createBenchmark(main, { +const bench = common.createBenchmark(main, { href: Object.keys(hrefs), path: Object.keys(paths), n: [1e5] }); function main(conf) { - var n = conf.n | 0; - var href = hrefs[conf.href]; - var path = paths[conf.path]; + const n = conf.n | 0; + const href = hrefs[conf.href]; + const path = paths[conf.path]; // Force-optimize url.resolve() so that the benchmark doesn't get // disrupted by the optimizer kicking in halfway through. diff --git a/benchmark/url/url-searchparams-sort.js b/benchmark/url/url-searchparams-sort.js new file mode 100644 index 00000000000000..677ce511cf3ea2 --- /dev/null +++ b/benchmark/url/url-searchparams-sort.js @@ -0,0 +1,48 @@ +'use strict'; +const common = require('../common.js'); +const URLSearchParams = require('url').URLSearchParams; + +const inputs = { + empty: '', + sorted: 'a&b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z', + almostsorted: 'a&b&c&d&e&f&g&i&h&j&k&l&m&n&o&p&q&r&s&t&u&w&v&x&y&z', + reversed: 'z&y&x&w&v&u&t&s&r&q&p&o&n&m&l&k&j&i&h&g&f&e&d&c&b&a', + random: 'm&t&d&c&z&v&a&n&p&y&u&o&h&l&f&j&e&q&b&i&s&x&k&w&r&g', + // 8 parameters + short: 'm&t&d&c&z&v&a&n', + // 88 parameters + long: 'g&r&t&h&s&r&d&w&b&n&h&k&x&m&k&h&o&e&x&c&c&g&e&b&p&p&s&n&j&b&y&z&' + + 'u&l&o&r&w&a&u&l&m&f&j&q&p&f&e&y&e&n&e&l&m&w&u&w&t&n&t&q&v&y&c&o&' + + 'k&f&j&i&l&m&g&j&d&i&z&q&p&x&q&q&d&n&y&w&g&i&v&r' +}; + +function getParams(str) { + const out = []; + for (const key of str.split('&')) { + out.push(key, ''); + } + return out; +} + +const bench = common.createBenchmark(main, { + type: Object.keys(inputs), + n: [1e6] +}, { + flags: ['--expose-internals'] +}); + +function main(conf) { + const searchParams = require('internal/url').searchParamsSymbol; + const input = inputs[conf.type]; + const n = conf.n | 0; + const params = new URLSearchParams(); + const array = getParams(input); + + var i; + bench.start(); + for (i = 0; i < n; i++) { + params[searchParams] = array.slice(); + params.sort(); + } + bench.end(n); +} diff --git a/doc/api/url.md b/doc/api/url.md old mode 100755 new mode 100644 index 50e7433e6110e5..61d27c5b68a15e --- a/doc/api/url.md +++ b/doc/api/url.md @@ -198,6 +198,47 @@ The formatting process operates as follows: string, an [`Error`][] is thrown. * `result` is returned. +## url.format(URL[, options]) + +> Stability: 1 - Experimental + +* `URL` {URL} A [WHATWG URL][] object +* `options` {Object} + * `auth` {Boolean} `true` if the serialized URL string should include the + username and password, `false` otherwise. Defaults to `true`. + * `fragment` {Boolean} `true` if the serialized URL string should include the + fragment, `false` otherwise. Defaults to `true`. + * `search` {Boolean} `true` if the serialized URL string should include the + search query, `false` otherwise. Defaults to `true`. + * `unicode` (Boolean) `true` if Unicode characters appearing in the host + component of the URL string should be encoded directly as opposed to being + Punycode encoded. Defaults to `false`. + +Returns a customizable serialization of a URL String representation of a +[WHATWG URL][] object. + +The URL object has both a `toString()` method and `href` property that return +string serializations of the URL. These are not, however, customizable in +any way. The `url.format(URL[, options])` method allows for basic customization +of the output. + +For example: + +```js +const myURL = new URL('https://a:b@你好你好?abc#foo'); + +console.log(myURL.href); + // Prints https://a:b@xn--6qqa088eba/?abc#foo + +console.log(myURL.toString()); + // Prints https://a:b@xn--6qqa088eba/?abc#foo + +console.log(url.format(myURL, {fragment: false, unicode: true, auth: false})); + // Prints 'https://你好你好?abc' +``` + +*Note*: This variation of the `url.format()` method is currently considered to +be experimental. ## url.parse(urlString[, parseQueryString[, slashesDenoteHost]])