| 'use strict'; |
| // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env` |
| require('../modules/es.string.iterator'); |
| var $ = require('../internals/export'); |
| var DESCRIPTORS = require('../internals/descriptors'); |
| var USE_NATIVE_URL = require('../internals/native-url'); |
| var global = require('../internals/global'); |
| var defineProperties = require('../internals/object-define-properties'); |
| var redefine = require('../internals/redefine'); |
| var anInstance = require('../internals/an-instance'); |
| var has = require('../internals/has'); |
| var assign = require('../internals/object-assign'); |
| var arrayFrom = require('../internals/array-from'); |
| var codeAt = require('../internals/string-multibyte').codeAt; |
| var toASCII = require('../internals/punycode-to-ascii'); |
| var setToStringTag = require('../internals/set-to-string-tag'); |
| var URLSearchParamsModule = require('../modules/web.url-search-params'); |
| var InternalStateModule = require('../internals/internal-state'); |
| |
| var NativeURL = global.URL; |
| var URLSearchParams = URLSearchParamsModule.URLSearchParams; |
| var getInternalSearchParamsState = URLSearchParamsModule.getState; |
| var setInternalState = InternalStateModule.set; |
| var getInternalURLState = InternalStateModule.getterFor('URL'); |
| var floor = Math.floor; |
| var pow = Math.pow; |
| |
| var INVALID_AUTHORITY = 'Invalid authority'; |
| var INVALID_SCHEME = 'Invalid scheme'; |
| var INVALID_HOST = 'Invalid host'; |
| var INVALID_PORT = 'Invalid port'; |
| |
| var ALPHA = /[A-Za-z]/; |
| var ALPHANUMERIC = /[\d+\-.A-Za-z]/; |
| var DIGIT = /\d/; |
| var HEX_START = /^(0x|0X)/; |
| var OCT = /^[0-7]+$/; |
| var DEC = /^\d+$/; |
| var HEX = /^[\dA-Fa-f]+$/; |
| // eslint-disable-next-line no-control-regex |
| var FORBIDDEN_HOST_CODE_POINT = /[\u0000\u0009\u000A\u000D #%/:?@[\\]]/; |
| // eslint-disable-next-line no-control-regex |
| var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\u0000\u0009\u000A\u000D #/:?@[\\]]/; |
| // eslint-disable-next-line no-control-regex |
| var LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE = /^[\u0000-\u001F ]+|[\u0000-\u001F ]+$/g; |
| // eslint-disable-next-line no-control-regex |
| var TAB_AND_NEW_LINE = /[\u0009\u000A\u000D]/g; |
| var EOF; |
| |
| var parseHost = function (url, input) { |
| var result, codePoints, index; |
| if (input.charAt(0) == '[') { |
| if (input.charAt(input.length - 1) != ']') return INVALID_HOST; |
| result = parseIPv6(input.slice(1, -1)); |
| if (!result) return INVALID_HOST; |
| url.host = result; |
| // opaque host |
| } else if (!isSpecial(url)) { |
| if (FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT.test(input)) return INVALID_HOST; |
| result = ''; |
| codePoints = arrayFrom(input); |
| for (index = 0; index < codePoints.length; index++) { |
| result += percentEncode(codePoints[index], C0ControlPercentEncodeSet); |
| } |
| url.host = result; |
| } else { |
| input = toASCII(input); |
| if (FORBIDDEN_HOST_CODE_POINT.test(input)) return INVALID_HOST; |
| result = parseIPv4(input); |
| if (result === null) return INVALID_HOST; |
| url.host = result; |
| } |
| }; |
| |
| var parseIPv4 = function (input) { |
| var parts = input.split('.'); |
| var partsLength, numbers, index, part, radix, number, ipv4; |
| if (parts.length && parts[parts.length - 1] == '') { |
| parts.pop(); |
| } |
| partsLength = parts.length; |
| if (partsLength > 4) return input; |
| numbers = []; |
| for (index = 0; index < partsLength; index++) { |
| part = parts[index]; |
| if (part == '') return input; |
| radix = 10; |
| if (part.length > 1 && part.charAt(0) == '0') { |
| radix = HEX_START.test(part) ? 16 : 8; |
| part = part.slice(radix == 8 ? 1 : 2); |
| } |
| if (part === '') { |
| number = 0; |
| } else { |
| if (!(radix == 10 ? DEC : radix == 8 ? OCT : HEX).test(part)) return input; |
| number = parseInt(part, radix); |
| } |
| numbers.push(number); |
| } |
| for (index = 0; index < partsLength; index++) { |
| number = numbers[index]; |
| if (index == partsLength - 1) { |
| if (number >= pow(256, 5 - partsLength)) return null; |
| } else if (number > 255) return null; |
| } |
| ipv4 = numbers.pop(); |
| for (index = 0; index < numbers.length; index++) { |
| ipv4 += numbers[index] * pow(256, 3 - index); |
| } |
| return ipv4; |
| }; |
| |
| // eslint-disable-next-line max-statements |
| var parseIPv6 = function (input) { |
| var address = [0, 0, 0, 0, 0, 0, 0, 0]; |
| var pieceIndex = 0; |
| var compress = null; |
| var pointer = 0; |
| var value, length, numbersSeen, ipv4Piece, number, swaps, swap; |
| |
| var char = function () { |
| return input.charAt(pointer); |
| }; |
| |
| if (char() == ':') { |
| if (input.charAt(1) != ':') return; |
| pointer += 2; |
| pieceIndex++; |
| compress = pieceIndex; |
| } |
| while (char()) { |
| if (pieceIndex == 8) return; |
| if (char() == ':') { |
| if (compress !== null) return; |
| pointer++; |
| pieceIndex++; |
| compress = pieceIndex; |
| continue; |
| } |
| value = length = 0; |
| while (length < 4 && HEX.test(char())) { |
| value = value * 16 + parseInt(char(), 16); |
| pointer++; |
| length++; |
| } |
| if (char() == '.') { |
| if (length == 0) return; |
| pointer -= length; |
| if (pieceIndex > 6) return; |
| numbersSeen = 0; |
| while (char()) { |
| ipv4Piece = null; |
| if (numbersSeen > 0) { |
| if (char() == '.' && numbersSeen < 4) pointer++; |
| else return; |
| } |
| if (!DIGIT.test(char())) return; |
| while (DIGIT.test(char())) { |
| number = parseInt(char(), 10); |
| if (ipv4Piece === null) ipv4Piece = number; |
| else if (ipv4Piece == 0) return; |
| else ipv4Piece = ipv4Piece * 10 + number; |
| if (ipv4Piece > 255) return; |
| pointer++; |
| } |
| address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece; |
| numbersSeen++; |
| if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++; |
| } |
| if (numbersSeen != 4) return; |
| break; |
| } else if (char() == ':') { |
| pointer++; |
| if (!char()) return; |
| } else if (char()) return; |
| address[pieceIndex++] = value; |
| } |
| if (compress !== null) { |
| swaps = pieceIndex - compress; |
| pieceIndex = 7; |
| while (pieceIndex != 0 && swaps > 0) { |
| swap = address[pieceIndex]; |
| address[pieceIndex--] = address[compress + swaps - 1]; |
| address[compress + --swaps] = swap; |
| } |
| } else if (pieceIndex != 8) return; |
| return address; |
| }; |
| |
| var findLongestZeroSequence = function (ipv6) { |
| var maxIndex = null; |
| var maxLength = 1; |
| var currStart = null; |
| var currLength = 0; |
| var index = 0; |
| for (; index < 8; index++) { |
| if (ipv6[index] !== 0) { |
| if (currLength > maxLength) { |
| maxIndex = currStart; |
| maxLength = currLength; |
| } |
| currStart = null; |
| currLength = 0; |
| } else { |
| if (currStart === null) currStart = index; |
| ++currLength; |
| } |
| } |
| if (currLength > maxLength) { |
| maxIndex = currStart; |
| maxLength = currLength; |
| } |
| return maxIndex; |
| }; |
| |
| var serializeHost = function (host) { |
| var result, index, compress, ignore0; |
| // ipv4 |
| if (typeof host == 'number') { |
| result = []; |
| for (index = 0; index < 4; index++) { |
| result.unshift(host % 256); |
| host = floor(host / 256); |
| } return result.join('.'); |
| // ipv6 |
| } else if (typeof host == 'object') { |
| result = ''; |
| compress = findLongestZeroSequence(host); |
| for (index = 0; index < 8; index++) { |
| if (ignore0 && host[index] === 0) continue; |
| if (ignore0) ignore0 = false; |
| if (compress === index) { |
| result += index ? ':' : '::'; |
| ignore0 = true; |
| } else { |
| result += host[index].toString(16); |
| if (index < 7) result += ':'; |
| } |
| } |
| return '[' + result + ']'; |
| } return host; |
| }; |
| |
| var C0ControlPercentEncodeSet = {}; |
| var fragmentPercentEncodeSet = assign({}, C0ControlPercentEncodeSet, { |
| ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1 |
| }); |
| var pathPercentEncodeSet = assign({}, fragmentPercentEncodeSet, { |
| '#': 1, '?': 1, '{': 1, '}': 1 |
| }); |
| var userinfoPercentEncodeSet = assign({}, pathPercentEncodeSet, { |
| '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1 |
| }); |
| |
| var percentEncode = function (char, set) { |
| var code = codeAt(char, 0); |
| return code > 0x20 && code < 0x7F && !has(set, char) ? char : encodeURIComponent(char); |
| }; |
| |
| var specialSchemes = { |
| ftp: 21, |
| file: null, |
| http: 80, |
| https: 443, |
| ws: 80, |
| wss: 443 |
| }; |
| |
| var isSpecial = function (url) { |
| return has(specialSchemes, url.scheme); |
| }; |
| |
| var includesCredentials = function (url) { |
| return url.username != '' || url.password != ''; |
| }; |
| |
| var cannotHaveUsernamePasswordPort = function (url) { |
| return !url.host || url.cannotBeABaseURL || url.scheme == 'file'; |
| }; |
| |
| var isWindowsDriveLetter = function (string, normalized) { |
| var second; |
| return string.length == 2 && ALPHA.test(string.charAt(0)) |
| && ((second = string.charAt(1)) == ':' || (!normalized && second == '|')); |
| }; |
| |
| var startsWithWindowsDriveLetter = function (string) { |
| var third; |
| return string.length > 1 && isWindowsDriveLetter(string.slice(0, 2)) && ( |
| string.length == 2 || |
| ((third = string.charAt(2)) === '/' || third === '\\' || third === '?' || third === '#') |
| ); |
| }; |
| |
| var shortenURLsPath = function (url) { |
| var path = url.path; |
| var pathSize = path.length; |
| if (pathSize && (url.scheme != 'file' || pathSize != 1 || !isWindowsDriveLetter(path[0], true))) { |
| path.pop(); |
| } |
| }; |
| |
| var isSingleDot = function (segment) { |
| return segment === '.' || segment.toLowerCase() === '%2e'; |
| }; |
| |
| var isDoubleDot = function (segment) { |
| segment = segment.toLowerCase(); |
| return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e'; |
| }; |
| |
| // States: |
| var SCHEME_START = {}; |
| var SCHEME = {}; |
| var NO_SCHEME = {}; |
| var SPECIAL_RELATIVE_OR_AUTHORITY = {}; |
| var PATH_OR_AUTHORITY = {}; |
| var RELATIVE = {}; |
| var RELATIVE_SLASH = {}; |
| var SPECIAL_AUTHORITY_SLASHES = {}; |
| var SPECIAL_AUTHORITY_IGNORE_SLASHES = {}; |
| var AUTHORITY = {}; |
| var HOST = {}; |
| var HOSTNAME = {}; |
| var PORT = {}; |
| var FILE = {}; |
| var FILE_SLASH = {}; |
| var FILE_HOST = {}; |
| var PATH_START = {}; |
| var PATH = {}; |
| var CANNOT_BE_A_BASE_URL_PATH = {}; |
| var QUERY = {}; |
| var FRAGMENT = {}; |
| |
| // eslint-disable-next-line max-statements |
| var parseURL = function (url, input, stateOverride, base) { |
| var state = stateOverride || SCHEME_START; |
| var pointer = 0; |
| var buffer = ''; |
| var seenAt = false; |
| var seenBracket = false; |
| var seenPasswordToken = false; |
| var codePoints, char, bufferCodePoints, failure; |
| |
| if (!stateOverride) { |
| url.scheme = ''; |
| url.username = ''; |
| url.password = ''; |
| url.host = null; |
| url.port = null; |
| url.path = []; |
| url.query = null; |
| url.fragment = null; |
| url.cannotBeABaseURL = false; |
| input = input.replace(LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, ''); |
| } |
| |
| input = input.replace(TAB_AND_NEW_LINE, ''); |
| |
| codePoints = arrayFrom(input); |
| |
| while (pointer <= codePoints.length) { |
| char = codePoints[pointer]; |
| switch (state) { |
| case SCHEME_START: |
| if (char && ALPHA.test(char)) { |
| buffer += char.toLowerCase(); |
| state = SCHEME; |
| } else if (!stateOverride) { |
| state = NO_SCHEME; |
| continue; |
| } else return INVALID_SCHEME; |
| break; |
| |
| case SCHEME: |
| if (char && (ALPHANUMERIC.test(char) || char == '+' || char == '-' || char == '.')) { |
| buffer += char.toLowerCase(); |
| } else if (char == ':') { |
| if (stateOverride && ( |
| (isSpecial(url) != has(specialSchemes, buffer)) || |
| (buffer == 'file' && (includesCredentials(url) || url.port !== null)) || |
| (url.scheme == 'file' && !url.host) |
| )) return; |
| url.scheme = buffer; |
| if (stateOverride) { |
| if (isSpecial(url) && specialSchemes[url.scheme] == url.port) url.port = null; |
| return; |
| } |
| buffer = ''; |
| if (url.scheme == 'file') { |
| state = FILE; |
| } else if (isSpecial(url) && base && base.scheme == url.scheme) { |
| state = SPECIAL_RELATIVE_OR_AUTHORITY; |
| } else if (isSpecial(url)) { |
| state = SPECIAL_AUTHORITY_SLASHES; |
| } else if (codePoints[pointer + 1] == '/') { |
| state = PATH_OR_AUTHORITY; |
| pointer++; |
| } else { |
| url.cannotBeABaseURL = true; |
| url.path.push(''); |
| state = CANNOT_BE_A_BASE_URL_PATH; |
| } |
| } else if (!stateOverride) { |
| buffer = ''; |
| state = NO_SCHEME; |
| pointer = 0; |
| continue; |
| } else return INVALID_SCHEME; |
| break; |
| |
| case NO_SCHEME: |
| if (!base || (base.cannotBeABaseURL && char != '#')) return INVALID_SCHEME; |
| if (base.cannotBeABaseURL && char == '#') { |
| url.scheme = base.scheme; |
| url.path = base.path.slice(); |
| url.query = base.query; |
| url.fragment = ''; |
| url.cannotBeABaseURL = true; |
| state = FRAGMENT; |
| break; |
| } |
| state = base.scheme == 'file' ? FILE : RELATIVE; |
| continue; |
| |
| case SPECIAL_RELATIVE_OR_AUTHORITY: |
| if (char == '/' && codePoints[pointer + 1] == '/') { |
| state = SPECIAL_AUTHORITY_IGNORE_SLASHES; |
| pointer++; |
| } else { |
| state = RELATIVE; |
| continue; |
| } break; |
| |
| case PATH_OR_AUTHORITY: |
| if (char == '/') { |
| state = AUTHORITY; |
| break; |
| } else { |
| state = PATH; |
| continue; |
| } |
| |
| case RELATIVE: |
| url.scheme = base.scheme; |
| if (char == EOF) { |
| url.username = base.username; |
| url.password = base.password; |
| url.host = base.host; |
| url.port = base.port; |
| url.path = base.path.slice(); |
| url.query = base.query; |
| } else if (char == '/' || (char == '\\' && isSpecial(url))) { |
| state = RELATIVE_SLASH; |
| } else if (char == '?') { |
| url.username = base.username; |
| url.password = base.password; |
| url.host = base.host; |
| url.port = base.port; |
| url.path = base.path.slice(); |
| url.query = ''; |
| state = QUERY; |
| } else if (char == '#') { |
| url.username = base.username; |
| url.password = base.password; |
| url.host = base.host; |
| url.port = base.port; |
| url.path = base.path.slice(); |
| url.query = base.query; |
| url.fragment = ''; |
| state = FRAGMENT; |
| } else { |
| url.username = base.username; |
| url.password = base.password; |
| url.host = base.host; |
| url.port = base.port; |
| url.path = base.path.slice(); |
| url.path.pop(); |
| state = PATH; |
| continue; |
| } break; |
| |
| case RELATIVE_SLASH: |
| if (isSpecial(url) && (char == '/' || char == '\\')) { |
| state = SPECIAL_AUTHORITY_IGNORE_SLASHES; |
| } else if (char == '/') { |
| state = AUTHORITY; |
| } else { |
| url.username = base.username; |
| url.password = base.password; |
| url.host = base.host; |
| url.port = base.port; |
| state = PATH; |
| continue; |
| } break; |
| |
| case SPECIAL_AUTHORITY_SLASHES: |
| state = SPECIAL_AUTHORITY_IGNORE_SLASHES; |
| if (char != '/' || buffer.charAt(pointer + 1) != '/') continue; |
| pointer++; |
| break; |
| |
| case SPECIAL_AUTHORITY_IGNORE_SLASHES: |
| if (char != '/' && char != '\\') { |
| state = AUTHORITY; |
| continue; |
| } break; |
| |
| case AUTHORITY: |
| if (char == '@') { |
| if (seenAt) buffer = '%40' + buffer; |
| seenAt = true; |
| bufferCodePoints = arrayFrom(buffer); |
| for (var i = 0; i < bufferCodePoints.length; i++) { |
| var codePoint = bufferCodePoints[i]; |
| if (codePoint == ':' && !seenPasswordToken) { |
| seenPasswordToken = true; |
| continue; |
| } |
| var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet); |
| if (seenPasswordToken) url.password += encodedCodePoints; |
| else url.username += encodedCodePoints; |
| } |
| buffer = ''; |
| } else if ( |
| char == EOF || char == '/' || char == '?' || char == '#' || |
| (char == '\\' && isSpecial(url)) |
| ) { |
| if (seenAt && buffer == '') return INVALID_AUTHORITY; |
| pointer -= arrayFrom(buffer).length + 1; |
| buffer = ''; |
| state = HOST; |
| } else buffer += char; |
| break; |
| |
| case HOST: |
| case HOSTNAME: |
| if (stateOverride && url.scheme == 'file') { |
| state = FILE_HOST; |
| continue; |
| } else if (char == ':' && !seenBracket) { |
| if (buffer == '') return INVALID_HOST; |
| failure = parseHost(url, buffer); |
| if (failure) return failure; |
| buffer = ''; |
| state = PORT; |
| if (stateOverride == HOSTNAME) return; |
| } else if ( |
| char == EOF || char == '/' || char == '?' || char == '#' || |
| (char == '\\' && isSpecial(url)) |
| ) { |
| if (isSpecial(url) && buffer == '') return INVALID_HOST; |
| if (stateOverride && buffer == '' && (includesCredentials(url) || url.port !== null)) return; |
| failure = parseHost(url, buffer); |
| if (failure) return failure; |
| buffer = ''; |
| state = PATH_START; |
| if (stateOverride) return; |
| continue; |
| } else { |
| if (char == '[') seenBracket = true; |
| else if (char == ']') seenBracket = false; |
| buffer += char; |
| } break; |
| |
| case PORT: |
| if (DIGIT.test(char)) { |
| buffer += char; |
| } else if ( |
| char == EOF || char == '/' || char == '?' || char == '#' || |
| (char == '\\' && isSpecial(url)) || |
| stateOverride |
| ) { |
| if (buffer != '') { |
| var port = parseInt(buffer, 10); |
| if (port > 0xFFFF) return INVALID_PORT; |
| url.port = (isSpecial(url) && port === specialSchemes[url.scheme]) ? null : port; |
| buffer = ''; |
| } |
| if (stateOverride) return; |
| state = PATH_START; |
| continue; |
| } else return INVALID_PORT; |
| break; |
| |
| case FILE: |
| url.scheme = 'file'; |
| if (char == '/' || char == '\\') state = FILE_SLASH; |
| else if (base && base.scheme == 'file') { |
| if (char == EOF) { |
| url.host = base.host; |
| url.path = base.path.slice(); |
| url.query = base.query; |
| } else if (char == '?') { |
| url.host = base.host; |
| url.path = base.path.slice(); |
| url.query = ''; |
| state = QUERY; |
| } else if (char == '#') { |
| url.host = base.host; |
| url.path = base.path.slice(); |
| url.query = base.query; |
| url.fragment = ''; |
| state = FRAGMENT; |
| } else { |
| if (!startsWithWindowsDriveLetter(codePoints.slice(pointer).join(''))) { |
| url.host = base.host; |
| url.path = base.path.slice(); |
| shortenURLsPath(url); |
| } |
| state = PATH; |
| continue; |
| } |
| } else { |
| state = PATH; |
| continue; |
| } break; |
| |
| case FILE_SLASH: |
| if (char == '/' || char == '\\') { |
| state = FILE_HOST; |
| break; |
| } |
| if (base && base.scheme == 'file' && !startsWithWindowsDriveLetter(codePoints.slice(pointer).join(''))) { |
| if (isWindowsDriveLetter(base.path[0], true)) url.path.push(base.path[0]); |
| else url.host = base.host; |
| } |
| state = PATH; |
| continue; |
| |
| case FILE_HOST: |
| if (char == EOF || char == '/' || char == '\\' || char == '?' || char == '#') { |
| if (!stateOverride && isWindowsDriveLetter(buffer)) { |
| state = PATH; |
| } else if (buffer == '') { |
| url.host = ''; |
| if (stateOverride) return; |
| state = PATH_START; |
| } else { |
| failure = parseHost(url, buffer); |
| if (failure) return failure; |
| if (url.host == 'localhost') url.host = ''; |
| if (stateOverride) return; |
| buffer = ''; |
| state = PATH_START; |
| } continue; |
| } else buffer += char; |
| break; |
| |
| case PATH_START: |
| if (isSpecial(url)) { |
| state = PATH; |
| if (char != '/' && char != '\\') continue; |
| } else if (!stateOverride && char == '?') { |
| url.query = ''; |
| state = QUERY; |
| } else if (!stateOverride && char == '#') { |
| url.fragment = ''; |
| state = FRAGMENT; |
| } else if (char != EOF) { |
| state = PATH; |
| if (char != '/') continue; |
| } break; |
| |
| case PATH: |
| if ( |
| char == EOF || char == '/' || |
| (char == '\\' && isSpecial(url)) || |
| (!stateOverride && (char == '?' || char == '#')) |
| ) { |
| if (isDoubleDot(buffer)) { |
| shortenURLsPath(url); |
| if (char != '/' && !(char == '\\' && isSpecial(url))) { |
| url.path.push(''); |
| } |
| } else if (isSingleDot(buffer)) { |
| if (char != '/' && !(char == '\\' && isSpecial(url))) { |
| url.path.push(''); |
| } |
| } else { |
| if (url.scheme == 'file' && !url.path.length && isWindowsDriveLetter(buffer)) { |
| if (url.host) url.host = ''; |
| buffer = buffer.charAt(0) + ':'; // normalize windows drive letter |
| } |
| url.path.push(buffer); |
| } |
| buffer = ''; |
| if (url.scheme == 'file' && (char == EOF || char == '?' || char == '#')) { |
| while (url.path.length > 1 && url.path[0] === '') { |
| url.path.shift(); |
| } |
| } |
| if (char == '?') { |
| url.query = ''; |
| state = QUERY; |
| } else if (char == '#') { |
| url.fragment = ''; |
| state = FRAGMENT; |
| } |
| } else { |
| buffer += percentEncode(char, pathPercentEncodeSet); |
| } break; |
| |
| case CANNOT_BE_A_BASE_URL_PATH: |
| if (char == '?') { |
| url.query = ''; |
| state = QUERY; |
| } else if (char == '#') { |
| url.fragment = ''; |
| state = FRAGMENT; |
| } else if (char != EOF) { |
| url.path[0] += percentEncode(char, C0ControlPercentEncodeSet); |
| } break; |
| |
| case QUERY: |
| if (!stateOverride && char == '#') { |
| url.fragment = ''; |
| state = FRAGMENT; |
| } else if (char != EOF) { |
| if (char == "'" && isSpecial(url)) url.query += '%27'; |
| else if (char == '#') url.query += '%23'; |
| else url.query += percentEncode(char, C0ControlPercentEncodeSet); |
| } break; |
| |
| case FRAGMENT: |
| if (char != EOF) url.fragment += percentEncode(char, fragmentPercentEncodeSet); |
| break; |
| } |
| |
| pointer++; |
| } |
| }; |
| |
| // `URL` constructor |
| // https://url.spec.whatwg.org/#url-class |
| var URLConstructor = function URL(url /* , base */) { |
| var that = anInstance(this, URLConstructor, 'URL'); |
| var base = arguments.length > 1 ? arguments[1] : undefined; |
| var urlString = String(url); |
| var state = setInternalState(that, { type: 'URL' }); |
| var baseState, failure; |
| if (base !== undefined) { |
| if (base instanceof URLConstructor) baseState = getInternalURLState(base); |
| else { |
| failure = parseURL(baseState = {}, String(base)); |
| if (failure) throw TypeError(failure); |
| } |
| } |
| failure = parseURL(state, urlString, null, baseState); |
| if (failure) throw TypeError(failure); |
| var searchParams = state.searchParams = new URLSearchParams(); |
| var searchParamsState = getInternalSearchParamsState(searchParams); |
| searchParamsState.updateSearchParams(state.query); |
| searchParamsState.updateURL = function () { |
| state.query = String(searchParams) || null; |
| }; |
| if (!DESCRIPTORS) { |
| that.href = serializeURL.call(that); |
| that.origin = getOrigin.call(that); |
| that.protocol = getProtocol.call(that); |
| that.username = getUsername.call(that); |
| that.password = getPassword.call(that); |
| that.host = getHost.call(that); |
| that.hostname = getHostname.call(that); |
| that.port = getPort.call(that); |
| that.pathname = getPathname.call(that); |
| that.search = getSearch.call(that); |
| that.searchParams = getSearchParams.call(that); |
| that.hash = getHash.call(that); |
| } |
| }; |
| |
| var URLPrototype = URLConstructor.prototype; |
| |
| var serializeURL = function () { |
| var url = getInternalURLState(this); |
| var scheme = url.scheme; |
| var username = url.username; |
| var password = url.password; |
| var host = url.host; |
| var port = url.port; |
| var path = url.path; |
| var query = url.query; |
| var fragment = url.fragment; |
| var output = scheme + ':'; |
| if (host !== null) { |
| output += '//'; |
| if (includesCredentials(url)) { |
| output += username + (password ? ':' + password : '') + '@'; |
| } |
| output += serializeHost(host); |
| if (port !== null) output += ':' + port; |
| } else if (scheme == 'file') output += '//'; |
| output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + path.join('/') : ''; |
| if (query !== null) output += '?' + query; |
| if (fragment !== null) output += '#' + fragment; |
| return output; |
| }; |
| |
| var getOrigin = function () { |
| var url = getInternalURLState(this); |
| var scheme = url.scheme; |
| var port = url.port; |
| if (scheme == 'blob') try { |
| return new URL(scheme.path[0]).origin; |
| } catch (error) { |
| return 'null'; |
| } |
| if (scheme == 'file' || !isSpecial(url)) return 'null'; |
| return scheme + '://' + serializeHost(url.host) + (port !== null ? ':' + port : ''); |
| }; |
| |
| var getProtocol = function () { |
| return getInternalURLState(this).scheme + ':'; |
| }; |
| |
| var getUsername = function () { |
| return getInternalURLState(this).username; |
| }; |
| |
| var getPassword = function () { |
| return getInternalURLState(this).password; |
| }; |
| |
| var getHost = function () { |
| var url = getInternalURLState(this); |
| var host = url.host; |
| var port = url.port; |
| return host === null ? '' |
| : port === null ? serializeHost(host) |
| : serializeHost(host) + ':' + port; |
| }; |
| |
| var getHostname = function () { |
| var host = getInternalURLState(this).host; |
| return host === null ? '' : serializeHost(host); |
| }; |
| |
| var getPort = function () { |
| var port = getInternalURLState(this).port; |
| return port === null ? '' : String(port); |
| }; |
| |
| var getPathname = function () { |
| var url = getInternalURLState(this); |
| var path = url.path; |
| return url.cannotBeABaseURL ? path[0] : path.length ? '/' + path.join('/') : ''; |
| }; |
| |
| var getSearch = function () { |
| var query = getInternalURLState(this).query; |
| return query ? '?' + query : ''; |
| }; |
| |
| var getSearchParams = function () { |
| return getInternalURLState(this).searchParams; |
| }; |
| |
| var getHash = function () { |
| var fragment = getInternalURLState(this).fragment; |
| return fragment ? '#' + fragment : ''; |
| }; |
| |
| var accessorDescriptor = function (getter, setter) { |
| return { get: getter, set: setter, configurable: true, enumerable: true }; |
| }; |
| |
| if (DESCRIPTORS) { |
| defineProperties(URLPrototype, { |
| // `URL.prototype.href` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-href |
| href: accessorDescriptor(serializeURL, function (href) { |
| var url = getInternalURLState(this); |
| var urlString = String(href); |
| var failure = parseURL(url, urlString); |
| if (failure) throw TypeError(failure); |
| getInternalSearchParamsState(url.searchParams).updateSearchParams(url.query); |
| }), |
| // `URL.prototype.origin` getter |
| // https://url.spec.whatwg.org/#dom-url-origin |
| origin: accessorDescriptor(getOrigin), |
| // `URL.prototype.protocol` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-protocol |
| protocol: accessorDescriptor(getProtocol, function (protocol) { |
| var url = getInternalURLState(this); |
| parseURL(url, String(protocol) + ':', SCHEME_START); |
| }), |
| // `URL.prototype.username` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-username |
| username: accessorDescriptor(getUsername, function (username) { |
| var url = getInternalURLState(this); |
| var codePoints = arrayFrom(String(username)); |
| if (cannotHaveUsernamePasswordPort(url)) return; |
| url.username = ''; |
| for (var i = 0; i < codePoints.length; i++) { |
| url.username += percentEncode(codePoints[i], userinfoPercentEncodeSet); |
| } |
| }), |
| // `URL.prototype.password` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-password |
| password: accessorDescriptor(getPassword, function (password) { |
| var url = getInternalURLState(this); |
| var codePoints = arrayFrom(String(password)); |
| if (cannotHaveUsernamePasswordPort(url)) return; |
| url.password = ''; |
| for (var i = 0; i < codePoints.length; i++) { |
| url.password += percentEncode(codePoints[i], userinfoPercentEncodeSet); |
| } |
| }), |
| // `URL.prototype.host` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-host |
| host: accessorDescriptor(getHost, function (host) { |
| var url = getInternalURLState(this); |
| if (url.cannotBeABaseURL) return; |
| parseURL(url, String(host), HOST); |
| }), |
| // `URL.prototype.hostname` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-hostname |
| hostname: accessorDescriptor(getHostname, function (hostname) { |
| var url = getInternalURLState(this); |
| if (url.cannotBeABaseURL) return; |
| parseURL(url, String(hostname), HOSTNAME); |
| }), |
| // `URL.prototype.port` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-port |
| port: accessorDescriptor(getPort, function (port) { |
| var url = getInternalURLState(this); |
| if (cannotHaveUsernamePasswordPort(url)) return; |
| port = String(port); |
| if (port == '') url.port = null; |
| else parseURL(url, port, PORT); |
| }), |
| // `URL.prototype.pathname` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-pathname |
| pathname: accessorDescriptor(getPathname, function (pathname) { |
| var url = getInternalURLState(this); |
| if (url.cannotBeABaseURL) return; |
| url.path = []; |
| parseURL(url, pathname + '', PATH_START); |
| }), |
| // `URL.prototype.search` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-search |
| search: accessorDescriptor(getSearch, function (search) { |
| var url = getInternalURLState(this); |
| search = String(search); |
| if (search == '') { |
| url.query = null; |
| } else { |
| if ('?' == search.charAt(0)) search = search.slice(1); |
| url.query = ''; |
| parseURL(url, search, QUERY); |
| } |
| getInternalSearchParamsState(url.searchParams).updateSearchParams(url.query); |
| }), |
| // `URL.prototype.searchParams` getter |
| // https://url.spec.whatwg.org/#dom-url-searchparams |
| searchParams: accessorDescriptor(getSearchParams), |
| // `URL.prototype.hash` accessors pair |
| // https://url.spec.whatwg.org/#dom-url-hash |
| hash: accessorDescriptor(getHash, function (hash) { |
| var url = getInternalURLState(this); |
| hash = String(hash); |
| if (hash == '') { |
| url.fragment = null; |
| return; |
| } |
| if ('#' == hash.charAt(0)) hash = hash.slice(1); |
| url.fragment = ''; |
| parseURL(url, hash, FRAGMENT); |
| }) |
| }); |
| } |
| |
| // `URL.prototype.toJSON` method |
| // https://url.spec.whatwg.org/#dom-url-tojson |
| redefine(URLPrototype, 'toJSON', function toJSON() { |
| return serializeURL.call(this); |
| }, { enumerable: true }); |
| |
| // `URL.prototype.toString` method |
| // https://url.spec.whatwg.org/#URL-stringification-behavior |
| redefine(URLPrototype, 'toString', function toString() { |
| return serializeURL.call(this); |
| }, { enumerable: true }); |
| |
| if (NativeURL) { |
| var nativeCreateObjectURL = NativeURL.createObjectURL; |
| var nativeRevokeObjectURL = NativeURL.revokeObjectURL; |
| // `URL.createObjectURL` method |
| // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL |
| // eslint-disable-next-line no-unused-vars |
| if (nativeCreateObjectURL) redefine(URLConstructor, 'createObjectURL', function createObjectURL(blob) { |
| return nativeCreateObjectURL.apply(NativeURL, arguments); |
| }); |
| // `URL.revokeObjectURL` method |
| // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL |
| // eslint-disable-next-line no-unused-vars |
| if (nativeRevokeObjectURL) redefine(URLConstructor, 'revokeObjectURL', function revokeObjectURL(url) { |
| return nativeRevokeObjectURL.apply(NativeURL, arguments); |
| }); |
| } |
| |
| setToStringTag(URLConstructor, 'URL'); |
| |
| $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, { |
| URL: URLConstructor |
| }); |