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