From 531656dc791e91a7e889817665d2d11e9c31ece7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <targos@protonmail.com>
Date: Wed, 8 Feb 2017 10:51:07 +0100
Subject: [PATCH] url: implement URL.prototype.toJSON

Refs: https://github.com/whatwg/url/pull/229
---
 doc/api/url.md                              | 24 ++++++++++++++++++++-
 lib/internal/url.js                         |  9 ++++++++
 test/parallel/test-whatwg-url-properties.js |  2 +-
 test/parallel/test-whatwg-url-tojson.js     | 16 ++++++++++++++
 4 files changed, 49 insertions(+), 2 deletions(-)
 create mode 100644 test/parallel/test-whatwg-url-tojson.js

diff --git a/doc/api/url.md b/doc/api/url.md
index 470357e089c4ae..8d9483cb12d417 100644
--- a/doc/api/url.md
+++ b/doc/api/url.md
@@ -652,12 +652,32 @@ and [`url.format()`][] methods would produce.
 * Returns: {String}
 
 The `toString()` method on the `URL` object returns the serialized URL. The
-value returned is equivalent to that of [`url.href`][].
+value returned is equivalent to that of [`url.href`][] and [`url.toJSON()`][].
 
 Because of the need for standard compliance, this method does not allow users
 to customize the serialization process of the URL. For more flexibility,
 [`require('url').format()`][] method might be of interest.
 
+#### url.toJSON()
+
+* Returns: {String}
+
+The `toJSON()` method on the `URL` object returns the serialized URL. The
+value returned is equivalent to that of [`url.href`][] and
+[`url.toString()`][].
+
+This method is automatically called when an `URL` object is serialized
+with [`JSON.stringify()`][].
+
+```js
+const myURLs = [
+  new URL('https://www.example.com'),
+  new URL('https://test.example.org')
+];
+console.log(JSON.stringify(myURLs));
+  // Prints ["https://www.example.com/","https://test.example.org/"]
+```
+
 ### Class: URLSearchParams
 
 The `URLSearchParams` API provides read and write access to the query of a
@@ -1043,3 +1063,5 @@ console.log(myURL.origin);
 [`urlSearchParams.entries()`]: #url_urlsearchparams_entries
 [`urlSearchParams@@iterator()`]: #url_urlsearchparams_iterator
 [stable sorting algorithm]: https://en.wikipedia.org/wiki/Sorting_algorithm#Stability
+[`JSON.stringify()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
+[`url.toJSON()`]: #url_url_tojson
diff --git a/lib/internal/url.js b/lib/internal/url.js
index 38192da1c0c98a..ad8db0ca374799 100644
--- a/lib/internal/url.js
+++ b/lib/internal/url.js
@@ -523,6 +523,15 @@ Object.defineProperties(URL.prototype, {
       binding.parse(hash, binding.kFragment, null, ctx,
                     onParseHashComplete.bind(this));
     }
+  },
+  toJSON: {
+    writable: true,
+    enumerable: true,
+    configurable: true,
+    // eslint-disable-next-line func-name-matching
+    value: function toJSON() {
+      return this[kFormat]({});
+    }
   }
 });
 
diff --git a/test/parallel/test-whatwg-url-properties.js b/test/parallel/test-whatwg-url-properties.js
index f093791b2de867..b5b3119422e668 100644
--- a/test/parallel/test-whatwg-url-properties.js
+++ b/test/parallel/test-whatwg-url-properties.js
@@ -23,7 +23,7 @@ for (const prop in url) {
 const expected = ['toString',
                   'href', 'origin', 'protocol',
                   'username', 'password', 'host', 'hostname', 'port',
-                  'pathname', 'search', 'searchParams', 'hash'];
+                  'pathname', 'search', 'searchParams', 'hash', 'toJSON'];
 
 assert.deepStrictEqual(props, expected);
 
diff --git a/test/parallel/test-whatwg-url-tojson.js b/test/parallel/test-whatwg-url-tojson.js
new file mode 100644
index 00000000000000..35af93261c79a5
--- /dev/null
+++ b/test/parallel/test-whatwg-url-tojson.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const common = require('../common');
+const URL = require('url').URL;
+const { test, assert_equals } = common.WPT;
+
+/* eslint-disable */
+/* WPT Refs:
+   https://github.com/w3c/web-platform-tests/blob/02585db/url/url-tojson.html
+   License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html
+*/
+test(() => {
+  const a = new URL("https://example.com/")
+  assert_equals(JSON.stringify(a), "\"https://example.com/\"")
+})
+/* eslint-enable */