summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2017-01-17 09:07:18 -0800
committerJames M Snell <jasnell@gmail.com>2017-02-02 12:35:55 -0800
commitc5e9654b5bdb8495debaff6716d8409bc1b737d1 (patch)
tree1eeed8013b651b06dc2a91f5b71586bcc9f43cf3 /lib
parenta334252fc8346ae914285b771d26c974d5b564e5 (diff)
downloadnode-new-c5e9654b5bdb8495debaff6716d8409bc1b737d1.tar.gz
url: extend url.format to support WHATWG URL
Removes the non-standard options on WHATWG URL toString and extends the existing url.format() API to support customizable serialization of the WHATWG URL object. This does not yet include the documentation updates because the documentation for the new WHATWG URL object has not yet landed. Example: ```js const url = require('url'); const URL = url.URL; const myURL = new URL('http://example.org/?a=b#c'); const str = url.format(myURL, {fragment: false, search: false}); console.log(str); // Prints: http://example.org/ ``` PR-URL: https://github.com/nodejs/node/pull/10857 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Timothy Gu <timothygu99@gmail.com> Reviewed-By: Brian White <mscdex@mscdex.net>
Diffstat (limited to 'lib')
-rw-r--r--lib/internal/url.js60
-rw-r--r--lib/url.js17
2 files changed, 40 insertions, 37 deletions
diff --git a/lib/internal/url.js b/lib/internal/url.js
index da4eb07a81..dc3c8a7cbd 100644
--- a/lib/internal/url.js
+++ b/lib/internal/url.js
@@ -1,13 +1,5 @@
'use strict';
-function getPunycode() {
- try {
- return process.binding('icu');
- } catch (err) {
- return require('punycode');
- }
-}
-const punycode = getPunycode();
const util = require('util');
const binding = process.binding('url');
const context = Symbol('context');
@@ -20,6 +12,7 @@ const kScheme = Symbol('scheme');
const kHost = Symbol('host');
const kPort = Symbol('port');
const kDomain = Symbol('domain');
+const kFormat = Symbol('format');
// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object
const IteratorPrototype = Object.getPrototypeOf(
@@ -263,18 +256,19 @@ class URL {
}
Object.defineProperties(URL.prototype, {
- toString: {
- // https://heycam.github.io/webidl/#es-stringifier
- writable: true,
- enumerable: true,
- configurable: true,
+ [kFormat]: {
+ enumerable: false,
+ configurable: false,
// eslint-disable-next-line func-name-matching
- value: function toString(options) {
- options = options || {};
- const fragment =
- options.fragment !== undefined ?
- !!options.fragment : true;
- const unicode = !!options.unicode;
+ value: function format(options) {
+ if (options && typeof options !== 'object')
+ throw new TypeError('options must be an object');
+ options = Object.assign({
+ fragment: true,
+ unicode: false,
+ search: true,
+ auth: true
+ }, options);
const ctx = this[context];
var ret;
if (this.protocol)
@@ -284,28 +278,23 @@ Object.defineProperties(URL.prototype, {
const has_username = typeof ctx.username === 'string';
const has_password = typeof ctx.password === 'string' &&
ctx.password !== '';
- if (has_username || has_password) {
+ if (options.auth && (has_username || has_password)) {
if (has_username)
ret += ctx.username;
if (has_password)
ret += `:${ctx.password}`;
ret += '@';
}
- if (unicode) {
- ret += punycode.toUnicode(this.hostname);
- if (this.port !== undefined)
- ret += `:${this.port}`;
- } else {
- ret += this.host;
- }
+ ret += options.unicode ?
+ domainToUnicode(this.host) : this.host;
} else if (ctx.scheme === 'file:') {
ret += '//';
}
if (this.pathname)
ret += this.pathname;
- if (typeof ctx.query === 'string')
+ if (options.search && typeof ctx.query === 'string')
ret += `?${ctx.query}`;
- if (fragment & typeof ctx.fragment === 'string')
+ if (options.fragment && typeof ctx.fragment === 'string')
ret += `#${ctx.fragment}`;
return ret;
}
@@ -314,11 +303,21 @@ Object.defineProperties(URL.prototype, {
configurable: true,
value: 'URL'
},
+ toString: {
+ // https://heycam.github.io/webidl/#es-stringifier
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ // eslint-disable-next-line func-name-matching
+ value: function toString() {
+ return this[kFormat]({});
+ }
+ },
href: {
enumerable: true,
configurable: true,
get() {
- return this.toString();
+ return this[kFormat]({});
},
set(input) {
parse(this, input);
@@ -1120,3 +1119,4 @@ exports.domainToASCII = domainToASCII;
exports.domainToUnicode = domainToUnicode;
exports.encodeAuth = encodeAuth;
exports.urlToOptions = urlToOptions;
+exports.formatSymbol = kFormat;
diff --git a/lib/url.js b/lib/url.js
index e4ced8e860..2b7dd6e532 100644
--- a/lib/url.js
+++ b/lib/url.js
@@ -538,19 +538,22 @@ function autoEscapeStr(rest) {
}
// format a parsed object into a url string
-function urlFormat(obj) {
+function urlFormat(obj, options) {
// ensure it's an object, and not a string url.
// If it's an obj, this is a no-op.
// this way, you can call url_format() on strings
// to clean up potentially wonky urls.
- if (typeof obj === 'string') obj = urlParse(obj);
-
- else if (typeof obj !== 'object' || obj === null)
+ if (typeof obj === 'string') {
+ obj = urlParse(obj);
+ } else if (typeof obj !== 'object' || obj === null) {
throw new TypeError('Parameter "urlObj" must be an object, not ' +
obj === null ? 'null' : typeof obj);
-
- else if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
-
+ } else if (!(obj instanceof Url)) {
+ var format = obj[internalUrl.formatSymbol];
+ return format ?
+ format.call(obj, options) :
+ Url.prototype.format.call(obj);
+ }
return obj.format();
}