whatwg-url 6.5.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  whatwg-url is a full implementation of the WHATWG [URL Standard](https://url.spec.whatwg.org/). It can be used standalone, but it also exposes a lot of the internal algorithms that are useful for integrating a URL parser into a project like [jsdom](https://github.com/tmpvar/jsdom).
4
4
 
5
- ## Current status
5
+ ## Specification conformance
6
6
 
7
7
  whatwg-url is currently up to date with the URL spec up to commit [6ef17eb](https://github.com/whatwg/url/commit/6ef17ebe1220a7e7c0cfff0785017502ee18808b).
8
8
 
9
+ For `file:` URLs, whose [origin is left unspecified](https://url.spec.whatwg.org/#concept-url-origin), whatwg-url chooses to use a new opaque origin (which serializes to `"null"`).
10
+
9
11
  ## API
10
12
 
11
13
  ### The `URL` and `URLSearchParams` classes
@@ -66,3 +68,24 @@ The URL record type has the following API:
66
68
  These properties should be treated with care, as in general changing them will cause the URL record to be in an inconsistent state until the appropriate invocation of `basicURLParse` is used to fix it up. You can see examples of this in the URL Standard, where there are many step sequences like "4. Set context object’s url’s fragment to the empty string. 5. Basic URL parse _input_ with context object’s url as _url_ and fragment state as _state override_." In between those two steps, a URL record is in an unusable state.
67
69
 
68
70
  The return value of "failure" in the spec is represented by `null`. That is, functions like `parseURL` and `basicURLParse` can return _either_ a URL record _or_ `null`.
71
+
72
+ ## Development instructions
73
+
74
+ First, install [Node.js](https://nodejs.org/). Then, fetch the dependencies of whatwg-url, by running from this directory:
75
+
76
+ npm install
77
+
78
+ To run tests:
79
+
80
+ npm test
81
+
82
+ To generate a coverage report:
83
+
84
+ npm run coverage
85
+
86
+ To build and run the live viewer:
87
+
88
+ npm run build
89
+ npm run build-live-viewer
90
+
91
+ Serve the contents of the `live-viewer` directory using any web server.
package/lib/URL-impl.js CHANGED
@@ -12,13 +12,13 @@ exports.implementation = class URLImpl {
12
12
  if (base !== undefined) {
13
13
  parsedBase = usm.basicURLParse(base);
14
14
  if (parsedBase === null) {
15
- throw new TypeError("Invalid base URL");
15
+ throw new TypeError(`Invalid base URL: ${base}`);
16
16
  }
17
17
  }
18
18
 
19
19
  const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase });
20
20
  if (parsedURL === null) {
21
- throw new TypeError("Invalid URL");
21
+ throw new TypeError(`Invalid URL: ${url}`);
22
22
  }
23
23
 
24
24
  const query = parsedURL.query !== null ? parsedURL.query : "";
@@ -38,7 +38,7 @@ exports.implementation = class URLImpl {
38
38
  set href(v) {
39
39
  const parsedURL = usm.basicURLParse(v);
40
40
  if (parsedURL === null) {
41
- throw new TypeError("Invalid URL");
41
+ throw new TypeError(`Invalid URL: ${v}`);
42
42
  }
43
43
 
44
44
  this._url = parsedURL;
package/lib/URL.js CHANGED
@@ -5,57 +5,44 @@ const utils = require("./utils.js");
5
5
 
6
6
  const impl = utils.implSymbol;
7
7
 
8
- function URL(url) {
9
- if (!new.target) {
10
- throw new TypeError(
11
- "Failed to construct 'URL'. Please use the 'new' operator; this constructor " + "cannot be called as a function."
12
- );
13
- }
14
- if (arguments.length < 1) {
15
- throw new TypeError(
16
- "Failed to construct 'URL': 1 " + "argument required, but only " + arguments.length + " present."
17
- );
18
- }
19
-
20
- const args = [];
21
- for (let i = 0; i < arguments.length && i < 2; ++i) {
22
- args[i] = arguments[i];
23
- }
24
-
25
- args[0] = conversions["USVString"](args[0], { context: "Failed to construct 'URL': parameter 1" });
26
-
27
- if (args[1] !== undefined) {
28
- args[1] = conversions["USVString"](args[1], { context: "Failed to construct 'URL': parameter 2" });
8
+ class URL {
9
+ constructor(url) {
10
+ if (arguments.length < 1) {
11
+ throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present.");
12
+ }
13
+ const args = [];
14
+ {
15
+ let curArg = arguments[0];
16
+ curArg = conversions["USVString"](curArg, { context: "Failed to construct 'URL': parameter 1" });
17
+ args.push(curArg);
18
+ }
19
+ {
20
+ let curArg = arguments[1];
21
+ if (curArg !== undefined) {
22
+ curArg = conversions["USVString"](curArg, { context: "Failed to construct 'URL': parameter 2" });
23
+ }
24
+ args.push(curArg);
25
+ }
26
+ return iface.setup(Object.create(new.target.prototype), args);
29
27
  }
30
28
 
31
- iface.setup(this, args);
32
- }
33
-
34
- Object.defineProperty(URL, "prototype", {
35
- value: URL.prototype,
36
- writable: false,
37
- enumerable: false,
38
- configurable: false
39
- });
29
+ toJSON() {
30
+ if (!this || !module.exports.is(this)) {
31
+ throw new TypeError("Illegal invocation");
32
+ }
40
33
 
41
- URL.prototype.toJSON = function toJSON() {
42
- if (!this || !module.exports.is(this)) {
43
- throw new TypeError("Illegal invocation");
34
+ return this[impl].toJSON();
44
35
  }
45
36
 
46
- return this[impl].toJSON();
47
- };
48
-
49
- Object.defineProperty(URL.prototype, "href", {
50
- get() {
37
+ get href() {
51
38
  if (!this || !module.exports.is(this)) {
52
39
  throw new TypeError("Illegal invocation");
53
40
  }
54
41
 
55
42
  return this[impl]["href"];
56
- },
43
+ }
57
44
 
58
- set(V) {
45
+ set href(V) {
59
46
  if (!this || !module.exports.is(this)) {
60
47
  throw new TypeError("Illegal invocation");
61
48
  }
@@ -63,42 +50,32 @@ Object.defineProperty(URL.prototype, "href", {
63
50
  V = conversions["USVString"](V, { context: "Failed to set the 'href' property on 'URL': The provided value" });
64
51
 
65
52
  this[impl]["href"] = V;
66
- },
67
-
68
- enumerable: true,
69
- configurable: true
70
- });
53
+ }
71
54
 
72
- URL.prototype.toString = function toString() {
73
- if (!this || !module.exports.is(this)) {
74
- throw new TypeError("Illegal invocation");
55
+ toString() {
56
+ if (!this || !module.exports.is(this)) {
57
+ throw new TypeError("Illegal invocation");
58
+ }
59
+ return this[impl]["href"];
75
60
  }
76
- return this[impl]["href"];
77
- };
78
61
 
79
- Object.defineProperty(URL.prototype, "origin", {
80
- get() {
62
+ get origin() {
81
63
  if (!this || !module.exports.is(this)) {
82
64
  throw new TypeError("Illegal invocation");
83
65
  }
84
66
 
85
67
  return this[impl]["origin"];
86
- },
87
-
88
- enumerable: true,
89
- configurable: true
90
- });
68
+ }
91
69
 
92
- Object.defineProperty(URL.prototype, "protocol", {
93
- get() {
70
+ get protocol() {
94
71
  if (!this || !module.exports.is(this)) {
95
72
  throw new TypeError("Illegal invocation");
96
73
  }
97
74
 
98
75
  return this[impl]["protocol"];
99
- },
76
+ }
100
77
 
101
- set(V) {
78
+ set protocol(V) {
102
79
  if (!this || !module.exports.is(this)) {
103
80
  throw new TypeError("Illegal invocation");
104
81
  }
@@ -106,22 +83,17 @@ Object.defineProperty(URL.prototype, "protocol", {
106
83
  V = conversions["USVString"](V, { context: "Failed to set the 'protocol' property on 'URL': The provided value" });
107
84
 
108
85
  this[impl]["protocol"] = V;
109
- },
110
-
111
- enumerable: true,
112
- configurable: true
113
- });
86
+ }
114
87
 
115
- Object.defineProperty(URL.prototype, "username", {
116
- get() {
88
+ get username() {
117
89
  if (!this || !module.exports.is(this)) {
118
90
  throw new TypeError("Illegal invocation");
119
91
  }
120
92
 
121
93
  return this[impl]["username"];
122
- },
94
+ }
123
95
 
124
- set(V) {
96
+ set username(V) {
125
97
  if (!this || !module.exports.is(this)) {
126
98
  throw new TypeError("Illegal invocation");
127
99
  }
@@ -129,22 +101,17 @@ Object.defineProperty(URL.prototype, "username", {
129
101
  V = conversions["USVString"](V, { context: "Failed to set the 'username' property on 'URL': The provided value" });
130
102
 
131
103
  this[impl]["username"] = V;
132
- },
133
-
134
- enumerable: true,
135
- configurable: true
136
- });
104
+ }
137
105
 
138
- Object.defineProperty(URL.prototype, "password", {
139
- get() {
106
+ get password() {
140
107
  if (!this || !module.exports.is(this)) {
141
108
  throw new TypeError("Illegal invocation");
142
109
  }
143
110
 
144
111
  return this[impl]["password"];
145
- },
112
+ }
146
113
 
147
- set(V) {
114
+ set password(V) {
148
115
  if (!this || !module.exports.is(this)) {
149
116
  throw new TypeError("Illegal invocation");
150
117
  }
@@ -152,22 +119,17 @@ Object.defineProperty(URL.prototype, "password", {
152
119
  V = conversions["USVString"](V, { context: "Failed to set the 'password' property on 'URL': The provided value" });
153
120
 
154
121
  this[impl]["password"] = V;
155
- },
156
-
157
- enumerable: true,
158
- configurable: true
159
- });
122
+ }
160
123
 
161
- Object.defineProperty(URL.prototype, "host", {
162
- get() {
124
+ get host() {
163
125
  if (!this || !module.exports.is(this)) {
164
126
  throw new TypeError("Illegal invocation");
165
127
  }
166
128
 
167
129
  return this[impl]["host"];
168
- },
130
+ }
169
131
 
170
- set(V) {
132
+ set host(V) {
171
133
  if (!this || !module.exports.is(this)) {
172
134
  throw new TypeError("Illegal invocation");
173
135
  }
@@ -175,22 +137,17 @@ Object.defineProperty(URL.prototype, "host", {
175
137
  V = conversions["USVString"](V, { context: "Failed to set the 'host' property on 'URL': The provided value" });
176
138
 
177
139
  this[impl]["host"] = V;
178
- },
179
-
180
- enumerable: true,
181
- configurable: true
182
- });
140
+ }
183
141
 
184
- Object.defineProperty(URL.prototype, "hostname", {
185
- get() {
142
+ get hostname() {
186
143
  if (!this || !module.exports.is(this)) {
187
144
  throw new TypeError("Illegal invocation");
188
145
  }
189
146
 
190
147
  return this[impl]["hostname"];
191
- },
148
+ }
192
149
 
193
- set(V) {
150
+ set hostname(V) {
194
151
  if (!this || !module.exports.is(this)) {
195
152
  throw new TypeError("Illegal invocation");
196
153
  }
@@ -198,22 +155,17 @@ Object.defineProperty(URL.prototype, "hostname", {
198
155
  V = conversions["USVString"](V, { context: "Failed to set the 'hostname' property on 'URL': The provided value" });
199
156
 
200
157
  this[impl]["hostname"] = V;
201
- },
202
-
203
- enumerable: true,
204
- configurable: true
205
- });
158
+ }
206
159
 
207
- Object.defineProperty(URL.prototype, "port", {
208
- get() {
160
+ get port() {
209
161
  if (!this || !module.exports.is(this)) {
210
162
  throw new TypeError("Illegal invocation");
211
163
  }
212
164
 
213
165
  return this[impl]["port"];
214
- },
166
+ }
215
167
 
216
- set(V) {
168
+ set port(V) {
217
169
  if (!this || !module.exports.is(this)) {
218
170
  throw new TypeError("Illegal invocation");
219
171
  }
@@ -221,22 +173,17 @@ Object.defineProperty(URL.prototype, "port", {
221
173
  V = conversions["USVString"](V, { context: "Failed to set the 'port' property on 'URL': The provided value" });
222
174
 
223
175
  this[impl]["port"] = V;
224
- },
225
-
226
- enumerable: true,
227
- configurable: true
228
- });
176
+ }
229
177
 
230
- Object.defineProperty(URL.prototype, "pathname", {
231
- get() {
178
+ get pathname() {
232
179
  if (!this || !module.exports.is(this)) {
233
180
  throw new TypeError("Illegal invocation");
234
181
  }
235
182
 
236
183
  return this[impl]["pathname"];
237
- },
184
+ }
238
185
 
239
- set(V) {
186
+ set pathname(V) {
240
187
  if (!this || !module.exports.is(this)) {
241
188
  throw new TypeError("Illegal invocation");
242
189
  }
@@ -244,22 +191,17 @@ Object.defineProperty(URL.prototype, "pathname", {
244
191
  V = conversions["USVString"](V, { context: "Failed to set the 'pathname' property on 'URL': The provided value" });
245
192
 
246
193
  this[impl]["pathname"] = V;
247
- },
248
-
249
- enumerable: true,
250
- configurable: true
251
- });
194
+ }
252
195
 
253
- Object.defineProperty(URL.prototype, "search", {
254
- get() {
196
+ get search() {
255
197
  if (!this || !module.exports.is(this)) {
256
198
  throw new TypeError("Illegal invocation");
257
199
  }
258
200
 
259
201
  return this[impl]["search"];
260
- },
202
+ }
261
203
 
262
- set(V) {
204
+ set search(V) {
263
205
  if (!this || !module.exports.is(this)) {
264
206
  throw new TypeError("Illegal invocation");
265
207
  }
@@ -267,14 +209,9 @@ Object.defineProperty(URL.prototype, "search", {
267
209
  V = conversions["USVString"](V, { context: "Failed to set the 'search' property on 'URL': The provided value" });
268
210
 
269
211
  this[impl]["search"] = V;
270
- },
271
-
272
- enumerable: true,
273
- configurable: true
274
- });
212
+ }
275
213
 
276
- Object.defineProperty(URL.prototype, "searchParams", {
277
- get() {
214
+ get searchParams() {
278
215
  if (!this || !module.exports.is(this)) {
279
216
  throw new TypeError("Illegal invocation");
280
217
  }
@@ -282,22 +219,17 @@ Object.defineProperty(URL.prototype, "searchParams", {
282
219
  return utils.getSameObject(this, "searchParams", () => {
283
220
  return utils.tryWrapperForImpl(this[impl]["searchParams"]);
284
221
  });
285
- },
286
-
287
- enumerable: true,
288
- configurable: true
289
- });
222
+ }
290
223
 
291
- Object.defineProperty(URL.prototype, "hash", {
292
- get() {
224
+ get hash() {
293
225
  if (!this || !module.exports.is(this)) {
294
226
  throw new TypeError("Illegal invocation");
295
227
  }
296
228
 
297
229
  return this[impl]["hash"];
298
- },
230
+ }
299
231
 
300
- set(V) {
232
+ set hash(V) {
301
233
  if (!this || !module.exports.is(this)) {
302
234
  throw new TypeError("Illegal invocation");
303
235
  }
@@ -305,28 +237,37 @@ Object.defineProperty(URL.prototype, "hash", {
305
237
  V = conversions["USVString"](V, { context: "Failed to set the 'hash' property on 'URL': The provided value" });
306
238
 
307
239
  this[impl]["hash"] = V;
308
- },
309
-
310
- enumerable: true,
311
- configurable: true
312
- });
313
-
314
- Object.defineProperty(URL.prototype, Symbol.toStringTag, {
315
- value: "URL",
316
- writable: false,
317
- enumerable: false,
318
- configurable: true
240
+ }
241
+ }
242
+ Object.defineProperties(URL.prototype, {
243
+ toJSON: { enumerable: true },
244
+ href: { enumerable: true },
245
+ toString: { enumerable: true },
246
+ origin: { enumerable: true },
247
+ protocol: { enumerable: true },
248
+ username: { enumerable: true },
249
+ password: { enumerable: true },
250
+ host: { enumerable: true },
251
+ hostname: { enumerable: true },
252
+ port: { enumerable: true },
253
+ pathname: { enumerable: true },
254
+ search: { enumerable: true },
255
+ searchParams: { enumerable: true },
256
+ hash: { enumerable: true },
257
+ [Symbol.toStringTag]: { value: "URL", configurable: true }
319
258
  });
320
-
321
259
  const iface = {
322
- mixedInto: [],
260
+ // When an interface-module that implements this interface as a mixin is loaded, it will append its own `.is()`
261
+ // method into this array. It allows objects that directly implements *those* interfaces to be recognized as
262
+ // implementing this mixin interface.
263
+ _mixedIntoPredicates: [],
323
264
  is(obj) {
324
265
  if (obj) {
325
- if (obj[impl] instanceof Impl.implementation) {
266
+ if (utils.hasOwn(obj, impl) && obj[impl] instanceof Impl.implementation) {
326
267
  return true;
327
268
  }
328
- for (let i = 0; i < module.exports.mixedInto.length; ++i) {
329
- if (obj instanceof module.exports.mixedInto[i]) {
269
+ for (const isMixedInto of module.exports._mixedIntoPredicates) {
270
+ if (isMixedInto(obj)) {
330
271
  return true;
331
272
  }
332
273
  }
@@ -340,8 +281,8 @@ const iface = {
340
281
  }
341
282
 
342
283
  const wrapper = utils.wrapperForImpl(obj);
343
- for (let i = 0; i < module.exports.mixedInto.length; ++i) {
344
- if (wrapper instanceof module.exports.mixedInto[i]) {
284
+ for (const isMixedInto of module.exports._mixedIntoPredicates) {
285
+ if (isMixedInto(wrapper)) {
345
286
  return true;
346
287
  }
347
288
  }
@@ -374,8 +315,6 @@ const iface = {
374
315
  this._internalSetup(obj);
375
316
  Object.defineProperty(obj, impl, {
376
317
  value: new Impl.implementation(constructorArgs, privateData),
377
- writable: false,
378
- enumerable: false,
379
318
  configurable: true
380
319
  });
381
320
 
@@ -393,4 +332,4 @@ const iface = {
393
332
  }; // iface
394
333
  module.exports = iface;
395
334
 
396
- const Impl = require(".//URL-impl.js");
335
+ const Impl = require("./URL-impl.js");
@@ -39,336 +39,323 @@ const IteratorPrototype = Object.create(utils.IteratorPrototype, {
39
39
  configurable: true
40
40
  },
41
41
  [Symbol.toStringTag]: {
42
- value: "URLSearchParamsIterator",
43
- writable: false,
44
- enumerable: false,
42
+ value: "URLSearchParams Iterator",
45
43
  configurable: true
46
44
  }
47
45
  });
48
-
49
- function URLSearchParams() {
50
- const args = [];
51
- for (let i = 0; i < arguments.length && i < 1; ++i) {
52
- args[i] = arguments[i];
53
- }
54
-
55
- if (args[0] !== undefined) {
56
- if (utils.isObject(args[0])) {
57
- if (args[0][Symbol.iterator] !== undefined) {
58
- if (!utils.isObject(args[0])) {
59
- throw new TypeError(
60
- "Failed to construct 'URLSearchParams': parameter 1" + " sequence" + " is not an iterable object."
61
- );
62
- } else {
63
- const V = [];
64
- const tmp = args[0];
65
- for (let nextItem of tmp) {
66
- if (!utils.isObject(nextItem)) {
46
+ class URLSearchParams {
47
+ constructor() {
48
+ const args = [];
49
+ {
50
+ let curArg = arguments[0];
51
+ if (curArg !== undefined) {
52
+ if (utils.isObject(curArg)) {
53
+ if (curArg[Symbol.iterator] !== undefined) {
54
+ if (!utils.isObject(curArg)) {
67
55
  throw new TypeError(
68
- "Failed to construct 'URLSearchParams': parameter 1" +
69
- " sequence" +
70
- "'s element" +
71
- " is not an iterable object."
56
+ "Failed to construct 'URLSearchParams': parameter 1" + " sequence" + " is not an iterable object."
72
57
  );
73
58
  } else {
74
59
  const V = [];
75
- const tmp = nextItem;
60
+ const tmp = curArg;
76
61
  for (let nextItem of tmp) {
77
- nextItem = conversions["USVString"](nextItem, {
78
- context:
79
- "Failed to construct 'URLSearchParams': parameter 1" + " sequence" + "'s element" + "'s element"
80
- });
62
+ if (!utils.isObject(nextItem)) {
63
+ throw new TypeError(
64
+ "Failed to construct 'URLSearchParams': parameter 1" +
65
+ " sequence" +
66
+ "'s element" +
67
+ " is not an iterable object."
68
+ );
69
+ } else {
70
+ const V = [];
71
+ const tmp = nextItem;
72
+ for (let nextItem of tmp) {
73
+ nextItem = conversions["USVString"](nextItem, {
74
+ context:
75
+ "Failed to construct 'URLSearchParams': parameter 1" + " sequence" + "'s element" + "'s element"
76
+ });
77
+
78
+ V.push(nextItem);
79
+ }
80
+ nextItem = V;
81
+ }
81
82
 
82
83
  V.push(nextItem);
83
84
  }
84
- nextItem = V;
85
+ curArg = V;
85
86
  }
86
-
87
- V.push(nextItem);
88
- }
89
- args[0] = V;
90
- }
91
- } else {
92
- if (!utils.isObject(args[0])) {
93
- throw new TypeError("Failed to construct 'URLSearchParams': parameter 1" + " record" + " is not an object.");
94
- } else {
95
- const result = Object.create(null);
96
- for (const key of Reflect.ownKeys(args[0])) {
97
- const desc = Object.getOwnPropertyDescriptor(args[0], key);
98
- if (desc && desc.enumerable) {
99
- let typedKey = key;
100
- let typedValue = args[0][key];
101
-
102
- typedKey = conversions["USVString"](typedKey, {
103
- context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s key"
104
- });
105
-
106
- typedValue = conversions["USVString"](typedValue, {
107
- context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s value"
108
- });
109
-
110
- result[typedKey] = typedValue;
87
+ } else {
88
+ if (!utils.isObject(curArg)) {
89
+ throw new TypeError(
90
+ "Failed to construct 'URLSearchParams': parameter 1" + " record" + " is not an object."
91
+ );
92
+ } else {
93
+ const result = Object.create(null);
94
+ for (const key of Reflect.ownKeys(curArg)) {
95
+ const desc = Object.getOwnPropertyDescriptor(curArg, key);
96
+ if (desc && desc.enumerable) {
97
+ let typedKey = key;
98
+ let typedValue = curArg[key];
99
+
100
+ typedKey = conversions["USVString"](typedKey, {
101
+ context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s key"
102
+ });
103
+
104
+ typedValue = conversions["USVString"](typedValue, {
105
+ context: "Failed to construct 'URLSearchParams': parameter 1" + " record" + "'s value"
106
+ });
107
+
108
+ result[typedKey] = typedValue;
109
+ }
110
+ }
111
+ curArg = result;
111
112
  }
112
113
  }
113
- args[0] = result;
114
+ } else {
115
+ curArg = conversions["USVString"](curArg, { context: "Failed to construct 'URLSearchParams': parameter 1" });
114
116
  }
117
+ } else {
118
+ curArg = "";
115
119
  }
116
- } else {
117
- args[0] = conversions["USVString"](args[0], { context: "Failed to construct 'URLSearchParams': parameter 1" });
120
+ args.push(curArg);
118
121
  }
119
- } else {
120
- args[0] = "";
122
+ return iface.setup(Object.create(new.target.prototype), args);
121
123
  }
122
124
 
123
- iface.setup(this, args);
124
- }
125
-
126
- Object.defineProperty(URLSearchParams, "prototype", {
127
- value: URLSearchParams.prototype,
128
- writable: false,
129
- enumerable: false,
130
- configurable: false
131
- });
132
-
133
- Object.defineProperty(URLSearchParams.prototype, Symbol.iterator, {
134
- writable: true,
135
- enumerable: false,
136
- configurable: true,
137
- value: function entries() {
125
+ append(name, value) {
138
126
  if (!this || !module.exports.is(this)) {
139
127
  throw new TypeError("Illegal invocation");
140
128
  }
141
- return module.exports.createDefaultIterator(this, "key+value");
142
- }
143
- });
144
- URLSearchParams.prototype.forEach = function forEach(callback) {
145
- if (!this || !module.exports.is(this)) {
146
- throw new TypeError("Illegal invocation");
147
- }
148
- if (arguments.length < 1) {
149
- throw new TypeError(
150
- "Failed to execute 'forEach' on 'URLSearchParams': 1 argument required, " + "but only 0 present."
151
- );
152
- }
153
- if (typeof callback !== "function") {
154
- throw new TypeError(
155
- "Failed to execute 'forEach' on 'URLSearchParams': The callback provided " + "as parameter 1 is not a function."
156
- );
157
- }
158
- const thisArg = arguments[1];
159
- let pairs = Array.from(this[impl]);
160
- let i = 0;
161
- while (i < pairs.length) {
162
- const [key, value] = pairs[i].map(utils.tryWrapperForImpl);
163
- callback.call(thisArg, value, key, this);
164
- pairs = Array.from(this[impl]);
165
- i++;
166
- }
167
- };
168
- URLSearchParams.prototype.append = function append(name, value) {
169
- if (!this || !module.exports.is(this)) {
170
- throw new TypeError("Illegal invocation");
171
- }
172
129
 
173
- if (arguments.length < 2) {
174
- throw new TypeError(
175
- "Failed to execute 'append' on 'URLSearchParams': 2 " +
176
- "arguments required, but only " +
177
- arguments.length +
178
- " present."
179
- );
180
- }
181
-
182
- const args = [];
183
- for (let i = 0; i < arguments.length && i < 2; ++i) {
184
- args[i] = arguments[i];
185
- }
186
-
187
- args[0] = conversions["USVString"](args[0], {
188
- context: "Failed to execute 'append' on 'URLSearchParams': parameter 1"
189
- });
190
-
191
- args[1] = conversions["USVString"](args[1], {
192
- context: "Failed to execute 'append' on 'URLSearchParams': parameter 2"
193
- });
194
-
195
- return this[impl].append(...args);
196
- };
197
-
198
- URLSearchParams.prototype.delete = function _(name) {
199
- if (!this || !module.exports.is(this)) {
200
- throw new TypeError("Illegal invocation");
201
- }
202
-
203
- if (arguments.length < 1) {
204
- throw new TypeError(
205
- "Failed to execute 'delete' on 'URLSearchParams': 1 " +
206
- "argument required, but only " +
207
- arguments.length +
208
- " present."
209
- );
210
- }
211
-
212
- const args = [];
213
- for (let i = 0; i < arguments.length && i < 1; ++i) {
214
- args[i] = arguments[i];
215
- }
216
-
217
- args[0] = conversions["USVString"](args[0], {
218
- context: "Failed to execute 'delete' on 'URLSearchParams': parameter 1"
219
- });
220
-
221
- return this[impl].delete(...args);
222
- };
223
-
224
- URLSearchParams.prototype.get = function get(name) {
225
- if (!this || !module.exports.is(this)) {
226
- throw new TypeError("Illegal invocation");
130
+ if (arguments.length < 2) {
131
+ throw new TypeError(
132
+ "Failed to execute 'append' on 'URLSearchParams': 2 arguments required, but only " +
133
+ arguments.length +
134
+ " present."
135
+ );
136
+ }
137
+ const args = [];
138
+ {
139
+ let curArg = arguments[0];
140
+ curArg = conversions["USVString"](curArg, {
141
+ context: "Failed to execute 'append' on 'URLSearchParams': parameter 1"
142
+ });
143
+ args.push(curArg);
144
+ }
145
+ {
146
+ let curArg = arguments[1];
147
+ curArg = conversions["USVString"](curArg, {
148
+ context: "Failed to execute 'append' on 'URLSearchParams': parameter 2"
149
+ });
150
+ args.push(curArg);
151
+ }
152
+ return this[impl].append(...args);
227
153
  }
228
154
 
229
- if (arguments.length < 1) {
230
- throw new TypeError(
231
- "Failed to execute 'get' on 'URLSearchParams': 1 " +
232
- "argument required, but only " +
233
- arguments.length +
234
- " present."
235
- );
236
- }
155
+ delete(name) {
156
+ if (!this || !module.exports.is(this)) {
157
+ throw new TypeError("Illegal invocation");
158
+ }
237
159
 
238
- const args = [];
239
- for (let i = 0; i < arguments.length && i < 1; ++i) {
240
- args[i] = arguments[i];
160
+ if (arguments.length < 1) {
161
+ throw new TypeError(
162
+ "Failed to execute 'delete' on 'URLSearchParams': 1 argument required, but only " +
163
+ arguments.length +
164
+ " present."
165
+ );
166
+ }
167
+ const args = [];
168
+ {
169
+ let curArg = arguments[0];
170
+ curArg = conversions["USVString"](curArg, {
171
+ context: "Failed to execute 'delete' on 'URLSearchParams': parameter 1"
172
+ });
173
+ args.push(curArg);
174
+ }
175
+ return this[impl].delete(...args);
241
176
  }
242
177
 
243
- args[0] = conversions["USVString"](args[0], { context: "Failed to execute 'get' on 'URLSearchParams': parameter 1" });
244
-
245
- return this[impl].get(...args);
246
- };
178
+ get(name) {
179
+ if (!this || !module.exports.is(this)) {
180
+ throw new TypeError("Illegal invocation");
181
+ }
247
182
 
248
- URLSearchParams.prototype.getAll = function getAll(name) {
249
- if (!this || !module.exports.is(this)) {
250
- throw new TypeError("Illegal invocation");
183
+ if (arguments.length < 1) {
184
+ throw new TypeError(
185
+ "Failed to execute 'get' on 'URLSearchParams': 1 argument required, but only " + arguments.length + " present."
186
+ );
187
+ }
188
+ const args = [];
189
+ {
190
+ let curArg = arguments[0];
191
+ curArg = conversions["USVString"](curArg, {
192
+ context: "Failed to execute 'get' on 'URLSearchParams': parameter 1"
193
+ });
194
+ args.push(curArg);
195
+ }
196
+ return this[impl].get(...args);
251
197
  }
252
198
 
253
- if (arguments.length < 1) {
254
- throw new TypeError(
255
- "Failed to execute 'getAll' on 'URLSearchParams': 1 " +
256
- "argument required, but only " +
257
- arguments.length +
258
- " present."
259
- );
260
- }
199
+ getAll(name) {
200
+ if (!this || !module.exports.is(this)) {
201
+ throw new TypeError("Illegal invocation");
202
+ }
261
203
 
262
- const args = [];
263
- for (let i = 0; i < arguments.length && i < 1; ++i) {
264
- args[i] = arguments[i];
204
+ if (arguments.length < 1) {
205
+ throw new TypeError(
206
+ "Failed to execute 'getAll' on 'URLSearchParams': 1 argument required, but only " +
207
+ arguments.length +
208
+ " present."
209
+ );
210
+ }
211
+ const args = [];
212
+ {
213
+ let curArg = arguments[0];
214
+ curArg = conversions["USVString"](curArg, {
215
+ context: "Failed to execute 'getAll' on 'URLSearchParams': parameter 1"
216
+ });
217
+ args.push(curArg);
218
+ }
219
+ return utils.tryWrapperForImpl(this[impl].getAll(...args));
265
220
  }
266
221
 
267
- args[0] = conversions["USVString"](args[0], {
268
- context: "Failed to execute 'getAll' on 'URLSearchParams': parameter 1"
269
- });
270
-
271
- return utils.tryWrapperForImpl(this[impl].getAll(...args));
272
- };
222
+ has(name) {
223
+ if (!this || !module.exports.is(this)) {
224
+ throw new TypeError("Illegal invocation");
225
+ }
273
226
 
274
- URLSearchParams.prototype.has = function has(name) {
275
- if (!this || !module.exports.is(this)) {
276
- throw new TypeError("Illegal invocation");
227
+ if (arguments.length < 1) {
228
+ throw new TypeError(
229
+ "Failed to execute 'has' on 'URLSearchParams': 1 argument required, but only " + arguments.length + " present."
230
+ );
231
+ }
232
+ const args = [];
233
+ {
234
+ let curArg = arguments[0];
235
+ curArg = conversions["USVString"](curArg, {
236
+ context: "Failed to execute 'has' on 'URLSearchParams': parameter 1"
237
+ });
238
+ args.push(curArg);
239
+ }
240
+ return this[impl].has(...args);
277
241
  }
278
242
 
279
- if (arguments.length < 1) {
280
- throw new TypeError(
281
- "Failed to execute 'has' on 'URLSearchParams': 1 " +
282
- "argument required, but only " +
283
- arguments.length +
284
- " present."
285
- );
286
- }
243
+ set(name, value) {
244
+ if (!this || !module.exports.is(this)) {
245
+ throw new TypeError("Illegal invocation");
246
+ }
287
247
 
288
- const args = [];
289
- for (let i = 0; i < arguments.length && i < 1; ++i) {
290
- args[i] = arguments[i];
248
+ if (arguments.length < 2) {
249
+ throw new TypeError(
250
+ "Failed to execute 'set' on 'URLSearchParams': 2 arguments required, but only " + arguments.length + " present."
251
+ );
252
+ }
253
+ const args = [];
254
+ {
255
+ let curArg = arguments[0];
256
+ curArg = conversions["USVString"](curArg, {
257
+ context: "Failed to execute 'set' on 'URLSearchParams': parameter 1"
258
+ });
259
+ args.push(curArg);
260
+ }
261
+ {
262
+ let curArg = arguments[1];
263
+ curArg = conversions["USVString"](curArg, {
264
+ context: "Failed to execute 'set' on 'URLSearchParams': parameter 2"
265
+ });
266
+ args.push(curArg);
267
+ }
268
+ return this[impl].set(...args);
291
269
  }
292
270
 
293
- args[0] = conversions["USVString"](args[0], { context: "Failed to execute 'has' on 'URLSearchParams': parameter 1" });
294
-
295
- return this[impl].has(...args);
296
- };
271
+ sort() {
272
+ if (!this || !module.exports.is(this)) {
273
+ throw new TypeError("Illegal invocation");
274
+ }
297
275
 
298
- URLSearchParams.prototype.set = function set(name, value) {
299
- if (!this || !module.exports.is(this)) {
300
- throw new TypeError("Illegal invocation");
276
+ return this[impl].sort();
301
277
  }
302
278
 
303
- if (arguments.length < 2) {
304
- throw new TypeError(
305
- "Failed to execute 'set' on 'URLSearchParams': 2 " +
306
- "arguments required, but only " +
307
- arguments.length +
308
- " present."
309
- );
310
- }
279
+ toString() {
280
+ if (!this || !module.exports.is(this)) {
281
+ throw new TypeError("Illegal invocation");
282
+ }
311
283
 
312
- const args = [];
313
- for (let i = 0; i < arguments.length && i < 2; ++i) {
314
- args[i] = arguments[i];
284
+ return this[impl].toString();
315
285
  }
316
286
 
317
- args[0] = conversions["USVString"](args[0], { context: "Failed to execute 'set' on 'URLSearchParams': parameter 1" });
318
-
319
- args[1] = conversions["USVString"](args[1], { context: "Failed to execute 'set' on 'URLSearchParams': parameter 2" });
320
-
321
- return this[impl].set(...args);
322
- };
323
-
324
- URLSearchParams.prototype.sort = function sort() {
325
- if (!this || !module.exports.is(this)) {
326
- throw new TypeError("Illegal invocation");
287
+ keys() {
288
+ if (!this || !module.exports.is(this)) {
289
+ throw new TypeError("Illegal invocation");
290
+ }
291
+ return module.exports.createDefaultIterator(this, "key");
327
292
  }
328
293
 
329
- return this[impl].sort();
330
- };
331
-
332
- URLSearchParams.prototype.toString = function toString() {
333
- if (!this || !module.exports.is(this)) {
334
- throw new TypeError("Illegal invocation");
294
+ values() {
295
+ if (!this || !module.exports.is(this)) {
296
+ throw new TypeError("Illegal invocation");
297
+ }
298
+ return module.exports.createDefaultIterator(this, "value");
335
299
  }
336
300
 
337
- return this[impl].toString();
338
- };
339
-
340
- URLSearchParams.prototype.entries = URLSearchParams.prototype[Symbol.iterator];
341
-
342
- URLSearchParams.prototype.keys = function keys() {
343
- if (!this || !module.exports.is(this)) {
344
- throw new TypeError("Illegal invocation");
301
+ entries() {
302
+ if (!this || !module.exports.is(this)) {
303
+ throw new TypeError("Illegal invocation");
304
+ }
305
+ return module.exports.createDefaultIterator(this, "key+value");
345
306
  }
346
- return module.exports.createDefaultIterator(this, "key");
347
- };
348
307
 
349
- URLSearchParams.prototype.values = function values() {
350
- if (!this || !module.exports.is(this)) {
351
- throw new TypeError("Illegal invocation");
308
+ forEach(callback) {
309
+ if (!this || !module.exports.is(this)) {
310
+ throw new TypeError("Illegal invocation");
311
+ }
312
+ if (arguments.length < 1) {
313
+ throw new TypeError("Failed to execute 'forEach' on 'iterable': 1 argument required, " + "but only 0 present.");
314
+ }
315
+ if (typeof callback !== "function") {
316
+ throw new TypeError(
317
+ "Failed to execute 'forEach' on 'iterable': The callback provided " + "as parameter 1 is not a function."
318
+ );
319
+ }
320
+ const thisArg = arguments[1];
321
+ let pairs = Array.from(this[impl]);
322
+ let i = 0;
323
+ while (i < pairs.length) {
324
+ const [key, value] = pairs[i].map(utils.tryWrapperForImpl);
325
+ callback.call(thisArg, value, key, this);
326
+ pairs = Array.from(this[impl]);
327
+ i++;
328
+ }
352
329
  }
353
- return module.exports.createDefaultIterator(this, "value");
354
- };
355
-
356
- Object.defineProperty(URLSearchParams.prototype, Symbol.toStringTag, {
357
- value: "URLSearchParams",
358
- writable: false,
359
- enumerable: false,
360
- configurable: true
330
+ }
331
+ Object.defineProperties(URLSearchParams.prototype, {
332
+ append: { enumerable: true },
333
+ delete: { enumerable: true },
334
+ get: { enumerable: true },
335
+ getAll: { enumerable: true },
336
+ has: { enumerable: true },
337
+ set: { enumerable: true },
338
+ sort: { enumerable: true },
339
+ toString: { enumerable: true },
340
+ keys: { enumerable: true },
341
+ values: { enumerable: true },
342
+ entries: { enumerable: true },
343
+ forEach: { enumerable: true },
344
+ [Symbol.toStringTag]: { value: "URLSearchParams", configurable: true },
345
+ [Symbol.iterator]: { value: URLSearchParams.prototype.entries, configurable: true, writable: true }
361
346
  });
362
-
363
347
  const iface = {
364
- mixedInto: [],
348
+ // When an interface-module that implements this interface as a mixin is loaded, it will append its own `.is()`
349
+ // method into this array. It allows objects that directly implements *those* interfaces to be recognized as
350
+ // implementing this mixin interface.
351
+ _mixedIntoPredicates: [],
365
352
  is(obj) {
366
353
  if (obj) {
367
- if (obj[impl] instanceof Impl.implementation) {
354
+ if (utils.hasOwn(obj, impl) && obj[impl] instanceof Impl.implementation) {
368
355
  return true;
369
356
  }
370
- for (let i = 0; i < module.exports.mixedInto.length; ++i) {
371
- if (obj instanceof module.exports.mixedInto[i]) {
357
+ for (const isMixedInto of module.exports._mixedIntoPredicates) {
358
+ if (isMixedInto(obj)) {
372
359
  return true;
373
360
  }
374
361
  }
@@ -382,8 +369,8 @@ const iface = {
382
369
  }
383
370
 
384
371
  const wrapper = utils.wrapperForImpl(obj);
385
- for (let i = 0; i < module.exports.mixedInto.length; ++i) {
386
- if (wrapper instanceof module.exports.mixedInto[i]) {
372
+ for (const isMixedInto of module.exports._mixedIntoPredicates) {
373
+ if (isMixedInto(wrapper)) {
387
374
  return true;
388
375
  }
389
376
  }
@@ -401,8 +388,6 @@ const iface = {
401
388
  const iterator = Object.create(IteratorPrototype);
402
389
  Object.defineProperty(iterator, utils.iterInternalSymbol, {
403
390
  value: { target, kind, index: 0 },
404
- writable: false,
405
- enumerable: false,
406
391
  configurable: true
407
392
  });
408
393
  return iterator;
@@ -427,8 +412,6 @@ const iface = {
427
412
  this._internalSetup(obj);
428
413
  Object.defineProperty(obj, impl, {
429
414
  value: new Impl.implementation(constructorArgs, privateData),
430
- writable: false,
431
- enumerable: false,
432
415
  configurable: true
433
416
  });
434
417
 
@@ -446,4 +429,4 @@ const iface = {
446
429
  }; // iface
447
430
  module.exports = iface;
448
431
 
449
- const Impl = require(".//URLSearchParams-impl.js");
432
+ const Impl = require("./URLSearchParams-impl.js");
@@ -1244,8 +1244,14 @@ module.exports.serializeURLOrigin = function (url) {
1244
1244
  port: url.port
1245
1245
  });
1246
1246
  case "file":
1247
- // spec says "exercise to the reader", chrome says "file://"
1248
- return "file://";
1247
+ // The spec says:
1248
+ // > Unfortunate as it is, this is left as an exercise to the reader. When in doubt, return a new opaque origin.
1249
+ // Browsers tested so far:
1250
+ // - Chrome says "file://", but treats file: URLs as cross-origin for most (all?) purposes; see e.g.
1251
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=37586
1252
+ // - Firefox says "null", but treats file: URLs as same-origin sometimes based on directory stuff; see
1253
+ // https://developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Same-origin_policy_for_file:_URIs
1254
+ return "null";
1249
1255
  default:
1250
1256
  // serializing an opaque origin returns "null"
1251
1257
  return "null";
package/lib/utils.js CHANGED
@@ -5,31 +5,34 @@ function isObject(value) {
5
5
  return typeof value === "object" && value !== null || typeof value === "function";
6
6
  }
7
7
 
8
- function getReferenceToBytes(bufferSource) {
9
- // Node.js' Buffer does not allow subclassing for now, so we can get away with a prototype object check for perf.
10
- if (Object.getPrototypeOf(bufferSource) === Buffer.prototype) {
11
- return bufferSource;
12
- }
13
- if (bufferSource instanceof ArrayBuffer) {
14
- return Buffer.from(bufferSource);
15
- }
16
- return Buffer.from(bufferSource.buffer, bufferSource.byteOffset, bufferSource.byteLength);
17
- }
18
-
19
- function getCopyToBytes(bufferSource) {
20
- return Buffer.from(getReferenceToBytes(bufferSource));
8
+ function hasOwn(obj, prop) {
9
+ return Object.prototype.hasOwnProperty.call(obj, prop);
21
10
  }
22
11
 
23
- function mixin(target, source) {
24
- const keys = Object.getOwnPropertyNames(source);
25
- for (let i = 0; i < keys.length; ++i) {
26
- if (keys[i] in target) {
27
- continue;
12
+ const getOwnPropertyDescriptors = typeof Object.getOwnPropertyDescriptors === "function" ?
13
+ Object.getOwnPropertyDescriptors :
14
+ // Polyfill exists until we require Node.js v8.x
15
+ // https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptors
16
+ obj => {
17
+ if (obj === undefined || obj === null) {
18
+ throw new TypeError("Cannot convert undefined or null to object");
28
19
  }
29
-
30
- Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i]));
31
- }
32
- }
20
+ obj = Object(obj);
21
+ const ownKeys = Reflect.ownKeys(obj);
22
+ const descriptors = {};
23
+ for (const key of ownKeys) {
24
+ const descriptor = Reflect.getOwnPropertyDescriptor(obj, key);
25
+ if (descriptor !== undefined) {
26
+ Reflect.defineProperty(descriptors, key, {
27
+ value: descriptor,
28
+ writable: true,
29
+ enumerable: true,
30
+ configurable: true
31
+ });
32
+ }
33
+ }
34
+ return descriptors;
35
+ };
33
36
 
34
37
  const wrapperSymbol = Symbol("wrapper");
35
38
  const implSymbol = Symbol("impl");
@@ -98,9 +101,8 @@ const namedDelete = Symbol("named property delete");
98
101
 
99
102
  module.exports = exports = {
100
103
  isObject,
101
- getReferenceToBytes,
102
- getCopyToBytes,
103
- mixin,
104
+ hasOwn,
105
+ getOwnPropertyDescriptors,
104
106
  wrapperSymbol,
105
107
  implSymbol,
106
108
  getSameObject,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whatwg-url",
3
- "version": "6.5.0",
3
+ "version": "7.0.0",
4
4
  "description": "An implementation of the WHATWG URL Standard's URL API and parsing machinery",
5
5
  "main": "lib/public-api.js",
6
6
  "files": [
@@ -17,13 +17,12 @@
17
17
  "devDependencies": {
18
18
  "browserify": "^16.2.2",
19
19
  "domexception": "^1.0.1",
20
- "eslint": "^4.19.1",
21
- "istanbul": "~0.4.5",
22
- "jest": "^22.4.3",
23
- "jsdom": "^11.8.0",
24
- "recast": "~0.14.7",
25
- "request": "^2.85.0",
26
- "webidl2js": "^7.4.0"
20
+ "eslint": "^5.4.0",
21
+ "jest": "^23.5.0",
22
+ "jsdom": "^11.12.0",
23
+ "recast": "^0.15.3",
24
+ "request": "^2.88.0",
25
+ "webidl2js": "^9.0.1"
27
26
  },
28
27
  "scripts": {
29
28
  "build": "node scripts/transform.js && node scripts/convert-idl.js",