.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / core-js / modules / web.url.js
1 'use strict';
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 defineProperties = require('../internals/object-define-properties');
9 var redefine = require('../internals/redefine');
10 var anInstance = require('../internals/an-instance');
11 var has = require('../internals/has');
12 var assign = require('../internals/object-assign');
13 var arrayFrom = require('../internals/array-from');
14 var codeAt = require('../internals/string-multibyte').codeAt;
15 var toASCII = require('../internals/string-punycode-to-ascii');
16 var setToStringTag = require('../internals/set-to-string-tag');
17 var URLSearchParamsModule = require('../modules/web.url-search-params');
18 var InternalStateModule = require('../internals/internal-state');
19
20 var NativeURL = global.URL;
21 var URLSearchParams = URLSearchParamsModule.URLSearchParams;
22 var getInternalSearchParamsState = URLSearchParamsModule.getState;
23 var setInternalState = InternalStateModule.set;
24 var getInternalURLState = InternalStateModule.getterFor('URL');
25 var floor = Math.floor;
26 var pow = Math.pow;
27
28 var INVALID_AUTHORITY = 'Invalid authority';
29 var INVALID_SCHEME = 'Invalid scheme';
30 var INVALID_HOST = 'Invalid host';
31 var INVALID_PORT = 'Invalid port';
32
33 var ALPHA = /[A-Za-z]/;
34 var ALPHANUMERIC = /[\d+-.A-Za-z]/;
35 var DIGIT = /\d/;
36 var HEX_START = /^(0x|0X)/;
37 var OCT = /^[0-7]+$/;
38 var DEC = /^\d+$/;
39 var HEX = /^[\dA-Fa-f]+$/;
40 /* eslint-disable no-control-regex -- safe */
41 var FORBIDDEN_HOST_CODE_POINT = /[\u0000\t\u000A\u000D #%/:?@[\\]]/;
42 var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\u0000\t\u000A\u000D #/:?@[\\]]/;
43 var LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE = /^[\u0000-\u001F ]+|[\u0000-\u001F ]+$/g;
44 var TAB_AND_NEW_LINE = /[\t\u000A\u000D]/g;
45 /* eslint-enable no-control-regex -- safe */
46 var EOF;
47
48 var parseHost = function (url, input) {
49   var result, codePoints, index;
50   if (input.charAt(0) == '[') {
51     if (input.charAt(input.length - 1) != ']') return INVALID_HOST;
52     result = parseIPv6(input.slice(1, -1));
53     if (!result) return INVALID_HOST;
54     url.host = result;
55   // opaque host
56   } else if (!isSpecial(url)) {
57     if (FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT.test(input)) return INVALID_HOST;
58     result = '';
59     codePoints = arrayFrom(input);
60     for (index = 0; index < codePoints.length; index++) {
61       result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
62     }
63     url.host = result;
64   } else {
65     input = toASCII(input);
66     if (FORBIDDEN_HOST_CODE_POINT.test(input)) return INVALID_HOST;
67     result = parseIPv4(input);
68     if (result === null) return INVALID_HOST;
69     url.host = result;
70   }
71 };
72
73 var parseIPv4 = function (input) {
74   var parts = input.split('.');
75   var partsLength, numbers, index, part, radix, number, ipv4;
76   if (parts.length && parts[parts.length - 1] == '') {
77     parts.pop();
78   }
79   partsLength = parts.length;
80   if (partsLength > 4) return input;
81   numbers = [];
82   for (index = 0; index < partsLength; index++) {
83     part = parts[index];
84     if (part == '') return input;
85     radix = 10;
86     if (part.length > 1 && part.charAt(0) == '0') {
87       radix = HEX_START.test(part) ? 16 : 8;
88       part = part.slice(radix == 8 ? 1 : 2);
89     }
90     if (part === '') {
91       number = 0;
92     } else {
93       if (!(radix == 10 ? DEC : radix == 8 ? OCT : HEX).test(part)) return input;
94       number = parseInt(part, radix);
95     }
96     numbers.push(number);
97   }
98   for (index = 0; index < partsLength; index++) {
99     number = numbers[index];
100     if (index == partsLength - 1) {
101       if (number >= pow(256, 5 - partsLength)) return null;
102     } else if (number > 255) return null;
103   }
104   ipv4 = numbers.pop();
105   for (index = 0; index < numbers.length; index++) {
106     ipv4 += numbers[index] * pow(256, 3 - index);
107   }
108   return ipv4;
109 };
110
111 // eslint-disable-next-line max-statements -- TODO
112 var parseIPv6 = function (input) {
113   var address = [0, 0, 0, 0, 0, 0, 0, 0];
114   var pieceIndex = 0;
115   var compress = null;
116   var pointer = 0;
117   var value, length, numbersSeen, ipv4Piece, number, swaps, swap;
118
119   var char = function () {
120     return input.charAt(pointer);
121   };
122
123   if (char() == ':') {
124     if (input.charAt(1) != ':') return;
125     pointer += 2;
126     pieceIndex++;
127     compress = pieceIndex;
128   }
129   while (char()) {
130     if (pieceIndex == 8) return;
131     if (char() == ':') {
132       if (compress !== null) return;
133       pointer++;
134       pieceIndex++;
135       compress = pieceIndex;
136       continue;
137     }
138     value = length = 0;
139     while (length < 4 && HEX.test(char())) {
140       value = value * 16 + parseInt(char(), 16);
141       pointer++;
142       length++;
143     }
144     if (char() == '.') {
145       if (length == 0) return;
146       pointer -= length;
147       if (pieceIndex > 6) return;
148       numbersSeen = 0;
149       while (char()) {
150         ipv4Piece = null;
151         if (numbersSeen > 0) {
152           if (char() == '.' && numbersSeen < 4) pointer++;
153           else return;
154         }
155         if (!DIGIT.test(char())) return;
156         while (DIGIT.test(char())) {
157           number = parseInt(char(), 10);
158           if (ipv4Piece === null) ipv4Piece = number;
159           else if (ipv4Piece == 0) return;
160           else ipv4Piece = ipv4Piece * 10 + number;
161           if (ipv4Piece > 255) return;
162           pointer++;
163         }
164         address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece;
165         numbersSeen++;
166         if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++;
167       }
168       if (numbersSeen != 4) return;
169       break;
170     } else if (char() == ':') {
171       pointer++;
172       if (!char()) return;
173     } else if (char()) return;
174     address[pieceIndex++] = value;
175   }
176   if (compress !== null) {
177     swaps = pieceIndex - compress;
178     pieceIndex = 7;
179     while (pieceIndex != 0 && swaps > 0) {
180       swap = address[pieceIndex];
181       address[pieceIndex--] = address[compress + swaps - 1];
182       address[compress + --swaps] = swap;
183     }
184   } else if (pieceIndex != 8) return;
185   return address;
186 };
187
188 var findLongestZeroSequence = function (ipv6) {
189   var maxIndex = null;
190   var maxLength = 1;
191   var currStart = null;
192   var currLength = 0;
193   var index = 0;
194   for (; index < 8; index++) {
195     if (ipv6[index] !== 0) {
196       if (currLength > maxLength) {
197         maxIndex = currStart;
198         maxLength = currLength;
199       }
200       currStart = null;
201       currLength = 0;
202     } else {
203       if (currStart === null) currStart = index;
204       ++currLength;
205     }
206   }
207   if (currLength > maxLength) {
208     maxIndex = currStart;
209     maxLength = currLength;
210   }
211   return maxIndex;
212 };
213
214 var serializeHost = function (host) {
215   var result, index, compress, ignore0;
216   // ipv4
217   if (typeof host == 'number') {
218     result = [];
219     for (index = 0; index < 4; index++) {
220       result.unshift(host % 256);
221       host = floor(host / 256);
222     } return result.join('.');
223   // ipv6
224   } else if (typeof host == 'object') {
225     result = '';
226     compress = findLongestZeroSequence(host);
227     for (index = 0; index < 8; index++) {
228       if (ignore0 && host[index] === 0) continue;
229       if (ignore0) ignore0 = false;
230       if (compress === index) {
231         result += index ? ':' : '::';
232         ignore0 = true;
233       } else {
234         result += host[index].toString(16);
235         if (index < 7) result += ':';
236       }
237     }
238     return '[' + result + ']';
239   } return host;
240 };
241
242 var C0ControlPercentEncodeSet = {};
243 var fragmentPercentEncodeSet = assign({}, C0ControlPercentEncodeSet, {
244   ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1
245 });
246 var pathPercentEncodeSet = assign({}, fragmentPercentEncodeSet, {
247   '#': 1, '?': 1, '{': 1, '}': 1
248 });
249 var userinfoPercentEncodeSet = assign({}, pathPercentEncodeSet, {
250   '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1
251 });
252
253 var percentEncode = function (char, set) {
254   var code = codeAt(char, 0);
255   return code > 0x20 && code < 0x7F && !has(set, char) ? char : encodeURIComponent(char);
256 };
257
258 var specialSchemes = {
259   ftp: 21,
260   file: null,
261   http: 80,
262   https: 443,
263   ws: 80,
264   wss: 443
265 };
266
267 var isSpecial = function (url) {
268   return has(specialSchemes, url.scheme);
269 };
270
271 var includesCredentials = function (url) {
272   return url.username != '' || url.password != '';
273 };
274
275 var cannotHaveUsernamePasswordPort = function (url) {
276   return !url.host || url.cannotBeABaseURL || url.scheme == 'file';
277 };
278
279 var isWindowsDriveLetter = function (string, normalized) {
280   var second;
281   return string.length == 2 && ALPHA.test(string.charAt(0))
282     && ((second = string.charAt(1)) == ':' || (!normalized && second == '|'));
283 };
284
285 var startsWithWindowsDriveLetter = function (string) {
286   var third;
287   return string.length > 1 && isWindowsDriveLetter(string.slice(0, 2)) && (
288     string.length == 2 ||
289     ((third = string.charAt(2)) === '/' || third === '\\' || third === '?' || third === '#')
290   );
291 };
292
293 var shortenURLsPath = function (url) {
294   var path = url.path;
295   var pathSize = path.length;
296   if (pathSize && (url.scheme != 'file' || pathSize != 1 || !isWindowsDriveLetter(path[0], true))) {
297     path.pop();
298   }
299 };
300
301 var isSingleDot = function (segment) {
302   return segment === '.' || segment.toLowerCase() === '%2e';
303 };
304
305 var isDoubleDot = function (segment) {
306   segment = segment.toLowerCase();
307   return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e';
308 };
309
310 // States:
311 var SCHEME_START = {};
312 var SCHEME = {};
313 var NO_SCHEME = {};
314 var SPECIAL_RELATIVE_OR_AUTHORITY = {};
315 var PATH_OR_AUTHORITY = {};
316 var RELATIVE = {};
317 var RELATIVE_SLASH = {};
318 var SPECIAL_AUTHORITY_SLASHES = {};
319 var SPECIAL_AUTHORITY_IGNORE_SLASHES = {};
320 var AUTHORITY = {};
321 var HOST = {};
322 var HOSTNAME = {};
323 var PORT = {};
324 var FILE = {};
325 var FILE_SLASH = {};
326 var FILE_HOST = {};
327 var PATH_START = {};
328 var PATH = {};
329 var CANNOT_BE_A_BASE_URL_PATH = {};
330 var QUERY = {};
331 var FRAGMENT = {};
332
333 // eslint-disable-next-line max-statements -- TODO
334 var parseURL = function (url, input, stateOverride, base) {
335   var state = stateOverride || SCHEME_START;
336   var pointer = 0;
337   var buffer = '';
338   var seenAt = false;
339   var seenBracket = false;
340   var seenPasswordToken = false;
341   var codePoints, char, bufferCodePoints, failure;
342
343   if (!stateOverride) {
344     url.scheme = '';
345     url.username = '';
346     url.password = '';
347     url.host = null;
348     url.port = null;
349     url.path = [];
350     url.query = null;
351     url.fragment = null;
352     url.cannotBeABaseURL = false;
353     input = input.replace(LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, '');
354   }
355
356   input = input.replace(TAB_AND_NEW_LINE, '');
357
358   codePoints = arrayFrom(input);
359
360   while (pointer <= codePoints.length) {
361     char = codePoints[pointer];
362     switch (state) {
363       case SCHEME_START:
364         if (char && ALPHA.test(char)) {
365           buffer += char.toLowerCase();
366           state = SCHEME;
367         } else if (!stateOverride) {
368           state = NO_SCHEME;
369           continue;
370         } else return INVALID_SCHEME;
371         break;
372
373       case SCHEME:
374         if (char && (ALPHANUMERIC.test(char) || char == '+' || char == '-' || char == '.')) {
375           buffer += char.toLowerCase();
376         } else if (char == ':') {
377           if (stateOverride && (
378             (isSpecial(url) != has(specialSchemes, buffer)) ||
379             (buffer == 'file' && (includesCredentials(url) || url.port !== null)) ||
380             (url.scheme == 'file' && !url.host)
381           )) return;
382           url.scheme = buffer;
383           if (stateOverride) {
384             if (isSpecial(url) && specialSchemes[url.scheme] == url.port) url.port = null;
385             return;
386           }
387           buffer = '';
388           if (url.scheme == 'file') {
389             state = FILE;
390           } else if (isSpecial(url) && base && base.scheme == url.scheme) {
391             state = SPECIAL_RELATIVE_OR_AUTHORITY;
392           } else if (isSpecial(url)) {
393             state = SPECIAL_AUTHORITY_SLASHES;
394           } else if (codePoints[pointer + 1] == '/') {
395             state = PATH_OR_AUTHORITY;
396             pointer++;
397           } else {
398             url.cannotBeABaseURL = true;
399             url.path.push('');
400             state = CANNOT_BE_A_BASE_URL_PATH;
401           }
402         } else if (!stateOverride) {
403           buffer = '';
404           state = NO_SCHEME;
405           pointer = 0;
406           continue;
407         } else return INVALID_SCHEME;
408         break;
409
410       case NO_SCHEME:
411         if (!base || (base.cannotBeABaseURL && char != '#')) return INVALID_SCHEME;
412         if (base.cannotBeABaseURL && char == '#') {
413           url.scheme = base.scheme;
414           url.path = base.path.slice();
415           url.query = base.query;
416           url.fragment = '';
417           url.cannotBeABaseURL = true;
418           state = FRAGMENT;
419           break;
420         }
421         state = base.scheme == 'file' ? FILE : RELATIVE;
422         continue;
423
424       case SPECIAL_RELATIVE_OR_AUTHORITY:
425         if (char == '/' && codePoints[pointer + 1] == '/') {
426           state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
427           pointer++;
428         } else {
429           state = RELATIVE;
430           continue;
431         } break;
432
433       case PATH_OR_AUTHORITY:
434         if (char == '/') {
435           state = AUTHORITY;
436           break;
437         } else {
438           state = PATH;
439           continue;
440         }
441
442       case RELATIVE:
443         url.scheme = base.scheme;
444         if (char == EOF) {
445           url.username = base.username;
446           url.password = base.password;
447           url.host = base.host;
448           url.port = base.port;
449           url.path = base.path.slice();
450           url.query = base.query;
451         } else if (char == '/' || (char == '\\' && isSpecial(url))) {
452           state = RELATIVE_SLASH;
453         } else if (char == '?') {
454           url.username = base.username;
455           url.password = base.password;
456           url.host = base.host;
457           url.port = base.port;
458           url.path = base.path.slice();
459           url.query = '';
460           state = QUERY;
461         } else if (char == '#') {
462           url.username = base.username;
463           url.password = base.password;
464           url.host = base.host;
465           url.port = base.port;
466           url.path = base.path.slice();
467           url.query = base.query;
468           url.fragment = '';
469           state = FRAGMENT;
470         } else {
471           url.username = base.username;
472           url.password = base.password;
473           url.host = base.host;
474           url.port = base.port;
475           url.path = base.path.slice();
476           url.path.pop();
477           state = PATH;
478           continue;
479         } break;
480
481       case RELATIVE_SLASH:
482         if (isSpecial(url) && (char == '/' || char == '\\')) {
483           state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
484         } else if (char == '/') {
485           state = AUTHORITY;
486         } else {
487           url.username = base.username;
488           url.password = base.password;
489           url.host = base.host;
490           url.port = base.port;
491           state = PATH;
492           continue;
493         } break;
494
495       case SPECIAL_AUTHORITY_SLASHES:
496         state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
497         if (char != '/' || buffer.charAt(pointer + 1) != '/') continue;
498         pointer++;
499         break;
500
501       case SPECIAL_AUTHORITY_IGNORE_SLASHES:
502         if (char != '/' && char != '\\') {
503           state = AUTHORITY;
504           continue;
505         } break;
506
507       case AUTHORITY:
508         if (char == '@') {
509           if (seenAt) buffer = '%40' + buffer;
510           seenAt = true;
511           bufferCodePoints = arrayFrom(buffer);
512           for (var i = 0; i < bufferCodePoints.length; i++) {
513             var codePoint = bufferCodePoints[i];
514             if (codePoint == ':' && !seenPasswordToken) {
515               seenPasswordToken = true;
516               continue;
517             }
518             var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet);
519             if (seenPasswordToken) url.password += encodedCodePoints;
520             else url.username += encodedCodePoints;
521           }
522           buffer = '';
523         } else if (
524           char == EOF || char == '/' || char == '?' || char == '#' ||
525           (char == '\\' && isSpecial(url))
526         ) {
527           if (seenAt && buffer == '') return INVALID_AUTHORITY;
528           pointer -= arrayFrom(buffer).length + 1;
529           buffer = '';
530           state = HOST;
531         } else buffer += char;
532         break;
533
534       case HOST:
535       case HOSTNAME:
536         if (stateOverride && url.scheme == 'file') {
537           state = FILE_HOST;
538           continue;
539         } else if (char == ':' && !seenBracket) {
540           if (buffer == '') return INVALID_HOST;
541           failure = parseHost(url, buffer);
542           if (failure) return failure;
543           buffer = '';
544           state = PORT;
545           if (stateOverride == HOSTNAME) return;
546         } else if (
547           char == EOF || char == '/' || char == '?' || char == '#' ||
548           (char == '\\' && isSpecial(url))
549         ) {
550           if (isSpecial(url) && buffer == '') return INVALID_HOST;
551           if (stateOverride && buffer == '' && (includesCredentials(url) || url.port !== null)) return;
552           failure = parseHost(url, buffer);
553           if (failure) return failure;
554           buffer = '';
555           state = PATH_START;
556           if (stateOverride) return;
557           continue;
558         } else {
559           if (char == '[') seenBracket = true;
560           else if (char == ']') seenBracket = false;
561           buffer += char;
562         } break;
563
564       case PORT:
565         if (DIGIT.test(char)) {
566           buffer += char;
567         } else if (
568           char == EOF || char == '/' || char == '?' || char == '#' ||
569           (char == '\\' && isSpecial(url)) ||
570           stateOverride
571         ) {
572           if (buffer != '') {
573             var port = parseInt(buffer, 10);
574             if (port > 0xFFFF) return INVALID_PORT;
575             url.port = (isSpecial(url) && port === specialSchemes[url.scheme]) ? null : port;
576             buffer = '';
577           }
578           if (stateOverride) return;
579           state = PATH_START;
580           continue;
581         } else return INVALID_PORT;
582         break;
583
584       case FILE:
585         url.scheme = 'file';
586         if (char == '/' || char == '\\') state = FILE_SLASH;
587         else if (base && base.scheme == 'file') {
588           if (char == EOF) {
589             url.host = base.host;
590             url.path = base.path.slice();
591             url.query = base.query;
592           } else if (char == '?') {
593             url.host = base.host;
594             url.path = base.path.slice();
595             url.query = '';
596             state = QUERY;
597           } else if (char == '#') {
598             url.host = base.host;
599             url.path = base.path.slice();
600             url.query = base.query;
601             url.fragment = '';
602             state = FRAGMENT;
603           } else {
604             if (!startsWithWindowsDriveLetter(codePoints.slice(pointer).join(''))) {
605               url.host = base.host;
606               url.path = base.path.slice();
607               shortenURLsPath(url);
608             }
609             state = PATH;
610             continue;
611           }
612         } else {
613           state = PATH;
614           continue;
615         } break;
616
617       case FILE_SLASH:
618         if (char == '/' || char == '\\') {
619           state = FILE_HOST;
620           break;
621         }
622         if (base && base.scheme == 'file' && !startsWithWindowsDriveLetter(codePoints.slice(pointer).join(''))) {
623           if (isWindowsDriveLetter(base.path[0], true)) url.path.push(base.path[0]);
624           else url.host = base.host;
625         }
626         state = PATH;
627         continue;
628
629       case FILE_HOST:
630         if (char == EOF || char == '/' || char == '\\' || char == '?' || char == '#') {
631           if (!stateOverride && isWindowsDriveLetter(buffer)) {
632             state = PATH;
633           } else if (buffer == '') {
634             url.host = '';
635             if (stateOverride) return;
636             state = PATH_START;
637           } else {
638             failure = parseHost(url, buffer);
639             if (failure) return failure;
640             if (url.host == 'localhost') url.host = '';
641             if (stateOverride) return;
642             buffer = '';
643             state = PATH_START;
644           } continue;
645         } else buffer += char;
646         break;
647
648       case PATH_START:
649         if (isSpecial(url)) {
650           state = PATH;
651           if (char != '/' && char != '\\') continue;
652         } else if (!stateOverride && char == '?') {
653           url.query = '';
654           state = QUERY;
655         } else if (!stateOverride && char == '#') {
656           url.fragment = '';
657           state = FRAGMENT;
658         } else if (char != EOF) {
659           state = PATH;
660           if (char != '/') continue;
661         } break;
662
663       case PATH:
664         if (
665           char == EOF || char == '/' ||
666           (char == '\\' && isSpecial(url)) ||
667           (!stateOverride && (char == '?' || char == '#'))
668         ) {
669           if (isDoubleDot(buffer)) {
670             shortenURLsPath(url);
671             if (char != '/' && !(char == '\\' && isSpecial(url))) {
672               url.path.push('');
673             }
674           } else if (isSingleDot(buffer)) {
675             if (char != '/' && !(char == '\\' && isSpecial(url))) {
676               url.path.push('');
677             }
678           } else {
679             if (url.scheme == 'file' && !url.path.length && isWindowsDriveLetter(buffer)) {
680               if (url.host) url.host = '';
681               buffer = buffer.charAt(0) + ':'; // normalize windows drive letter
682             }
683             url.path.push(buffer);
684           }
685           buffer = '';
686           if (url.scheme == 'file' && (char == EOF || char == '?' || char == '#')) {
687             while (url.path.length > 1 && url.path[0] === '') {
688               url.path.shift();
689             }
690           }
691           if (char == '?') {
692             url.query = '';
693             state = QUERY;
694           } else if (char == '#') {
695             url.fragment = '';
696             state = FRAGMENT;
697           }
698         } else {
699           buffer += percentEncode(char, pathPercentEncodeSet);
700         } break;
701
702       case CANNOT_BE_A_BASE_URL_PATH:
703         if (char == '?') {
704           url.query = '';
705           state = QUERY;
706         } else if (char == '#') {
707           url.fragment = '';
708           state = FRAGMENT;
709         } else if (char != EOF) {
710           url.path[0] += percentEncode(char, C0ControlPercentEncodeSet);
711         } break;
712
713       case QUERY:
714         if (!stateOverride && char == '#') {
715           url.fragment = '';
716           state = FRAGMENT;
717         } else if (char != EOF) {
718           if (char == "'" && isSpecial(url)) url.query += '%27';
719           else if (char == '#') url.query += '%23';
720           else url.query += percentEncode(char, C0ControlPercentEncodeSet);
721         } break;
722
723       case FRAGMENT:
724         if (char != EOF) url.fragment += percentEncode(char, fragmentPercentEncodeSet);
725         break;
726     }
727
728     pointer++;
729   }
730 };
731
732 // `URL` constructor
733 // https://url.spec.whatwg.org/#url-class
734 var URLConstructor = function URL(url /* , base */) {
735   var that = anInstance(this, URLConstructor, 'URL');
736   var base = arguments.length > 1 ? arguments[1] : undefined;
737   var urlString = String(url);
738   var state = setInternalState(that, { type: 'URL' });
739   var baseState, failure;
740   if (base !== undefined) {
741     if (base instanceof URLConstructor) baseState = getInternalURLState(base);
742     else {
743       failure = parseURL(baseState = {}, String(base));
744       if (failure) throw TypeError(failure);
745     }
746   }
747   failure = parseURL(state, urlString, null, baseState);
748   if (failure) throw TypeError(failure);
749   var searchParams = state.searchParams = new URLSearchParams();
750   var searchParamsState = getInternalSearchParamsState(searchParams);
751   searchParamsState.updateSearchParams(state.query);
752   searchParamsState.updateURL = function () {
753     state.query = String(searchParams) || null;
754   };
755   if (!DESCRIPTORS) {
756     that.href = serializeURL.call(that);
757     that.origin = getOrigin.call(that);
758     that.protocol = getProtocol.call(that);
759     that.username = getUsername.call(that);
760     that.password = getPassword.call(that);
761     that.host = getHost.call(that);
762     that.hostname = getHostname.call(that);
763     that.port = getPort.call(that);
764     that.pathname = getPathname.call(that);
765     that.search = getSearch.call(that);
766     that.searchParams = getSearchParams.call(that);
767     that.hash = getHash.call(that);
768   }
769 };
770
771 var URLPrototype = URLConstructor.prototype;
772
773 var serializeURL = function () {
774   var url = getInternalURLState(this);
775   var scheme = url.scheme;
776   var username = url.username;
777   var password = url.password;
778   var host = url.host;
779   var port = url.port;
780   var path = url.path;
781   var query = url.query;
782   var fragment = url.fragment;
783   var output = scheme + ':';
784   if (host !== null) {
785     output += '//';
786     if (includesCredentials(url)) {
787       output += username + (password ? ':' + password : '') + '@';
788     }
789     output += serializeHost(host);
790     if (port !== null) output += ':' + port;
791   } else if (scheme == 'file') output += '//';
792   output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + path.join('/') : '';
793   if (query !== null) output += '?' + query;
794   if (fragment !== null) output += '#' + fragment;
795   return output;
796 };
797
798 var getOrigin = function () {
799   var url = getInternalURLState(this);
800   var scheme = url.scheme;
801   var port = url.port;
802   if (scheme == 'blob') try {
803     return new URL(scheme.path[0]).origin;
804   } catch (error) {
805     return 'null';
806   }
807   if (scheme == 'file' || !isSpecial(url)) return 'null';
808   return scheme + '://' + serializeHost(url.host) + (port !== null ? ':' + port : '');
809 };
810
811 var getProtocol = function () {
812   return getInternalURLState(this).scheme + ':';
813 };
814
815 var getUsername = function () {
816   return getInternalURLState(this).username;
817 };
818
819 var getPassword = function () {
820   return getInternalURLState(this).password;
821 };
822
823 var getHost = function () {
824   var url = getInternalURLState(this);
825   var host = url.host;
826   var port = url.port;
827   return host === null ? ''
828     : port === null ? serializeHost(host)
829     : serializeHost(host) + ':' + port;
830 };
831
832 var getHostname = function () {
833   var host = getInternalURLState(this).host;
834   return host === null ? '' : serializeHost(host);
835 };
836
837 var getPort = function () {
838   var port = getInternalURLState(this).port;
839   return port === null ? '' : String(port);
840 };
841
842 var getPathname = function () {
843   var url = getInternalURLState(this);
844   var path = url.path;
845   return url.cannotBeABaseURL ? path[0] : path.length ? '/' + path.join('/') : '';
846 };
847
848 var getSearch = function () {
849   var query = getInternalURLState(this).query;
850   return query ? '?' + query : '';
851 };
852
853 var getSearchParams = function () {
854   return getInternalURLState(this).searchParams;
855 };
856
857 var getHash = function () {
858   var fragment = getInternalURLState(this).fragment;
859   return fragment ? '#' + fragment : '';
860 };
861
862 var accessorDescriptor = function (getter, setter) {
863   return { get: getter, set: setter, configurable: true, enumerable: true };
864 };
865
866 if (DESCRIPTORS) {
867   defineProperties(URLPrototype, {
868     // `URL.prototype.href` accessors pair
869     // https://url.spec.whatwg.org/#dom-url-href
870     href: accessorDescriptor(serializeURL, function (href) {
871       var url = getInternalURLState(this);
872       var urlString = String(href);
873       var failure = parseURL(url, urlString);
874       if (failure) throw TypeError(failure);
875       getInternalSearchParamsState(url.searchParams).updateSearchParams(url.query);
876     }),
877     // `URL.prototype.origin` getter
878     // https://url.spec.whatwg.org/#dom-url-origin
879     origin: accessorDescriptor(getOrigin),
880     // `URL.prototype.protocol` accessors pair
881     // https://url.spec.whatwg.org/#dom-url-protocol
882     protocol: accessorDescriptor(getProtocol, function (protocol) {
883       var url = getInternalURLState(this);
884       parseURL(url, String(protocol) + ':', SCHEME_START);
885     }),
886     // `URL.prototype.username` accessors pair
887     // https://url.spec.whatwg.org/#dom-url-username
888     username: accessorDescriptor(getUsername, function (username) {
889       var url = getInternalURLState(this);
890       var codePoints = arrayFrom(String(username));
891       if (cannotHaveUsernamePasswordPort(url)) return;
892       url.username = '';
893       for (var i = 0; i < codePoints.length; i++) {
894         url.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
895       }
896     }),
897     // `URL.prototype.password` accessors pair
898     // https://url.spec.whatwg.org/#dom-url-password
899     password: accessorDescriptor(getPassword, function (password) {
900       var url = getInternalURLState(this);
901       var codePoints = arrayFrom(String(password));
902       if (cannotHaveUsernamePasswordPort(url)) return;
903       url.password = '';
904       for (var i = 0; i < codePoints.length; i++) {
905         url.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
906       }
907     }),
908     // `URL.prototype.host` accessors pair
909     // https://url.spec.whatwg.org/#dom-url-host
910     host: accessorDescriptor(getHost, function (host) {
911       var url = getInternalURLState(this);
912       if (url.cannotBeABaseURL) return;
913       parseURL(url, String(host), HOST);
914     }),
915     // `URL.prototype.hostname` accessors pair
916     // https://url.spec.whatwg.org/#dom-url-hostname
917     hostname: accessorDescriptor(getHostname, function (hostname) {
918       var url = getInternalURLState(this);
919       if (url.cannotBeABaseURL) return;
920       parseURL(url, String(hostname), HOSTNAME);
921     }),
922     // `URL.prototype.port` accessors pair
923     // https://url.spec.whatwg.org/#dom-url-port
924     port: accessorDescriptor(getPort, function (port) {
925       var url = getInternalURLState(this);
926       if (cannotHaveUsernamePasswordPort(url)) return;
927       port = String(port);
928       if (port == '') url.port = null;
929       else parseURL(url, port, PORT);
930     }),
931     // `URL.prototype.pathname` accessors pair
932     // https://url.spec.whatwg.org/#dom-url-pathname
933     pathname: accessorDescriptor(getPathname, function (pathname) {
934       var url = getInternalURLState(this);
935       if (url.cannotBeABaseURL) return;
936       url.path = [];
937       parseURL(url, pathname + '', PATH_START);
938     }),
939     // `URL.prototype.search` accessors pair
940     // https://url.spec.whatwg.org/#dom-url-search
941     search: accessorDescriptor(getSearch, function (search) {
942       var url = getInternalURLState(this);
943       search = String(search);
944       if (search == '') {
945         url.query = null;
946       } else {
947         if ('?' == search.charAt(0)) search = search.slice(1);
948         url.query = '';
949         parseURL(url, search, QUERY);
950       }
951       getInternalSearchParamsState(url.searchParams).updateSearchParams(url.query);
952     }),
953     // `URL.prototype.searchParams` getter
954     // https://url.spec.whatwg.org/#dom-url-searchparams
955     searchParams: accessorDescriptor(getSearchParams),
956     // `URL.prototype.hash` accessors pair
957     // https://url.spec.whatwg.org/#dom-url-hash
958     hash: accessorDescriptor(getHash, function (hash) {
959       var url = getInternalURLState(this);
960       hash = String(hash);
961       if (hash == '') {
962         url.fragment = null;
963         return;
964       }
965       if ('#' == hash.charAt(0)) hash = hash.slice(1);
966       url.fragment = '';
967       parseURL(url, hash, FRAGMENT);
968     })
969   });
970 }
971
972 // `URL.prototype.toJSON` method
973 // https://url.spec.whatwg.org/#dom-url-tojson
974 redefine(URLPrototype, 'toJSON', function toJSON() {
975   return serializeURL.call(this);
976 }, { enumerable: true });
977
978 // `URL.prototype.toString` method
979 // https://url.spec.whatwg.org/#URL-stringification-behavior
980 redefine(URLPrototype, 'toString', function toString() {
981   return serializeURL.call(this);
982 }, { enumerable: true });
983
984 if (NativeURL) {
985   var nativeCreateObjectURL = NativeURL.createObjectURL;
986   var nativeRevokeObjectURL = NativeURL.revokeObjectURL;
987   // `URL.createObjectURL` method
988   // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
989   // eslint-disable-next-line no-unused-vars -- required for `.length`
990   if (nativeCreateObjectURL) redefine(URLConstructor, 'createObjectURL', function createObjectURL(blob) {
991     return nativeCreateObjectURL.apply(NativeURL, arguments);
992   });
993   // `URL.revokeObjectURL` method
994   // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
995   // eslint-disable-next-line no-unused-vars -- required for `.length`
996   if (nativeRevokeObjectURL) redefine(URLConstructor, 'revokeObjectURL', function revokeObjectURL(url) {
997     return nativeRevokeObjectURL.apply(NativeURL, arguments);
998   });
999 }
1000
1001 setToStringTag(URLConstructor, 'URL');
1002
1003 $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {
1004   URL: URLConstructor
1005 });