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