whatwg-url 5.0.0 → 7.1.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 +38 -7
- package/lib/URL-impl.js +26 -9
- package/lib/URL.js +290 -151
- package/lib/URLSearchParams-impl.js +122 -0
- package/lib/URLSearchParams.js +432 -0
- package/lib/infra.js +24 -0
- package/lib/public-api.js +9 -4
- package/lib/url-state-machine.js +1303 -1297
- package/lib/urlencoded.js +138 -0
- package/lib/utils.js +120 -13
- package/package.json +35 -13
package/README.md
CHANGED
|
@@ -2,29 +2,32 @@
|
|
|
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
|
-
##
|
|
5
|
+
## Specification conformance
|
|
6
6
|
|
|
7
|
-
whatwg-url is currently up to date with the URL spec up to commit [
|
|
7
|
+
whatwg-url is currently up to date with the URL spec up to commit [7ae1c69](https://github.com/whatwg/url/commit/7ae1c691c96f0d82fafa24c33aa1e8df9ffbf2bc).
|
|
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"`).
|
|
8
10
|
|
|
9
11
|
## API
|
|
10
12
|
|
|
11
|
-
### The `URL`
|
|
13
|
+
### The `URL` and `URLSearchParams` classes
|
|
12
14
|
|
|
13
|
-
The main API is the [`URL`](https://url.spec.whatwg.org/#url)
|
|
15
|
+
The main API is provided by the [`URL`](https://url.spec.whatwg.org/#url-class) and [`URLSearchParams`](https://url.spec.whatwg.org/#interface-urlsearchparams) exports, which follows the spec's behavior in all ways (including e.g. `USVString` conversion). Most consumers of this library will want to use these.
|
|
14
16
|
|
|
15
17
|
### Low-level URL Standard API
|
|
16
18
|
|
|
17
|
-
The following methods are exported for use by places like jsdom that need to implement things like [`HTMLHyperlinkElementUtils`](https://html.spec.whatwg.org/#htmlhyperlinkelementutils). They operate on or return an "internal URL" or ["URL record"](https://url.spec.whatwg.org/#concept-url) type.
|
|
19
|
+
The following methods are exported for use by places like jsdom that need to implement things like [`HTMLHyperlinkElementUtils`](https://html.spec.whatwg.org/#htmlhyperlinkelementutils). They mostly operate on or return an "internal URL" or ["URL record"](https://url.spec.whatwg.org/#concept-url) type.
|
|
18
20
|
|
|
19
21
|
- [URL parser](https://url.spec.whatwg.org/#concept-url-parser): `parseURL(input, { baseURL, encodingOverride })`
|
|
20
22
|
- [Basic URL parser](https://url.spec.whatwg.org/#concept-basic-url-parser): `basicURLParse(input, { baseURL, encodingOverride, url, stateOverride })`
|
|
21
23
|
- [URL serializer](https://url.spec.whatwg.org/#concept-url-serializer): `serializeURL(urlRecord, excludeFragment)`
|
|
22
24
|
- [Host serializer](https://url.spec.whatwg.org/#concept-host-serializer): `serializeHost(hostFromURLRecord)`
|
|
23
25
|
- [Serialize an integer](https://url.spec.whatwg.org/#serialize-an-integer): `serializeInteger(number)`
|
|
24
|
-
- [Origin](https://url.spec.whatwg.org/#concept-url-origin) [serializer](https://html.spec.whatwg.org/multipage/
|
|
26
|
+
- [Origin](https://url.spec.whatwg.org/#concept-url-origin) [serializer](https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin): `serializeURLOrigin(urlRecord)`
|
|
25
27
|
- [Set the username](https://url.spec.whatwg.org/#set-the-username): `setTheUsername(urlRecord, usernameString)`
|
|
26
28
|
- [Set the password](https://url.spec.whatwg.org/#set-the-password): `setThePassword(urlRecord, passwordString)`
|
|
27
29
|
- [Cannot have a username/password/port](https://url.spec.whatwg.org/#cannot-have-a-username-password-port): `cannotHaveAUsernamePasswordPort(urlRecord)`
|
|
30
|
+
- [Percent decode](https://url.spec.whatwg.org/#percent-decode): `percentDecode(buffer)`
|
|
28
31
|
|
|
29
32
|
The `stateOverride` parameter is one of the following strings:
|
|
30
33
|
|
|
@@ -64,4 +67,32 @@ The URL record type has the following API:
|
|
|
64
67
|
|
|
65
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.
|
|
66
69
|
|
|
67
|
-
The return value of "failure" in the spec is represented by
|
|
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.
|
|
92
|
+
|
|
93
|
+
## Supporting whatwg-url
|
|
94
|
+
|
|
95
|
+
The jsdom project (including whatwg-url) is a community-driven project maintained by a team of [volunteers](https://github.com/orgs/jsdom/people). You could support us by:
|
|
96
|
+
|
|
97
|
+
- [Getting professional support for whatwg-url](https://tidelift.com/subscription/pkg/npm-whatwg-url?utm_source=npm-whatwg-url&utm_medium=referral&utm_campaign=readme) as part of a Tidelift subscription. Tidelift helps making open source sustainable for us while giving teams assurances for maintenance, licensing, and security.
|
|
98
|
+
- Contributing directly to the project.
|
package/lib/URL-impl.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const usm = require("./url-state-machine");
|
|
3
|
+
const urlencoded = require("./urlencoded");
|
|
4
|
+
const URLSearchParams = require("./URLSearchParams");
|
|
3
5
|
|
|
4
6
|
exports.implementation = class URLImpl {
|
|
5
7
|
constructor(constructorArgs) {
|
|
@@ -9,19 +11,24 @@ exports.implementation = class URLImpl {
|
|
|
9
11
|
let parsedBase = null;
|
|
10
12
|
if (base !== undefined) {
|
|
11
13
|
parsedBase = usm.basicURLParse(base);
|
|
12
|
-
if (parsedBase ===
|
|
13
|
-
throw new TypeError(
|
|
14
|
+
if (parsedBase === null) {
|
|
15
|
+
throw new TypeError(`Invalid base URL: ${base}`);
|
|
14
16
|
}
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase });
|
|
18
|
-
if (parsedURL ===
|
|
19
|
-
throw new TypeError(
|
|
20
|
+
if (parsedURL === null) {
|
|
21
|
+
throw new TypeError(`Invalid URL: ${url}`);
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
const query = parsedURL.query !== null ? parsedURL.query : "";
|
|
25
|
+
|
|
22
26
|
this._url = parsedURL;
|
|
23
27
|
|
|
24
|
-
//
|
|
28
|
+
// We cannot invoke the "new URLSearchParams object" algorithm without going through the constructor, which strips
|
|
29
|
+
// question mark by default. Therefore the doNotStripQMark hack is used.
|
|
30
|
+
this._query = URLSearchParams.createImpl([query], { doNotStripQMark: true });
|
|
31
|
+
this._query._url = this;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
get href() {
|
|
@@ -30,11 +37,17 @@ exports.implementation = class URLImpl {
|
|
|
30
37
|
|
|
31
38
|
set href(v) {
|
|
32
39
|
const parsedURL = usm.basicURLParse(v);
|
|
33
|
-
if (parsedURL ===
|
|
34
|
-
throw new TypeError(
|
|
40
|
+
if (parsedURL === null) {
|
|
41
|
+
throw new TypeError(`Invalid URL: ${v}`);
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
this._url = parsedURL;
|
|
45
|
+
|
|
46
|
+
this._query._list.splice(0);
|
|
47
|
+
const { query } = parsedURL;
|
|
48
|
+
if (query !== null) {
|
|
49
|
+
this._query._list = urlencoded.parseUrlencoded(query);
|
|
50
|
+
}
|
|
38
51
|
}
|
|
39
52
|
|
|
40
53
|
get origin() {
|
|
@@ -161,18 +174,22 @@ exports.implementation = class URLImpl {
|
|
|
161
174
|
}
|
|
162
175
|
|
|
163
176
|
set search(v) {
|
|
164
|
-
// TODO: query stuff
|
|
165
|
-
|
|
166
177
|
const url = this._url;
|
|
167
178
|
|
|
168
179
|
if (v === "") {
|
|
169
180
|
url.query = null;
|
|
181
|
+
this._query._list = [];
|
|
170
182
|
return;
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
const input = v[0] === "?" ? v.substring(1) : v;
|
|
174
186
|
url.query = "";
|
|
175
187
|
usm.basicURLParse(input, { url, stateOverride: "query" });
|
|
188
|
+
this._query._list = urlencoded.parseUrlencoded(input);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
get searchParams() {
|
|
192
|
+
return this._query;
|
|
176
193
|
}
|
|
177
194
|
|
|
178
195
|
get hash() {
|
package/lib/URL.js
CHANGED
|
@@ -2,195 +2,334 @@
|
|
|
2
2
|
|
|
3
3
|
const conversions = require("webidl-conversions");
|
|
4
4
|
const utils = require("./utils.js");
|
|
5
|
-
const Impl = require(".//URL-impl.js");
|
|
6
5
|
|
|
7
6
|
const impl = utils.implSymbol;
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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);
|
|
12
27
|
}
|
|
13
|
-
|
|
14
|
-
|
|
28
|
+
|
|
29
|
+
toJSON() {
|
|
30
|
+
if (!this || !module.exports.is(this)) {
|
|
31
|
+
throw new TypeError("Illegal invocation");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return this[impl].toJSON();
|
|
15
35
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
36
|
+
|
|
37
|
+
get href() {
|
|
38
|
+
if (!this || !module.exports.is(this)) {
|
|
39
|
+
throw new TypeError("Illegal invocation");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return this[impl]["href"];
|
|
19
43
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
44
|
+
|
|
45
|
+
set href(V) {
|
|
46
|
+
if (!this || !module.exports.is(this)) {
|
|
47
|
+
throw new TypeError("Illegal invocation");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'href' property on 'URL': The provided value" });
|
|
51
|
+
|
|
52
|
+
this[impl]["href"] = V;
|
|
23
53
|
}
|
|
24
54
|
|
|
25
|
-
|
|
26
|
-
|
|
55
|
+
toString() {
|
|
56
|
+
if (!this || !module.exports.is(this)) {
|
|
57
|
+
throw new TypeError("Illegal invocation");
|
|
58
|
+
}
|
|
59
|
+
return this[impl]["href"];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get origin() {
|
|
63
|
+
if (!this || !module.exports.is(this)) {
|
|
64
|
+
throw new TypeError("Illegal invocation");
|
|
65
|
+
}
|
|
27
66
|
|
|
28
|
-
|
|
29
|
-
if (!this || !module.exports.is(this)) {
|
|
30
|
-
throw new TypeError("Illegal invocation");
|
|
67
|
+
return this[impl]["origin"];
|
|
31
68
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
69
|
+
|
|
70
|
+
get protocol() {
|
|
71
|
+
if (!this || !module.exports.is(this)) {
|
|
72
|
+
throw new TypeError("Illegal invocation");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return this[impl]["protocol"];
|
|
35
76
|
}
|
|
36
|
-
return this[impl].toJSON.apply(this[impl], args);
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(URL.prototype, "href", {
|
|
39
|
-
get() {
|
|
40
|
-
return this[impl].href;
|
|
41
|
-
},
|
|
42
|
-
set(V) {
|
|
43
|
-
V = conversions["USVString"](V);
|
|
44
|
-
this[impl].href = V;
|
|
45
|
-
},
|
|
46
|
-
enumerable: true,
|
|
47
|
-
configurable: true
|
|
48
|
-
});
|
|
49
77
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
set protocol(V) {
|
|
79
|
+
if (!this || !module.exports.is(this)) {
|
|
80
|
+
throw new TypeError("Illegal invocation");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'protocol' property on 'URL': The provided value" });
|
|
84
|
+
|
|
85
|
+
this[impl]["protocol"] = V;
|
|
53
86
|
}
|
|
54
|
-
return this.href;
|
|
55
|
-
};
|
|
56
87
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
enumerable: true,
|
|
62
|
-
configurable: true
|
|
63
|
-
});
|
|
88
|
+
get username() {
|
|
89
|
+
if (!this || !module.exports.is(this)) {
|
|
90
|
+
throw new TypeError("Illegal invocation");
|
|
91
|
+
}
|
|
64
92
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return this[impl].protocol;
|
|
68
|
-
},
|
|
69
|
-
set(V) {
|
|
70
|
-
V = conversions["USVString"](V);
|
|
71
|
-
this[impl].protocol = V;
|
|
72
|
-
},
|
|
73
|
-
enumerable: true,
|
|
74
|
-
configurable: true
|
|
75
|
-
});
|
|
93
|
+
return this[impl]["username"];
|
|
94
|
+
}
|
|
76
95
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
set(V) {
|
|
82
|
-
V = conversions["USVString"](V);
|
|
83
|
-
this[impl].username = V;
|
|
84
|
-
},
|
|
85
|
-
enumerable: true,
|
|
86
|
-
configurable: true
|
|
87
|
-
});
|
|
96
|
+
set username(V) {
|
|
97
|
+
if (!this || !module.exports.is(this)) {
|
|
98
|
+
throw new TypeError("Illegal invocation");
|
|
99
|
+
}
|
|
88
100
|
|
|
89
|
-
|
|
90
|
-
get() {
|
|
91
|
-
return this[impl].password;
|
|
92
|
-
},
|
|
93
|
-
set(V) {
|
|
94
|
-
V = conversions["USVString"](V);
|
|
95
|
-
this[impl].password = V;
|
|
96
|
-
},
|
|
97
|
-
enumerable: true,
|
|
98
|
-
configurable: true
|
|
99
|
-
});
|
|
101
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'username' property on 'URL': The provided value" });
|
|
100
102
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return this[impl].host;
|
|
104
|
-
},
|
|
105
|
-
set(V) {
|
|
106
|
-
V = conversions["USVString"](V);
|
|
107
|
-
this[impl].host = V;
|
|
108
|
-
},
|
|
109
|
-
enumerable: true,
|
|
110
|
-
configurable: true
|
|
111
|
-
});
|
|
103
|
+
this[impl]["username"] = V;
|
|
104
|
+
}
|
|
112
105
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
set(V) {
|
|
118
|
-
V = conversions["USVString"](V);
|
|
119
|
-
this[impl].hostname = V;
|
|
120
|
-
},
|
|
121
|
-
enumerable: true,
|
|
122
|
-
configurable: true
|
|
123
|
-
});
|
|
106
|
+
get password() {
|
|
107
|
+
if (!this || !module.exports.is(this)) {
|
|
108
|
+
throw new TypeError("Illegal invocation");
|
|
109
|
+
}
|
|
124
110
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return this[impl].port;
|
|
128
|
-
},
|
|
129
|
-
set(V) {
|
|
130
|
-
V = conversions["USVString"](V);
|
|
131
|
-
this[impl].port = V;
|
|
132
|
-
},
|
|
133
|
-
enumerable: true,
|
|
134
|
-
configurable: true
|
|
135
|
-
});
|
|
111
|
+
return this[impl]["password"];
|
|
112
|
+
}
|
|
136
113
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
set(V) {
|
|
142
|
-
V = conversions["USVString"](V);
|
|
143
|
-
this[impl].pathname = V;
|
|
144
|
-
},
|
|
145
|
-
enumerable: true,
|
|
146
|
-
configurable: true
|
|
147
|
-
});
|
|
114
|
+
set password(V) {
|
|
115
|
+
if (!this || !module.exports.is(this)) {
|
|
116
|
+
throw new TypeError("Illegal invocation");
|
|
117
|
+
}
|
|
148
118
|
|
|
149
|
-
|
|
150
|
-
get() {
|
|
151
|
-
return this[impl].search;
|
|
152
|
-
},
|
|
153
|
-
set(V) {
|
|
154
|
-
V = conversions["USVString"](V);
|
|
155
|
-
this[impl].search = V;
|
|
156
|
-
},
|
|
157
|
-
enumerable: true,
|
|
158
|
-
configurable: true
|
|
159
|
-
});
|
|
119
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'password' property on 'URL': The provided value" });
|
|
160
120
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
121
|
+
this[impl]["password"] = V;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
get host() {
|
|
125
|
+
if (!this || !module.exports.is(this)) {
|
|
126
|
+
throw new TypeError("Illegal invocation");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return this[impl]["host"];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
set host(V) {
|
|
133
|
+
if (!this || !module.exports.is(this)) {
|
|
134
|
+
throw new TypeError("Illegal invocation");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'host' property on 'URL': The provided value" });
|
|
138
|
+
|
|
139
|
+
this[impl]["host"] = V;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
get hostname() {
|
|
143
|
+
if (!this || !module.exports.is(this)) {
|
|
144
|
+
throw new TypeError("Illegal invocation");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return this[impl]["hostname"];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
set hostname(V) {
|
|
151
|
+
if (!this || !module.exports.is(this)) {
|
|
152
|
+
throw new TypeError("Illegal invocation");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'hostname' property on 'URL': The provided value" });
|
|
156
|
+
|
|
157
|
+
this[impl]["hostname"] = V;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get port() {
|
|
161
|
+
if (!this || !module.exports.is(this)) {
|
|
162
|
+
throw new TypeError("Illegal invocation");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return this[impl]["port"];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
set port(V) {
|
|
169
|
+
if (!this || !module.exports.is(this)) {
|
|
170
|
+
throw new TypeError("Illegal invocation");
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'port' property on 'URL': The provided value" });
|
|
174
|
+
|
|
175
|
+
this[impl]["port"] = V;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
get pathname() {
|
|
179
|
+
if (!this || !module.exports.is(this)) {
|
|
180
|
+
throw new TypeError("Illegal invocation");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return this[impl]["pathname"];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
set pathname(V) {
|
|
187
|
+
if (!this || !module.exports.is(this)) {
|
|
188
|
+
throw new TypeError("Illegal invocation");
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'pathname' property on 'URL': The provided value" });
|
|
192
|
+
|
|
193
|
+
this[impl]["pathname"] = V;
|
|
194
|
+
}
|
|
172
195
|
|
|
196
|
+
get search() {
|
|
197
|
+
if (!this || !module.exports.is(this)) {
|
|
198
|
+
throw new TypeError("Illegal invocation");
|
|
199
|
+
}
|
|
173
200
|
|
|
174
|
-
|
|
201
|
+
return this[impl]["search"];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
set search(V) {
|
|
205
|
+
if (!this || !module.exports.is(this)) {
|
|
206
|
+
throw new TypeError("Illegal invocation");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'search' property on 'URL': The provided value" });
|
|
210
|
+
|
|
211
|
+
this[impl]["search"] = V;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
get searchParams() {
|
|
215
|
+
if (!this || !module.exports.is(this)) {
|
|
216
|
+
throw new TypeError("Illegal invocation");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return utils.getSameObject(this, "searchParams", () => {
|
|
220
|
+
return utils.tryWrapperForImpl(this[impl]["searchParams"]);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
get hash() {
|
|
225
|
+
if (!this || !module.exports.is(this)) {
|
|
226
|
+
throw new TypeError("Illegal invocation");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return this[impl]["hash"];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
set hash(V) {
|
|
233
|
+
if (!this || !module.exports.is(this)) {
|
|
234
|
+
throw new TypeError("Illegal invocation");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
V = conversions["USVString"](V, { context: "Failed to set the 'hash' property on 'URL': The provided value" });
|
|
238
|
+
|
|
239
|
+
this[impl]["hash"] = V;
|
|
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 }
|
|
258
|
+
});
|
|
259
|
+
const iface = {
|
|
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: [],
|
|
175
264
|
is(obj) {
|
|
176
|
-
|
|
265
|
+
if (obj) {
|
|
266
|
+
if (utils.hasOwn(obj, impl) && obj[impl] instanceof Impl.implementation) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
for (const isMixedInto of module.exports._mixedIntoPredicates) {
|
|
270
|
+
if (isMixedInto(obj)) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
},
|
|
277
|
+
isImpl(obj) {
|
|
278
|
+
if (obj) {
|
|
279
|
+
if (obj instanceof Impl.implementation) {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const wrapper = utils.wrapperForImpl(obj);
|
|
284
|
+
for (const isMixedInto of module.exports._mixedIntoPredicates) {
|
|
285
|
+
if (isMixedInto(wrapper)) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return false;
|
|
291
|
+
},
|
|
292
|
+
convert(obj, { context = "The provided value" } = {}) {
|
|
293
|
+
if (module.exports.is(obj)) {
|
|
294
|
+
return utils.implForWrapper(obj);
|
|
295
|
+
}
|
|
296
|
+
throw new TypeError(`${context} is not of type 'URL'.`);
|
|
177
297
|
},
|
|
298
|
+
|
|
178
299
|
create(constructorArgs, privateData) {
|
|
179
300
|
let obj = Object.create(URL.prototype);
|
|
180
|
-
this.setup(obj, constructorArgs, privateData);
|
|
301
|
+
obj = this.setup(obj, constructorArgs, privateData);
|
|
181
302
|
return obj;
|
|
182
303
|
},
|
|
304
|
+
createImpl(constructorArgs, privateData) {
|
|
305
|
+
let obj = Object.create(URL.prototype);
|
|
306
|
+
obj = this.setup(obj, constructorArgs, privateData);
|
|
307
|
+
return utils.implForWrapper(obj);
|
|
308
|
+
},
|
|
309
|
+
_internalSetup(obj) {},
|
|
183
310
|
setup(obj, constructorArgs, privateData) {
|
|
184
311
|
if (!privateData) privateData = {};
|
|
312
|
+
|
|
185
313
|
privateData.wrapper = obj;
|
|
186
314
|
|
|
187
|
-
|
|
315
|
+
this._internalSetup(obj);
|
|
316
|
+
Object.defineProperty(obj, impl, {
|
|
317
|
+
value: new Impl.implementation(constructorArgs, privateData),
|
|
318
|
+
configurable: true
|
|
319
|
+
});
|
|
320
|
+
|
|
188
321
|
obj[impl][utils.wrapperSymbol] = obj;
|
|
322
|
+
if (Impl.init) {
|
|
323
|
+
Impl.init(obj[impl], privateData);
|
|
324
|
+
}
|
|
325
|
+
return obj;
|
|
189
326
|
},
|
|
190
327
|
interface: URL,
|
|
191
328
|
expose: {
|
|
192
|
-
Window: { URL
|
|
193
|
-
Worker: { URL
|
|
329
|
+
Window: { URL },
|
|
330
|
+
Worker: { URL }
|
|
194
331
|
}
|
|
195
|
-
};
|
|
332
|
+
}; // iface
|
|
333
|
+
module.exports = iface;
|
|
196
334
|
|
|
335
|
+
const Impl = require("./URL-impl.js");
|