You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
huazhiyu/node_modules/core-js/modules/web.url.constructor.js

1048 lines
35 KiB

'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/url-constructor-detection');
var global = require('../internals/global');
var bind = require('../internals/function-bind-context');
var uncurryThis = require('../internals/function-uncurry-this');
var defineBuiltIn = require('../internals/define-built-in');
var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
var anInstance = require('../internals/an-instance');
var hasOwn = require('../internals/has-own-property');
var assign = require('../internals/object-assign');
var arrayFrom = require('../internals/array-from');
var arraySlice = require('../internals/array-slice-simple');
var codeAt = require('../internals/string-multibyte').codeAt;
var toASCII = require('../internals/string-punycode-to-ascii');
var $toString = require('../internals/to-string');
var setToStringTag = require('../internals/set-to-string-tag');
var validateArgumentsLength = require('../internals/validate-arguments-length');
var URLSearchParamsModule = require('../modules/web.url-search-params.constructor');
var InternalStateModule = require('../internals/internal-state');
var setInternalState = InternalStateModule.set;
var getInternalURLState = InternalStateModule.getterFor('URL');
var URLSearchParams = URLSearchParamsModule.URLSearchParams;
var getInternalSearchParamsState = URLSearchParamsModule.getState;
var NativeURL = global.URL;
var TypeError = global.TypeError;
var parseInt = global.parseInt;
var floor = Math.floor;
var pow = Math.pow;
var charAt = uncurryThis(''.charAt);
var exec = uncurryThis(/./.exec);
var join = uncurryThis([].join);
var numberToString = uncurryThis(1.0.toString);
var pop = uncurryThis([].pop);
var push = uncurryThis([].push);
var replace = uncurryThis(''.replace);
var shift = uncurryThis([].shift);
var split = uncurryThis(''.split);
var stringSlice = uncurryThis(''.slice);
var toLowerCase = uncurryThis(''.toLowerCase);
var unshift = uncurryThis([].unshift);
var INVALID_AUTHORITY = 'Invalid authority';
var INVALID_SCHEME = 'Invalid scheme';
var INVALID_HOST = 'Invalid host';
var INVALID_PORT = 'Invalid port';
var ALPHA = /[a-z]/i;
// eslint-disable-next-line regexp/no-obscure-range -- safe
var ALPHANUMERIC = /[\d+-.a-z]/i;
var DIGIT = /\d/;
var HEX_START = /^0x/i;
var OCT = /^[0-7]+$/;
var DEC = /^\d+$/;
var HEX = /^[\da-f]+$/i;
/* eslint-disable regexp/no-control-character -- safe */
var FORBIDDEN_HOST_CODE_POINT = /[\0\t\n\r #%/:<>?@[\\\]^|]/;
var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\0\t\n\r #/:<>?@[\\\]^|]/;
var LEADING_C0_CONTROL_OR_SPACE = /^[\u0000-\u0020]+/;
var TRAILING_C0_CONTROL_OR_SPACE = /(^|[^\u0000-\u0020])[\u0000-\u0020]+$/;
var TAB_AND_NEW_LINE = /[\t\n\r]/g;
/* eslint-enable regexp/no-control-character -- safe */
var EOF;
// https://url.spec.whatwg.org/#ipv4-number-parser
var parseIPv4 = function (input) {
var parts = split(input, '.');
var partsLength, numbers, index, part, radix, number, ipv4;
if (parts.length && parts[parts.length - 1] === '') {
parts.length--;
}
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 && charAt(part, 0) === '0') {
radix = exec(HEX_START, part) ? 16 : 8;
part = stringSlice(part, radix === 8 ? 1 : 2);
}
if (part === '') {
number = 0;
} else {
if (!exec(radix === 10 ? DEC : radix === 8 ? OCT : HEX, part)) return input;
number = parseInt(part, radix);
}
push(numbers, 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 = pop(numbers);
for (index = 0; index < numbers.length; index++) {
ipv4 += numbers[index] * pow(256, 3 - index);
}
return ipv4;
};
// https://url.spec.whatwg.org/#concept-ipv6-parser
// eslint-disable-next-line max-statements -- TODO
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 chr = function () {
return charAt(input, pointer);
};
if (chr() === ':') {
if (charAt(input, 1) !== ':') return;
pointer += 2;
pieceIndex++;
compress = pieceIndex;
}
while (chr()) {
if (pieceIndex === 8) return;
if (chr() === ':') {
if (compress !== null) return;
pointer++;
pieceIndex++;
compress = pieceIndex;
continue;
}
value = length = 0;
while (length < 4 && exec(HEX, chr())) {
value = value * 16 + parseInt(chr(), 16);
pointer++;
length++;
}
if (chr() === '.') {
if (length === 0) return;
pointer -= length;
if (pieceIndex > 6) return;
numbersSeen = 0;
while (chr()) {
ipv4Piece = null;
if (numbersSeen > 0) {
if (chr() === '.' && numbersSeen < 4) pointer++;
else return;
}
if (!exec(DIGIT, chr())) return;
while (exec(DIGIT, chr())) {
number = parseInt(chr(), 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 (chr() === ':') {
pointer++;
if (!chr()) return;
} else if (chr()) 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;
};
// https://url.spec.whatwg.org/#host-serializing
var serializeHost = function (host) {
var result, index, compress, ignore0;
// ipv4
if (typeof host == 'number') {
result = [];
for (index = 0; index < 4; index++) {
unshift(result, host % 256);
host = floor(host / 256);
} return join(result, '.');
// 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 += numberToString(host[index], 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 (chr, set) {
var code = codeAt(chr, 0);
return code > 0x20 && code < 0x7F && !hasOwn(set, chr) ? chr : encodeURIComponent(chr);
};
// https://url.spec.whatwg.org/#special-scheme
var specialSchemes = {
ftp: 21,
file: null,
http: 80,
https: 443,
ws: 80,
wss: 443
};
// https://url.spec.whatwg.org/#windows-drive-letter
var isWindowsDriveLetter = function (string, normalized) {
var second;
return string.length === 2 && exec(ALPHA, charAt(string, 0))
&& ((second = charAt(string, 1)) === ':' || (!normalized && second === '|'));
};
// https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
var startsWithWindowsDriveLetter = function (string) {
var third;
return string.length > 1 && isWindowsDriveLetter(stringSlice(string, 0, 2)) && (
string.length === 2 ||
((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#')
);
};
// https://url.spec.whatwg.org/#single-dot-path-segment
var isSingleDot = function (segment) {
return segment === '.' || toLowerCase(segment) === '%2e';
};
// https://url.spec.whatwg.org/#double-dot-path-segment
var isDoubleDot = function (segment) {
segment = toLowerCase(segment);
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 = {};
var URLState = function (url, isBase, base) {
var urlString = $toString(url);
var baseState, failure, searchParams;
if (isBase) {
failure = this.parse(urlString);
if (failure) throw new TypeError(failure);
this.searchParams = null;
} else {
if (base !== undefined) baseState = new URLState(base, true);
failure = this.parse(urlString, null, baseState);
if (failure) throw new TypeError(failure);
searchParams = getInternalSearchParamsState(new URLSearchParams());
searchParams.bindURL(this);
this.searchParams = searchParams;
}
};
URLState.prototype = {
type: 'URL',
// https://url.spec.whatwg.org/#url-parsing
// eslint-disable-next-line max-statements -- TODO
parse: function (input, stateOverride, base) {
var url = this;
var state = stateOverride || SCHEME_START;
var pointer = 0;
var buffer = '';
var seenAt = false;
var seenBracket = false;
var seenPasswordToken = false;
var codePoints, chr, bufferCodePoints, failure;
input = $toString(input);
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 = replace(input, LEADING_C0_CONTROL_OR_SPACE, '');
input = replace(input, TRAILING_C0_CONTROL_OR_SPACE, '$1');
}
input = replace(input, TAB_AND_NEW_LINE, '');
codePoints = arrayFrom(input);
while (pointer <= codePoints.length) {
chr = codePoints[pointer];
switch (state) {
case SCHEME_START:
if (chr && exec(ALPHA, chr)) {
buffer += toLowerCase(chr);
state = SCHEME;
} else if (!stateOverride) {
state = NO_SCHEME;
continue;
} else return INVALID_SCHEME;
break;
case SCHEME:
if (chr && (exec(ALPHANUMERIC, chr) || chr === '+' || chr === '-' || chr === '.')) {
buffer += toLowerCase(chr);
} else if (chr === ':') {
if (stateOverride && (
(url.isSpecial() !== hasOwn(specialSchemes, buffer)) ||
(buffer === 'file' && (url.includesCredentials() || url.port !== null)) ||
(url.scheme === 'file' && !url.host)
)) return;
url.scheme = buffer;
if (stateOverride) {
if (url.isSpecial() && specialSchemes[url.scheme] === url.port) url.port = null;
return;
}
buffer = '';
if (url.scheme === 'file') {
state = FILE;
} else if (url.isSpecial() && base && base.scheme === url.scheme) {
state = SPECIAL_RELATIVE_OR_AUTHORITY;
} else if (url.isSpecial()) {
state = SPECIAL_AUTHORITY_SLASHES;
} else if (codePoints[pointer + 1] === '/') {
state = PATH_OR_AUTHORITY;
pointer++;
} else {
url.cannotBeABaseURL = true;
push(url.path, '');
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 && chr !== '#')) return INVALID_SCHEME;
if (base.cannotBeABaseURL && chr === '#') {
url.scheme = base.scheme;
url.path = arraySlice(base.path);
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 (chr === '/' && codePoints[pointer + 1] === '/') {
state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
pointer++;
} else {
state = RELATIVE;
continue;
} break;
case PATH_OR_AUTHORITY:
if (chr === '/') {
state = AUTHORITY;
break;
} else {
state = PATH;
continue;
}
case RELATIVE:
url.scheme = base.scheme;
if (chr === EOF) {
url.username = base.username;
url.password = base.password;
url.host = base.host;
url.port = base.port;
url.path = arraySlice(base.path);
url.query = base.query;
} else if (chr === '/' || (chr === '\\' && url.isSpecial())) {
state = RELATIVE_SLASH;
} else if (chr === '?') {
url.username = base.username;
url.password = base.password;
url.host = base.host;
url.port = base.port;
url.path = arraySlice(base.path);
url.query = '';
state = QUERY;
} else if (chr === '#') {
url.username = base.username;
url.password = base.password;
url.host = base.host;
url.port = base.port;
url.path = arraySlice(base.path);
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 = arraySlice(base.path);
url.path.length--;
state = PATH;
continue;
} break;
case RELATIVE_SLASH:
if (url.isSpecial() && (chr === '/' || chr === '\\')) {
state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
} else if (chr === '/') {
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 (chr !== '/' || charAt(buffer, pointer + 1) !== '/') continue;
pointer++;
break;
case SPECIAL_AUTHORITY_IGNORE_SLASHES:
if (chr !== '/' && chr !== '\\') {
state = AUTHORITY;
continue;
} break;
case AUTHORITY:
if (chr === '@') {
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 (
chr === EOF || chr === '/' || chr === '?' || chr === '#' ||
(chr === '\\' && url.isSpecial())
) {
if (seenAt && buffer === '') return INVALID_AUTHORITY;
pointer -= arrayFrom(buffer).length + 1;
buffer = '';
state = HOST;
} else buffer += chr;
break;
case HOST:
case HOSTNAME:
if (stateOverride && url.scheme === 'file') {
state = FILE_HOST;
continue;
} else if (chr === ':' && !seenBracket) {
if (buffer === '') return INVALID_HOST;
failure = url.parseHost(buffer);
if (failure) return failure;
buffer = '';
state = PORT;
if (stateOverride === HOSTNAME) return;
} else if (
chr === EOF || chr === '/' || chr === '?' || chr === '#' ||
(chr === '\\' && url.isSpecial())
) {
if (url.isSpecial() && buffer === '') return INVALID_HOST;
if (stateOverride && buffer === '' && (url.includesCredentials() || url.port !== null)) return;
failure = url.parseHost(buffer);
if (failure) return failure;
buffer = '';
state = PATH_START;
if (stateOverride) return;
continue;
} else {
if (chr === '[') seenBracket = true;
else if (chr === ']') seenBracket = false;
buffer += chr;
} break;
case PORT:
if (exec(DIGIT, chr)) {
buffer += chr;
} else if (
chr === EOF || chr === '/' || chr === '?' || chr === '#' ||
(chr === '\\' && url.isSpecial()) ||
stateOverride
) {
if (buffer !== '') {
var port = parseInt(buffer, 10);
if (port > 0xFFFF) return INVALID_PORT;
url.port = (url.isSpecial() && 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 (chr === '/' || chr === '\\') state = FILE_SLASH;
else if (base && base.scheme === 'file') {
switch (chr) {
case EOF:
url.host = base.host;
url.path = arraySlice(base.path);
url.query = base.query;
break;
case '?':
url.host = base.host;
url.path = arraySlice(base.path);
url.query = '';
state = QUERY;
break;
case '#':
url.host = base.host;
url.path = arraySlice(base.path);
url.query = base.query;
url.fragment = '';
state = FRAGMENT;
break;
default:
if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
url.host = base.host;
url.path = arraySlice(base.path);
url.shortenPath();
}
state = PATH;
continue;
}
} else {
state = PATH;
continue;
} break;
case FILE_SLASH:
if (chr === '/' || chr === '\\') {
state = FILE_HOST;
break;
}
if (base && base.scheme === 'file' && !startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
if (isWindowsDriveLetter(base.path[0], true)) push(url.path, base.path[0]);
else url.host = base.host;
}
state = PATH;
continue;
case FILE_HOST:
if (chr === EOF || chr === '/' || chr === '\\' || chr === '?' || chr === '#') {
if (!stateOverride && isWindowsDriveLetter(buffer)) {
state = PATH;
} else if (buffer === '') {
url.host = '';
if (stateOverride) return;
state = PATH_START;
} else {
failure = url.parseHost(buffer);
if (failure) return failure;
if (url.host === 'localhost') url.host = '';
if (stateOverride) return;
buffer = '';
state = PATH_START;
} continue;
} else buffer += chr;
break;
case PATH_START:
if (url.isSpecial()) {
state = PATH;
if (chr !== '/' && chr !== '\\') continue;
} else if (!stateOverride && chr === '?') {
url.query = '';
state = QUERY;
} else if (!stateOverride && chr === '#') {
url.fragment = '';
state = FRAGMENT;
} else if (chr !== EOF) {
state = PATH;
if (chr !== '/') continue;
} break;
case PATH:
if (
chr === EOF || chr === '/' ||
(chr === '\\' && url.isSpecial()) ||
(!stateOverride && (chr === '?' || chr === '#'))
) {
if (isDoubleDot(buffer)) {
url.shortenPath();
if (chr !== '/' && !(chr === '\\' && url.isSpecial())) {
push(url.path, '');
}
} else if (isSingleDot(buffer)) {
if (chr !== '/' && !(chr === '\\' && url.isSpecial())) {
push(url.path, '');
}
} else {
if (url.scheme === 'file' && !url.path.length && isWindowsDriveLetter(buffer)) {
if (url.host) url.host = '';
buffer = charAt(buffer, 0) + ':'; // normalize windows drive letter
}
push(url.path, buffer);
}
buffer = '';
if (url.scheme === 'file' && (chr === EOF || chr === '?' || chr === '#')) {
while (url.path.length > 1 && url.path[0] === '') {
shift(url.path);
}
}
if (chr === '?') {
url.query = '';
state = QUERY;
} else if (chr === '#') {
url.fragment = '';
state = FRAGMENT;
}
} else {
buffer += percentEncode(chr, pathPercentEncodeSet);
} break;
case CANNOT_BE_A_BASE_URL_PATH:
if (chr === '?') {
url.query = '';
state = QUERY;
} else if (chr === '#') {
url.fragment = '';
state = FRAGMENT;
} else if (chr !== EOF) {
url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet);
} break;
case QUERY:
if (!stateOverride && chr === '#') {
url.fragment = '';
state = FRAGMENT;
} else if (chr !== EOF) {
if (chr === "'" && url.isSpecial()) url.query += '%27';
else if (chr === '#') url.query += '%23';
else url.query += percentEncode(chr, C0ControlPercentEncodeSet);
} break;
case FRAGMENT:
if (chr !== EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet);
break;
}
pointer++;
}
},
// https://url.spec.whatwg.org/#host-parsing
parseHost: function (input) {
var result, codePoints, index;
if (charAt(input, 0) === '[') {
if (charAt(input, input.length - 1) !== ']') return INVALID_HOST;
result = parseIPv6(stringSlice(input, 1, -1));
if (!result) return INVALID_HOST;
this.host = result;
// opaque host
} else if (!this.isSpecial()) {
if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST;
result = '';
codePoints = arrayFrom(input);
for (index = 0; index < codePoints.length; index++) {
result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
}
this.host = result;
} else {
input = toASCII(input);
if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST;
result = parseIPv4(input);
if (result === null) return INVALID_HOST;
this.host = result;
}
},
// https://url.spec.whatwg.org/#cannot-have-a-username-password-port
cannotHaveUsernamePasswordPort: function () {
return !this.host || this.cannotBeABaseURL || this.scheme === 'file';
},
// https://url.spec.whatwg.org/#include-credentials
includesCredentials: function () {
return this.username !== '' || this.password !== '';
},
// https://url.spec.whatwg.org/#is-special
isSpecial: function () {
return hasOwn(specialSchemes, this.scheme);
},
// https://url.spec.whatwg.org/#shorten-a-urls-path
shortenPath: function () {
var path = this.path;
var pathSize = path.length;
if (pathSize && (this.scheme !== 'file' || pathSize !== 1 || !isWindowsDriveLetter(path[0], true))) {
path.length--;
}
},
// https://url.spec.whatwg.org/#concept-url-serializer
serialize: function () {
var url = 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 (url.includesCredentials()) {
output += username + (password ? ':' + password : '') + '@';
}
output += serializeHost(host);
if (port !== null) output += ':' + port;
} else if (scheme === 'file') output += '//';
output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
if (query !== null) output += '?' + query;
if (fragment !== null) output += '#' + fragment;
return output;
},
// https://url.spec.whatwg.org/#dom-url-href
setHref: function (href) {
var failure = this.parse(href);
if (failure) throw new TypeError(failure);
this.searchParams.update();
},
// https://url.spec.whatwg.org/#dom-url-origin
getOrigin: function () {
var scheme = this.scheme;
var port = this.port;
if (scheme === 'blob') try {
return new URLConstructor(scheme.path[0]).origin;
} catch (error) {
return 'null';
}
if (scheme === 'file' || !this.isSpecial()) return 'null';
return scheme + '://' + serializeHost(this.host) + (port !== null ? ':' + port : '');
},
// https://url.spec.whatwg.org/#dom-url-protocol
getProtocol: function () {
return this.scheme + ':';
},
setProtocol: function (protocol) {
this.parse($toString(protocol) + ':', SCHEME_START);
},
// https://url.spec.whatwg.org/#dom-url-username
getUsername: function () {
return this.username;
},
setUsername: function (username) {
var codePoints = arrayFrom($toString(username));
if (this.cannotHaveUsernamePasswordPort()) return;
this.username = '';
for (var i = 0; i < codePoints.length; i++) {
this.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
}
},
// https://url.spec.whatwg.org/#dom-url-password
getPassword: function () {
return this.password;
},
setPassword: function (password) {
var codePoints = arrayFrom($toString(password));
if (this.cannotHaveUsernamePasswordPort()) return;
this.password = '';
for (var i = 0; i < codePoints.length; i++) {
this.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
}
},
// https://url.spec.whatwg.org/#dom-url-host
getHost: function () {
var host = this.host;
var port = this.port;
return host === null ? ''
: port === null ? serializeHost(host)
: serializeHost(host) + ':' + port;
},
setHost: function (host) {
if (this.cannotBeABaseURL) return;
this.parse(host, HOST);
},
// https://url.spec.whatwg.org/#dom-url-hostname
getHostname: function () {
var host = this.host;
return host === null ? '' : serializeHost(host);
},
setHostname: function (hostname) {
if (this.cannotBeABaseURL) return;
this.parse(hostname, HOSTNAME);
},
// https://url.spec.whatwg.org/#dom-url-port
getPort: function () {
var port = this.port;
return port === null ? '' : $toString(port);
},
setPort: function (port) {
if (this.cannotHaveUsernamePasswordPort()) return;
port = $toString(port);
if (port === '') this.port = null;
else this.parse(port, PORT);
},
// https://url.spec.whatwg.org/#dom-url-pathname
getPathname: function () {
var path = this.path;
return this.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
},
setPathname: function (pathname) {
if (this.cannotBeABaseURL) return;
this.path = [];
this.parse(pathname, PATH_START);
},
// https://url.spec.whatwg.org/#dom-url-search
getSearch: function () {
var query = this.query;
return query ? '?' + query : '';
},
setSearch: function (search) {
search = $toString(search);
if (search === '') {
this.query = null;
} else {
if (charAt(search, 0) === '?') search = stringSlice(search, 1);
this.query = '';
this.parse(search, QUERY);
}
this.searchParams.update();
},
// https://url.spec.whatwg.org/#dom-url-searchparams
getSearchParams: function () {
return this.searchParams.facade;
},
// https://url.spec.whatwg.org/#dom-url-hash
getHash: function () {
var fragment = this.fragment;
return fragment ? '#' + fragment : '';
},
setHash: function (hash) {
hash = $toString(hash);
if (hash === '') {
this.fragment = null;
return;
}
if (charAt(hash, 0) === '#') hash = stringSlice(hash, 1);
this.fragment = '';
this.parse(hash, FRAGMENT);
},
update: function () {
this.query = this.searchParams.serialize() || null;
}
};
// `URL` constructor
// https://url.spec.whatwg.org/#url-class
var URLConstructor = function URL(url /* , base */) {
var that = anInstance(this, URLPrototype);
var base = validateArgumentsLength(arguments.length, 1) > 1 ? arguments[1] : undefined;
var state = setInternalState(that, new URLState(url, false, base));
if (!DESCRIPTORS) {
that.href = state.serialize();
that.origin = state.getOrigin();
that.protocol = state.getProtocol();
that.username = state.getUsername();
that.password = state.getPassword();
that.host = state.getHost();
that.hostname = state.getHostname();
that.port = state.getPort();
that.pathname = state.getPathname();
that.search = state.getSearch();
that.searchParams = state.getSearchParams();
that.hash = state.getHash();
}
};
var URLPrototype = URLConstructor.prototype;
var accessorDescriptor = function (getter, setter) {
return {
get: function () {
return getInternalURLState(this)[getter]();
},
set: setter && function (value) {
return getInternalURLState(this)[setter](value);
},
configurable: true,
enumerable: true
};
};
if (DESCRIPTORS) {
// `URL.prototype.href` accessors pair
// https://url.spec.whatwg.org/#dom-url-href
defineBuiltInAccessor(URLPrototype, 'href', accessorDescriptor('serialize', 'setHref'));
// `URL.prototype.origin` getter
// https://url.spec.whatwg.org/#dom-url-origin
defineBuiltInAccessor(URLPrototype, 'origin', accessorDescriptor('getOrigin'));
// `URL.prototype.protocol` accessors pair
// https://url.spec.whatwg.org/#dom-url-protocol
defineBuiltInAccessor(URLPrototype, 'protocol', accessorDescriptor('getProtocol', 'setProtocol'));
// `URL.prototype.username` accessors pair
// https://url.spec.whatwg.org/#dom-url-username
defineBuiltInAccessor(URLPrototype, 'username', accessorDescriptor('getUsername', 'setUsername'));
// `URL.prototype.password` accessors pair
// https://url.spec.whatwg.org/#dom-url-password
defineBuiltInAccessor(URLPrototype, 'password', accessorDescriptor('getPassword', 'setPassword'));
// `URL.prototype.host` accessors pair
// https://url.spec.whatwg.org/#dom-url-host
defineBuiltInAccessor(URLPrototype, 'host', accessorDescriptor('getHost', 'setHost'));
// `URL.prototype.hostname` accessors pair
// https://url.spec.whatwg.org/#dom-url-hostname
defineBuiltInAccessor(URLPrototype, 'hostname', accessorDescriptor('getHostname', 'setHostname'));
// `URL.prototype.port` accessors pair
// https://url.spec.whatwg.org/#dom-url-port
defineBuiltInAccessor(URLPrototype, 'port', accessorDescriptor('getPort', 'setPort'));
// `URL.prototype.pathname` accessors pair
// https://url.spec.whatwg.org/#dom-url-pathname
defineBuiltInAccessor(URLPrototype, 'pathname', accessorDescriptor('getPathname', 'setPathname'));
// `URL.prototype.search` accessors pair
// https://url.spec.whatwg.org/#dom-url-search
defineBuiltInAccessor(URLPrototype, 'search', accessorDescriptor('getSearch', 'setSearch'));
// `URL.prototype.searchParams` getter
// https://url.spec.whatwg.org/#dom-url-searchparams
defineBuiltInAccessor(URLPrototype, 'searchParams', accessorDescriptor('getSearchParams'));
// `URL.prototype.hash` accessors pair
// https://url.spec.whatwg.org/#dom-url-hash
defineBuiltInAccessor(URLPrototype, 'hash', accessorDescriptor('getHash', 'setHash'));
}
// `URL.prototype.toJSON` method
// https://url.spec.whatwg.org/#dom-url-tojson
defineBuiltIn(URLPrototype, 'toJSON', function toJSON() {
return getInternalURLState(this).serialize();
}, { enumerable: true });
// `URL.prototype.toString` method
// https://url.spec.whatwg.org/#URL-stringification-behavior
defineBuiltIn(URLPrototype, 'toString', function toString() {
return getInternalURLState(this).serialize();
}, { 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
if (nativeCreateObjectURL) defineBuiltIn(URLConstructor, 'createObjectURL', bind(nativeCreateObjectURL, NativeURL));
// `URL.revokeObjectURL` method
// https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
if (nativeRevokeObjectURL) defineBuiltIn(URLConstructor, 'revokeObjectURL', bind(nativeRevokeObjectURL, NativeURL));
}
setToStringTag(URLConstructor, 'URL');
$({ global: true, constructor: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {
URL: URLConstructor
});