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