diff --git a/doc/api/errors.md b/doc/api/errors.md index d68640d82ca707..d78caacd63a793 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1204,7 +1204,6 @@ A Node.js API function was called with an incompatible `this` value. Example: ```js -const { URLSearchParams } = require('url'); const urlSearchParams = new URLSearchParams('foo=bar&baz=new'); const buf = Buffer.alloc(1); diff --git a/doc/api/esm.md b/doc/api/esm.md index 0e86c381f1ab60..e9b38735bef990 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -143,7 +143,6 @@ rules with only JS file extension and Node builtin modules support could be written: ```js -import url from 'url'; import path from 'path'; import process from 'process'; import Module from 'module'; @@ -164,7 +163,7 @@ export function resolve(specifier, parentModuleURL/*, defaultResolve */) { throw new Error( `imports must begin with '/', './', or '../'; '${specifier}' does not`); } - const resolved = new url.URL(specifier, parentModuleURL); + const resolved = new URL(specifier, parentModuleURL); const ext = path.extname(resolved.pathname); if (!JS_EXTENSIONS.has(ext)) { throw new Error( diff --git a/doc/api/fs.md b/doc/api/fs.md index f26dc6efbd204b..8e6ca9e7dd2beb 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -173,7 +173,6 @@ are supported. ```js const fs = require('fs'); -const { URL } = require('url'); const fileUrl = new URL('file:///tmp/hello'); fs.readFileSync(fileUrl); diff --git a/doc/api/globals.md b/doc/api/globals.md index a2e5b5fc898686..9ed63764d3b44f 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -138,6 +138,24 @@ added: v0.0.1 [`setTimeout`] is described in the [timers][] section. +## URL + + + + +The WHATWG `URL` class. See the [`URL`][] section. + +## URLSearchParams + + + + +The WHATWG `URLSearchParams` class. See the [`URLSearchParams`][] section. + [`__dirname`]: modules.html#modules_dirname [`__filename`]: modules.html#modules_filename [`clearImmediate`]: timers.html#timers_clearimmediate_immediate @@ -151,6 +169,8 @@ added: v0.0.1 [`setImmediate`]: timers.html#timers_setimmediate_callback_args [`setInterval`]: timers.html#timers_setinterval_callback_delay_args [`setTimeout`]: timers.html#timers_settimeout_callback_delay_args +[`URL`]: url.html#url_class_url +[`URLSearchParams`]: url.html#url_class_urlsearchparams [buffer section]: buffer.html [built-in objects]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects [module system documentation]: modules.html diff --git a/doc/api/http.md b/doc/api/http.md index 02c78550e0d703..46ea8511ffe6b8 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -1871,8 +1871,6 @@ There are a few special headers that should be noted. Example using a [`URL`][] as `options`: ```js -const { URL } = require('url'); - const options = new URL('http://abc:xyz@example.com'); const req = http.request(options, (res) => { diff --git a/doc/api/http2.md b/doc/api/http2.md index 3ac7dd91e5c55e..ab4fb03cb5b34c 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -2186,7 +2186,6 @@ An HTTP/2 CONNECT proxy: const http2 = require('http2'); const { NGHTTP2_REFUSED_STREAM } = http2.constants; const net = require('net'); -const { URL } = require('url'); const proxy = http2.createServer(); proxy.on('stream', (stream, headers) => { diff --git a/doc/api/https.md b/doc/api/https.md index cb22873a01e1ba..1db1e8eb069553 100644 --- a/doc/api/https.md +++ b/doc/api/https.md @@ -242,8 +242,6 @@ const req = https.request(options, (res) => { Example using a [`URL`][] as `options`: ```js -const { URL } = require('url'); - const options = new URL('https://abc:xyz@example.com'); const req = https.request(options, (res) => { diff --git a/doc/api/url.md b/doc/api/url.md index 5f504a5bc8937f..3f75de06026306 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -57,15 +57,10 @@ properties of a WHATWG `URL` object. Parsing the URL string using the WHATWG API: ```js -const { URL } = require('url'); const myURL = new URL('https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash'); ``` -*Note*: In Web Browsers, the WHATWG `URL` class is a global that is always -available. In Node.js, however, the `URL` class must be accessed via -`require('url').URL`. - Parsing the URL string using the Legacy API: ```js @@ -75,14 +70,19 @@ const myURL = ``` ## The WHATWG URL API + +### Class: URL -### Class: URL - Browser-compatible `URL` class, implemented by following the WHATWG URL Standard. [Examples of parsed URLs][] may be found in the Standard itself. +The `URL` class is also available on the global object. *Note*: In accordance with browser conventions, all properties of `URL` objects are implemented as getters and setters on the class prototype, rather than as @@ -101,7 +101,6 @@ Creates a new `URL` object by parsing the `input` relative to the `base`. If `base` is passed as a string, it will be parsed equivalent to `new URL(base)`. ```js -const { URL } = require('url'); const myURL = new URL('/foo', 'https://example.org/'); // https://example.org/foo ``` @@ -111,7 +110,6 @@ that an effort will be made to coerce the given values into strings. For instance: ```js -const { URL } = require('url'); const myURL = new URL({ toString: () => 'https://example.org/' }); // https://example.org/ ``` @@ -120,7 +118,6 @@ Unicode characters appearing within the hostname of `input` will be automatically converted to ASCII using the [Punycode][] algorithm. ```js -const { URL } = require('url'); const myURL = new URL('https://你好你好'); // https://xn--6qqa088eba/ ``` @@ -135,7 +132,6 @@ with [ICU][] enabled. If not, the domain names are passed through unchanged. Gets and sets the fragment portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org/foo#bar'); console.log(myURL.hash); // Prints #bar @@ -157,7 +153,6 @@ percent-encode may vary somewhat from what the [`url.parse()`][] and Gets and sets the host portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org:81/foo'); console.log(myURL.host); // Prints example.org:81 @@ -178,7 +173,6 @@ Gets and sets the hostname portion of the URL. The key difference between port. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org:81/foo'); console.log(myURL.hostname); // Prints example.org @@ -197,7 +191,6 @@ Invalid hostname values assigned to the `hostname` property are ignored. Gets and sets the serialized URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org/foo'); console.log(myURL.href); // Prints https://example.org/foo @@ -224,14 +217,12 @@ will be thrown. Gets the read-only serialization of the URL's origin. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org/foo/bar?baz'); console.log(myURL.origin); // Prints https://example.org ``` ```js -const { URL } = require('url'); const idnURL = new URL('https://你好你好'); console.log(idnURL.origin); // Prints https://xn--6qqa088eba @@ -247,7 +238,6 @@ console.log(idnURL.hostname); Gets and sets the password portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://abc:xyz@example.com'); console.log(myURL.password); // Prints xyz @@ -269,7 +259,6 @@ percent-encode may vary somewhat from what the [`url.parse()`][] and Gets and sets the path portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org/abc/xyz?123'); console.log(myURL.pathname); // Prints /abc/xyz @@ -291,7 +280,6 @@ to percent-encode may vary somewhat from what the [`url.parse()`][] and Gets and sets the port portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org:8888'); console.log(myURL.port); // Prints 8888 @@ -347,7 +335,6 @@ lies outside the range denoted above, it is ignored. Gets and sets the protocol portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org'); console.log(myURL.protocol); // Prints https: @@ -366,7 +353,6 @@ Invalid URL protocol values assigned to the `protocol` property are ignored. Gets and sets the serialized query portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org/abc?123'); console.log(myURL.search); // Prints ?123 @@ -397,7 +383,6 @@ documentation for details. Gets and sets the username portion of the URL. ```js -const { URL } = require('url'); const myURL = new URL('https://abc:xyz@example.com'); console.log(myURL.username); // Prints abc @@ -435,7 +420,6 @@ This method is automatically called when an `URL` object is serialized with [`JSON.stringify()`][]. ```js -const { URL } = require('url'); const myURLs = [ new URL('https://www.example.com'), new URL('https://test.example.org') @@ -447,11 +431,16 @@ console.log(JSON.stringify(myURLs)); ### Class: URLSearchParams The `URLSearchParams` API provides read and write access to the query of a `URL`. The `URLSearchParams` class can also be used standalone with one of the four following constructors. +The `URLSearchParams` class is also available on the global object. The WHATWG `URLSearchParams` interface and the [`querystring`][] module have similar purpose, but the purpose of the [`querystring`][] module is more @@ -459,8 +448,6 @@ general, as it allows the customization of delimiter characters (`&` and `=`). On the other hand, this API is designed purely for URL query strings. ```js -const { URL, URLSearchParams } = require('url'); - const myURL = new URL('https://example.org/?abc=123'); console.log(myURL.searchParams.get('abc')); // Prints 123 @@ -505,7 +492,6 @@ Parse the `string` as a query string, and use it to instantiate a new `URLSearchParams` object. A leading `'?'`, if present, is ignored. ```js -const { URLSearchParams } = require('url'); let params; params = new URLSearchParams('user=abc&query=xyz'); @@ -534,7 +520,6 @@ values are not allowed. Arrays are stringified using [`array.toString()`][], which simply joins all array elements with commas. ```js -const { URLSearchParams } = require('url'); const params = new URLSearchParams({ user: 'abc', query: ['first', 'second'] @@ -562,7 +547,6 @@ themselves be any iterable object. Duplicate keys are allowed. ```js -const { URLSearchParams } = require('url'); let params; // Using an array @@ -631,7 +615,6 @@ Alias for [`urlSearchParams[@@iterator]()`][`urlSearchParams@@iterator()`]. Iterates over each name-value pair in the query and invokes the given function. ```js -const { URL } = require('url'); const myURL = new URL('https://example.org/?a=b&c=d'); myURL.searchParams.forEach((value, name, searchParams) => { console.log(name, value, myURL.searchParams === searchParams); @@ -672,7 +655,6 @@ Returns `true` if there is at least one name-value pair whose name is `name`. Returns an ES6 Iterator over the names of each name-value pair. ```js -const { URLSearchParams } = require('url'); const params = new URLSearchParams('foo=bar&foo=baz'); for (const name of params.keys()) { console.log(name); @@ -693,8 +675,6 @@ set the first such pair's value to `value` and remove all others. If not, append the name-value pair to the query string. ```js -const { URLSearchParams } = require('url'); - const params = new URLSearchParams(); params.append('foo', 'bar'); params.append('foo', 'baz'); @@ -720,7 +700,6 @@ with the same name is preserved. This method can be used, in particular, to increase cache hits. ```js -const { URLSearchParams } = require('url'); const params = new URLSearchParams('query[]=abc&type=search&query[]=123'); params.sort(); console.log(params.toString()); @@ -751,7 +730,6 @@ is the `name`, the second item of the Array is the `value`. Alias for [`urlSearchParams.entries()`][]. ```js -const { URLSearchParams } = require('url'); const params = new URLSearchParams('foo=bar&xyz=baz'); for (const [name, value] of params) { console.log(name, value); @@ -835,7 +813,6 @@ of the output. For example: ```js -const { URL } = require('url'); const myURL = new URL('https://a:b@你好你好?abc#foo'); console.log(myURL.href); @@ -1135,7 +1112,6 @@ using the [Punycode][] algorithm. Note, however, that a hostname *may* contain *both* Punycode encoded and percent-encoded characters. For example: ```js -const { URL } = require('url'); const myURL = new URL('https://%CF%80.com/foo'); console.log(myURL.href); // Prints https://xn--1xa.com/foo diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index f3f3264f353c24..e269d7dc153a4d 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -72,6 +72,7 @@ if (browserGlobals) { setupGlobalTimeouts(); setupGlobalConsole(); + setupGlobalURL(); } // Ensure setURLConstructor() is called before the native @@ -372,6 +373,24 @@ setupInspector(originalConsole, wrappedConsole, Module); } + function setupGlobalURL() { + const { URL, URLSearchParams } = NativeModule.require('internal/url'); + Object.defineProperties(global, { + URL: { + value: URL, + writable: true, + configurable: true, + enumerable: false + }, + URLSearchParams: { + value: URLSearchParams, + writable: true, + configurable: true, + enumerable: false + } + }); + } + function setupInspector(originalConsole, wrappedConsole, Module) { if (!process.config.variables.v8_enable_inspector) { return; diff --git a/test/parallel/test-whatwg-url-global.js b/test/parallel/test-whatwg-url-global.js new file mode 100644 index 00000000000000..b4e85a49ad6343 --- /dev/null +++ b/test/parallel/test-whatwg-url-global.js @@ -0,0 +1,25 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const { URL, URLSearchParams } = require('url'); + +assert.deepStrictEqual( + Object.getOwnPropertyDescriptor(global, 'URL'), + { + value: URL, + writable: true, + configurable: true, + enumerable: false + } +); + +assert.deepStrictEqual( + Object.getOwnPropertyDescriptor(global, 'URLSearchParams'), + { + value: URLSearchParams, + writable: true, + configurable: true, + enumerable: false + } +);