2 // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
3 require('../modules/es.string.iterator');
4 var $ = require('../internals/export');
5 var DESCRIPTORS = require('../internals/descriptors');
6 var USE_NATIVE_URL = require('../internals/native-url');
7 var global = require('../internals/global');
8 var bind = require('../internals/function-bind-context');
9 var uncurryThis = require('../internals/function-uncurry-this');
10 var defineProperties = require('../internals/object-define-properties');
11 var redefine = require('../internals/redefine');
12 var anInstance = require('../internals/an-instance');
13 var hasOwn = require('../internals/has-own-property');
14 var assign = require('../internals/object-assign');
15 var arrayFrom = require('../internals/array-from');
16 var arraySlice = require('../internals/array-slice-simple');
17 var codeAt = require('../internals/string-multibyte').codeAt;
18 var toASCII = require('../internals/string-punycode-to-ascii');
19 var $toString = require('../internals/to-string');
20 var setToStringTag = require('../internals/set-to-string-tag');
21 var URLSearchParamsModule = require('../modules/web.url-search-params');
22 var InternalStateModule = require('../internals/internal-state');
24 var setInternalState = InternalStateModule.set;
25 var getInternalURLState = InternalStateModule.getterFor('URL');
26 var URLSearchParams = URLSearchParamsModule.URLSearchParams;
27 var getInternalSearchParamsState = URLSearchParamsModule.getState;
29 var NativeURL = global.URL;
30 var TypeError = global.TypeError;
31 var parseInt = global.parseInt;
32 var floor = Math.floor;
34 var charAt = uncurryThis(''.charAt);
35 var exec = uncurryThis(/./.exec);
36 var join = uncurryThis([].join);
37 var numberToString = uncurryThis(1.0.toString);
38 var pop = uncurryThis([].pop);
39 var push = uncurryThis([].push);
40 var replace = uncurryThis(''.replace);
41 var shift = uncurryThis([].shift);
42 var split = uncurryThis(''.split);
43 var stringSlice = uncurryThis(''.slice);
44 var toLowerCase = uncurryThis(''.toLowerCase);
45 var unshift = uncurryThis([].unshift);
47 var INVALID_AUTHORITY = 'Invalid authority';
48 var INVALID_SCHEME = 'Invalid scheme';
49 var INVALID_HOST = 'Invalid host';
50 var INVALID_PORT = 'Invalid port';
53 // eslint-disable-next-line regexp/no-obscure-range -- safe
54 var ALPHANUMERIC = /[\d+-.a-z]/i;
56 var HEX_START = /^0x/i;
59 var HEX = /^[\da-f]+$/i;
60 /* eslint-disable regexp/no-control-character -- safe */
61 var FORBIDDEN_HOST_CODE_POINT = /[\0\t\n\r #%/:<>?@[\\\]^|]/;
62 var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\0\t\n\r #/:<>?@[\\\]^|]/;
63 var LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE = /^[\u0000-\u0020]+|[\u0000-\u0020]+$/g;
64 var TAB_AND_NEW_LINE = /[\t\n\r]/g;
65 /* eslint-enable regexp/no-control-character -- safe */
68 // https://url.spec.whatwg.org/#ipv4-number-parser
69 var parseIPv4 = function (input) {
70 var parts = split(input, '.');
71 var partsLength, numbers, index, part, radix, number, ipv4;
72 if (parts.length && parts[parts.length - 1] == '') {
75 partsLength = parts.length;
76 if (partsLength > 4) return input;
78 for (index = 0; index < partsLength; index++) {
80 if (part == '') return input;
82 if (part.length > 1 && charAt(part, 0) == '0') {
83 radix = exec(HEX_START, part) ? 16 : 8;
84 part = stringSlice(part, radix == 8 ? 1 : 2);
89 if (!exec(radix == 10 ? DEC : radix == 8 ? OCT : HEX, part)) return input;
90 number = parseInt(part, radix);
92 push(numbers, number);
94 for (index = 0; index < partsLength; index++) {
95 number = numbers[index];
96 if (index == partsLength - 1) {
97 if (number >= pow(256, 5 - partsLength)) return null;
98 } else if (number > 255) return null;
101 for (index = 0; index < numbers.length; index++) {
102 ipv4 += numbers[index] * pow(256, 3 - index);
107 // https://url.spec.whatwg.org/#concept-ipv6-parser
108 // eslint-disable-next-line max-statements -- TODO
109 var parseIPv6 = function (input) {
110 var address = [0, 0, 0, 0, 0, 0, 0, 0];
114 var value, length, numbersSeen, ipv4Piece, number, swaps, swap;
116 var chr = function () {
117 return charAt(input, pointer);
121 if (charAt(input, 1) != ':') return;
124 compress = pieceIndex;
127 if (pieceIndex == 8) return;
129 if (compress !== null) return;
132 compress = pieceIndex;
136 while (length < 4 && exec(HEX, chr())) {
137 value = value * 16 + parseInt(chr(), 16);
142 if (length == 0) return;
144 if (pieceIndex > 6) return;
148 if (numbersSeen > 0) {
149 if (chr() == '.' && numbersSeen < 4) pointer++;
152 if (!exec(DIGIT, chr())) return;
153 while (exec(DIGIT, chr())) {
154 number = parseInt(chr(), 10);
155 if (ipv4Piece === null) ipv4Piece = number;
156 else if (ipv4Piece == 0) return;
157 else ipv4Piece = ipv4Piece * 10 + number;
158 if (ipv4Piece > 255) return;
161 address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece;
163 if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++;
165 if (numbersSeen != 4) return;
167 } else if (chr() == ':') {
170 } else if (chr()) return;
171 address[pieceIndex++] = value;
173 if (compress !== null) {
174 swaps = pieceIndex - compress;
176 while (pieceIndex != 0 && swaps > 0) {
177 swap = address[pieceIndex];
178 address[pieceIndex--] = address[compress + swaps - 1];
179 address[compress + --swaps] = swap;
181 } else if (pieceIndex != 8) return;
185 var findLongestZeroSequence = function (ipv6) {
188 var currStart = null;
191 for (; index < 8; index++) {
192 if (ipv6[index] !== 0) {
193 if (currLength > maxLength) {
194 maxIndex = currStart;
195 maxLength = currLength;
200 if (currStart === null) currStart = index;
204 if (currLength > maxLength) {
205 maxIndex = currStart;
206 maxLength = currLength;
211 // https://url.spec.whatwg.org/#host-serializing
212 var serializeHost = function (host) {
213 var result, index, compress, ignore0;
215 if (typeof host == 'number') {
217 for (index = 0; index < 4; index++) {
218 unshift(result, host % 256);
219 host = floor(host / 256);
220 } return join(result, '.');
222 } else if (typeof host == 'object') {
224 compress = findLongestZeroSequence(host);
225 for (index = 0; index < 8; index++) {
226 if (ignore0 && host[index] === 0) continue;
227 if (ignore0) ignore0 = false;
228 if (compress === index) {
229 result += index ? ':' : '::';
232 result += numberToString(host[index], 16);
233 if (index < 7) result += ':';
236 return '[' + result + ']';
240 var C0ControlPercentEncodeSet = {};
241 var fragmentPercentEncodeSet = assign({}, C0ControlPercentEncodeSet, {
242 ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1
244 var pathPercentEncodeSet = assign({}, fragmentPercentEncodeSet, {
245 '#': 1, '?': 1, '{': 1, '}': 1
247 var userinfoPercentEncodeSet = assign({}, pathPercentEncodeSet, {
248 '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1
251 var percentEncode = function (chr, set) {
252 var code = codeAt(chr, 0);
253 return code > 0x20 && code < 0x7F && !hasOwn(set, chr) ? chr : encodeURIComponent(chr);
256 // https://url.spec.whatwg.org/#special-scheme
257 var specialSchemes = {
266 // https://url.spec.whatwg.org/#windows-drive-letter
267 var isWindowsDriveLetter = function (string, normalized) {
269 return string.length == 2 && exec(ALPHA, charAt(string, 0))
270 && ((second = charAt(string, 1)) == ':' || (!normalized && second == '|'));
273 // https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
274 var startsWithWindowsDriveLetter = function (string) {
276 return string.length > 1 && isWindowsDriveLetter(stringSlice(string, 0, 2)) && (
277 string.length == 2 ||
278 ((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#')
282 // https://url.spec.whatwg.org/#single-dot-path-segment
283 var isSingleDot = function (segment) {
284 return segment === '.' || toLowerCase(segment) === '%2e';
287 // https://url.spec.whatwg.org/#double-dot-path-segment
288 var isDoubleDot = function (segment) {
289 segment = toLowerCase(segment);
290 return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e';
294 var SCHEME_START = {};
297 var SPECIAL_RELATIVE_OR_AUTHORITY = {};
298 var PATH_OR_AUTHORITY = {};
300 var RELATIVE_SLASH = {};
301 var SPECIAL_AUTHORITY_SLASHES = {};
302 var SPECIAL_AUTHORITY_IGNORE_SLASHES = {};
312 var CANNOT_BE_A_BASE_URL_PATH = {};
316 var URLState = function (url, isBase, base) {
317 var urlString = $toString(url);
318 var baseState, failure, searchParams;
320 failure = this.parse(urlString);
321 if (failure) throw TypeError(failure);
322 this.searchParams = null;
324 if (base !== undefined) baseState = new URLState(base, true);
325 failure = this.parse(urlString, null, baseState);
326 if (failure) throw TypeError(failure);
327 searchParams = getInternalSearchParamsState(new URLSearchParams());
328 searchParams.bindURL(this);
329 this.searchParams = searchParams;
333 URLState.prototype = {
335 // https://url.spec.whatwg.org/#url-parsing
336 // eslint-disable-next-line max-statements -- TODO
337 parse: function (input, stateOverride, base) {
339 var state = stateOverride || SCHEME_START;
343 var seenBracket = false;
344 var seenPasswordToken = false;
345 var codePoints, chr, bufferCodePoints, failure;
347 input = $toString(input);
349 if (!stateOverride) {
358 url.cannotBeABaseURL = false;
359 input = replace(input, LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, '');
362 input = replace(input, TAB_AND_NEW_LINE, '');
364 codePoints = arrayFrom(input);
366 while (pointer <= codePoints.length) {
367 chr = codePoints[pointer];
370 if (chr && exec(ALPHA, chr)) {
371 buffer += toLowerCase(chr);
373 } else if (!stateOverride) {
376 } else return INVALID_SCHEME;
380 if (chr && (exec(ALPHANUMERIC, chr) || chr == '+' || chr == '-' || chr == '.')) {
381 buffer += toLowerCase(chr);
382 } else if (chr == ':') {
383 if (stateOverride && (
384 (url.isSpecial() != hasOwn(specialSchemes, buffer)) ||
385 (buffer == 'file' && (url.includesCredentials() || url.port !== null)) ||
386 (url.scheme == 'file' && !url.host)
390 if (url.isSpecial() && specialSchemes[url.scheme] == url.port) url.port = null;
394 if (url.scheme == 'file') {
396 } else if (url.isSpecial() && base && base.scheme == url.scheme) {
397 state = SPECIAL_RELATIVE_OR_AUTHORITY;
398 } else if (url.isSpecial()) {
399 state = SPECIAL_AUTHORITY_SLASHES;
400 } else if (codePoints[pointer + 1] == '/') {
401 state = PATH_OR_AUTHORITY;
404 url.cannotBeABaseURL = true;
406 state = CANNOT_BE_A_BASE_URL_PATH;
408 } else if (!stateOverride) {
413 } else return INVALID_SCHEME;
417 if (!base || (base.cannotBeABaseURL && chr != '#')) return INVALID_SCHEME;
418 if (base.cannotBeABaseURL && chr == '#') {
419 url.scheme = base.scheme;
420 url.path = arraySlice(base.path);
421 url.query = base.query;
423 url.cannotBeABaseURL = true;
427 state = base.scheme == 'file' ? FILE : RELATIVE;
430 case SPECIAL_RELATIVE_OR_AUTHORITY:
431 if (chr == '/' && codePoints[pointer + 1] == '/') {
432 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
439 case PATH_OR_AUTHORITY:
449 url.scheme = base.scheme;
451 url.username = base.username;
452 url.password = base.password;
453 url.host = base.host;
454 url.port = base.port;
455 url.path = arraySlice(base.path);
456 url.query = base.query;
457 } else if (chr == '/' || (chr == '\\' && url.isSpecial())) {
458 state = RELATIVE_SLASH;
459 } else if (chr == '?') {
460 url.username = base.username;
461 url.password = base.password;
462 url.host = base.host;
463 url.port = base.port;
464 url.path = arraySlice(base.path);
467 } else if (chr == '#') {
468 url.username = base.username;
469 url.password = base.password;
470 url.host = base.host;
471 url.port = base.port;
472 url.path = arraySlice(base.path);
473 url.query = base.query;
477 url.username = base.username;
478 url.password = base.password;
479 url.host = base.host;
480 url.port = base.port;
481 url.path = arraySlice(base.path);
488 if (url.isSpecial() && (chr == '/' || chr == '\\')) {
489 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
490 } else if (chr == '/') {
493 url.username = base.username;
494 url.password = base.password;
495 url.host = base.host;
496 url.port = base.port;
501 case SPECIAL_AUTHORITY_SLASHES:
502 state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
503 if (chr != '/' || charAt(buffer, pointer + 1) != '/') continue;
507 case SPECIAL_AUTHORITY_IGNORE_SLASHES:
508 if (chr != '/' && chr != '\\') {
515 if (seenAt) buffer = '%40' + buffer;
517 bufferCodePoints = arrayFrom(buffer);
518 for (var i = 0; i < bufferCodePoints.length; i++) {
519 var codePoint = bufferCodePoints[i];
520 if (codePoint == ':' && !seenPasswordToken) {
521 seenPasswordToken = true;
524 var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet);
525 if (seenPasswordToken) url.password += encodedCodePoints;
526 else url.username += encodedCodePoints;
530 chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
531 (chr == '\\' && url.isSpecial())
533 if (seenAt && buffer == '') return INVALID_AUTHORITY;
534 pointer -= arrayFrom(buffer).length + 1;
537 } else buffer += chr;
542 if (stateOverride && url.scheme == 'file') {
545 } else if (chr == ':' && !seenBracket) {
546 if (buffer == '') return INVALID_HOST;
547 failure = url.parseHost(buffer);
548 if (failure) return failure;
551 if (stateOverride == HOSTNAME) return;
553 chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
554 (chr == '\\' && url.isSpecial())
556 if (url.isSpecial() && buffer == '') return INVALID_HOST;
557 if (stateOverride && buffer == '' && (url.includesCredentials() || url.port !== null)) return;
558 failure = url.parseHost(buffer);
559 if (failure) return failure;
562 if (stateOverride) return;
565 if (chr == '[') seenBracket = true;
566 else if (chr == ']') seenBracket = false;
571 if (exec(DIGIT, chr)) {
574 chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
575 (chr == '\\' && url.isSpecial()) ||
579 var port = parseInt(buffer, 10);
580 if (port > 0xFFFF) return INVALID_PORT;
581 url.port = (url.isSpecial() && port === specialSchemes[url.scheme]) ? null : port;
584 if (stateOverride) return;
587 } else return INVALID_PORT;
592 if (chr == '/' || chr == '\\') state = FILE_SLASH;
593 else if (base && base.scheme == 'file') {
595 url.host = base.host;
596 url.path = arraySlice(base.path);
597 url.query = base.query;
598 } else if (chr == '?') {
599 url.host = base.host;
600 url.path = arraySlice(base.path);
603 } else if (chr == '#') {
604 url.host = base.host;
605 url.path = arraySlice(base.path);
606 url.query = base.query;
610 if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
611 url.host = base.host;
612 url.path = arraySlice(base.path);
624 if (chr == '/' || chr == '\\') {
628 if (base && base.scheme == 'file' && !startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
629 if (isWindowsDriveLetter(base.path[0], true)) push(url.path, base.path[0]);
630 else url.host = base.host;
636 if (chr == EOF || chr == '/' || chr == '\\' || chr == '?' || chr == '#') {
637 if (!stateOverride && isWindowsDriveLetter(buffer)) {
639 } else if (buffer == '') {
641 if (stateOverride) return;
644 failure = url.parseHost(buffer);
645 if (failure) return failure;
646 if (url.host == 'localhost') url.host = '';
647 if (stateOverride) return;
651 } else buffer += chr;
655 if (url.isSpecial()) {
657 if (chr != '/' && chr != '\\') continue;
658 } else if (!stateOverride && chr == '?') {
661 } else if (!stateOverride && chr == '#') {
664 } else if (chr != EOF) {
666 if (chr != '/') continue;
671 chr == EOF || chr == '/' ||
672 (chr == '\\' && url.isSpecial()) ||
673 (!stateOverride && (chr == '?' || chr == '#'))
675 if (isDoubleDot(buffer)) {
677 if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
680 } else if (isSingleDot(buffer)) {
681 if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
685 if (url.scheme == 'file' && !url.path.length && isWindowsDriveLetter(buffer)) {
686 if (url.host) url.host = '';
687 buffer = charAt(buffer, 0) + ':'; // normalize windows drive letter
689 push(url.path, buffer);
692 if (url.scheme == 'file' && (chr == EOF || chr == '?' || chr == '#')) {
693 while (url.path.length > 1 && url.path[0] === '') {
700 } else if (chr == '#') {
705 buffer += percentEncode(chr, pathPercentEncodeSet);
708 case CANNOT_BE_A_BASE_URL_PATH:
712 } else if (chr == '#') {
715 } else if (chr != EOF) {
716 url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet);
720 if (!stateOverride && chr == '#') {
723 } else if (chr != EOF) {
724 if (chr == "'" && url.isSpecial()) url.query += '%27';
725 else if (chr == '#') url.query += '%23';
726 else url.query += percentEncode(chr, C0ControlPercentEncodeSet);
730 if (chr != EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet);
737 // https://url.spec.whatwg.org/#host-parsing
738 parseHost: function (input) {
739 var result, codePoints, index;
740 if (charAt(input, 0) == '[') {
741 if (charAt(input, input.length - 1) != ']') return INVALID_HOST;
742 result = parseIPv6(stringSlice(input, 1, -1));
743 if (!result) return INVALID_HOST;
746 } else if (!this.isSpecial()) {
747 if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST;
749 codePoints = arrayFrom(input);
750 for (index = 0; index < codePoints.length; index++) {
751 result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
755 input = toASCII(input);
756 if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST;
757 result = parseIPv4(input);
758 if (result === null) return INVALID_HOST;
762 // https://url.spec.whatwg.org/#cannot-have-a-username-password-port
763 cannotHaveUsernamePasswordPort: function () {
764 return !this.host || this.cannotBeABaseURL || this.scheme == 'file';
766 // https://url.spec.whatwg.org/#include-credentials
767 includesCredentials: function () {
768 return this.username != '' || this.password != '';
770 // https://url.spec.whatwg.org/#is-special
771 isSpecial: function () {
772 return hasOwn(specialSchemes, this.scheme);
774 // https://url.spec.whatwg.org/#shorten-a-urls-path
775 shortenPath: function () {
776 var path = this.path;
777 var pathSize = path.length;
778 if (pathSize && (this.scheme != 'file' || pathSize != 1 || !isWindowsDriveLetter(path[0], true))) {
782 // https://url.spec.whatwg.org/#concept-url-serializer
783 serialize: function () {
785 var scheme = url.scheme;
786 var username = url.username;
787 var password = url.password;
791 var query = url.query;
792 var fragment = url.fragment;
793 var output = scheme + ':';
796 if (url.includesCredentials()) {
797 output += username + (password ? ':' + password : '') + '@';
799 output += serializeHost(host);
800 if (port !== null) output += ':' + port;
801 } else if (scheme == 'file') output += '//';
802 output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
803 if (query !== null) output += '?' + query;
804 if (fragment !== null) output += '#' + fragment;
807 // https://url.spec.whatwg.org/#dom-url-href
808 setHref: function (href) {
809 var failure = this.parse(href);
810 if (failure) throw TypeError(failure);
811 this.searchParams.update();
813 // https://url.spec.whatwg.org/#dom-url-origin
814 getOrigin: function () {
815 var scheme = this.scheme;
816 var port = this.port;
817 if (scheme == 'blob') try {
818 return new URLConstructor(scheme.path[0]).origin;
822 if (scheme == 'file' || !this.isSpecial()) return 'null';
823 return scheme + '://' + serializeHost(this.host) + (port !== null ? ':' + port : '');
825 // https://url.spec.whatwg.org/#dom-url-protocol
826 getProtocol: function () {
827 return this.scheme + ':';
829 setProtocol: function (protocol) {
830 this.parse($toString(protocol) + ':', SCHEME_START);
832 // https://url.spec.whatwg.org/#dom-url-username
833 getUsername: function () {
834 return this.username;
836 setUsername: function (username) {
837 var codePoints = arrayFrom($toString(username));
838 if (this.cannotHaveUsernamePasswordPort()) return;
840 for (var i = 0; i < codePoints.length; i++) {
841 this.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
844 // https://url.spec.whatwg.org/#dom-url-password
845 getPassword: function () {
846 return this.password;
848 setPassword: function (password) {
849 var codePoints = arrayFrom($toString(password));
850 if (this.cannotHaveUsernamePasswordPort()) return;
852 for (var i = 0; i < codePoints.length; i++) {
853 this.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
856 // https://url.spec.whatwg.org/#dom-url-host
857 getHost: function () {
858 var host = this.host;
859 var port = this.port;
860 return host === null ? ''
861 : port === null ? serializeHost(host)
862 : serializeHost(host) + ':' + port;
864 setHost: function (host) {
865 if (this.cannotBeABaseURL) return;
866 this.parse(host, HOST);
868 // https://url.spec.whatwg.org/#dom-url-hostname
869 getHostname: function () {
870 var host = this.host;
871 return host === null ? '' : serializeHost(host);
873 setHostname: function (hostname) {
874 if (this.cannotBeABaseURL) return;
875 this.parse(hostname, HOSTNAME);
877 // https://url.spec.whatwg.org/#dom-url-port
878 getPort: function () {
879 var port = this.port;
880 return port === null ? '' : $toString(port);
882 setPort: function (port) {
883 if (this.cannotHaveUsernamePasswordPort()) return;
884 port = $toString(port);
885 if (port == '') this.port = null;
886 else this.parse(port, PORT);
888 // https://url.spec.whatwg.org/#dom-url-pathname
889 getPathname: function () {
890 var path = this.path;
891 return this.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
893 setPathname: function (pathname) {
894 if (this.cannotBeABaseURL) return;
896 this.parse(pathname, PATH_START);
898 // https://url.spec.whatwg.org/#dom-url-search
899 getSearch: function () {
900 var query = this.query;
901 return query ? '?' + query : '';
903 setSearch: function (search) {
904 search = $toString(search);
908 if ('?' == charAt(search, 0)) search = stringSlice(search, 1);
910 this.parse(search, QUERY);
912 this.searchParams.update();
914 // https://url.spec.whatwg.org/#dom-url-searchparams
915 getSearchParams: function () {
916 return this.searchParams.facade;
918 // https://url.spec.whatwg.org/#dom-url-hash
919 getHash: function () {
920 var fragment = this.fragment;
921 return fragment ? '#' + fragment : '';
923 setHash: function (hash) {
924 hash = $toString(hash);
926 this.fragment = null;
929 if ('#' == charAt(hash, 0)) hash = stringSlice(hash, 1);
931 this.parse(hash, FRAGMENT);
933 update: function () {
934 this.query = this.searchParams.serialize() || null;
939 // https://url.spec.whatwg.org/#url-class
940 var URLConstructor = function URL(url /* , base */) {
941 var that = anInstance(this, URLPrototype);
942 var base = arguments.length > 1 ? arguments[1] : undefined;
943 var state = setInternalState(that, new URLState(url, false, base));
945 that.href = state.serialize();
946 that.origin = state.getOrigin();
947 that.protocol = state.getProtocol();
948 that.username = state.getUsername();
949 that.password = state.getPassword();
950 that.host = state.getHost();
951 that.hostname = state.getHostname();
952 that.port = state.getPort();
953 that.pathname = state.getPathname();
954 that.search = state.getSearch();
955 that.searchParams = state.getSearchParams();
956 that.hash = state.getHash();
960 var URLPrototype = URLConstructor.prototype;
962 var accessorDescriptor = function (getter, setter) {
965 return getInternalURLState(this)[getter]();
967 set: setter && function (value) {
968 return getInternalURLState(this)[setter](value);
976 defineProperties(URLPrototype, {
977 // `URL.prototype.href` accessors pair
978 // https://url.spec.whatwg.org/#dom-url-href
979 href: accessorDescriptor('serialize', 'setHref'),
980 // `URL.prototype.origin` getter
981 // https://url.spec.whatwg.org/#dom-url-origin
982 origin: accessorDescriptor('getOrigin'),
983 // `URL.prototype.protocol` accessors pair
984 // https://url.spec.whatwg.org/#dom-url-protocol
985 protocol: accessorDescriptor('getProtocol', 'setProtocol'),
986 // `URL.prototype.username` accessors pair
987 // https://url.spec.whatwg.org/#dom-url-username
988 username: accessorDescriptor('getUsername', 'setUsername'),
989 // `URL.prototype.password` accessors pair
990 // https://url.spec.whatwg.org/#dom-url-password
991 password: accessorDescriptor('getPassword', 'setPassword'),
992 // `URL.prototype.host` accessors pair
993 // https://url.spec.whatwg.org/#dom-url-host
994 host: accessorDescriptor('getHost', 'setHost'),
995 // `URL.prototype.hostname` accessors pair
996 // https://url.spec.whatwg.org/#dom-url-hostname
997 hostname: accessorDescriptor('getHostname', 'setHostname'),
998 // `URL.prototype.port` accessors pair
999 // https://url.spec.whatwg.org/#dom-url-port
1000 port: accessorDescriptor('getPort', 'setPort'),
1001 // `URL.prototype.pathname` accessors pair
1002 // https://url.spec.whatwg.org/#dom-url-pathname
1003 pathname: accessorDescriptor('getPathname', 'setPathname'),
1004 // `URL.prototype.search` accessors pair
1005 // https://url.spec.whatwg.org/#dom-url-search
1006 search: accessorDescriptor('getSearch', 'setSearch'),
1007 // `URL.prototype.searchParams` getter
1008 // https://url.spec.whatwg.org/#dom-url-searchparams
1009 searchParams: accessorDescriptor('getSearchParams'),
1010 // `URL.prototype.hash` accessors pair
1011 // https://url.spec.whatwg.org/#dom-url-hash
1012 hash: accessorDescriptor('getHash', 'setHash')
1016 // `URL.prototype.toJSON` method
1017 // https://url.spec.whatwg.org/#dom-url-tojson
1018 redefine(URLPrototype, 'toJSON', function toJSON() {
1019 return getInternalURLState(this).serialize();
1020 }, { enumerable: true });
1022 // `URL.prototype.toString` method
1023 // https://url.spec.whatwg.org/#URL-stringification-behavior
1024 redefine(URLPrototype, 'toString', function toString() {
1025 return getInternalURLState(this).serialize();
1026 }, { enumerable: true });
1029 var nativeCreateObjectURL = NativeURL.createObjectURL;
1030 var nativeRevokeObjectURL = NativeURL.revokeObjectURL;
1031 // `URL.createObjectURL` method
1032 // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
1033 if (nativeCreateObjectURL) redefine(URLConstructor, 'createObjectURL', bind(nativeCreateObjectURL, NativeURL));
1034 // `URL.revokeObjectURL` method
1035 // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
1036 if (nativeRevokeObjectURL) redefine(URLConstructor, 'revokeObjectURL', bind(nativeRevokeObjectURL, NativeURL));
1039 setToStringTag(URLConstructor, 'URL');
1041 $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {