massive update, probably broken
[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 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');
23
24 var setInternalState = InternalStateModule.set;
25 var getInternalURLState = InternalStateModule.getterFor('URL');
26 var URLSearchParams = URLSearchParamsModule.URLSearchParams;
27 var getInternalSearchParamsState = URLSearchParamsModule.getState;
28
29 var NativeURL = global.URL;
30 var TypeError = global.TypeError;
31 var parseInt = global.parseInt;
32 var floor = Math.floor;
33 var pow = Math.pow;
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);
46
47 var INVALID_AUTHORITY = 'Invalid authority';
48 var INVALID_SCHEME = 'Invalid scheme';
49 var INVALID_HOST = 'Invalid host';
50 var INVALID_PORT = 'Invalid port';
51
52 var ALPHA = /[a-z]/i;
53 // eslint-disable-next-line regexp/no-obscure-range -- safe
54 var ALPHANUMERIC = /[\d+-.a-z]/i;
55 var DIGIT = /\d/;
56 var HEX_START = /^0x/i;
57 var OCT = /^[0-7]+$/;
58 var DEC = /^\d+$/;
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 */
66 var EOF;
67
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] == '') {
73     parts.length--;
74   }
75   partsLength = parts.length;
76   if (partsLength > 4) return input;
77   numbers = [];
78   for (index = 0; index < partsLength; index++) {
79     part = parts[index];
80     if (part == '') return input;
81     radix = 10;
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);
85     }
86     if (part === '') {
87       number = 0;
88     } else {
89       if (!exec(radix == 10 ? DEC : radix == 8 ? OCT : HEX, part)) return input;
90       number = parseInt(part, radix);
91     }
92     push(numbers, number);
93   }
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;
99   }
100   ipv4 = pop(numbers);
101   for (index = 0; index < numbers.length; index++) {
102     ipv4 += numbers[index] * pow(256, 3 - index);
103   }
104   return ipv4;
105 };
106
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];
111   var pieceIndex = 0;
112   var compress = null;
113   var pointer = 0;
114   var value, length, numbersSeen, ipv4Piece, number, swaps, swap;
115
116   var chr = function () {
117     return charAt(input, pointer);
118   };
119
120   if (chr() == ':') {
121     if (charAt(input, 1) != ':') return;
122     pointer += 2;
123     pieceIndex++;
124     compress = pieceIndex;
125   }
126   while (chr()) {
127     if (pieceIndex == 8) return;
128     if (chr() == ':') {
129       if (compress !== null) return;
130       pointer++;
131       pieceIndex++;
132       compress = pieceIndex;
133       continue;
134     }
135     value = length = 0;
136     while (length < 4 && exec(HEX, chr())) {
137       value = value * 16 + parseInt(chr(), 16);
138       pointer++;
139       length++;
140     }
141     if (chr() == '.') {
142       if (length == 0) return;
143       pointer -= length;
144       if (pieceIndex > 6) return;
145       numbersSeen = 0;
146       while (chr()) {
147         ipv4Piece = null;
148         if (numbersSeen > 0) {
149           if (chr() == '.' && numbersSeen < 4) pointer++;
150           else return;
151         }
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;
159           pointer++;
160         }
161         address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece;
162         numbersSeen++;
163         if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++;
164       }
165       if (numbersSeen != 4) return;
166       break;
167     } else if (chr() == ':') {
168       pointer++;
169       if (!chr()) return;
170     } else if (chr()) return;
171     address[pieceIndex++] = value;
172   }
173   if (compress !== null) {
174     swaps = pieceIndex - compress;
175     pieceIndex = 7;
176     while (pieceIndex != 0 && swaps > 0) {
177       swap = address[pieceIndex];
178       address[pieceIndex--] = address[compress + swaps - 1];
179       address[compress + --swaps] = swap;
180     }
181   } else if (pieceIndex != 8) return;
182   return address;
183 };
184
185 var findLongestZeroSequence = function (ipv6) {
186   var maxIndex = null;
187   var maxLength = 1;
188   var currStart = null;
189   var currLength = 0;
190   var index = 0;
191   for (; index < 8; index++) {
192     if (ipv6[index] !== 0) {
193       if (currLength > maxLength) {
194         maxIndex = currStart;
195         maxLength = currLength;
196       }
197       currStart = null;
198       currLength = 0;
199     } else {
200       if (currStart === null) currStart = index;
201       ++currLength;
202     }
203   }
204   if (currLength > maxLength) {
205     maxIndex = currStart;
206     maxLength = currLength;
207   }
208   return maxIndex;
209 };
210
211 // https://url.spec.whatwg.org/#host-serializing
212 var serializeHost = function (host) {
213   var result, index, compress, ignore0;
214   // ipv4
215   if (typeof host == 'number') {
216     result = [];
217     for (index = 0; index < 4; index++) {
218       unshift(result, host % 256);
219       host = floor(host / 256);
220     } return join(result, '.');
221   // ipv6
222   } else if (typeof host == 'object') {
223     result = '';
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 ? ':' : '::';
230         ignore0 = true;
231       } else {
232         result += numberToString(host[index], 16);
233         if (index < 7) result += ':';
234       }
235     }
236     return '[' + result + ']';
237   } return host;
238 };
239
240 var C0ControlPercentEncodeSet = {};
241 var fragmentPercentEncodeSet = assign({}, C0ControlPercentEncodeSet, {
242   ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1
243 });
244 var pathPercentEncodeSet = assign({}, fragmentPercentEncodeSet, {
245   '#': 1, '?': 1, '{': 1, '}': 1
246 });
247 var userinfoPercentEncodeSet = assign({}, pathPercentEncodeSet, {
248   '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1
249 });
250
251 var percentEncode = function (chr, set) {
252   var code = codeAt(chr, 0);
253   return code > 0x20 && code < 0x7F && !hasOwn(set, chr) ? chr : encodeURIComponent(chr);
254 };
255
256 // https://url.spec.whatwg.org/#special-scheme
257 var specialSchemes = {
258   ftp: 21,
259   file: null,
260   http: 80,
261   https: 443,
262   ws: 80,
263   wss: 443
264 };
265
266 // https://url.spec.whatwg.org/#windows-drive-letter
267 var isWindowsDriveLetter = function (string, normalized) {
268   var second;
269   return string.length == 2 && exec(ALPHA, charAt(string, 0))
270     && ((second = charAt(string, 1)) == ':' || (!normalized && second == '|'));
271 };
272
273 // https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
274 var startsWithWindowsDriveLetter = function (string) {
275   var third;
276   return string.length > 1 && isWindowsDriveLetter(stringSlice(string, 0, 2)) && (
277     string.length == 2 ||
278     ((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#')
279   );
280 };
281
282 // https://url.spec.whatwg.org/#single-dot-path-segment
283 var isSingleDot = function (segment) {
284   return segment === '.' || toLowerCase(segment) === '%2e';
285 };
286
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';
291 };
292
293 // States:
294 var SCHEME_START = {};
295 var SCHEME = {};
296 var NO_SCHEME = {};
297 var SPECIAL_RELATIVE_OR_AUTHORITY = {};
298 var PATH_OR_AUTHORITY = {};
299 var RELATIVE = {};
300 var RELATIVE_SLASH = {};
301 var SPECIAL_AUTHORITY_SLASHES = {};
302 var SPECIAL_AUTHORITY_IGNORE_SLASHES = {};
303 var AUTHORITY = {};
304 var HOST = {};
305 var HOSTNAME = {};
306 var PORT = {};
307 var FILE = {};
308 var FILE_SLASH = {};
309 var FILE_HOST = {};
310 var PATH_START = {};
311 var PATH = {};
312 var CANNOT_BE_A_BASE_URL_PATH = {};
313 var QUERY = {};
314 var FRAGMENT = {};
315
316 var URLState = function (url, isBase, base) {
317   var urlString = $toString(url);
318   var baseState, failure, searchParams;
319   if (isBase) {
320     failure = this.parse(urlString);
321     if (failure) throw TypeError(failure);
322     this.searchParams = null;
323   } else {
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;
330   }
331 };
332
333 URLState.prototype = {
334   type: 'URL',
335   // https://url.spec.whatwg.org/#url-parsing
336   // eslint-disable-next-line max-statements -- TODO
337   parse: function (input, stateOverride, base) {
338     var url = this;
339     var state = stateOverride || SCHEME_START;
340     var pointer = 0;
341     var buffer = '';
342     var seenAt = false;
343     var seenBracket = false;
344     var seenPasswordToken = false;
345     var codePoints, chr, bufferCodePoints, failure;
346
347     input = $toString(input);
348
349     if (!stateOverride) {
350       url.scheme = '';
351       url.username = '';
352       url.password = '';
353       url.host = null;
354       url.port = null;
355       url.path = [];
356       url.query = null;
357       url.fragment = null;
358       url.cannotBeABaseURL = false;
359       input = replace(input, LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, '');
360     }
361
362     input = replace(input, TAB_AND_NEW_LINE, '');
363
364     codePoints = arrayFrom(input);
365
366     while (pointer <= codePoints.length) {
367       chr = codePoints[pointer];
368       switch (state) {
369         case SCHEME_START:
370           if (chr && exec(ALPHA, chr)) {
371             buffer += toLowerCase(chr);
372             state = SCHEME;
373           } else if (!stateOverride) {
374             state = NO_SCHEME;
375             continue;
376           } else return INVALID_SCHEME;
377           break;
378
379         case 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)
387             )) return;
388             url.scheme = buffer;
389             if (stateOverride) {
390               if (url.isSpecial() && specialSchemes[url.scheme] == url.port) url.port = null;
391               return;
392             }
393             buffer = '';
394             if (url.scheme == 'file') {
395               state = 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;
402               pointer++;
403             } else {
404               url.cannotBeABaseURL = true;
405               push(url.path, '');
406               state = CANNOT_BE_A_BASE_URL_PATH;
407             }
408           } else if (!stateOverride) {
409             buffer = '';
410             state = NO_SCHEME;
411             pointer = 0;
412             continue;
413           } else return INVALID_SCHEME;
414           break;
415
416         case NO_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;
422             url.fragment = '';
423             url.cannotBeABaseURL = true;
424             state = FRAGMENT;
425             break;
426           }
427           state = base.scheme == 'file' ? FILE : RELATIVE;
428           continue;
429
430         case SPECIAL_RELATIVE_OR_AUTHORITY:
431           if (chr == '/' && codePoints[pointer + 1] == '/') {
432             state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
433             pointer++;
434           } else {
435             state = RELATIVE;
436             continue;
437           } break;
438
439         case PATH_OR_AUTHORITY:
440           if (chr == '/') {
441             state = AUTHORITY;
442             break;
443           } else {
444             state = PATH;
445             continue;
446           }
447
448         case RELATIVE:
449           url.scheme = base.scheme;
450           if (chr == EOF) {
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);
465             url.query = '';
466             state = QUERY;
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;
474             url.fragment = '';
475             state = FRAGMENT;
476           } else {
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);
482             url.path.length--;
483             state = PATH;
484             continue;
485           } break;
486
487         case RELATIVE_SLASH:
488           if (url.isSpecial() && (chr == '/' || chr == '\\')) {
489             state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
490           } else if (chr == '/') {
491             state = AUTHORITY;
492           } else {
493             url.username = base.username;
494             url.password = base.password;
495             url.host = base.host;
496             url.port = base.port;
497             state = PATH;
498             continue;
499           } break;
500
501         case SPECIAL_AUTHORITY_SLASHES:
502           state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
503           if (chr != '/' || charAt(buffer, pointer + 1) != '/') continue;
504           pointer++;
505           break;
506
507         case SPECIAL_AUTHORITY_IGNORE_SLASHES:
508           if (chr != '/' && chr != '\\') {
509             state = AUTHORITY;
510             continue;
511           } break;
512
513         case AUTHORITY:
514           if (chr == '@') {
515             if (seenAt) buffer = '%40' + buffer;
516             seenAt = true;
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;
522                 continue;
523               }
524               var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet);
525               if (seenPasswordToken) url.password += encodedCodePoints;
526               else url.username += encodedCodePoints;
527             }
528             buffer = '';
529           } else if (
530             chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
531             (chr == '\\' && url.isSpecial())
532           ) {
533             if (seenAt && buffer == '') return INVALID_AUTHORITY;
534             pointer -= arrayFrom(buffer).length + 1;
535             buffer = '';
536             state = HOST;
537           } else buffer += chr;
538           break;
539
540         case HOST:
541         case HOSTNAME:
542           if (stateOverride && url.scheme == 'file') {
543             state = FILE_HOST;
544             continue;
545           } else if (chr == ':' && !seenBracket) {
546             if (buffer == '') return INVALID_HOST;
547             failure = url.parseHost(buffer);
548             if (failure) return failure;
549             buffer = '';
550             state = PORT;
551             if (stateOverride == HOSTNAME) return;
552           } else if (
553             chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
554             (chr == '\\' && url.isSpecial())
555           ) {
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;
560             buffer = '';
561             state = PATH_START;
562             if (stateOverride) return;
563             continue;
564           } else {
565             if (chr == '[') seenBracket = true;
566             else if (chr == ']') seenBracket = false;
567             buffer += chr;
568           } break;
569
570         case PORT:
571           if (exec(DIGIT, chr)) {
572             buffer += chr;
573           } else if (
574             chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
575             (chr == '\\' && url.isSpecial()) ||
576             stateOverride
577           ) {
578             if (buffer != '') {
579               var port = parseInt(buffer, 10);
580               if (port > 0xFFFF) return INVALID_PORT;
581               url.port = (url.isSpecial() && port === specialSchemes[url.scheme]) ? null : port;
582               buffer = '';
583             }
584             if (stateOverride) return;
585             state = PATH_START;
586             continue;
587           } else return INVALID_PORT;
588           break;
589
590         case FILE:
591           url.scheme = 'file';
592           if (chr == '/' || chr == '\\') state = FILE_SLASH;
593           else if (base && base.scheme == 'file') {
594             if (chr == EOF) {
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);
601               url.query = '';
602               state = QUERY;
603             } else if (chr == '#') {
604               url.host = base.host;
605               url.path = arraySlice(base.path);
606               url.query = base.query;
607               url.fragment = '';
608               state = FRAGMENT;
609             } else {
610               if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
611                 url.host = base.host;
612                 url.path = arraySlice(base.path);
613                 url.shortenPath();
614               }
615               state = PATH;
616               continue;
617             }
618           } else {
619             state = PATH;
620             continue;
621           } break;
622
623         case FILE_SLASH:
624           if (chr == '/' || chr == '\\') {
625             state = FILE_HOST;
626             break;
627           }
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;
631           }
632           state = PATH;
633           continue;
634
635         case FILE_HOST:
636           if (chr == EOF || chr == '/' || chr == '\\' || chr == '?' || chr == '#') {
637             if (!stateOverride && isWindowsDriveLetter(buffer)) {
638               state = PATH;
639             } else if (buffer == '') {
640               url.host = '';
641               if (stateOverride) return;
642               state = PATH_START;
643             } else {
644               failure = url.parseHost(buffer);
645               if (failure) return failure;
646               if (url.host == 'localhost') url.host = '';
647               if (stateOverride) return;
648               buffer = '';
649               state = PATH_START;
650             } continue;
651           } else buffer += chr;
652           break;
653
654         case PATH_START:
655           if (url.isSpecial()) {
656             state = PATH;
657             if (chr != '/' && chr != '\\') continue;
658           } else if (!stateOverride && chr == '?') {
659             url.query = '';
660             state = QUERY;
661           } else if (!stateOverride && chr == '#') {
662             url.fragment = '';
663             state = FRAGMENT;
664           } else if (chr != EOF) {
665             state = PATH;
666             if (chr != '/') continue;
667           } break;
668
669         case PATH:
670           if (
671             chr == EOF || chr == '/' ||
672             (chr == '\\' && url.isSpecial()) ||
673             (!stateOverride && (chr == '?' || chr == '#'))
674           ) {
675             if (isDoubleDot(buffer)) {
676               url.shortenPath();
677               if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
678                 push(url.path, '');
679               }
680             } else if (isSingleDot(buffer)) {
681               if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
682                 push(url.path, '');
683               }
684             } else {
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
688               }
689               push(url.path, buffer);
690             }
691             buffer = '';
692             if (url.scheme == 'file' && (chr == EOF || chr == '?' || chr == '#')) {
693               while (url.path.length > 1 && url.path[0] === '') {
694                 shift(url.path);
695               }
696             }
697             if (chr == '?') {
698               url.query = '';
699               state = QUERY;
700             } else if (chr == '#') {
701               url.fragment = '';
702               state = FRAGMENT;
703             }
704           } else {
705             buffer += percentEncode(chr, pathPercentEncodeSet);
706           } break;
707
708         case CANNOT_BE_A_BASE_URL_PATH:
709           if (chr == '?') {
710             url.query = '';
711             state = QUERY;
712           } else if (chr == '#') {
713             url.fragment = '';
714             state = FRAGMENT;
715           } else if (chr != EOF) {
716             url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet);
717           } break;
718
719         case QUERY:
720           if (!stateOverride && chr == '#') {
721             url.fragment = '';
722             state = FRAGMENT;
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);
727           } break;
728
729         case FRAGMENT:
730           if (chr != EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet);
731           break;
732       }
733
734       pointer++;
735     }
736   },
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;
744       this.host = result;
745     // opaque host
746     } else if (!this.isSpecial()) {
747       if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST;
748       result = '';
749       codePoints = arrayFrom(input);
750       for (index = 0; index < codePoints.length; index++) {
751         result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
752       }
753       this.host = result;
754     } else {
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;
759       this.host = result;
760     }
761   },
762   // https://url.spec.whatwg.org/#cannot-have-a-username-password-port
763   cannotHaveUsernamePasswordPort: function () {
764     return !this.host || this.cannotBeABaseURL || this.scheme == 'file';
765   },
766   // https://url.spec.whatwg.org/#include-credentials
767   includesCredentials: function () {
768     return this.username != '' || this.password != '';
769   },
770   // https://url.spec.whatwg.org/#is-special
771   isSpecial: function () {
772     return hasOwn(specialSchemes, this.scheme);
773   },
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))) {
779       path.length--;
780     }
781   },
782   // https://url.spec.whatwg.org/#concept-url-serializer
783   serialize: function () {
784     var url = this;
785     var scheme = url.scheme;
786     var username = url.username;
787     var password = url.password;
788     var host = url.host;
789     var port = url.port;
790     var path = url.path;
791     var query = url.query;
792     var fragment = url.fragment;
793     var output = scheme + ':';
794     if (host !== null) {
795       output += '//';
796       if (url.includesCredentials()) {
797         output += username + (password ? ':' + password : '') + '@';
798       }
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;
805     return output;
806   },
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();
812   },
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;
819     } catch (error) {
820       return 'null';
821     }
822     if (scheme == 'file' || !this.isSpecial()) return 'null';
823     return scheme + '://' + serializeHost(this.host) + (port !== null ? ':' + port : '');
824   },
825   // https://url.spec.whatwg.org/#dom-url-protocol
826   getProtocol: function () {
827     return this.scheme + ':';
828   },
829   setProtocol: function (protocol) {
830     this.parse($toString(protocol) + ':', SCHEME_START);
831   },
832   // https://url.spec.whatwg.org/#dom-url-username
833   getUsername: function () {
834     return this.username;
835   },
836   setUsername: function (username) {
837     var codePoints = arrayFrom($toString(username));
838     if (this.cannotHaveUsernamePasswordPort()) return;
839     this.username = '';
840     for (var i = 0; i < codePoints.length; i++) {
841       this.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
842     }
843   },
844   // https://url.spec.whatwg.org/#dom-url-password
845   getPassword: function () {
846     return this.password;
847   },
848   setPassword: function (password) {
849     var codePoints = arrayFrom($toString(password));
850     if (this.cannotHaveUsernamePasswordPort()) return;
851     this.password = '';
852     for (var i = 0; i < codePoints.length; i++) {
853       this.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
854     }
855   },
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;
863   },
864   setHost: function (host) {
865     if (this.cannotBeABaseURL) return;
866     this.parse(host, HOST);
867   },
868   // https://url.spec.whatwg.org/#dom-url-hostname
869   getHostname: function () {
870     var host = this.host;
871     return host === null ? '' : serializeHost(host);
872   },
873   setHostname: function (hostname) {
874     if (this.cannotBeABaseURL) return;
875     this.parse(hostname, HOSTNAME);
876   },
877   // https://url.spec.whatwg.org/#dom-url-port
878   getPort: function () {
879     var port = this.port;
880     return port === null ? '' : $toString(port);
881   },
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);
887   },
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, '/') : '';
892   },
893   setPathname: function (pathname) {
894     if (this.cannotBeABaseURL) return;
895     this.path = [];
896     this.parse(pathname, PATH_START);
897   },
898   // https://url.spec.whatwg.org/#dom-url-search
899   getSearch: function () {
900     var query = this.query;
901     return query ? '?' + query : '';
902   },
903   setSearch: function (search) {
904     search = $toString(search);
905     if (search == '') {
906       this.query = null;
907     } else {
908       if ('?' == charAt(search, 0)) search = stringSlice(search, 1);
909       this.query = '';
910       this.parse(search, QUERY);
911     }
912     this.searchParams.update();
913   },
914   // https://url.spec.whatwg.org/#dom-url-searchparams
915   getSearchParams: function () {
916     return this.searchParams.facade;
917   },
918   // https://url.spec.whatwg.org/#dom-url-hash
919   getHash: function () {
920     var fragment = this.fragment;
921     return fragment ? '#' + fragment : '';
922   },
923   setHash: function (hash) {
924     hash = $toString(hash);
925     if (hash == '') {
926       this.fragment = null;
927       return;
928     }
929     if ('#' == charAt(hash, 0)) hash = stringSlice(hash, 1);
930     this.fragment = '';
931     this.parse(hash, FRAGMENT);
932   },
933   update: function () {
934     this.query = this.searchParams.serialize() || null;
935   }
936 };
937
938 // `URL` constructor
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));
944   if (!DESCRIPTORS) {
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();
957   }
958 };
959
960 var URLPrototype = URLConstructor.prototype;
961
962 var accessorDescriptor = function (getter, setter) {
963   return {
964     get: function () {
965       return getInternalURLState(this)[getter]();
966     },
967     set: setter && function (value) {
968       return getInternalURLState(this)[setter](value);
969     },
970     configurable: true,
971     enumerable: true
972   };
973 };
974
975 if (DESCRIPTORS) {
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')
1013   });
1014 }
1015
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 });
1021
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 });
1027
1028 if (NativeURL) {
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));
1037 }
1038
1039 setToStringTag(URLConstructor, 'URL');
1040
1041 $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {
1042   URL: URLConstructor
1043 });