Innovenergy_trunk/frontend/node_modules/testcafe-hammerhead/lib/client/hammerhead.js

44140 lines
1.7 MiB
JavaScript
Raw Normal View History

(function initHammerheadClient () {
(function () {
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn) {
var module = { exports: {} };
return fn(module, module.exports), module.exports;
}
var PENDING = 'pending';
var SETTLED = 'settled';
var FULFILLED = 'fulfilled';
var REJECTED = 'rejected';
var NOOP = function () {};
var isNode = typeof commonjsGlobal !== 'undefined' && typeof commonjsGlobal.process !== 'undefined' && typeof commonjsGlobal.process.emit === 'function';
var asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate;
var asyncQueue = [];
var asyncTimer;
function asyncFlush() {
// run promise callbacks
for (var i = 0; i < asyncQueue.length; i++) {
asyncQueue[i][0](asyncQueue[i][1]);
}
// reset async asyncQueue
asyncQueue = [];
asyncTimer = false;
}
function asyncCall(callback, arg) {
asyncQueue.push([callback, arg]);
if (!asyncTimer) {
asyncTimer = true;
asyncSetTimer(asyncFlush, 0);
}
}
function invokeResolver(resolver, promise) {
function resolvePromise(value) {
resolve(promise, value);
}
function rejectPromise(reason) {
reject(promise, reason);
}
try {
resolver(resolvePromise, rejectPromise);
} catch (e) {
rejectPromise(e);
}
}
function invokeCallback(subscriber) {
var owner = subscriber.owner;
var settled = owner._state;
var value = owner._data;
var callback = subscriber[settled];
var promise = subscriber.then;
if (typeof callback === 'function') {
settled = FULFILLED;
try {
value = callback(value);
} catch (e) {
reject(promise, e);
}
}
if (!handleThenable(promise, value)) {
if (settled === FULFILLED) {
resolve(promise, value);
}
if (settled === REJECTED) {
reject(promise, value);
}
}
}
function handleThenable(promise, value) {
var resolved;
try {
if (promise === value) {
throw new TypeError('A promises callback cannot return that same promise.');
}
if (value && (typeof value === 'function' || typeof value === 'object')) {
// then should be retrieved only once
var then = value.then;
if (typeof then === 'function') {
then.call(value, function (val) {
if (!resolved) {
resolved = true;
if (value === val) {
fulfill(promise, val);
} else {
resolve(promise, val);
}
}
}, function (reason) {
if (!resolved) {
resolved = true;
reject(promise, reason);
}
});
return true;
}
}
} catch (e) {
if (!resolved) {
reject(promise, e);
}
return true;
}
return false;
}
function resolve(promise, value) {
if (promise === value || !handleThenable(promise, value)) {
fulfill(promise, value);
}
}
function fulfill(promise, value) {
if (promise._state === PENDING) {
promise._state = SETTLED;
promise._data = value;
asyncCall(publishFulfillment, promise);
}
}
function reject(promise, reason) {
if (promise._state === PENDING) {
promise._state = SETTLED;
promise._data = reason;
asyncCall(publishRejection, promise);
}
}
function publish(promise) {
promise._then = promise._then.forEach(invokeCallback);
}
function publishFulfillment(promise) {
promise._state = FULFILLED;
publish(promise);
}
function publishRejection(promise) {
promise._state = REJECTED;
publish(promise);
if (!promise._handled && isNode) {
commonjsGlobal.process.emit('unhandledRejection', promise._data, promise);
}
}
function notifyRejectionHandled(promise) {
commonjsGlobal.process.emit('rejectionHandled', promise);
}
/**
* @class
*/
function Promise$1(resolver) {
if (typeof resolver !== 'function') {
throw new TypeError('Promise resolver ' + resolver + ' is not a function');
}
if (this instanceof Promise$1 === false) {
throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
}
this._then = [];
invokeResolver(resolver, this);
}
Promise$1.prototype = {
constructor: Promise$1,
_state: PENDING,
_then: null,
_data: undefined,
_handled: false,
then: function (onFulfillment, onRejection) {
var subscriber = {
owner: this,
then: new this.constructor(NOOP),
fulfilled: onFulfillment,
rejected: onRejection
};
if ((onRejection || onFulfillment) && !this._handled) {
this._handled = true;
if (this._state === REJECTED && isNode) {
asyncCall(notifyRejectionHandled, this);
}
}
if (this._state === FULFILLED || this._state === REJECTED) {
// already resolved, call callback async
asyncCall(invokeCallback, subscriber);
} else {
// subscribe
this._then.push(subscriber);
}
return subscriber.then;
},
catch: function (onRejection) {
return this.then(null, onRejection);
}
};
Promise$1.all = function (promises) {
if (!Array.isArray(promises)) {
throw new TypeError('You must pass an array to Promise.all().');
}
return new Promise$1(function (resolve, reject) {
var results = [];
var remaining = 0;
function resolver(index) {
remaining++;
return function (value) {
results[index] = value;
if (!--remaining) {
resolve(results);
}
};
}
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function') {
promise.then(resolver(i), reject);
} else {
results[i] = promise;
}
}
if (!remaining) {
resolve(results);
}
});
};
Promise$1.race = function (promises) {
if (!Array.isArray(promises)) {
throw new TypeError('You must pass an array to Promise.race().');
}
return new Promise$1(function (resolve, reject) {
for (var i = 0, promise; i < promises.length; i++) {
promise = promises[i];
if (promise && typeof promise.then === 'function') {
promise.then(resolve, reject);
} else {
resolve(promise);
}
}
});
};
Promise$1.resolve = function (value) {
if (value && typeof value === 'object' && value.constructor === Promise$1) {
return value;
}
return new Promise$1(function (resolve) {
resolve(value);
});
};
Promise$1.reject = function (reason) {
return new Promise$1(function (resolve, reject) {
reject(reason);
});
};
var pinkie = Promise$1;
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
var INTERNAL_PROPS = {
processDomMethodName: 'hammerhead|process-dom-method',
processedContext: 'hammerhead|processed-context',
documentWasCleaned: 'hammerhead|document-was-cleaned',
documentCharset: 'hammerhead|document-charset',
iframeNativeMethods: 'hammerhead|iframe-native-methods',
hammerhead: '%hammerhead%',
selection: 'hammerhead|selection',
shadowUIElement: 'hammerhead|shadow-ui-element',
forceProxySrcForImage: 'hammerhead|image|force-proxy-src-flag',
skipNextLoadEventForImage: 'hammerhead|image|skip-next-load-event-flag',
cachedImage: 'hammerhead|image|cached-image',
sandboxIsReattached: 'hammerhead|sandbox-is-reattached',
nativeStrRepresentation: 'hammerhead|native-string-representation',
currentBaseUrl: 'hammerhead|current-base-url',
};
var isInWorker = typeof window === 'undefined' && typeof self === 'object';
var global$1 = (isInWorker ? self : window);
var globalContextInfo = {
isInWorker: isInWorker,
global: global$1,
isServiceWorker: isInWorker && !global$1.XMLHttpRequest,
};
function replaceNativeAccessor(descriptor, accessorName, newAccessor) {
if (newAccessor && descriptor[accessorName]) {
var stringifiedNativeAccessor_1 = descriptor[accessorName].toString();
newAccessor.toString = function () { return stringifiedNativeAccessor_1; };
}
descriptor[accessorName] = newAccessor;
}
function createOverriddenDescriptor(obj, prop, _a) {
var getter = _a.getter, setter = _a.setter, value = _a.value;
var descriptor = nativeMethods.objectGetOwnPropertyDescriptor(obj, prop);
if ((getter || setter) && value)
throw new Error('Cannot both specify accessors and a value or writable attribute.');
if (!descriptor)
return void 0;
if (value) {
if (!nativeMethods.objectHasOwnProperty.call(descriptor, 'writable')) {
descriptor.writable = !!descriptor.set;
delete descriptor.get;
delete descriptor.set;
}
descriptor.value = value; // eslint-disable-line no-restricted-properties
}
else {
if (nativeMethods.objectHasOwnProperty.call(descriptor, 'writable')) {
delete descriptor.value; // eslint-disable-line no-restricted-properties
delete descriptor.writable;
}
if (getter !== null)
replaceNativeAccessor(descriptor, 'get', getter);
if (setter !== null)
replaceNativeAccessor(descriptor, 'set', setter);
}
return descriptor;
}
function overrideDescriptor(obj, prop, propertyAccessors) {
if (!obj)
return;
var descriptor = createOverriddenDescriptor(obj, prop, propertyAccessors);
if (descriptor)
nativeMethods.objectDefineProperty(obj, prop, descriptor);
else
overrideDescriptor(nativeMethods.objectGetPrototypeOf(obj), prop, propertyAccessors);
}
function overrideFunctionName(fn, name) {
var nameDescriptor = nativeMethods.objectGetOwnPropertyDescriptor(fn, 'name');
if (!nameDescriptor)
return;
nameDescriptor.value = name; // eslint-disable-line no-restricted-properties
nativeMethods.objectDefineProperty(fn, 'name', nameDescriptor);
}
function overrideToString(nativeFnWrapper, nativeFn) {
nativeMethods.objectDefineProperty(nativeFnWrapper, INTERNAL_PROPS.nativeStrRepresentation, {
value: nativeMethods.Function.prototype.toString.call(nativeFn),
configurable: true,
});
}
// TODO: this function should not be used outside this file
// for now it's used to flag cases in which we assign our wrapper to a native function when it is missing
function overrideStringRepresentation(nativeFnWrapper, nativeFn) {
overrideFunctionName(nativeFnWrapper, nativeFn.name);
overrideToString(nativeFnWrapper, nativeFn);
}
function isNativeFunction(fn) {
return !nativeMethods.objectHasOwnProperty.call(fn, INTERNAL_PROPS.nativeStrRepresentation);
}
function overrideFunction(obj, fnName, wrapper) {
var fn = obj[fnName];
if (isNativeFunction(fn)) {
overrideStringRepresentation(wrapper, fn);
obj[fnName] = wrapper;
}
}
function overrideConstructor(obj, fnName, wrapper, overrideProtoConstructor) {
if (overrideProtoConstructor === void 0) { overrideProtoConstructor = false; }
var nativePrototype = obj[fnName]['prototype'];
overrideFunction(obj, fnName, wrapper);
// NOTE: restore native prototype (to make `instanceof` work as expected)
wrapper.prototype = nativePrototype;
// NOTE: we need to override the `constructor` property of a prototype
// because sometimes native constructor can be retrieved from it
if (overrideProtoConstructor)
nativePrototype.constructor = wrapper;
}
var overridingUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
createOverriddenDescriptor: createOverriddenDescriptor,
overrideDescriptor: overrideDescriptor,
overrideStringRepresentation: overrideStringRepresentation,
isNativeFunction: isNativeFunction,
overrideFunction: overrideFunction,
overrideConstructor: overrideConstructor
});
/*!
* Bowser - a browser detector
* https://github.com/ded/bowser
* MIT License | (c) Dustin Diaz 2015
*/
var bowser = createCommonjsModule(function (module) {
!function (root, name, definition) {
if (module.exports) module.exports = definition();
else root[name] = definition();
}(commonjsGlobal, 'bowser', function () {
/**
* See useragents.js for examples of navigator.userAgent
*/
var t = true;
function detect(ua) {
function getFirstMatch(regex) {
var match = ua.match(regex);
return (match && match.length > 1 && match[1]) || '';
}
function getSecondMatch(regex) {
var match = ua.match(regex);
return (match && match.length > 1 && match[2]) || '';
}
var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase()
, likeAndroid = /like android/i.test(ua)
, android = !likeAndroid && /android/i.test(ua)
, nexusMobile = /nexus\s*[0-6]\s*/i.test(ua)
, nexusTablet = !nexusMobile && /nexus\s*[0-9]+/i.test(ua)
, chromeos = /CrOS/.test(ua)
, silk = /silk/i.test(ua)
, sailfish = /sailfish/i.test(ua)
, tizen = /tizen/i.test(ua)
, webos = /(web|hpw)os/i.test(ua)
, windowsphone = /windows phone/i.test(ua)
; /SamsungBrowser/i.test(ua)
; var windows = !windowsphone && /windows/i.test(ua)
, mac = !iosdevice && !silk && /macintosh/i.test(ua)
, linux = !android && !sailfish && !tizen && !webos && /linux/i.test(ua)
, edgeVersion = getFirstMatch(/edge\/(\d+(\.\d+)?)/i)
, versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i)
, tablet = /tablet/i.test(ua)
, mobile = !tablet && /[^-]mobi/i.test(ua)
, xbox = /xbox/i.test(ua)
, result;
if (/opera/i.test(ua)) {
// an old Opera
result = {
name: 'Opera'
, opera: t
, version: versionIdentifier || getFirstMatch(/(?:opera|opr|opios)[\s\/](\d+(\.\d+)?)/i)
};
} else if (/opr|opios/i.test(ua)) {
// a new Opera
result = {
name: 'Opera'
, opera: t
, version: getFirstMatch(/(?:opr|opios)[\s\/](\d+(\.\d+)?)/i) || versionIdentifier
};
}
else if (/SamsungBrowser/i.test(ua)) {
result = {
name: 'Samsung Internet for Android'
, samsungBrowser: t
, version: versionIdentifier || getFirstMatch(/(?:SamsungBrowser)[\s\/](\d+(\.\d+)?)/i)
};
}
else if (/coast/i.test(ua)) {
result = {
name: 'Opera Coast'
, coast: t
, version: versionIdentifier || getFirstMatch(/(?:coast)[\s\/](\d+(\.\d+)?)/i)
};
}
else if (/yabrowser/i.test(ua)) {
result = {
name: 'Yandex Browser'
, yandexbrowser: t
, version: versionIdentifier || getFirstMatch(/(?:yabrowser)[\s\/](\d+(\.\d+)?)/i)
};
}
else if (/ucbrowser/i.test(ua)) {
result = {
name: 'UC Browser'
, ucbrowser: t
, version: getFirstMatch(/(?:ucbrowser)[\s\/](\d+(?:\.\d+)+)/i)
};
}
else if (/mxios/i.test(ua)) {
result = {
name: 'Maxthon'
, maxthon: t
, version: getFirstMatch(/(?:mxios)[\s\/](\d+(?:\.\d+)+)/i)
};
}
else if (/epiphany/i.test(ua)) {
result = {
name: 'Epiphany'
, epiphany: t
, version: getFirstMatch(/(?:epiphany)[\s\/](\d+(?:\.\d+)+)/i)
};
}
else if (/puffin/i.test(ua)) {
result = {
name: 'Puffin'
, puffin: t
, version: getFirstMatch(/(?:puffin)[\s\/](\d+(?:\.\d+)?)/i)
};
}
else if (/sleipnir/i.test(ua)) {
result = {
name: 'Sleipnir'
, sleipnir: t
, version: getFirstMatch(/(?:sleipnir)[\s\/](\d+(?:\.\d+)+)/i)
};
}
else if (/k-meleon/i.test(ua)) {
result = {
name: 'K-Meleon'
, kMeleon: t
, version: getFirstMatch(/(?:k-meleon)[\s\/](\d+(?:\.\d+)+)/i)
};
}
else if (windowsphone) {
result = {
name: 'Windows Phone'
, windowsphone: t
};
if (edgeVersion) {
result.msedge = t;
result.version = edgeVersion;
}
else {
result.msie = t;
result.version = getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i);
}
}
else if (/msie|trident/i.test(ua)) {
result = {
name: 'Internet Explorer'
, msie: t
, version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i)
};
} else if (chromeos) {
result = {
name: 'Chrome'
, chromeos: t
, chromeBook: t
, chrome: t
, version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)
};
} else if (/chrome.+? edge/i.test(ua)) {
result = {
name: 'Microsoft Edge'
, msedge: t
, version: edgeVersion
};
}
else if (/vivaldi/i.test(ua)) {
result = {
name: 'Vivaldi'
, vivaldi: t
, version: getFirstMatch(/vivaldi\/(\d+(\.\d+)?)/i) || versionIdentifier
};
}
else if (sailfish) {
result = {
name: 'Sailfish'
, sailfish: t
, version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i)
};
}
else if (/seamonkey\//i.test(ua)) {
result = {
name: 'SeaMonkey'
, seamonkey: t
, version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i)
};
}
else if (/firefox|iceweasel|fxios/i.test(ua)) {
result = {
name: 'Firefox'
, firefox: t
, version: getFirstMatch(/(?:firefox|iceweasel|fxios)[ \/](\d+(\.\d+)?)/i)
};
if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) {
result.firefoxos = t;
}
}
else if (silk) {
result = {
name: 'Amazon Silk'
, silk: t
, version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i)
};
}
else if (/phantom/i.test(ua)) {
result = {
name: 'PhantomJS'
, phantom: t
, version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i)
};
}
else if (/slimerjs/i.test(ua)) {
result = {
name: 'SlimerJS'
, slimer: t
, version: getFirstMatch(/slimerjs\/(\d+(\.\d+)?)/i)
};
}
else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) {
result = {
name: 'BlackBerry'
, blackberry: t
, version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i)
};
}
else if (webos) {
result = {
name: 'WebOS'
, webos: t
, version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i)
};
/touchpad\//i.test(ua) && (result.touchpad = t);
}
else if (/bada/i.test(ua)) {
result = {
name: 'Bada'
, bada: t
, version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i)
};
}
else if (tizen) {
result = {
name: 'Tizen'
, tizen: t
, version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier
};
}
else if (/qupzilla/i.test(ua)) {
result = {
name: 'QupZilla'
, qupzilla: t
, version: getFirstMatch(/(?:qupzilla)[\s\/](\d+(?:\.\d+)+)/i) || versionIdentifier
};
}
else if (/chromium/i.test(ua)) {
result = {
name: 'Chromium'
, chromium: t
, version: getFirstMatch(/(?:chromium)[\s\/](\d+(?:\.\d+)?)/i) || versionIdentifier
};
}
else if (/chrome|crios|crmo/i.test(ua)) {
result = {
name: 'Chrome'
, chrome: t
, version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i)
};
}
else if (android) {
result = {
name: 'Android'
, version: versionIdentifier
};
}
else if (/safari|applewebkit/i.test(ua)) {
result = {
name: 'Safari'
, safari: t
};
if (versionIdentifier) {
result.version = versionIdentifier;
}
}
else if (iosdevice) {
result = {
name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod'
};
// WTF: version is not part of user agent in web apps
if (versionIdentifier) {
result.version = versionIdentifier;
}
}
else if(/googlebot/i.test(ua)) {
result = {
name: 'Googlebot'
, googlebot: t
, version: getFirstMatch(/googlebot\/(\d+(\.\d+))/i) || versionIdentifier
};
}
else {
result = {
name: getFirstMatch(/^(.*)\/(.*) /),
version: getSecondMatch(/^(.*)\/(.*) /)
};
}
// set webkit or gecko flag for browsers based on these engines
if (!result.msedge && /(apple)?webkit/i.test(ua)) {
if (/(apple)?webkit\/537\.36/i.test(ua)) {
result.name = result.name || "Blink";
result.blink = t;
} else {
result.name = result.name || "Webkit";
result.webkit = t;
}
if (!result.version && versionIdentifier) {
result.version = versionIdentifier;
}
} else if (!result.opera && /gecko\//i.test(ua)) {
result.name = result.name || "Gecko";
result.gecko = t;
result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i);
}
// set OS flags for platforms that have multiple browsers
if (!result.windowsphone && !result.msedge && (android || result.silk)) {
result.android = t;
} else if (!result.windowsphone && !result.msedge && iosdevice) {
result[iosdevice] = t;
result.ios = t;
} else if (mac) {
result.mac = t;
} else if (xbox) {
result.xbox = t;
} else if (windows) {
result.windows = t;
} else if (linux) {
result.linux = t;
}
// OS version extraction
var osVersion = '';
if (result.windowsphone) {
osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i);
} else if (iosdevice) {
osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i);
osVersion = osVersion.replace(/[_\s]/g, '.');
} else if (android) {
osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i);
} else if (result.webos) {
osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i);
} else if (result.blackberry) {
osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i);
} else if (result.bada) {
osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i);
} else if (result.tizen) {
osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i);
}
if (osVersion) {
result.osversion = osVersion;
}
// device type extraction
var osMajorVersion = osVersion.split('.')[0];
if (
tablet
|| nexusTablet
|| iosdevice == 'ipad'
|| (android && (osMajorVersion == 3 || (osMajorVersion >= 4 && !mobile)))
|| result.silk
) {
result.tablet = t;
} else if (
mobile
|| iosdevice == 'iphone'
|| iosdevice == 'ipod'
|| android
|| nexusMobile
|| result.blackberry
|| result.webos
|| result.bada
) {
result.mobile = t;
}
// Graded Browser Support
// http://developer.yahoo.com/yui/articles/gbs
if (result.msedge ||
(result.msie && result.version >= 10) ||
(result.yandexbrowser && result.version >= 15) ||
(result.vivaldi && result.version >= 1.0) ||
(result.chrome && result.version >= 20) ||
(result.samsungBrowser && result.version >= 4) ||
(result.firefox && result.version >= 20.0) ||
(result.safari && result.version >= 6) ||
(result.opera && result.version >= 10.0) ||
(result.ios && result.osversion && result.osversion.split(".")[0] >= 6) ||
(result.blackberry && result.version >= 10.1)
|| (result.chromium && result.version >= 20)
) {
result.a = t;
}
else if ((result.msie && result.version < 10) ||
(result.chrome && result.version < 20) ||
(result.firefox && result.version < 20.0) ||
(result.safari && result.version < 6) ||
(result.opera && result.version < 10.0) ||
(result.ios && result.osversion && result.osversion.split(".")[0] < 6)
|| (result.chromium && result.version < 20)
) {
result.c = t;
} else result.x = t;
return result
}
var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent || '' : '');
bowser.test = function (browserList) {
for (var i = 0; i < browserList.length; ++i) {
var browserItem = browserList[i];
if (typeof browserItem=== 'string') {
if (browserItem in bowser) {
return true;
}
}
}
return false;
};
/**
* Get version precisions count
*
* @example
* getVersionPrecision("1.10.3") // 3
*
* @param {string} version
* @return {number}
*/
function getVersionPrecision(version) {
return version.split(".").length;
}
/**
* Array::map polyfill
*
* @param {Array} arr
* @param {Function} iterator
* @return {Array}
*/
function map(arr, iterator) {
var result = [], i;
if (Array.prototype.map) {
return Array.prototype.map.call(arr, iterator);
}
for (i = 0; i < arr.length; i++) {
result.push(iterator(arr[i]));
}
return result;
}
/**
* Calculate browser version weight
*
* @example
* compareVersions(['1.10.2.1', '1.8.2.1.90']) // 1
* compareVersions(['1.010.2.1', '1.09.2.1.90']); // 1
* compareVersions(['1.10.2.1', '1.10.2.1']); // 0
* compareVersions(['1.10.2.1', '1.0800.2']); // -1
*
* @param {Array<String>} versions versions to compare
* @return {Number} comparison result
*/
function compareVersions(versions) {
// 1) get common precision for both versions, for example for "10.0" and "9" it should be 2
var precision = Math.max(getVersionPrecision(versions[0]), getVersionPrecision(versions[1]));
var chunks = map(versions, function (version) {
var delta = precision - getVersionPrecision(version);
// 2) "9" -> "9.0" (for precision = 2)
version = version + new Array(delta + 1).join(".0");
// 3) "9.0" -> ["000000000"", "000000009"]
return map(version.split("."), function (chunk) {
return new Array(20 - chunk.length).join("0") + chunk;
}).reverse();
});
// iterate in reverse order by reversed chunks array
while (--precision >= 0) {
// 4) compare: "000000009" > "000000010" = false (but "9" > "10" = true)
if (chunks[0][precision] > chunks[1][precision]) {
return 1;
}
else if (chunks[0][precision] === chunks[1][precision]) {
if (precision === 0) {
// all version chunks are same
return 0;
}
}
else {
return -1;
}
}
}
/**
* Check if browser is unsupported
*
* @example
* bowser.isUnsupportedBrowser({
* msie: "10",
* firefox: "23",
* chrome: "29",
* safari: "5.1",
* opera: "16",
* phantom: "534"
* });
*
* @param {Object} minVersions map of minimal version to browser
* @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map
* @param {String} [ua] user agent string
* @return {Boolean}
*/
function isUnsupportedBrowser(minVersions, strictMode, ua) {
var _bowser = bowser;
// make strictMode param optional with ua param usage
if (typeof strictMode === 'string') {
ua = strictMode;
strictMode = void(0);
}
if (strictMode === void(0)) {
strictMode = false;
}
if (ua) {
_bowser = detect(ua);
}
var version = "" + _bowser.version;
for (var browser in minVersions) {
if (minVersions.hasOwnProperty(browser)) {
if (_bowser[browser]) {
if (typeof minVersions[browser] !== 'string') {
throw new Error('Browser version in the minVersion map should be a string: ' + browser + ': ' + String(minVersions));
}
// browser version and min supported version.
return compareVersions([version, minVersions[browser]]) < 0;
}
}
}
return strictMode; // not found
}
/**
* Check if browser is supported
*
* @param {Object} minVersions map of minimal version to browser
* @param {Boolean} [strictMode = false] flag to return false if browser wasn't found in map
* @param {String} [ua] user agent string
* @return {Boolean}
*/
function check(minVersions, strictMode, ua) {
return !isUnsupportedBrowser(minVersions, strictMode, ua);
}
bowser.isUnsupportedBrowser = isUnsupportedBrowser;
bowser.compareVersions = compareVersions;
bowser.check = check;
/*
* Set our detect method to the main bowser object so we can
* reuse it to test other user agents.
* This is needed to implement future tests.
*/
bowser._detect = detect;
return bowser
});
});
var userAgent = navigator.userAgent.toLowerCase();
//@ts-ignore
var info = bowser._detect(userAgent);
var webkitVersionMatch = userAgent.match(/applewebkit\/(\d+(:?\.\d+)*)/);
//Helper
//@ts-ignore
var compareVersions = bowser.compareVersions;
//Platforms
var isMacPlatform = !!info.mac;
var isAndroid = !!info.android;
var isIOS = !!info.ios;
var isMobile = !!info.mobile;
var isTablet = !!info.tablet;
//Browsers
var version = parseInt(info.version, 10);
var fullVersion = info.version;
var webkitVersion = webkitVersionMatch && webkitVersionMatch[1] || '';
var isIE = !!(info.msie || info.msedge);
var isIE11 = isIE && version === 11;
var isIE10 = isIE && version === 10;
var isIE9 = isIE && version === 9;
var isFirefox = !!info.firefox;
var isMSEdge = !!info.msedge;
var isChrome = !!info.chrome;
var isSafari = !!info.safari;
var isWebKit = !!(info.webkit || info.blink);
var isElectron = /electron/g.test(userAgent);
var browserUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
compareVersions: compareVersions,
isMacPlatform: isMacPlatform,
isAndroid: isAndroid,
isIOS: isIOS,
isMobile: isMobile,
isTablet: isTablet,
version: version,
fullVersion: fullVersion,
webkitVersion: webkitVersion,
isIE: isIE,
isIE11: isIE11,
isIE10: isIE10,
isIE9: isIE9,
isFirefox: isFirefox,
isMSEdge: isMSEdge,
isChrome: isChrome,
isSafari: isSafari,
isWebKit: isWebKit,
isElectron: isElectron
});
function inaccessibleTypeToStr(obj) {
return obj === null ? 'null' : 'undefined';
}
function isNullOrUndefined(obj) {
return obj === null || obj === void 0;
}
function isPrimitiveType(obj) {
var objType = typeof obj;
return objType !== 'object' && objType !== 'function';
}
function isNull(obj) {
//Some times IE cannot compare null correctly
return isIE
// eslint-disable-next-line eqeqeq
? obj == null
: obj === null;
}
function isNumber(val) {
return typeof val === 'number';
}
function isFunction(val) {
return typeof val === 'function';
}
var typeUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
inaccessibleTypeToStr: inaccessibleTypeToStr,
isNullOrUndefined: isNullOrUndefined,
isPrimitiveType: isPrimitiveType,
isNull: isNull,
isNumber: isNumber,
isFunction: isFunction
});
/*global Document, Window */
var NATIVE_CODE_RE = /\[native code]/;
var NativeMethods = /** @class */ (function () {
function NativeMethods(doc, win) {
win = win || globalContextInfo.global;
this.refreshWindowMeths(win, globalContextInfo.isInWorker);
this.refreshWorkerMeths(win);
if (globalContextInfo.isInWorker)
return;
this.refreshDocumentMeths(doc, win);
this.refreshElementMeths(doc, win);
}
NativeMethods._getDocumentPropOwnerName = function (docPrototype, propName) {
return docPrototype.hasOwnProperty(propName) ? 'Document' : 'HTMLDocument'; // eslint-disable-line no-prototype-builtins
};
NativeMethods.prototype.getStoragesPropsOwner = function (win) {
return this.isStoragePropsLocatedInProto ? win.Window.prototype : win;
};
NativeMethods.prototype.refreshWorkerMeths = function (scope /* WorkerGlobalScope */) {
this.importScripts = scope.importScripts;
};
NativeMethods.prototype.refreshDocumentMeths = function (doc, win) {
doc = doc || document;
win = win || window;
var docPrototype = win.Document.prototype;
// Dom
this.createDocumentFragment = docPrototype.createDocumentFragment;
this.createElement = docPrototype.createElement;
this.createElementNS = docPrototype.createElementNS;
this.createTextNode = docPrototype.createTextNode;
this.documentOpenPropOwnerName = NativeMethods._getDocumentPropOwnerName(docPrototype, 'open');
this.documentClosePropOwnerName = NativeMethods._getDocumentPropOwnerName(docPrototype, 'close');
this.documentWritePropOwnerName = NativeMethods._getDocumentPropOwnerName(docPrototype, 'write');
this.documentWriteLnPropOwnerName = NativeMethods._getDocumentPropOwnerName(docPrototype, 'writeln');
this.documentOpen = win[this.documentOpenPropOwnerName].prototype.open;
this.documentClose = win[this.documentClosePropOwnerName].prototype.close;
this.documentWrite = win[this.documentWritePropOwnerName].prototype.write;
this.documentWriteLn = win[this.documentWriteLnPropOwnerName].prototype.writeln;
this.elementFromPoint = docPrototype.elementFromPoint;
this.caretRangeFromPoint = docPrototype.caretRangeFromPoint;
// @ts-ignore Experimental method in Firefox
this.caretPositionFromPoint = docPrototype.caretPositionFromPoint;
this.getElementById = docPrototype.getElementById;
this.getElementsByClassName = docPrototype.getElementsByClassName;
this.getElementsByName = docPrototype.getElementsByName;
this.getElementsByTagName = docPrototype.getElementsByTagName;
this.querySelector = docPrototype.querySelector;
this.querySelectorAll = docPrototype.querySelectorAll;
this.createHTMLDocument = win.DOMImplementation.prototype.createHTMLDocument;
// @ts-ignore
if (doc.registerElement) {
// @ts-ignore
this.registerElement = docPrototype.registerElement;
}
// Event
// NOTE: IE11 has no EventTarget so we should save "Event" methods separately
if (!win.EventTarget) {
this.documentAddEventListener = docPrototype.addEventListener;
this.documentRemoveEventListener = docPrototype.removeEventListener;
}
this.documentCreateEvent = docPrototype.createEvent;
// @ts-ignore Deprecated
this.documentCreateTouch = docPrototype.createTouch;
// @ts-ignore Deprecated
this.documentCreateTouchList = docPrototype.createTouchList;
// getters/setters
this.documentCookiePropOwnerName = NativeMethods._getDocumentPropOwnerName(docPrototype, 'cookie');
var documentCookieDescriptor = win.Object.getOwnPropertyDescriptor(win[this.documentCookiePropOwnerName].prototype, 'cookie');
// TODO: remove this condition after the GH-1649 fix
if (!this.isNativeCode(documentCookieDescriptor.get) ||
!this.isNativeCode(documentCookieDescriptor.get.toString)) {
try {
var parentNativeMethods = win.parent['%hammerhead%'].nativeMethods;
documentCookieDescriptor.get = parentNativeMethods.documentCookieGetter;
documentCookieDescriptor.set = parentNativeMethods.documentCookieSetter;
}
catch (_a) { } // eslint-disable-line no-empty
}
this.documentReferrerGetter = win.Object.getOwnPropertyDescriptor(docPrototype, 'referrer').get;
this.documentStyleSheetsGetter = win.Object.getOwnPropertyDescriptor(docPrototype, 'styleSheets').get;
this.documentActiveElementGetter = win.Object.getOwnPropertyDescriptor(docPrototype, 'activeElement').get;
this.documentCookieGetter = documentCookieDescriptor.get;
this.documentCookieSetter = documentCookieDescriptor.set;
var documentDocumentURIDescriptor = win.Object.getOwnPropertyDescriptor(docPrototype, 'documentURI');
if (documentDocumentURIDescriptor)
this.documentDocumentURIGetter = documentDocumentURIDescriptor.get;
var documentTitleDescriptor = win.Object.getOwnPropertyDescriptor(docPrototype, 'title');
this.documentTitleGetter = documentTitleDescriptor.get;
this.documentTitleSetter = documentTitleDescriptor.set;
};
NativeMethods.prototype.refreshElementMeths = function (doc, win) {
var _this = this;
win = win || window;
var createElement = (function (tagName) { return _this.createElement.call(doc || document, tagName); });
var nativeElement = createElement('div');
var createTextNode = function (data) { return _this.createTextNode.call(doc || document, data); };
var textNode = createTextNode('text');
// Dom
this.appendChild = win.Node.prototype.appendChild;
this.append = win.Element.prototype.append;
this.prepend = win.Element.prototype.prepend;
this.after = win.Element.prototype.after;
this.attachShadow = win.Element.prototype.attachShadow;
this.replaceChild = nativeElement.replaceChild;
this.cloneNode = nativeElement.cloneNode;
this.elementGetElementsByClassName = nativeElement.getElementsByClassName;
this.elementGetElementsByTagName = nativeElement.getElementsByTagName;
this.elementQuerySelector = nativeElement.querySelector;
this.elementQuerySelectorAll = nativeElement.querySelectorAll;
this.getAttribute = nativeElement.getAttribute;
this.getAttributeNS = nativeElement.getAttributeNS;
this.getAttributeNode = nativeElement.getAttributeNode;
this.getAttributeNodeNS = nativeElement.getAttributeNodeNS;
this.insertBefore = nativeElement.insertBefore;
this.insertCell = createElement('tr').insertCell;
this.insertTableRow = createElement('table').insertRow;
this.insertTBodyRow = createElement('tbody').insertRow;
this.removeAttribute = nativeElement.removeAttribute;
this.removeAttributeNS = nativeElement.removeAttributeNS;
this.removeAttributeNode = nativeElement.removeAttributeNode;
this.removeChild = win.Node.prototype.removeChild;
this.remove = win.Element.prototype.remove;
this.elementReplaceWith = win.Element.prototype.replaceWith;
this.setAttribute = nativeElement.setAttribute;
this.setAttributeNS = nativeElement.setAttributeNS;
this.hasAttribute = nativeElement.hasAttribute;
this.hasAttributeNS = nativeElement.hasAttributeNS;
this.hasAttributes = nativeElement.hasAttributes;
this.anchorToString = win.HTMLAnchorElement.prototype.toString;
this.matches = nativeElement.matches || nativeElement.msMatchesSelector;
this.closest = nativeElement.closest;
// NOTE: The 'insertAdjacent...' methods is located in HTMLElement prototype in IE11 only
this.insertAdjacentMethodsOwner = win.Element.prototype.hasOwnProperty('insertAdjacentElement') // eslint-disable-line no-prototype-builtins
? win.Element.prototype
: win.HTMLElement.prototype;
this.insertAdjacentElement = this.insertAdjacentMethodsOwner.insertAdjacentElement;
this.insertAdjacentHTML = this.insertAdjacentMethodsOwner.insertAdjacentHTML;
this.insertAdjacentText = this.insertAdjacentMethodsOwner.insertAdjacentText;
// Text node
this.appendData = textNode.appendData;
// TODO: remove this condition after the GH-1649 fix
if (!this.isNativeCode(this.elementGetElementsByTagName)) {
try {
var parentNativeMethods = win.parent['%hammerhead%'].nativeMethods;
this.elementGetElementsByTagName = parentNativeMethods.elementGetElementsByTagName;
}
// eslint-disable-next-line no-empty
catch (e) {
}
}
// Event
if (win.EventTarget) {
this.addEventListener = win.EventTarget.prototype.addEventListener;
this.removeEventListener = win.EventTarget.prototype.removeEventListener;
this.dispatchEvent = win.EventTarget.prototype.dispatchEvent;
}
// NOTE: IE11 has no EventTarget
else {
this.addEventListener = nativeElement.addEventListener;
this.removeEventListener = nativeElement.removeEventListener;
this.dispatchEvent = nativeElement.dispatchEvent;
}
this.blur = nativeElement.blur;
this.click = nativeElement.click;
this.focus = nativeElement.focus;
// @ts-ignore
this.select = window.TextRange ? createElement('body').createTextRange().select : null;
this.setSelectionRange = createElement('input').setSelectionRange;
this.textAreaSetSelectionRange = createElement('textarea').setSelectionRange;
this.svgFocus = win.SVGElement ? win.SVGElement.prototype.focus : this.focus;
this.svgBlur = win.SVGElement ? win.SVGElement.prototype.blur : this.blur;
// Style
// NOTE: The 'style' descriptor is located in the Element.prototype in the Safari on IOS
this.htmlElementStylePropOwnerName = win.Element.prototype.hasOwnProperty('style') ? 'Element' : 'HTMLElement'; // eslint-disable-line no-prototype-builtins
var htmlElementStyleDescriptor = win.Object.getOwnPropertyDescriptor(win[this.htmlElementStylePropOwnerName].prototype, 'style');
this.htmlElementStyleGetter = htmlElementStyleDescriptor.get;
// NOTE: IE does not allow to set a style property
if (htmlElementStyleDescriptor.set)
this.htmlElementStyleSetter = htmlElementStyleDescriptor.set;
var styleCssTextDescriptor = win.Object.getOwnPropertyDescriptor(win.CSSStyleDeclaration.prototype, 'cssText');
this.styleCssTextGetter = styleCssTextDescriptor.get;
this.styleCssTextSetter = styleCssTextDescriptor.set;
};
NativeMethods.prototype._refreshGettersAndSetters = function (win, isInWorker) {
if (isInWorker === void 0) { isInWorker = false; }
win = win || window;
var winProto = win.constructor.prototype;
// NOTE: Event properties is located in window prototype only in IE11
this.isEventPropsLocatedInProto = winProto.hasOwnProperty('onerror'); // eslint-disable-line no-prototype-builtins
var eventPropsOwner = this.isEventPropsLocatedInProto ? winProto : win;
var winOnBeforeUnloadDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onbeforeunload');
var winOnUnloadDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onunload');
var winOnPageHideDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onpagehide');
var winOnMessageDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onmessage');
var winOnErrorDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onerror');
var winOnHashChangeDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onhashchange');
this.winOnBeforeUnloadSetter = winOnBeforeUnloadDescriptor && winOnBeforeUnloadDescriptor.set;
this.winOnUnloadSetter = winOnUnloadDescriptor && winOnUnloadDescriptor.set;
this.winOnPageHideSetter = winOnPageHideDescriptor && winOnPageHideDescriptor.set;
this.winOnMessageSetter = winOnMessageDescriptor && winOnMessageDescriptor.set;
this.winOnErrorSetter = winOnErrorDescriptor && winOnErrorDescriptor.set;
this.winOnHashChangeSetter = winOnHashChangeDescriptor && winOnHashChangeDescriptor.set;
var winOnUnhandledRejectionDescriptor = win.Object.getOwnPropertyDescriptor(eventPropsOwner, 'onunhandledrejection');
if (winOnUnhandledRejectionDescriptor)
this.winOnUnhandledRejectionSetter = winOnUnhandledRejectionDescriptor.set;
// Getters
if (win.WebSocket) {
var urlPropDescriptor = win.Object.getOwnPropertyDescriptor(win.WebSocket.prototype, 'url');
if (urlPropDescriptor && urlPropDescriptor.get && urlPropDescriptor.configurable)
this.webSocketUrlGetter = urlPropDescriptor.get;
}
this.messageEventOriginGetter = win.Object.getOwnPropertyDescriptor(win.MessageEvent.prototype, 'origin').get;
// NOTE: At present we proxy only the PerformanceNavigationTiming.
// Another types of the PerformanceEntry will be fixed later
// https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry
if (win.PerformanceNavigationTiming)
this.performanceEntryNameGetter = win.Object.getOwnPropertyDescriptor(win.PerformanceEntry.prototype, 'name').get;
var dataPropDescriptor = win.Object.getOwnPropertyDescriptor(win.MessageEvent.prototype, 'data');
// NOTE: This condition is used for the Android 6.0 browser
if (dataPropDescriptor)
this.messageEventDataGetter = dataPropDescriptor.get;
if (win.fetch) {
this.responseStatusGetter = win.Object.getOwnPropertyDescriptor(win.Response.prototype, 'status').get;
this.responseTypeGetter = win.Object.getOwnPropertyDescriptor(win.Response.prototype, 'type').get;
this.responseUrlGetter = win.Object.getOwnPropertyDescriptor(win.Response.prototype, 'url').get;
this.requestUrlGetter = win.Object.getOwnPropertyDescriptor(win.Request.prototype, 'url').get;
this.requestReferrerGetter = win.Object.getOwnPropertyDescriptor(win.Request.prototype, 'referrer').get;
}
if (win.XMLHttpRequest) {
var xhrResponseURLDescriptor = win.Object.getOwnPropertyDescriptor(win.XMLHttpRequest.prototype, 'responseURL');
// NOTE: IE doesn't support the 'responseURL' property
if (xhrResponseURLDescriptor)
this.xhrResponseURLGetter = xhrResponseURLDescriptor.get;
}
// eslint-disable-next-line no-restricted-properties
if (win.Window) {
// NOTE: The 'localStorage' and 'sessionStorage' properties is located in window prototype only in IE11
this.isStoragePropsLocatedInProto = win.Window.prototype.hasOwnProperty('localStorage'); // eslint-disable-line no-prototype-builtins
var storagesPropsOwner = this.getStoragesPropsOwner(win);
this.winLocalStorageGetter = win.Object.getOwnPropertyDescriptor(storagesPropsOwner, 'localStorage').get;
this.winSessionStorageGetter = win.Object.getOwnPropertyDescriptor(storagesPropsOwner, 'sessionStorage').get;
}
if (isInWorker)
return;
this.storageGetItem = win.Storage.prototype.getItem;
this.storageSetItem = win.Storage.prototype.setItem;
this.storageRemoveItem = win.Storage.prototype.removeItem;
this.storageClear = win.Storage.prototype.clear;
this.storageKey = win.Storage.prototype.key;
this.storageLengthGetter = win.Object.getOwnPropertyDescriptor(win.Storage.prototype, 'length');
var objectDataDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLObjectElement.prototype, 'data');
var inputTypeDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'type');
var inputValueDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'value');
var inputDisabledDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'disabled');
var inputRequiredDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'required');
var textAreaValueDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLTextAreaElement.prototype, 'value');
var imageSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLImageElement.prototype, 'src');
var imageSrcsetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLImageElement.prototype, 'srcset');
var scriptSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLScriptElement.prototype, 'src');
var scriptIntegrityDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLScriptElement.prototype, 'integrity');
var embedSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLEmbedElement.prototype, 'src');
var sourceSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLSourceElement.prototype, 'src');
var mediaSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLMediaElement.prototype, 'src');
var inputSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'src');
var frameSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLFrameElement.prototype, 'src');
var iframeSrcDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLIFrameElement.prototype, 'src');
var anchorHrefDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'href');
var linkHrefDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLLinkElement.prototype, 'href');
var linkIntegrityDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLLinkElement.prototype, 'integrity');
var linkRelDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLLinkElement.prototype, 'rel');
var linkAsDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLLinkElement.prototype, 'as');
var areaHrefDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAreaElement.prototype, 'href');
var baseHrefDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLBaseElement.prototype, 'href');
var anchorHostDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'host');
var anchorHostnameDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'hostname');
var anchorPathnameDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'pathname');
var anchorPortDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'port');
var anchorProtocolDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'protocol');
var anchorSearchDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'search');
var anchorTargetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'target');
var formTargetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLFormElement.prototype, 'target');
var areaTargetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAreaElement.prototype, 'target');
var baseTargetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLBaseElement.prototype, 'target');
var inputFormTargetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'formTarget');
var buttonFormTargetDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLButtonElement.prototype, 'formTarget');
var svgImageHrefDescriptor = win.Object.getOwnPropertyDescriptor(win.SVGImageElement.prototype, 'href');
var svgAnimStrAnimValDescriptor = win.Object.getOwnPropertyDescriptor(win.SVGAnimatedString.prototype, 'animVal');
var svgAnimStrBaseValDescriptor = win.Object.getOwnPropertyDescriptor(win.SVGAnimatedString.prototype, 'baseVal');
var inputAutocompleteDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'autocomplete');
var formActionDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLFormElement.prototype, 'action');
var inputFormActionDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'formAction');
var buttonFormActionDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLButtonElement.prototype, 'formAction');
var nodeTextContentDescriptor = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'textContent');
var htmlElementInnerTextDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLElement.prototype, 'innerText');
var scriptTextDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLScriptElement.prototype, 'text');
var anchorTextDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'text');
var titleElementTextDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLTitleElement.prototype, 'text');
var iframeSandboxDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLIFrameElement.prototype, 'sandbox');
var metaHttpEquivDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLMetaElement.prototype, 'httpEquiv');
var windowOriginDescriptor = win.Object.getOwnPropertyDescriptor(win, 'origin');
if (windowOriginDescriptor) {
this.windowOriginGetter = windowOriginDescriptor.get;
this.windowOriginSetter = windowOriginDescriptor.set;
}
// NOTE: We need 'disabled' property only for Chrome.
// In Chrome it's located in HTMLInputElement.prototype
// But in IE11 it's located in HTMLElement.prototype
// So we need the null check
if (inputDisabledDescriptor) {
this.inputDisabledSetter = inputDisabledDescriptor.set;
this.inputDisabledGetter = inputDisabledDescriptor.get;
}
// NOTE: Html properties is located in HTMLElement prototype in IE11 only
this.elementHTMLPropOwnerName = win.Element.prototype.hasOwnProperty('innerHTML') ? 'Element' : 'HTMLElement'; // eslint-disable-line no-prototype-builtins
var elementInnerHTMLDescriptor = win.Object.getOwnPropertyDescriptor(win[this.elementHTMLPropOwnerName].prototype, 'innerHTML');
var elementOuterHTMLDescriptor = win.Object.getOwnPropertyDescriptor(win[this.elementHTMLPropOwnerName].prototype, 'outerHTML');
// Setters
this.objectDataSetter = objectDataDescriptor.set;
this.inputTypeSetter = inputTypeDescriptor.set;
this.inputValueSetter = inputValueDescriptor.set;
this.inputRequiredSetter = inputRequiredDescriptor.set;
this.textAreaValueSetter = textAreaValueDescriptor.set;
this.imageSrcSetter = imageSrcDescriptor.set;
this.scriptSrcSetter = scriptSrcDescriptor.set;
this.embedSrcSetter = embedSrcDescriptor.set;
this.sourceSrcSetter = sourceSrcDescriptor.set;
this.mediaSrcSetter = mediaSrcDescriptor.set;
this.inputSrcSetter = inputSrcDescriptor.set;
this.frameSrcSetter = frameSrcDescriptor.set;
this.iframeSrcSetter = iframeSrcDescriptor.set;
this.anchorHrefSetter = anchorHrefDescriptor.set;
this.linkHrefSetter = linkHrefDescriptor.set;
this.linkRelSetter = linkRelDescriptor.set;
this.linkAsSetter = linkAsDescriptor && linkAsDescriptor.set;
this.areaHrefSetter = areaHrefDescriptor.set;
this.baseHrefSetter = baseHrefDescriptor.set;
this.anchorHostSetter = anchorHostDescriptor.set;
this.anchorHostnameSetter = anchorHostnameDescriptor.set;
this.anchorPathnameSetter = anchorPathnameDescriptor.set;
this.anchorPortSetter = anchorPortDescriptor.set;
this.anchorProtocolSetter = anchorProtocolDescriptor.set;
this.anchorSearchSetter = anchorSearchDescriptor.set;
this.anchorTargetSetter = anchorTargetDescriptor.set;
this.formTargetSetter = formTargetDescriptor.set;
this.areaTargetSetter = areaTargetDescriptor.set;
this.baseTargetSetter = baseTargetDescriptor.set;
this.inputFormTargetSetter = inputFormTargetDescriptor.set;
this.buttonFormTargetSetter = buttonFormTargetDescriptor.set;
this.svgAnimStrBaseValSetter = svgAnimStrBaseValDescriptor.set;
this.inputAutocompleteSetter = inputAutocompleteDescriptor.set;
this.formActionSetter = formActionDescriptor.set;
this.inputFormActionSetter = inputFormActionDescriptor.set;
this.buttonFormActionSetter = buttonFormActionDescriptor.set;
this.iframeSandboxSetter = iframeSandboxDescriptor.set;
this.metaHttpEquivSetter = metaHttpEquivDescriptor.set;
this.htmlElementOnloadSetter = win.Object.getOwnPropertyDescriptor(win.HTMLElement.prototype, 'onload').set;
this.nodeTextContentSetter = nodeTextContentDescriptor.set;
this.htmlElementInnerTextSetter = htmlElementInnerTextDescriptor.set;
this.scriptTextSetter = scriptTextDescriptor.set;
this.anchorTextSetter = anchorTextDescriptor.set;
this.elementInnerHTMLSetter = elementInnerHTMLDescriptor.set;
this.elementOuterHTMLSetter = elementOuterHTMLDescriptor.set;
// NOTE: Some browsers (for example, Edge, Internet Explorer 11, Safari) don't support the 'integrity' property.
if (scriptIntegrityDescriptor && linkIntegrityDescriptor) {
this.scriptIntegritySetter = scriptIntegrityDescriptor.set;
this.linkIntegritySetter = linkIntegrityDescriptor.set;
}
this.titleElementTextSetter = titleElementTextDescriptor.set;
// NOTE: the classList property is located in HTMLElement prototype in IE11
this.elementClassListPropOwnerName = win.Element.prototype.hasOwnProperty('classList') ? 'Element' : 'HTMLElement'; // eslint-disable-line no-prototype-builtins
this.elementClassListGetter = win.Object.getOwnPropertyDescriptor(win[this.elementClassListPropOwnerName].prototype, 'classList').get;
this.htmlCollectionLengthGetter = win.Object.getOwnPropertyDescriptor(win.HTMLCollection.prototype, 'length').get;
this.nodeListLengthGetter = win.Object.getOwnPropertyDescriptor(win.NodeList.prototype, 'length').get;
this.elementChildElementCountGetter = win.Object.getOwnPropertyDescriptor(win.Element.prototype, 'childElementCount').get;
this.inputFilesGetter = win.Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'files').get;
this.styleSheetHrefGetter = win.Object.getOwnPropertyDescriptor(win.StyleSheet.prototype, 'href').get;
this.objectDataGetter = objectDataDescriptor.get;
this.inputTypeGetter = inputTypeDescriptor.get;
this.inputValueGetter = inputValueDescriptor.get;
this.inputRequiredGetter = inputRequiredDescriptor.get;
this.textAreaValueGetter = textAreaValueDescriptor.get;
this.imageSrcGetter = imageSrcDescriptor.get;
this.scriptSrcGetter = scriptSrcDescriptor.get;
this.embedSrcGetter = embedSrcDescriptor.get;
this.sourceSrcGetter = sourceSrcDescriptor.get;
this.mediaSrcGetter = mediaSrcDescriptor.get;
this.inputSrcGetter = inputSrcDescriptor.get;
this.frameSrcGetter = frameSrcDescriptor.get;
this.iframeSrcGetter = iframeSrcDescriptor.get;
this.anchorHrefGetter = anchorHrefDescriptor.get;
this.linkHrefGetter = linkHrefDescriptor.get;
this.linkRelGetter = linkRelDescriptor.get;
this.areaHrefGetter = areaHrefDescriptor.get;
this.baseHrefGetter = baseHrefDescriptor.get;
this.anchorHostGetter = anchorHostDescriptor.get;
this.anchorHostnameGetter = anchorHostnameDescriptor.get;
this.anchorPathnameGetter = anchorPathnameDescriptor.get;
this.anchorPortGetter = anchorPortDescriptor.get;
this.anchorProtocolGetter = anchorProtocolDescriptor.get;
this.anchorSearchGetter = anchorSearchDescriptor.get;
this.anchorTargetGetter = anchorTargetDescriptor.get;
this.formTargetGetter = formTargetDescriptor.get;
this.areaTargetGetter = areaTargetDescriptor.get;
this.baseTargetGetter = baseTargetDescriptor.get;
this.inputFormTargetGetter = inputFormTargetDescriptor.get;
this.buttonFormTargetGetter = buttonFormTargetDescriptor.get;
this.svgImageHrefGetter = svgImageHrefDescriptor.get;
this.svgAnimStrAnimValGetter = svgAnimStrAnimValDescriptor.get;
this.svgAnimStrBaseValGetter = svgAnimStrBaseValDescriptor.get;
this.inputAutocompleteGetter = inputAutocompleteDescriptor.get;
this.formActionGetter = formActionDescriptor.get;
this.inputFormActionGetter = inputFormActionDescriptor.get;
this.buttonFormActionGetter = buttonFormActionDescriptor.get;
this.iframeSandboxGetter = iframeSandboxDescriptor.get;
this.metaHttpEquivGetter = metaHttpEquivDescriptor.get;
this.contentWindowGetter = win.Object.getOwnPropertyDescriptor(win.HTMLIFrameElement.prototype, 'contentWindow').get;
this.contentDocumentGetter = win.Object.getOwnPropertyDescriptor(win.HTMLIFrameElement.prototype, 'contentDocument').get;
this.frameContentWindowGetter = win.Object.getOwnPropertyDescriptor(win.HTMLFrameElement.prototype, 'contentWindow').get;
this.nodeTextContentGetter = nodeTextContentDescriptor.get;
this.htmlElementInnerTextGetter = htmlElementInnerTextDescriptor.get;
this.scriptTextGetter = scriptTextDescriptor.get;
this.anchorTextGetter = anchorTextDescriptor.get;
this.elementInnerHTMLGetter = elementInnerHTMLDescriptor.get;
this.elementOuterHTMLGetter = elementOuterHTMLDescriptor.get;
this.nodeFirstChildGetter = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'firstChild').get;
this.nodeLastChildGetter = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'lastChild').get;
this.nodeNextSiblingGetter = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'nextSibling').get;
this.nodePrevSiblingGetter = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'previousSibling').get;
this.nodeParentNodeGetter = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'parentNode').get;
this.nodeChildNodesGetter = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'childNodes').get;
this.elementFirstElementChildGetter = win.Object.getOwnPropertyDescriptor(win.Element.prototype, 'firstElementChild').get;
this.elementLastElementChildGetter = win.Object.getOwnPropertyDescriptor(win.Element.prototype, 'lastElementChild').get;
this.elementNextElementSiblingGetter = win.Object.getOwnPropertyDescriptor(win.Element.prototype, 'nextElementSibling').get;
this.elementPrevElementSiblingGetter = win.Object.getOwnPropertyDescriptor(win.Element.prototype, 'previousElementSibling').get;
// NOTE: Some browsers (for example, Edge, Internet Explorer 11, Safari) don't support the 'integrity' property.
if (scriptIntegrityDescriptor && linkIntegrityDescriptor) {
this.scriptIntegrityGetter = scriptIntegrityDescriptor.get;
this.linkIntegrityGetter = linkIntegrityDescriptor.get;
}
// NOTE: In the Internet Explorer 11 the children property is located in HTMLElement.
var childrenPropOwner = win.Element.prototype.hasOwnProperty('children') // eslint-disable-line no-prototype-builtins
? win.Element.prototype
: win.HTMLElement.prototype;
this.elementChildrenGetter = win.Object.getOwnPropertyDescriptor(childrenPropOwner, 'children').get;
var anchorOriginDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLAnchorElement.prototype, 'origin');
// NOTE: IE and Edge don't support origin property
if (anchorOriginDescriptor)
this.anchorOriginGetter = anchorOriginDescriptor.get;
var iframeSrcdocDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLIFrameElement.prototype, 'srcdoc');
// NOTE: IE11 doesn't support the 'srcdoc' property
if (iframeSrcdocDescriptor) {
this.iframeSrcdocGetter = iframeSrcdocDescriptor.get;
this.iframeSrcdocSetter = iframeSrcdocDescriptor.set;
}
var cssStyleSheetHrefDescriptor = win.Object.getOwnPropertyDescriptor(win.CSSStyleSheet.prototype, 'href');
// NOTE: IE11 doesn't support the 'href' property
if (cssStyleSheetHrefDescriptor)
this.cssStyleSheetHrefGetter = cssStyleSheetHrefDescriptor.get;
var nodeBaseURIDescriptor = win.Object.getOwnPropertyDescriptor(win.Node.prototype, 'baseURI');
// NOTE: IE11 doesn't support the 'baseURI' property
if (nodeBaseURIDescriptor)
this.nodeBaseURIGetter = nodeBaseURIDescriptor.get;
// NOTE: The 'attributes' property is located in Node prototype in IE11 only
this.elementAttributesPropOwnerName = win.Element.prototype.hasOwnProperty('attributes') ? 'Element' : 'Node'; // eslint-disable-line no-prototype-builtins
this.elementAttributesGetter = win.Object.getOwnPropertyDescriptor(win[this.elementAttributesPropOwnerName].prototype, 'attributes').get;
var htmlManifestDescriptor = win.Object.getOwnPropertyDescriptor(win.HTMLHtmlElement.prototype, 'manifest');
// NOTE: Only the Safari browser supports the 'manifest' property
if (htmlManifestDescriptor) {
this.htmlManifestGetter = htmlManifestDescriptor.get;
this.htmlManifestSetter = htmlManifestDescriptor.set;
}
// NOTE: IE11 doesn't support the 'srcset' property
if (iframeSrcdocDescriptor) {
this.imageSrcsetSetter = imageSrcsetDescriptor.set;
this.imageSrcsetGetter = imageSrcsetDescriptor.get;
}
this.titleElementTextGetter = titleElementTextDescriptor.get;
// MutationRecord
this.mutationRecordNextSiblingGetter = win.Object.getOwnPropertyDescriptor(win.MutationRecord.prototype, 'nextSibling').get;
this.mutationRecordPrevSiblingGetter = win.Object.getOwnPropertyDescriptor(win.MutationRecord.prototype, 'previousSibling').get;
};
NativeMethods.prototype.refreshWindowMeths = function (win, isInWorker) {
if (isInWorker === void 0) { isInWorker = false; }
win = win || window;
var winProto = win.constructor.prototype;
// Dom
this.eval = win.eval;
this.formSubmit = win.HTMLFormElement && win.HTMLFormElement.prototype.submit;
this.documentFragmentQuerySelector = win.DocumentFragment && win.DocumentFragment.prototype.querySelector;
this.documentFragmentQuerySelectorAll = win.DocumentFragment && win.DocumentFragment.prototype.querySelectorAll;
this.preventDefault = win.Event.prototype.preventDefault;
this.historyPushState = win.history && win.history.pushState;
this.historyReplaceState = win.history && win.history.replaceState;
this.postMessage = win.postMessage || winProto.postMessage;
this.windowOpen = win.open || winProto.open;
this.setTimeout = win.setTimeout || winProto.setTimeout;
this.setInterval = win.setInterval || winProto.setInterval;
this.clearTimeout = win.clearTimeout || winProto.clearTimeout;
this.clearInterval = win.clearInterval || winProto.clearInterval;
this.registerProtocolHandler = win.navigator.registerProtocolHandler;
this.sendBeacon = win.Navigator && win.Navigator.prototype.sendBeacon;
if (win.XMLHttpRequest) {
// NOTE: IE11 has no EventTarget so we should save "Event" methods separately
var xhrEventProto = (win.EventTarget || win.XMLHttpRequest).prototype;
this.xhrAbort = win.XMLHttpRequest.prototype.abort;
this.xhrOpen = win.XMLHttpRequest.prototype.open;
this.xhrSend = win.XMLHttpRequest.prototype.send;
this.xhrAddEventListener = xhrEventProto.addEventListener;
this.xhrRemoveEventListener = xhrEventProto.removeEventListener;
this.xhrDispatchEvent = xhrEventProto.dispatchEvent;
this.xhrGetResponseHeader = win.XMLHttpRequest.prototype.getResponseHeader;
this.xhrGetAllResponseHeaders = win.XMLHttpRequest.prototype.getAllResponseHeaders;
this.xhrSetRequestHeader = win.XMLHttpRequest.prototype.setRequestHeader;
this.xhrOverrideMimeType = win.XMLHttpRequest.prototype.overrideMimeType;
}
try {
this.registerServiceWorker = win.navigator.serviceWorker.register;
this.getRegistrationServiceWorker = win.navigator.serviceWorker.getRegistration;
}
catch (e) {
this.registerServiceWorker = null;
this.getRegistrationServiceWorker = null;
}
this.createContextualFragment = win.Range && win.Range.prototype.createContextualFragment;
var nativePerformance = win.performance;
if (nativePerformance) {
// eslint-disable-next-line no-restricted-properties
var nativePerformanceNow_1 = win.performance.now || win.Performance.prototype.now;
this.performanceNow = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return nativePerformanceNow_1.apply(nativePerformance, args);
};
}
// Fetch
this.fetch = win.fetch;
this.Request = win.Request;
if (win.Headers) {
this.Headers = win.Headers;
this.headersSet = win.Headers.prototype.set;
this.headersGet = win.Headers.prototype.get;
this.headersDelete = win.Headers.prototype.delete;
this.headersEntries = win.Headers.prototype.entries;
this.headersForEach = win.Headers.prototype.forEach;
this.headersValues = win.Headers.prototype.values;
}
// Event
this.windowAddEventListener = win.addEventListener || winProto.addEventListener;
this.windowRemoveEventListener = win.removeEventListener || winProto.removeEventListener;
this.windowDispatchEvent = win.dispatchEvent;
this.WindowPointerEvent = win.PointerEvent || winProto.PointerEvent;
this.WindowMSPointerEvent = win.MSPointerEvent || winProto.MSPointerEvent;
this.WindowTouch = win.Touch || winProto.Touch;
this.WindowTouchEvent = win.TouchEvent || winProto.TouchEvent;
this.WindowKeyboardEvent = win.KeyboardEvent || winProto.KeyboardEvent;
this.WindowFocusEvent = win.FocusEvent || winProto.FocusEvent;
this.WindowTextEvent = win.TextEvent || winProto.TextEvent;
this.WindowInputEvent = win.InputEvent || winProto.InputEvent;
this.WindowMouseEvent = win.MouseEvent || winProto.MouseEvent;
this.eventTargetGetter = win.Object.getOwnPropertyDescriptor(win.Event.prototype, 'target').get;
this.canvasContextDrawImage = win.CanvasRenderingContext2D && win.CanvasRenderingContext2D.prototype.drawImage;
// FormData
this.formDataAppend = win.FormData && win.FormData.prototype.append;
// DateTime
this.date = win.Date;
this.dateNow = win.Date.now; // eslint-disable-line no-restricted-properties
// Math
this.math = win.Math;
this.mathRandom = win.Math.random;
// Object
this.objectToString = win.Object.prototype.toString;
this.objectAssign = win.Object.assign;
this.objectKeys = win.Object.keys;
this.objectDefineProperty = win.Object.defineProperty;
this.objectDefineProperties = win.Object.defineProperties;
this.objectCreate = win.Object.create;
this.objectIsExtensible = win.Object.isExtensible;
this.objectIsFrozen = win.Object.isFrozen;
this.objectGetOwnPropertyDescriptor = win.Object.getOwnPropertyDescriptor;
this.objectHasOwnProperty = win.Object.hasOwnProperty;
this.objectGetOwnPropertyNames = win.Object.getOwnPropertyNames;
this.objectGetPrototypeOf = win.Object.getPrototypeOf;
this.objectSetPrototypeOf = win.Object.setPrototypeOf;
this.objectGetOwnPropertySymbols = win.Object.getOwnPropertySymbols;
// Array
this.arraySlice = win.Array.prototype.slice;
this.arrayConcat = win.Array.prototype.concat;
this.arrayFilter = win.Array.prototype.filter;
this.arrayFind = win.Array.prototype.find;
this.arrayMap = win.Array.prototype.map;
this.arrayJoin = win.Array.prototype.join;
this.arraySplice = win.Array.prototype.splice;
this.arrayUnshift = win.Array.prototype.unshift;
this.arrayForEach = win.Array.prototype.forEach;
this.arrayIndexOf = win.Array.prototype.indexOf;
this.arraySome = win.Array.prototype.some;
this.arrayEvery = win.Array.prototype.every;
this.arrayReverse = win.Array.prototype.reverse;
this.arrayReduce = win.Array.prototype.reduce;
this.arrayFrom = win.Array.from;
this.isArray = win.Array.isArray;
this.DOMParserParseFromString = win.DOMParser && win.DOMParser.prototype.parseFromString;
this.arrayBufferIsView = win.ArrayBuffer.prototype.constructor.isView;
// NOTE: this section relates to getting properties from DOM classes
if (!isInWorker) {
// DOMTokenList
this.tokenListAdd = win.DOMTokenList.prototype.add;
this.tokenListRemove = win.DOMTokenList.prototype.remove;
this.tokenListReplace = win.DOMTokenList.prototype.replace;
this.tokenListSupports = win.DOMTokenList.prototype.supports;
this.tokenListToggle = win.DOMTokenList.prototype.toggle;
this.tokenListContains = win.DOMTokenList.prototype.contains;
var tokenListValueDescriptor = win.Object.getOwnPropertyDescriptor(win.DOMTokenList.prototype, 'value');
// NOTE: IE11 doesn't support the 'value' property of the DOMTokenList interface
if (tokenListValueDescriptor)
this.tokenListValueSetter = tokenListValueDescriptor.set;
// Stylesheets
this.styleGetPropertyValue = win.CSSStyleDeclaration.prototype.getPropertyValue;
this.styleSetProperty = win.CSSStyleDeclaration.prototype.setProperty;
this.styleRemoveProperty = win.CSSStyleDeclaration.prototype.removeProperty;
this.styleInsertRule = win.CSSStyleSheet.prototype.insertRule;
this.scrollTo = win.scrollTo;
}
if (win.Promise) {
this.promiseThen = win.Promise.prototype.then;
this.promiseReject = win.Promise.reject;
}
// Console
this.console = win.console;
if (this.console) {
this.consoleMeths = {
log: win.console.log,
warn: win.console.warn,
error: win.console.error,
info: win.console.info,
};
}
this.crypto = win.crypto || win.msCrypto;
this.cryptoGetRandomValues = this.crypto && this.crypto.getRandomValues;
this.refreshClasses(win);
this._refreshGettersAndSetters(win, isInWorker);
};
NativeMethods.prototype.refreshClasses = function (win) {
this.windowClass = win.Window;
this.documentClass = win.Document;
this.locationClass = win.Location;
this.elementClass = win.Element;
this.svgElementClass = win.SVGElement;
this.Worker = win.Worker;
this.MessageChannel = win.MessageChannel;
this.Array = win.Array;
this.ArrayBuffer = win.ArrayBuffer;
this.Uint8Array = win.Uint8Array;
this.Uint16Array = win.Uint16Array;
this.Uint32Array = win.Uint32Array;
this.DataView = win.DataView;
this.Blob = win.Blob;
this.XMLHttpRequest = win.XMLHttpRequest;
this.Image = win.Image;
this.Function = win.Function;
this.functionToString = win.Function.prototype.toString;
this.functionBind = win.Function.prototype.bind;
this.Error = win.Error;
this.FontFace = win.FontFace;
this.StorageEvent = win.StorageEvent;
this.MutationObserver = win.MutationObserver;
this.EventSource = win.EventSource;
this.Proxy = win.Proxy;
this.WebSocket = win.WebSocket;
this.HTMLCollection = win.HTMLCollection;
this.NodeList = win.NodeList;
this.Node = win.Node;
this.URL = win.URL;
this.DataTransfer = win.DataTransfer;
this.DataTransferItemList = win.DataTransferItemList;
this.DataTransferItem = win.DataTransferItem;
this.FileList = win.FileList;
// NOTE: non-IE11 case. window.File in IE11 is not constructable.
if (win.File && isFunction(win.File))
this.File = win.File;
};
NativeMethods.prototype.refreshElectronMeths = function (vmModule) {
if (this.createScript && isNativeFunction(vmModule.createScript))
return false;
this.createScript = vmModule.createScript;
this.runInDebugContext = vmModule.runInDebugContext;
this.runInContext = vmModule.runInContext;
this.runInNewContext = vmModule.runInNewContext;
this.runInThisContext = vmModule.runInThisContext;
return true;
};
NativeMethods._ensureDocumentMethodRestore = function (document, prototype, methodName, savedNativeMethod) {
prototype[methodName] = savedNativeMethod;
if (document[methodName] !== prototype[methodName])
document[methodName] = savedNativeMethod;
};
NativeMethods.prototype.restoreDocumentMeths = function (window, document) {
var docPrototype = window.Document.prototype;
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'createDocumentFragment', this.createDocumentFragment);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'createElement', this.createElement);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'createElementNS', this.createElementNS);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'elementFromPoint', this.elementFromPoint);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'caretRangeFromPoint', this.caretRangeFromPoint);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'caretPositionFromPoint', this.caretPositionFromPoint);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'getElementById', this.getElementById);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'getElementsByClassName', this.getElementsByClassName);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'getElementsByName', this.getElementsByName);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'getElementsByTagName', this.getElementsByTagName);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'querySelector', this.querySelector);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'querySelectorAll', this.querySelectorAll);
// Event
// NOTE: IE11 has no EventTarget
if (!window.EventTarget) {
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'addEventListener', this.documentAddEventListener);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'removeEventListener', this.documentRemoveEventListener);
}
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'createEvent', this.documentCreateEvent);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'createTouch', this.documentCreateTouch);
NativeMethods._ensureDocumentMethodRestore(document, docPrototype, 'createTouchList', this.documentCreateTouchList);
NativeMethods._ensureDocumentMethodRestore(document, window[this.documentOpenPropOwnerName].prototype, 'open', this.documentOpen);
NativeMethods._ensureDocumentMethodRestore(document, window[this.documentClosePropOwnerName].prototype, 'close', this.documentClose);
NativeMethods._ensureDocumentMethodRestore(document, window[this.documentWritePropOwnerName].prototype, 'write', this.documentWrite);
NativeMethods._ensureDocumentMethodRestore(document, window[this.documentWriteLnPropOwnerName].prototype, 'writeln', this.documentWriteLn);
};
NativeMethods.prototype.refreshIfNecessary = function (doc, win) {
var _this = this;
var tryToExecuteCode = function (func) {
try {
return func();
}
catch (e) {
return true;
}
};
var needToRefreshDocumentMethods = tryToExecuteCode(function () { return !doc.createElement || isNativeFunction(document.createElement); });
var needToRefreshElementMethods = tryToExecuteCode(function () {
var nativeElement = _this.createElement.call(doc, 'div');
return isNativeFunction(nativeElement.getAttribute);
});
var needToRefreshWindowMethods = tryToExecuteCode(function () {
_this.setTimeout.call(win, function () { return void 0; }, 0);
return isNativeFunction(win.XMLHttpRequest.prototype.open);
});
// NOTE: T173709
if (needToRefreshDocumentMethods)
this.refreshDocumentMeths(doc, win);
if (needToRefreshElementMethods)
this.refreshElementMeths(doc, win);
// NOTE: T239109
if (needToRefreshWindowMethods)
this.refreshWindowMeths(win);
};
NativeMethods.prototype.isNativeCode = function (fn) {
return NATIVE_CODE_RE.test(this.functionToString.call(fn));
};
return NativeMethods;
}());
var nativeMethods = new NativeMethods();
var EventEmitter = /** @class */ (function () {
function EventEmitter() {
this.eventsListeners = nativeMethods.objectCreate(null);
}
EventEmitter.prototype.emit = function (evt) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var listeners = this.eventsListeners[evt];
if (!listeners)
return;
var index = 0;
while (listeners[index]) {
// HACK: For IE: after calling document.write, the IFrameSandbox event handler throws the
// 'Can't execute code from a freed script' exception because the document has been
// recreated.
if (isIE) {
try {
listeners[index].toString();
}
catch (e) {
nativeMethods.arraySplice.call(listeners, index, 1);
continue;
}
}
listeners[index++].apply(this, args);
}
};
EventEmitter.prototype.off = function (evt, listener) {
var listeners = this.eventsListeners[evt];
if (!listeners)
return;
this.eventsListeners[evt] = nativeMethods.arrayFilter.call(listeners, function (currentListener) { return currentListener !== listener; });
};
EventEmitter.prototype.on = function (evt, listener) {
this.eventsListeners[evt] = this.eventsListeners[evt] || [];
if (this.eventsListeners[evt].indexOf(listener) === -1)
this.eventsListeners[evt].push(listener);
return listener;
};
return EventEmitter;
}());
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
var INTERNAL_ATTRIBUTES = {
storedAttrPostfix: '-hammerhead-stored-value',
hoverPseudoClass: 'data-hammerhead-hovered',
focusPseudoClass: 'data-hammerhead-focused',
uploadInfoHiddenInputName: 'hammerhead|upload-info-hidden-input-name',
};
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
var POSTFIX = '-hammerhead-shadow-ui';
var SHADOW_UI_CLASS_NAME = {
postfix: POSTFIX,
charset: 'charset' + POSTFIX,
script: 'script' + POSTFIX,
selfRemovingScript: 'self-removing-script' + POSTFIX,
uiStylesheet: 'ui-stylesheet' + POSTFIX,
};
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
// NOTE: Some websites override the String.prototype.trim method. When we use this function
// in our scripts, we expect it to have the default behavior. Therefore, in order to protect
// ourselves from spoofing, we must use our own implementation. Also, we cannot use the
// String.prototype.trim method because on the client-side it is the same in the top window and
// an iframe window. The client code may override this method in the top window before the
// iframe is initialized, so that the iframe will lose access to the native method.
function trim$1 (str) {
return typeof str === 'string' ? str.replace(/(^\s+)|(\s+$)/g, '') : str;
}
// -------------------------------------------------------------
var URL_RE = /^\s*([\w-]+?:)?(?:\/\/(?:([^/]+)@)?(([^/%?;#: ]*)(?::(\d+))?))?(.*?)\s*$/;
var PROTOCOL_RE = /^([\w-]+?:)(\/\/|[^\\/]|$)/;
var QUERY_AND_HASH_RE = /(\?.+|#[^#]*)$/;
var PATH_AFTER_HOST_RE = /^\/([^/]+?)\/([\S\s]+)$/;
var HTTP_RE = /^https?:/;
var FILE_RE = /^file:/i;
var SHORT_ORIGIN_RE = /^http(s)?:\/\//;
var IS_SECURE_ORIGIN_RE = /^s\*/;
var META_REFRESH_RE = /^(.+?[;,]\s*(?:url\s*=\s*)?(['"])?)(.+?)?(\2)?$/i;
var SUPPORTED_PROTOCOL_RE = /^(?:https?|file):/i;
var HASH_RE$1 = /^#/;
var REQUEST_DESCRIPTOR_VALUES_SEPARATOR$1 = '!';
var REQUEST_DESCRIPTOR_SESSION_INFO_VALUES_SEPARATOR = '*';
var TRAILING_SLASH_RE = /\/$/;
var SPECIAL_BLANK_PAGE = 'about:blank';
var SPECIAL_ERROR_PAGE = 'about:error';
var SPECIAL_PAGES = [SPECIAL_BLANK_PAGE, SPECIAL_ERROR_PAGE];
var HTTP_DEFAULT_PORT = '80';
var HTTPS_DEFAULT_PORT = '443';
var Credentials;
(function (Credentials) {
Credentials[Credentials["include"] = 0] = "include";
Credentials[Credentials["sameOrigin"] = 1] = "sameOrigin";
Credentials[Credentials["omit"] = 2] = "omit";
Credentials[Credentials["unknown"] = 3] = "unknown";
})(Credentials || (Credentials = {})); // eslint-disable-line no-shadow
var SPECIAL_PAGE_DEST_RESOURCE_INFO = {
protocol: 'about:',
host: '',
hostname: '',
port: '',
partAfterHost: '',
};
var RESOURCE_TYPES = [
{ name: 'isIframe', flag: 'i' },
{ name: 'isForm', flag: 'f' },
{ name: 'isScript', flag: 's' },
{ name: 'isEventSource', flag: 'e' },
{ name: 'isHtmlImport', flag: 'h' },
{ name: 'isWebSocket', flag: 'w' },
{ name: 'isServiceWorker', flag: 'c' },
{ name: 'isAjax', flag: 'a' },
{ name: 'isObject', flag: 'o' },
];
function parseResourceType$1(resourceType) {
var parsedResourceType = {};
if (!resourceType)
return parsedResourceType;
for (var _i = 0, RESOURCE_TYPES_1 = RESOURCE_TYPES; _i < RESOURCE_TYPES_1.length; _i++) {
var _a = RESOURCE_TYPES_1[_i], name_1 = _a.name, flag = _a.flag;
if (resourceType.indexOf(flag) > -1)
parsedResourceType[name_1] = true;
}
return parsedResourceType;
}
function getResourceTypeString(parsedResourceType) {
if (!parsedResourceType)
return null;
var resourceType = '';
for (var _i = 0, RESOURCE_TYPES_2 = RESOURCE_TYPES; _i < RESOURCE_TYPES_2.length; _i++) {
var _a = RESOURCE_TYPES_2[_i], name_2 = _a.name, flag = _a.flag;
if (parsedResourceType[name_2])
resourceType += flag;
}
return resourceType || null;
}
function makeShortOrigin(origin) {
return origin === 'null' ? '' : origin.replace(SHORT_ORIGIN_RE, function (_, secure) { return secure ? 's*' : ''; });
}
function restoreShortOrigin(origin) {
if (!origin)
return 'null';
return IS_SECURE_ORIGIN_RE.test(origin) ? origin.replace(IS_SECURE_ORIGIN_RE, 'https://') : 'http://' + origin;
}
function isSubDomain$1(domain, subDomain) {
domain = domain.replace(/^www./i, '');
subDomain = subDomain.replace(/^www./i, '');
if (domain === subDomain)
return true;
var index = subDomain.lastIndexOf(domain);
return subDomain[index - 1] === '.' && subDomain.length === index + domain.length;
}
function sameOriginCheck$1(location, checkedUrl) {
if (!checkedUrl)
return true;
var parsedCheckedUrl = parseUrl$1(checkedUrl);
var isRelative = !parsedCheckedUrl.host;
if (isRelative)
return true;
var parsedLocation = parseUrl$1(location);
var parsedProxyLocation = parseProxyUrl$1(location);
if (parsedCheckedUrl.host === parsedLocation.host && parsedCheckedUrl.protocol === parsedLocation.protocol)
return true;
var parsedDestUrl = parsedProxyLocation ? parsedProxyLocation.destResourceInfo : parsedLocation;
if (!parsedDestUrl)
return false;
var isSameProtocol = !parsedCheckedUrl.protocol || parsedCheckedUrl.protocol === parsedDestUrl.protocol;
var portsEq = !parsedDestUrl.port && !parsedCheckedUrl.port ||
parsedDestUrl.port && parsedDestUrl.port.toString() === parsedCheckedUrl.port;
return isSameProtocol && !!portsEq && parsedDestUrl.hostname === parsedCheckedUrl.hostname;
}
// NOTE: Convert the destination protocol and hostname to the lower case. (GH-1)
function convertHostToLowerCase(url) {
var parsedUrl = parseUrl$1(url);
parsedUrl.protocol = parsedUrl.protocol && parsedUrl.protocol.toLowerCase();
parsedUrl.host = parsedUrl.host && parsedUrl.host.toLowerCase();
return formatUrl$1(parsedUrl);
}
function getURLString(url) {
// TODO: fix it
// eslint-disable-next-line no-undef
if (url === null && /iPad|iPhone/i.test(window.navigator.userAgent))
return '';
return String(url).replace(/[\n\t]/g, '');
}
function getProxyUrl$1(url, opts) {
var sessionInfo = [opts.sessionId];
if (opts.windowId)
sessionInfo.push(opts.windowId);
var params = [sessionInfo.join(REQUEST_DESCRIPTOR_SESSION_INFO_VALUES_SEPARATOR)];
if (opts.resourceType)
params.push(opts.resourceType);
if (opts.charset)
params.push(opts.charset.toLowerCase());
if (typeof opts.credentials === 'number')
params.push(opts.credentials.toString());
if (opts.reqOrigin)
params.push(encodeURIComponent(makeShortOrigin(opts.reqOrigin)));
var descriptor = params.join(REQUEST_DESCRIPTOR_VALUES_SEPARATOR$1);
var proxyProtocol = opts.proxyProtocol || 'http:';
return "".concat(proxyProtocol, "//").concat(opts.proxyHostname, ":").concat(opts.proxyPort, "/").concat(descriptor, "/").concat(convertHostToLowerCase(url));
}
function getDomain(parsed) {
if (parsed.protocol === 'file:')
return 'null';
return formatUrl$1({
protocol: parsed.protocol,
host: parsed.host,
hostname: parsed.hostname,
port: String(parsed.port || ''),
});
}
function parseRequestDescriptor(desc) {
var _a = desc.split(REQUEST_DESCRIPTOR_VALUES_SEPARATOR$1), sessionInfo = _a[0], resourceType = _a[1], resourceData = _a.slice(2);
if (!sessionInfo)
return null;
var _b = sessionInfo.split(REQUEST_DESCRIPTOR_SESSION_INFO_VALUES_SEPARATOR), sessionId = _b[0], windowId = _b[1];
var parsedDesc = { sessionId: sessionId, resourceType: resourceType || null };
if (windowId)
parsedDesc.windowId = windowId;
if (resourceType && resourceData.length) {
var parsedResourceType = parseResourceType$1(resourceType);
if (parsedResourceType.isScript || parsedResourceType.isServiceWorker)
parsedDesc.charset = resourceData[0];
else if (parsedResourceType.isWebSocket)
parsedDesc.reqOrigin = decodeURIComponent(restoreShortOrigin(resourceData[0]));
else if (parsedResourceType.isIframe && resourceData[0])
parsedDesc.reqOrigin = decodeURIComponent(restoreShortOrigin(resourceData[0]));
else if (parsedResourceType.isAjax) {
parsedDesc.credentials = parseInt(resourceData[0], 10);
if (resourceData.length === 2)
parsedDesc.reqOrigin = decodeURIComponent(restoreShortOrigin(resourceData[1]));
}
}
return parsedDesc;
}
function parseProxyUrl$1(proxyUrl) {
// TODO: Remove it.
var parsedUrl = parseUrl$1(proxyUrl);
if (!parsedUrl.partAfterHost)
return null;
var match = parsedUrl.partAfterHost.match(PATH_AFTER_HOST_RE);
if (!match)
return null;
var parsedDesc = parseRequestDescriptor(match[1]);
// NOTE: We should have, at least, the job uid and the owner token.
if (!parsedDesc)
return null;
var destUrl = match[2];
// Browser can redirect to a special page with hash (GH-1671)
var destUrlWithoutHash = destUrl.replace(/#[\S\s]*$/, '');
if (!isSpecialPage$1(destUrlWithoutHash) && !SUPPORTED_PROTOCOL_RE.test(destUrl))
return null;
var destResourceInfo;
if (isSpecialPage$1(destUrlWithoutHash))
destResourceInfo = SPECIAL_PAGE_DEST_RESOURCE_INFO;
else {
destUrl = omitDefaultPort(destUrl);
destResourceInfo = parseUrl$1(destUrl);
}
return {
destUrl: destUrl,
destResourceInfo: destResourceInfo,
partAfterHost: parsedUrl.partAfterHost,
proxy: {
hostname: parsedUrl.hostname || '',
port: parsedUrl.port || '',
},
sessionId: parsedDesc.sessionId,
resourceType: parsedDesc.resourceType,
charset: parsedDesc.charset,
reqOrigin: parsedDesc.reqOrigin,
windowId: parsedDesc.windowId,
credentials: parsedDesc.credentials,
};
}
function getPathname(path) {
return path.replace(QUERY_AND_HASH_RE, '');
}
function parseUrl$1(url) {
url = processSpecialChars(url);
if (!url)
return {};
var urlMatch = url.match(URL_RE);
return urlMatch ? {
protocol: urlMatch[1],
auth: urlMatch[2],
host: urlMatch[3],
hostname: urlMatch[4],
port: urlMatch[5],
partAfterHost: urlMatch[6],
} : {};
}
function isSupportedProtocol$1(url) {
url = trim$1(url || '');
var isHash = HASH_RE$1.test(url);
if (isHash)
return false;
var protocol = url.match(PROTOCOL_RE);
if (!protocol)
return true;
return SUPPORTED_PROTOCOL_RE.test(protocol[0]);
}
function resolveUrlAsDest$1(url, getProxyUrlMeth, isUrlsSet) {
if (isUrlsSet === void 0) { isUrlsSet = false; }
if (isUrlsSet)
return handleUrlsSet(resolveUrlAsDest$1, url, getProxyUrlMeth);
getProxyUrlMeth = getProxyUrlMeth || getProxyUrl$1;
if (isSupportedProtocol$1(url)) {
var proxyUrl = getProxyUrlMeth(url);
var parsedProxyUrl = parseProxyUrl$1(proxyUrl);
return parsedProxyUrl ? formatUrl$1(parsedProxyUrl.destResourceInfo) : url;
}
return url;
}
function formatUrl$1(parsedUrl) {
// NOTE: the URL is relative.
if (parsedUrl.protocol !== 'file:' && parsedUrl.protocol !== 'about:' &&
!parsedUrl.host && (!parsedUrl.hostname || !parsedUrl.port))
return parsedUrl.partAfterHost || '';
var url = parsedUrl.protocol || '';
if (parsedUrl.protocol !== 'about:')
url += '//';
if (parsedUrl.auth)
url += parsedUrl.auth + '@';
if (parsedUrl.host)
url += parsedUrl.host;
else if (parsedUrl.hostname) {
url += parsedUrl.hostname;
if (parsedUrl.port)
url += ':' + parsedUrl.port;
}
if (parsedUrl.partAfterHost)
url += parsedUrl.partAfterHost;
return url;
}
function handleUrlsSet(handler, url) {
var args = [];
for (var _i = 2; _i < arguments.length; _i++) {
args[_i - 2] = arguments[_i];
}
var resourceUrls = url.split(',');
var replacedUrls = [];
for (var _a = 0, resourceUrls_1 = resourceUrls; _a < resourceUrls_1.length; _a++) {
var fullUrlStr = resourceUrls_1[_a];
var _b = fullUrlStr.replace(/ +/g, ' ').trim().split(' '), urlStr = _b[0], postUrlStr = _b[1];
if (urlStr) {
var replacedUrl = handler.apply(void 0, __spreadArray([urlStr], args, false));
replacedUrls.push(replacedUrl + (postUrlStr ? " ".concat(postUrlStr) : ''));
}
}
return replacedUrls.join(',');
}
function correctMultipleSlashes(url, pageProtocol) {
if (pageProtocol === void 0) { pageProtocol = ''; }
// NOTE: Remove unnecessary slashes from the beginning of the url and after scheme.
// For example:
// "//////example.com" -> "//example.com" (scheme-less HTTP(S) URL)
// "////home/testcafe/documents" -> "///home/testcafe/documents" (scheme-less unix file URL)
// "http:///example.com" -> "http://example.com"
//
// And add missing slashes after the file scheme.
// "file://C:/document.txt" -> "file:///C:/document.txt"
if (url.match(FILE_RE) || pageProtocol.match(FILE_RE)) {
return url
.replace(/^(file:)?\/+(\/\/\/.*$)/i, '$1$2')
.replace(/^(file:)?\/*([A-Za-z]):/i, '$1///$2:');
}
return url.replace(/^(https?:)?\/+(\/\/.*$)/i, '$1$2');
}
function processSpecialChars(url) {
return correctMultipleSlashes(getURLString(url));
}
function ensureTrailingSlash(srcUrl, processedUrl) {
if (!isValidUrl(processedUrl))
return processedUrl;
var srcUrlEndsWithTrailingSlash = TRAILING_SLASH_RE.test(srcUrl);
var processedUrlEndsWithTrailingSlash = TRAILING_SLASH_RE.test(processedUrl);
if (srcUrlEndsWithTrailingSlash && !processedUrlEndsWithTrailingSlash)
processedUrl += '/';
else if (srcUrl && !srcUrlEndsWithTrailingSlash && processedUrlEndsWithTrailingSlash)
processedUrl = processedUrl.replace(TRAILING_SLASH_RE, '');
return processedUrl;
}
function isSpecialPage$1(url) {
return SPECIAL_PAGES.indexOf(url) !== -1;
}
function isRelativeUrl(url) {
var parsedUrl = parseUrl$1(url);
return parsedUrl.protocol !== 'file:' && !parsedUrl.host;
}
function isValidPort(port) {
var parsedPort = parseInt(port, 10);
return parsedPort > 0 && parsedPort <= 65535;
}
function isValidUrl(url) {
var parsedUrl = parseUrl$1(url);
return parsedUrl.protocol === 'file:' || parsedUrl.protocol === 'about:' ||
!!parsedUrl.hostname && (!parsedUrl.port || isValidPort(parsedUrl.port));
}
function ensureOriginTrailingSlash(url) {
// NOTE: If you request an url containing only port, host and protocol
// then browser adds the trailing slash itself.
var parsedUrl = parseUrl$1(url);
if (!parsedUrl.partAfterHost && parsedUrl.protocol && HTTP_RE.test(parsedUrl.protocol))
return url + '/';
return url;
}
function omitDefaultPort(url) {
// NOTE: If you request an url containing default port
// then browser remove this one itself.
var parsedUrl = parseUrl$1(url);
var hasDefaultPort = parsedUrl.protocol === 'https:' && parsedUrl.port === HTTPS_DEFAULT_PORT ||
parsedUrl.protocol === 'http:' && parsedUrl.port === HTTP_DEFAULT_PORT;
if (hasDefaultPort) {
parsedUrl.host = parsedUrl.hostname;
parsedUrl.port = '';
return formatUrl$1(parsedUrl);
}
return url;
}
function prepareUrl(url) {
url = omitDefaultPort(url);
url = ensureOriginTrailingSlash(url);
return url;
}
function updateScriptImportUrls(cachedScript, serverInfo, sessionId, windowId) {
var regExp = new RegExp('(' + serverInfo.protocol + '//' + serverInfo.hostname + ':(?:' + serverInfo.port + '|' +
serverInfo.crossDomainPort + ')/)[^/' + REQUEST_DESCRIPTOR_VALUES_SEPARATOR$1 + ']+', 'g');
var pattern = '$1' + sessionId + (windowId ? REQUEST_DESCRIPTOR_SESSION_INFO_VALUES_SEPARATOR + windowId : '');
return cachedScript.replace(regExp, pattern);
}
function processMetaRefreshContent(content, urlReplacer) {
var match = content.match(META_REFRESH_RE);
if (!match || !match[3])
return content;
return match[1] + urlReplacer(match[3]) + (match[4] || '');
}
var sharedUrlUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
SUPPORTED_PROTOCOL_RE: SUPPORTED_PROTOCOL_RE,
HASH_RE: HASH_RE$1,
REQUEST_DESCRIPTOR_VALUES_SEPARATOR: REQUEST_DESCRIPTOR_VALUES_SEPARATOR$1,
REQUEST_DESCRIPTOR_SESSION_INFO_VALUES_SEPARATOR: REQUEST_DESCRIPTOR_SESSION_INFO_VALUES_SEPARATOR,
TRAILING_SLASH_RE: TRAILING_SLASH_RE,
SPECIAL_BLANK_PAGE: SPECIAL_BLANK_PAGE,
SPECIAL_ERROR_PAGE: SPECIAL_ERROR_PAGE,
SPECIAL_PAGES: SPECIAL_PAGES,
HTTP_DEFAULT_PORT: HTTP_DEFAULT_PORT,
HTTPS_DEFAULT_PORT: HTTPS_DEFAULT_PORT,
get Credentials () { return Credentials; },
parseResourceType: parseResourceType$1,
getResourceTypeString: getResourceTypeString,
restoreShortOrigin: restoreShortOrigin,
isSubDomain: isSubDomain$1,
sameOriginCheck: sameOriginCheck$1,
getURLString: getURLString,
getProxyUrl: getProxyUrl$1,
getDomain: getDomain,
parseProxyUrl: parseProxyUrl$1,
getPathname: getPathname,
parseUrl: parseUrl$1,
isSupportedProtocol: isSupportedProtocol$1,
resolveUrlAsDest: resolveUrlAsDest$1,
formatUrl: formatUrl$1,
handleUrlsSet: handleUrlsSet,
correctMultipleSlashes: correctMultipleSlashes,
processSpecialChars: processSpecialChars,
ensureTrailingSlash: ensureTrailingSlash,
isSpecialPage: isSpecialPage$1,
isRelativeUrl: isRelativeUrl,
isValidUrl: isValidUrl,
ensureOriginTrailingSlash: ensureOriginTrailingSlash,
omitDefaultPort: omitDefaultPort,
prepareUrl: prepareUrl,
updateScriptImportUrls: updateScriptImportUrls,
processMetaRefreshContent: processMetaRefreshContent
});
var DOCUMENT_URL_RESOLVER = 'hammerhead|document-url-resolver';
var urlResolver = {
_createResolver: function (doc) {
var htmlDocument = nativeMethods.createHTMLDocument.call(doc.implementation, 'title');
var a = nativeMethods.createElement.call(htmlDocument, 'a');
var base = nativeMethods.createElement.call(htmlDocument, 'base');
nativeMethods.appendChild.call(htmlDocument.body, a);
nativeMethods.appendChild.call(htmlDocument.head, base);
return htmlDocument;
},
_getResolver: function (doc) {
// NOTE: Once a document is recreated (document.open, document.write is called), nativeMethods will be refreshed.
// If we call urlResolve.updateBase after this,
// we will use native methods from an actual document.
// However, a document that contains an element for url resolving is created using a previous version of nativeMethods.
if (!doc[DOCUMENT_URL_RESOLVER]) {
nativeMethods.objectDefineProperty(doc, DOCUMENT_URL_RESOLVER, {
value: this._createResolver(doc),
writable: true,
});
}
return doc[DOCUMENT_URL_RESOLVER];
},
_isNestedIframeWithoutSrc: function (win) {
if (!win || !win.parent || win.parent === win || win.parent.parent === win.parent)
return false;
var iframeElement = getFrameElement(window);
return !!iframeElement && isIframeWithoutSrc(iframeElement);
},
init: function (doc) {
this.updateBase(get$2(), doc);
},
getResolverElement: function (doc) {
return nativeMethods.nodeFirstChildGetter.call(this._getResolver(doc).body);
},
resolve: function (url, doc) {
var resolver = this.getResolverElement(doc);
var href = null;
if (url === null)
nativeMethods.removeAttribute.call(resolver, 'href');
else {
nativeMethods.anchorHrefSetter.call(resolver, url);
href = nativeMethods.anchorHrefGetter.call(resolver);
// NOTE: It looks like a Chrome bug: in a nested iframe without src (when an iframe is placed into another
// iframe) you cannot set a relative link href while the iframe loading is not completed. So, we'll do it with
// the parent's urlResolver Safari demonstrates similar behavior, but urlResolver.href has a relative URL value.
var needUseParentResolver = url && (!href || href.charAt(0) === '/') &&
this._isNestedIframeWithoutSrc(doc.defaultView);
if (needUseParentResolver)
return this.resolve(url, window.parent.document);
}
return ensureTrailingSlash(url, href);
},
updateBase: function (url, doc) {
if (this.proxyless)
return;
var resolverDocument = this._getResolver(doc);
var baseElement = nativeMethods.elementGetElementsByTagName.call(resolverDocument.head, 'base')[0];
url = url || get$2();
/*eslint-disable no-restricted-properties*/
var parsedUrl = parseUrl$1(url);
var isRelativeUrl = parsedUrl.protocol !== 'file:' && parsedUrl.protocol !== 'about:' && !parsedUrl.host;
var isProtocolRelativeUrl = /^\/\//.test(url) && !!parsedUrl.host;
/*eslint-enable no-restricted-properties*/
if (isRelativeUrl || isProtocolRelativeUrl) {
var destinationLocation = get$2();
this.updateBase(destinationLocation, doc);
url = this.resolve(url, doc);
}
nativeMethods.setAttribute.call(baseElement, 'href', url);
},
getBaseUrl: function (doc) {
var baseElement = nativeMethods.elementGetElementsByTagName.call(this._getResolver(doc).head, 'base')[0];
return nativeMethods.getAttribute.call(baseElement, 'href');
},
changeUrlPart: function (url, nativePropSetter, value, doc) {
var resolver = this.getResolverElement(doc);
nativeMethods.anchorHrefSetter.call(resolver, url);
nativePropSetter.call(resolver, value);
return nativeMethods.anchorHrefGetter.call(resolver);
},
dispose: function (doc) {
doc[DOCUMENT_URL_RESOLVER] = null;
},
get proxyless() {
return this._proxyless;
},
set proxyless(value) {
this._proxyless = value;
},
};
var Settings = /** @class */ (function () {
function Settings() {
this._settings = {
isFirstPageLoad: true,
sessionId: '',
forceProxySrcForImage: false,
crossDomainProxyPort: '',
referer: '',
serviceMsgUrl: '',
transportWorkerUrl: '',
iframeTaskScriptTemplate: '',
cookie: '',
allowMultipleWindows: false,
isRecordMode: false,
windowId: '',
proxyless: false,
disableCrossDomain: false,
};
}
Settings.prototype.set = function (value) {
this._settings = value;
};
Settings.prototype.get = function () {
return this._settings;
};
return Settings;
}());
var settings = new Settings();
var forcedLocation = null;
// NOTE: exposed only for tests
function getLocation() {
// NOTE: Used for testing. Unfortunately, we cannot override the 'getLocation' method in a test.
if (forcedLocation)
return forcedLocation;
var frameElement = getFrameElement(globalContextInfo.global);
// NOTE: Fallback to the owner page's URL if we are in an iframe without src.
if (frameElement && isIframeWithoutSrc(frameElement))
return settings.get().referer;
return globalContextInfo.global.location.toString();
}
// NOTE: We need to be able to force the page location. During the test, Hammerhead should think that it is on the
// proxied page, not in the test environment. Unfortunately, we cannot do it in any other way.
function forceLocation(url) {
forcedLocation = url;
}
function sameOriginCheck(location, checkedUrl) {
if (checkedUrl)
checkedUrl = resolveUrl(checkedUrl);
return settings.get().disableCrossDomain || sameOriginCheck$1(location, checkedUrl);
}
function resolveUrl(url, doc) {
var preProcessedUrl = getURLString(url);
if (preProcessedUrl && preProcessedUrl.indexOf('//') === 0) {
// eslint-disable-next-line no-restricted-properties
var pageProtocol = getParsed().protocol;
preProcessedUrl = pageProtocol + correctMultipleSlashes(preProcessedUrl, pageProtocol);
}
else
preProcessedUrl = correctMultipleSlashes(preProcessedUrl);
if (globalContextInfo.isInWorker) {
if (self.location.protocol !== 'blob:') // eslint-disable-line no-restricted-properties
return new nativeMethods.URL(preProcessedUrl, get$2()).href; // eslint-disable-line no-restricted-properties
return String(url);
}
return urlResolver.resolve(preProcessedUrl, doc || document);
}
var get$2 = function () {
var location = getLocation();
var parsedProxyUrl = parseProxyUrl$1(location);
return parsedProxyUrl ? parsedProxyUrl.destUrl : location;
};
function getReferrer() {
var location = getLocation();
var parsedProxyUrl = parseProxyUrl$1(location);
return (parsedProxyUrl === null || parsedProxyUrl === void 0 ? void 0 : parsedProxyUrl.reqOrigin) ? parsedProxyUrl.reqOrigin + '/' : '';
}
function overrideGet(func) {
get$2 = func;
}
function withHash(hash) {
var location = get$2();
// NOTE: Remove the previous hash if there is any.
location = location.replace(/(#.*)$/, '');
return location + hash;
}
function parseLocationThroughAnchor(url) {
var resolver = urlResolver.getResolverElement(document);
// eslint-disable-next-line no-restricted-properties
var destPort = parseUrl$1(url).port;
// NOTE: IE browser adds the default port for the https protocol while resolving.
nativeMethods.anchorHrefSetter.call(resolver, get$2());
var hostname = nativeMethods.anchorHostnameGetter.call(resolver);
var pathname = nativeMethods.anchorPathnameGetter.call(resolver);
// NOTE: IE ignores the first '/' symbol in the pathname.
if (pathname.charAt(0) !== '/')
pathname = '/' + pathname;
// TODO: Describe default ports logic.
return {
protocol: nativeMethods.anchorProtocolGetter.call(resolver),
// NOTE: Remove the default port.
port: destPort ? nativeMethods.anchorPortGetter.call(resolver) : '',
hostname: hostname,
// NOTE: Remove the default port from the host.
host: destPort ? nativeMethods.anchorHostGetter.call(resolver) : hostname,
pathname: pathname,
hash: resolver.hash,
search: nativeMethods.anchorSearchGetter.call(resolver),
};
}
function parseLocationThroughURL(url) {
var parsedUrl = new nativeMethods.URL(url);
/* eslint-disable no-restricted-properties */
return {
protocol: parsedUrl.protocol,
port: parsedUrl.port,
hostname: parsedUrl.hostname,
host: parsedUrl.host,
pathname: parsedUrl.pathname,
hash: parsedUrl.hash,
search: parsedUrl.search,
};
/* eslint-enable no-restricted-properties */
}
function getParsed() {
var dest = get$2();
return globalContextInfo.isInWorker ? parseLocationThroughURL(dest) : parseLocationThroughAnchor(dest);
}
function getOriginHeader() {
return getDomain(getParsed());
}
var destLocationUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
getLocation: getLocation,
forceLocation: forceLocation,
sameOriginCheck: sameOriginCheck,
resolveUrl: resolveUrl,
get get () { return get$2; },
getReferrer: getReferrer,
overrideGet: overrideGet,
withHash: withHash,
getParsed: getParsed,
getOriginHeader: getOriginHeader
});
var HASH_RE = /#[\S\s]*$/;
var SUPPORTED_WEB_SOCKET_PROTOCOL_RE = /^wss?:/i;
var SCOPE_RE = /\/[^/]*$/;
// NOTE: The window.location equals 'about:blank' in iframes without src
// therefore we need to find a window with src to get the proxy settings
var DEFAULT_PROXY_SETTINGS = (function () {
/*eslint-disable no-restricted-properties*/
var locationWindow = globalContextInfo.isInWorker ? { location: parseUrl(self.location.origin), parent: null } : window;
var proxyLocation = locationWindow.location;
while (!proxyLocation.hostname) {
// about:blank page in proxyless mode
if (!globalContextInfo.isInWorker
&& locationWindow === locationWindow.top)
break;
locationWindow = locationWindow.parent;
proxyLocation = locationWindow.location;
}
return {
hostname: proxyLocation.hostname,
port: proxyLocation.port.toString(),
protocol: proxyLocation.protocol,
};
/*eslint-enable no-restricted-properties*/
})();
var REQUEST_DESCRIPTOR_VALUES_SEPARATOR = REQUEST_DESCRIPTOR_VALUES_SEPARATOR$1;
function getCharsetFromDocument(parsedResourceType) {
if (!parsedResourceType.isScript && !parsedResourceType.isServiceWorker)
return null;
return self.document && document[INTERNAL_PROPS.documentCharset] || null;
}
var getProxyUrl = function (url, opts, proxyless) {
if (opts === void 0) { opts = {}; }
if (proxyless === void 0) { proxyless = false; }
if (opts.isUrlsSet) {
opts.isUrlsSet = false;
return handleUrlsSet(getProxyUrl, String(url), opts, proxyless);
}
if (proxyless)
return String(url);
url = getURLString(url);
var resourceType = opts && opts.resourceType;
var parsedResourceType = parseResourceType$1(resourceType);
if (!parsedResourceType.isWebSocket && !isSupportedProtocol(url) && !isSpecialPage(url))
return url;
// NOTE: Resolves relative URLs.
var resolvedUrl = resolveUrl(url, opts && opts.doc);
if (parsedResourceType.isWebSocket && !isValidWebSocketUrl(resolvedUrl) || !isValidUrl(resolvedUrl))
return url;
/*eslint-disable no-restricted-properties*/
var proxyHostname = opts && opts.proxyHostname || DEFAULT_PROXY_SETTINGS.hostname;
var proxyPort = opts && opts.proxyPort || DEFAULT_PROXY_SETTINGS.port;
var proxyServerProtocol = opts && opts.proxyProtocol || DEFAULT_PROXY_SETTINGS.protocol;
/*eslint-enable no-restricted-properties*/
var proxyProtocol = parsedResourceType.isWebSocket
? proxyServerProtocol.replace('http', 'ws')
: proxyServerProtocol;
var sessionId = opts && opts.sessionId || settings.get().sessionId;
var windowId = opts && opts.windowId || settings.get().windowId;
var credentials = opts && opts.credentials;
var charset = opts && opts.charset;
var reqOrigin = opts && opts.reqOrigin;
var crossDomainPort = getCrossDomainProxyPort(proxyPort);
// NOTE: If the relative URL contains no slash (e.g. 'img123'), the resolver will keep
// the original proxy information, so that we can return such URL as is.
// TODO: Implement the isProxyURL function.
var parsedProxyUrl = parseProxyUrl$1(resolvedUrl);
/*eslint-disable no-restricted-properties*/
var isValidProxyUrl = !!parsedProxyUrl && parsedProxyUrl.proxy.hostname === proxyHostname &&
(parsedProxyUrl.proxy.port === proxyPort || parsedProxyUrl.proxy.port === crossDomainPort);
/*eslint-enable no-restricted-properties*/
if (isValidProxyUrl) {
if (resourceType && parsedProxyUrl.resourceType === resourceType)
return resolvedUrl;
// NOTE: Need to change the proxy URL resource type.
var destUrl = formatUrl$1(parsedProxyUrl.destResourceInfo);
return getProxyUrl(destUrl, {
proxyProtocol: proxyProtocol,
proxyHostname: proxyHostname,
proxyPort: proxyPort,
sessionId: sessionId,
resourceType: resourceType,
charset: charset,
reqOrigin: reqOrigin,
credentials: credentials,
});
}
var parsedUrl = parseUrl$1(resolvedUrl);
if (!parsedUrl.protocol) // eslint-disable-line no-restricted-properties
return url;
charset = charset || getCharsetFromDocument(parsedResourceType);
// NOTE: It seems that the relative URL had the leading slash or dots, so that the proxy info path part was
// removed by the resolver and we have an origin URL with the incorrect host and protocol.
/*eslint-disable no-restricted-properties*/
if (parsedUrl.protocol === proxyServerProtocol && parsedUrl.hostname === proxyHostname &&
parsedUrl.port === proxyPort) {
var parsedDestLocation = getParsed();
parsedUrl.protocol = parsedDestLocation.protocol;
parsedUrl.host = parsedDestLocation.host;
parsedUrl.hostname = parsedDestLocation.hostname;
parsedUrl.port = parsedDestLocation.port || '';
resolvedUrl = formatUrl$1(parsedUrl);
}
/*eslint-enable no-restricted-properties*/
if (parsedResourceType.isWebSocket) {
// eslint-disable-next-line no-restricted-properties
parsedUrl.protocol = parsedUrl.protocol.replace('ws', 'http');
resolvedUrl = formatUrl$1(parsedUrl);
reqOrigin = reqOrigin || getOriginHeader();
}
if (parsedResourceType.isIframe && proxyPort === settings.get().crossDomainProxyPort)
reqOrigin = reqOrigin || getOriginHeader();
return getProxyUrl$1(resolvedUrl, {
proxyProtocol: proxyProtocol,
proxyHostname: proxyHostname,
proxyPort: proxyPort,
sessionId: sessionId,
resourceType: resourceType,
charset: charset,
reqOrigin: reqOrigin,
windowId: windowId,
credentials: credentials,
});
};
function overrideGetProxyUrl(func) {
getProxyUrl = func;
}
function getProxyNavigationUrl(url, win) {
// NOTE: For the 'about:blank' page, we perform url proxing only for the top window, 'location' object and links.
// For images and iframes, we keep urls as they were.
// See details in https://github.com/DevExpress/testcafe-hammerhead/issues/339
var destinationLocation = null;
var isIframe = win.top !== win;
var winLocation = win.location.toString();
if (isIframe)
destinationLocation = winLocation;
else {
var parsedProxyUrl = parseProxyUrl(winLocation);
destinationLocation = parsedProxyUrl && parsedProxyUrl.destUrl;
}
if (isSpecialPage(destinationLocation) && isRelativeUrl(url))
return '';
url = prepareUrl(url);
return getProxyUrl(url);
}
function getNavigationUrl(url, win, proxyless) {
if (proxyless === void 0) { proxyless = false; }
return proxyless
? url
: getProxyNavigationUrl(url, win);
}
var getCrossDomainIframeProxyUrl = function (url) {
return getProxyUrl(url, {
proxyPort: settings.get().crossDomainProxyPort,
resourceType: getResourceTypeString({ isIframe: true }),
});
};
function overrideGetCrossDomainIframeProxyUrl(func) {
getCrossDomainIframeProxyUrl = func;
}
function getPageProxyUrl(url, windowId) {
var parsedProxyUrl = parseProxyUrl(url);
var resourceType = null;
if (parsedProxyUrl) {
url = parsedProxyUrl.destUrl;
resourceType = parsedProxyUrl.resourceType;
}
if (resourceType) {
var parsedResourceType = parseResourceType(resourceType);
parsedResourceType.isIframe = false;
resourceType = stringifyResourceType(parsedResourceType);
}
var isCrossDomainUrl = !sameOriginCheck(getLocation(), url);
var proxyPort = isCrossDomainUrl ? settings.get().crossDomainProxyPort : location.port.toString(); // eslint-disable-line no-restricted-properties
return getProxyUrl(url, { windowId: windowId, proxyPort: proxyPort, resourceType: resourceType });
}
function getCrossDomainProxyPort(proxyPort) {
return settings.get().crossDomainProxyPort === proxyPort
// eslint-disable-next-line no-restricted-properties
? location.port.toString()
: settings.get().crossDomainProxyPort;
}
var resolveUrlAsDest = function (url, isUrlsSet) {
if (isUrlsSet === void 0) { isUrlsSet = false; }
return resolveUrlAsDest$1(url, getProxyUrl, isUrlsSet);
};
function overrideResolveUrlAsDest(func) {
resolveUrlAsDest = func;
}
function formatUrl(parsedUrl) {
return formatUrl$1(parsedUrl);
}
var parseProxyUrl = function (proxyUrl) {
return parseProxyUrl$1(proxyUrl);
};
function overrideParseProxyUrl(func) {
parseProxyUrl = func;
}
function parseUrl(url) {
return parseUrl$1(url);
}
var convertToProxyUrl = function (url, resourceType, charset, isCrossDomain) {
if (isCrossDomain === void 0) { isCrossDomain = false; }
return getProxyUrl(url, {
resourceType: resourceType,
charset: charset,
// eslint-disable-next-line no-restricted-properties
proxyPort: isCrossDomain ? settings.get().crossDomainProxyPort : DEFAULT_PROXY_SETTINGS.port,
});
};
function getCrossDomainProxyOrigin() {
return getDomain({
protocol: location.protocol,
hostname: location.hostname,
port: settings.get().crossDomainProxyPort,
});
}
function overrideConvertToProxyUrl(func) {
convertToProxyUrl = func;
}
function changeDestUrlPart(proxyUrl, nativePropSetter, value, resourceType) {
var parsed = parseProxyUrl$1(proxyUrl);
if (parsed) {
var sessionId = parsed.sessionId;
var proxy = parsed.proxy;
var destUrl = urlResolver.changeUrlPart(parsed.destUrl, nativePropSetter, value, document);
return getProxyUrl(destUrl, {
/*eslint-disable no-restricted-properties*/
proxyHostname: proxy.hostname,
proxyPort: proxy.port,
/*eslint-enable no-restricted-properties*/
sessionId: sessionId,
resourceType: resourceType,
});
}
return proxyUrl;
}
function isValidWebSocketUrl(url) {
var resolvedUrl = resolveUrlAsDest(url);
return SUPPORTED_WEB_SOCKET_PROTOCOL_RE.test(resolvedUrl);
}
function isSubDomain(domain, subDomain) {
return isSubDomain$1(domain, subDomain);
}
function isSupportedProtocol(url) {
return isSupportedProtocol$1(url);
}
function isSpecialPage(url) {
return isSpecialPage$1(url);
}
function parseResourceType(resourceType) {
return parseResourceType$1(resourceType);
}
function stringifyResourceType(resourceType) {
return getResourceTypeString(resourceType);
}
function isChangedOnlyHash(currentUrl, newUrl) {
// NOTE: we compare proxied urls because urls passed into the function may be proxied, non-proxied
// or relative. The getProxyUrl function solves all the corresponding problems.
return getProxyUrl(currentUrl).replace(HASH_RE, '') === getProxyUrl(newUrl).replace(HASH_RE, '');
}
function getDestinationUrl(proxyUrl) {
var parsedProxyUrl = parseProxyUrl(proxyUrl);
return parsedProxyUrl ? parsedProxyUrl.destUrl : proxyUrl;
}
function getScope(url) {
if (!isSupportedProtocol(url))
return null;
var parsedUrl = parseUrl(resolveUrlAsDest(url));
if (!parsedUrl)
return null;
// NOTE: Delete query and hash parts. These parts are not related to the scope (GH-2524)
var partAfterHostWithoutQueryAndHash = getPathname(parsedUrl.partAfterHost);
return partAfterHostWithoutQueryAndHash.replace(SCOPE_RE, '/') || '/';
}
function getAjaxProxyUrl(url, credentials, proxyless) {
if (proxyless === void 0) { proxyless = false; }
if (proxyless)
return String(url);
var isCrossDomain = !sameOriginCheck(getLocation(), url);
var opts = { resourceType: stringifyResourceType({ isAjax: true }), credentials: credentials };
if (isCrossDomain) {
opts.proxyPort = settings.get().crossDomainProxyPort;
opts.reqOrigin = getOriginHeader();
}
return getProxyUrl(url, opts);
}
var urlUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
DEFAULT_PROXY_SETTINGS: DEFAULT_PROXY_SETTINGS,
REQUEST_DESCRIPTOR_VALUES_SEPARATOR: REQUEST_DESCRIPTOR_VALUES_SEPARATOR,
get getProxyUrl () { return getProxyUrl; },
overrideGetProxyUrl: overrideGetProxyUrl,
getNavigationUrl: getNavigationUrl,
get getCrossDomainIframeProxyUrl () { return getCrossDomainIframeProxyUrl; },
overrideGetCrossDomainIframeProxyUrl: overrideGetCrossDomainIframeProxyUrl,
getPageProxyUrl: getPageProxyUrl,
getCrossDomainProxyPort: getCrossDomainProxyPort,
get resolveUrlAsDest () { return resolveUrlAsDest; },
overrideResolveUrlAsDest: overrideResolveUrlAsDest,
formatUrl: formatUrl,
get parseProxyUrl () { return parseProxyUrl; },
overrideParseProxyUrl: overrideParseProxyUrl,
parseUrl: parseUrl,
get convertToProxyUrl () { return convertToProxyUrl; },
getCrossDomainProxyOrigin: getCrossDomainProxyOrigin,
overrideConvertToProxyUrl: overrideConvertToProxyUrl,
changeDestUrlPart: changeDestUrlPart,
isValidWebSocketUrl: isValidWebSocketUrl,
isSubDomain: isSubDomain,
isSupportedProtocol: isSupportedProtocol,
isSpecialPage: isSpecialPage,
parseResourceType: parseResourceType,
stringifyResourceType: stringifyResourceType,
isChangedOnlyHash: isChangedOnlyHash,
getDestinationUrl: getDestinationUrl,
getScope: getScope,
getAjaxProxyUrl: getAjaxProxyUrl
});
var emptyActionAttrFallbacksToTheLocation = false;
var instanceAndPrototypeToStringAreEqual = false;
var hasTouchEvents = false;
var hasTouchPoints = false;
var isTouchDevice = false;
var hasDataTransfer = false;
var attrGetNamedItemIsNotEnumerable = false;
var getElementsByNameReturnsHTMLCollection = false;
if (nativeMethods.createElement) {
var form = nativeMethods.createElement.call(document, 'form');
var elements = nativeMethods.getElementsByName.call(document, '');
// NOTE: In some browsers, elements without the url attribute return the location url
// when accessing this attribute directly. See form.action in Edge 25 as an example.
emptyActionAttrFallbacksToTheLocation = nativeMethods.formActionGetter.call(form) === window.location.toString();
// NOTE: In Chrome, toString(window) equals '[object Window]' and toString(Window.prototype) equals '[object Blob]',
// this condition is also satisfied for Blob, Document, XMLHttpRequest, etc
instanceAndPrototypeToStringAreEqual = nativeMethods.objectToString.call(window) ===
nativeMethods.objectToString.call(Window.prototype);
hasTouchEvents = 'ontouchstart' in window;
// NOTE: We need to check touch points only for IE, because it has PointerEvent and MSPointerEvent (IE10, IE11)
// instead of TouchEvent (T109295).
hasTouchPoints = isIE && navigator.maxTouchPoints > 0;
isTouchDevice = (isMobile || isTablet) && hasTouchEvents;
// @ts-ignore
hasDataTransfer = !!window.DataTransfer;
// NOTE: In the Edge 17, the getNamedItem method of attributes object is not enumerable
attrGetNamedItemIsNotEnumerable = !!nativeMethods.objectGetOwnPropertyDescriptor.call(window.Object, NamedNodeMap.prototype, 'getNamedItem');
// Both IE and Edge return an HTMLCollection, not a NodeList
// @ts-ignore
getElementsByNameReturnsHTMLCollection = nativeMethods.objectGetPrototypeOf.call(window.Object, elements) ===
nativeMethods.HTMLCollection.prototype;
}
var featureDetection = /*#__PURE__*/Object.freeze({
__proto__: null,
get emptyActionAttrFallbacksToTheLocation () { return emptyActionAttrFallbacksToTheLocation; },
get instanceAndPrototypeToStringAreEqual () { return instanceAndPrototypeToStringAreEqual; },
get hasTouchEvents () { return hasTouchEvents; },
get hasTouchPoints () { return hasTouchPoints; },
get isTouchDevice () { return isTouchDevice; },
get hasDataTransfer () { return hasDataTransfer; },
get attrGetNamedItemIsNotEnumerable () { return attrGetNamedItemIsNotEnumerable; },
get getElementsByNameReturnsHTMLCollection () { return getElementsByNameReturnsHTMLCollection; }
});
// NOTE: For Chrome.
var MIN_SELECT_SIZE_VALUE = 4;
function getParsedValue(value, parseFn) {
value = value || '';
var parsedValue = parseFn(value.replace('px', ''), 10);
return isNaN(parsedValue) ? 0 : parsedValue;
}
function getIntValue(value) {
return getParsedValue(value, parseInt);
}
function getFloatValue(value) {
return getParsedValue(value, parseFloat);
}
function get$1(el, property, doc, win) {
el = el.documentElement || el;
var computedStyle = getComputedStyle(el, doc, win);
return computedStyle && computedStyle[property];
}
function set(el, property, value) {
el = el.documentElement || el;
el.style[property] = value;
}
function getBordersWidthInternal(el, parseFn) {
return {
bottom: parseFn(get$1(el, 'borderBottomWidth')),
left: parseFn(get$1(el, 'borderLeftWidth')),
right: parseFn(get$1(el, 'borderRightWidth')),
top: parseFn(get$1(el, 'borderTopWidth')),
};
}
function getBordersWidth(el) {
return getBordersWidthInternal(el, getIntValue);
}
function getBordersWidthFloat(el) {
return getBordersWidthInternal(el, getFloatValue);
}
function getComputedStyle(el, doc, win) {
// NOTE: In Firefox, after calling the 'document.write' function for nested iframes with html src value
// document.defaultView equals 'null'. But 'window.document' equals 'document'.
// This is why, we are forced to calculate the targetWindow instead of use document.defaultView.
doc = doc || document;
win = win || window;
var targetWin = doc.defaultView || win;
return targetWin.getComputedStyle(el, null);
}
function getElementMargin(el) {
return {
bottom: getIntValue(get$1(el, 'marginBottom')),
left: getIntValue(get$1(el, 'marginLeft')),
right: getIntValue(get$1(el, 'marginRight')),
top: getIntValue(get$1(el, 'marginTop')),
};
}
function getElementPaddingInternal(el, parseFn) {
return {
bottom: parseFn(get$1(el, 'paddingBottom')),
left: parseFn(get$1(el, 'paddingLeft')),
right: parseFn(get$1(el, 'paddingRight')),
top: parseFn(get$1(el, 'paddingTop')),
};
}
function getElementPadding(el) {
return getElementPaddingInternal(el, getIntValue);
}
function getElementPaddingFloat(el) {
return getElementPaddingInternal(el, getFloatValue);
}
function getElementScroll(el) {
var isHtmlElement$1 = isHtmlElement(el);
var currentWindow = window;
if (isHtmlElement$1 && isElementInIframe(el)) {
var currentIframe = getIframeByElement(el);
if (currentIframe)
currentWindow = nativeMethods.contentWindowGetter.call(currentIframe);
}
var targetEl = isHtmlElement$1 ? currentWindow : el;
return {
left: getScrollLeft(targetEl),
top: getScrollTop(targetEl),
};
}
function getWidth(el) {
if (!el)
return null;
if (isWindow(el))
return el.document.documentElement.clientWidth;
if (isDocument(el)) {
var doc = el.documentElement;
var clientProp = 'clientWidth';
var scrollProp = 'scrollWidth';
var offsetProp = 'offsetWidth';
if (doc[clientProp] >= doc[scrollProp])
return doc[clientProp];
return Math.max(el.body[scrollProp], doc[scrollProp], el.body[offsetProp], doc[offsetProp]);
}
var value = el.offsetWidth;
value -= getIntValue(get$1(el, 'paddingLeft'));
value -= getIntValue(get$1(el, 'paddingRight'));
value -= getIntValue(get$1(el, 'borderLeftWidth'));
value -= getIntValue(get$1(el, 'borderRightWidth'));
return value;
}
function getHeight(el) {
if (!el)
return null;
if (isWindow(el))
return el.document.documentElement.clientHeight;
if (isDocument(el)) {
var doc = el.documentElement;
var clientProp = 'clientHeight';
var scrollProp = 'scrollHeight';
var offsetProp = 'offsetHeight';
if (doc[clientProp] >= doc[scrollProp])
return doc[clientProp];
return Math.max(el.body[scrollProp], doc[scrollProp], el.body[offsetProp], doc[offsetProp]);
}
var value = el.offsetHeight;
value -= getIntValue(get$1(el, 'paddingTop'));
value -= getIntValue(get$1(el, 'paddingBottom'));
value -= getIntValue(get$1(el, 'borderTopWidth'));
value -= getIntValue(get$1(el, 'borderBottomWidth'));
return value;
}
function getInnerWidth(el) {
if (!el)
return null;
if (isWindow(el))
return el.document.documentElement.clientWidth;
if (isDocument(el))
return el.documentElement.clientWidth;
var value = el.offsetWidth;
value -= getIntValue(get$1(el, 'borderLeftWidth'));
value -= getIntValue(get$1(el, 'borderRightWidth'));
return value;
}
function getInnerHeight(el) {
if (!el)
return null;
if (isWindow(el))
return el.document.documentElement.clientHeight;
if (isDocument(el))
return el.documentElement.clientHeight;
var value = el.offsetHeight;
value -= getIntValue(get$1(el, 'borderTopWidth'));
value -= getIntValue(get$1(el, 'borderBottomWidth'));
return value;
}
function getOptionHeight(select) {
var realSizeValue = getSelectElementSize(select);
var selectPadding = getElementPadding(select);
var selectScrollHeight = select.scrollHeight - (selectPadding.top + selectPadding.bottom);
var childrenCount = getSelectVisibleChildren(select).length;
if (realSizeValue === 1)
return getHeight(select);
return isIE && realSizeValue > childrenCount
? Math.round(selectScrollHeight / childrenCount)
: Math.round(selectScrollHeight / Math.max(childrenCount, realSizeValue));
}
function getSelectElementSize(select) {
// NOTE: iOS and Android ignore 'size' and 'multiple' attributes,
// all select elements behave like a select with size=1.
if (isSafari && hasTouchEvents || isAndroid)
return 1;
var sizeAttr = nativeMethods.getAttribute.call(select, 'size');
var multipleAttr = nativeMethods.hasAttribute.call(select, 'multiple');
var size = !sizeAttr ? 1 : parseInt(sizeAttr, 10);
if (multipleAttr && (!sizeAttr || size < 1))
size = MIN_SELECT_SIZE_VALUE;
return size;
}
function isVisibleChild(el) {
var select = getSelectParent(el);
var tagName = getTagName(el);
return isSelectElement(select) && getSelectElementSize(select) > 1 &&
(tagName === 'option' || tagName === 'optgroup') &&
// NOTE: Firefox does not display groups without a label or with an empty label.
(!isFirefox || el.label);
}
function getScrollLeft(el) {
if (!el)
return null;
if (isWindow(el))
return el.pageXOffset;
if (isDocument(el))
return el.defaultView.pageXOffset;
return el.scrollLeft;
}
function getScrollTop(el) {
if (!el)
return null;
if (isWindow(el))
return el.pageYOffset;
if (isDocument(el))
return el.defaultView.pageYOffset;
return el.scrollTop;
}
function setScrollLeft(el, value) {
if (!el)
return;
if (isWindow(el) || isDocument(el)) {
var win = findDocument(el).defaultView;
var scrollTop = getScrollTop(el);
nativeMethods.scrollTo.call(win, value, scrollTop);
}
else
el.scrollLeft = value;
}
function setScrollTop(el, value) {
if (!el)
return;
if (isWindow(el) || isDocument(el)) {
var win = findDocument(el).defaultView;
var scrollLeft = getScrollLeft(el);
nativeMethods.scrollTo.call(win, scrollLeft, value);
}
else
el.scrollTop = value;
}
function getOffsetParent(el) {
if (el) {
var offsetParent = el.offsetParent || document.body;
while (offsetParent && (!/^(?:body|html)$/i.test(offsetParent.nodeName) &&
get$1(offsetParent, 'position') === 'static'))
offsetParent = offsetParent.offsetParent;
return offsetParent;
}
return void 0;
}
function getOffset(el) {
if (!el || isWindow(el) || isDocument(el))
return null;
var clientRect = el.getBoundingClientRect();
// NOTE: A detached node or documentElement.
var doc = el.ownerDocument;
var docElement = doc.documentElement;
if (!docElement.contains(el) || el === docElement) {
return {
top: clientRect.top,
left: clientRect.left,
};
}
var win = doc.defaultView;
var clientTop = docElement.clientTop || doc.body.clientTop || 0;
var clientLeft = docElement.clientLeft || doc.body.clientLeft || 0;
var scrollTop = win.pageYOffset || docElement.scrollTop || doc.body.scrollTop;
var scrollLeft = win.pageXOffset || docElement.scrollLeft || doc.body.scrollLeft;
clientRect = el.getBoundingClientRect();
return {
top: clientRect.top + scrollTop - clientTop,
left: clientRect.left + scrollLeft - clientLeft,
};
}
function isElementVisible(el, doc) {
if (!isElementInDocument(el, doc))
return false;
while (el) {
if (get$1(el, 'display', doc) === 'none' || get$1(el, 'visibility', doc) === 'hidden')
return false;
el = getParentExceptShadowRoot(el);
}
return true;
}
function isElementInInvisibleIframe(el) {
var frameElement = getIframeByElement(el);
return frameElement && !isElementVisible(frameElement, findDocument(frameElement));
}
var styleUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
get: get$1,
set: set,
getBordersWidthInternal: getBordersWidthInternal,
getBordersWidth: getBordersWidth,
getBordersWidthFloat: getBordersWidthFloat,
getComputedStyle: getComputedStyle,
getElementMargin: getElementMargin,
getElementPaddingInternal: getElementPaddingInternal,
getElementPadding: getElementPadding,
getElementPaddingFloat: getElementPaddingFloat,
getElementScroll: getElementScroll,
getWidth: getWidth,
getHeight: getHeight,
getInnerWidth: getInnerWidth,
getInnerHeight: getInnerHeight,
getOptionHeight: getOptionHeight,
getSelectElementSize: getSelectElementSize,
isVisibleChild: isVisibleChild,
getScrollLeft: getScrollLeft,
getScrollTop: getScrollTop,
setScrollLeft: setScrollLeft,
setScrollTop: setScrollTop,
getOffsetParent: getOffsetParent,
getOffset: getOffset,
isElementVisible: isElementVisible,
isElementInInvisibleIframe: isElementInInvisibleIframe
});
function getNativeQuerySelector(el) {
if (isDomElement(el))
return nativeMethods.elementQuerySelector;
return isDocumentFragmentNode(el) || isShadowRoot(el)
? nativeMethods.documentFragmentQuerySelector
: nativeMethods.querySelector;
}
function getNativeQuerySelectorAll(el) {
// NOTE: Do not return the isDocument function instead of the isDomElement
// it leads to the `Invalid calling object` error in some cases in IE11 (GH-1846)
if (isDomElement(el))
return nativeMethods.elementQuerySelectorAll;
return isDocumentFragmentNode(el) || isShadowRoot(el)
? nativeMethods.documentFragmentQuerySelectorAll
: nativeMethods.querySelectorAll;
}
var scrollbarSize = 0;
var NATIVE_MAP_ELEMENT_STRINGS = [
'[object HTMLMapElement]',
'[object HTMLAreaElement]',
];
var WINDOW_IS_UNDEFINED = typeof window === 'undefined';
var NATIVE_WINDOW_STR = WINDOW_IS_UNDEFINED ? '' : instanceToString(window);
var IS_DOCUMENT_RE = /^\[object .*?Document]$/i;
var IS_PROCESSING_INSTRUCTION_RE = /^\[object .*?ProcessingInstruction]$/i;
var IS_SVG_ELEMENT_RE = /^\[object SVG\w+?Element]$/i;
var IS_HTML_ELEMENT_RE = /^\[object HTML.*?Element]$/i;
var IS_ARRAY_BUFFER_RE = /^\[object ArrayBuffer]$/i;
var IS_DATA_VIEW_RE = /^\[object DataView]$/i;
var NATIVE_TABLE_CELL_STR = WINDOW_IS_UNDEFINED ? '' : instanceToString(nativeMethods.createElement.call(document, 'td'));
var ELEMENT_NODE_TYPE = WINDOW_IS_UNDEFINED ? -1 : Node.ELEMENT_NODE;
var NOT_CONTENT_EDITABLE_ELEMENTS_RE = /^(select|option|applet|area|audio|canvas|datalist|keygen|map|meter|object|progress|source|track|video|img)$/;
var INPUT_ELEMENTS_RE = /^(input|textarea|button)$/;
var SCRIPT_OR_STYLE_RE = /^(script|style)$/i;
var EDITABLE_INPUT_TYPES_RE = /^(email|number|password|search|tel|text|url)$/;
var NUMBER_OR_EMAIL_INPUT_RE = /^(number|email)$/;
// NOTE: input with 'file' type processed separately in 'UploadSandbox'
var INPUT_WITH_NATIVE_DIALOG = /^(color|date|datetime-local|month|week)$/;
// NOTE: We don't take into account the case of embedded contentEditable elements, and we
// specify the contentEditable attribute for focusable elements.
var FOCUSABLE_SELECTOR = 'input, select, textarea, button, body, iframe, [contenteditable="true"], [contenteditable=""], [tabIndex]';
function isHidden(el) {
return el.offsetWidth <= 0 && el.offsetHeight <= 0;
}
function isAlwaysNotEditableElement(el) {
var tagName = getTagName(el);
return !!tagName && (NOT_CONTENT_EDITABLE_ELEMENTS_RE.test(tagName) || INPUT_ELEMENTS_RE.test(tagName));
}
function isLocationByProto(instance) {
var instanceCtor = null;
try {
// eslint-disable-next-line no-proto
instanceCtor = instance.__proto__;
}
catch (e) {
// NOTE: Try to detect cross-domain window location.
// A cross-domain location has no the "assign" function in Safari, Chrome and FireFox.
var shouldNotHaveAssign = isSafari || isChrome || isFirefox;
return instance.replace && (shouldNotHaveAssign || !!instance.assign);
}
if (!instanceCtor)
return false;
var stringifiedInstanceCtor = nativeMethods.objectToString.call(instanceCtor);
return stringifiedInstanceCtor === '[object LocationPrototype]' ||
stringifiedInstanceCtor === '[object Location]'; // NOTE: "iPhone" Chrome device emulation case (GH-2080)
}
function closestFallback(el, selector) {
while (el) {
if (matches(el, selector))
return el;
el = nativeMethods.nodeParentNodeGetter.call(el);
}
return null;
}
function instanceToString(instance) {
if (!instanceAndPrototypeToStringAreEqual)
return nativeMethods.objectToString.call(instance);
return instance && typeof instance === 'object'
? nativeMethods.objectToString.call(nativeMethods.objectGetPrototypeOf(instance))
: '';
}
function getActiveElement(currentDocument) {
// NOTE: Sometimes document.activeElement returns an empty object or null (IE11).
// https://github.com/DevExpress/testcafe-hammerhead/issues/768
var doc = currentDocument || document;
var activeElement = nativeMethods.documentActiveElementGetter.call(doc);
var el = isDomElement(activeElement) ? activeElement : doc.body;
while (el && el.shadowRoot) {
// eslint-disable-next-line no-restricted-properties
var shadowEl = el.shadowRoot.activeElement;
if (!shadowEl)
break;
el = shadowEl;
}
return el;
}
function getChildVisibleIndex(select, child) {
var childrenArray = getSelectVisibleChildren(select);
return childrenArray.indexOf(child);
}
function getIframeByElement(el) {
var elWindow = el[INTERNAL_PROPS.processedContext];
return getFrameElement(elWindow);
}
function getIframeLocation(iframe) {
var documentLocation = null;
try {
// eslint-disable-next-line no-restricted-properties
documentLocation = nativeMethods.contentDocumentGetter.call(iframe).location.href;
}
catch (e) {
documentLocation = null;
}
var srcLocation = nativeMethods.getAttribute.call(iframe, 'src' + INTERNAL_ATTRIBUTES.storedAttrPostfix) ||
nativeMethods.getAttribute.call(iframe, 'src') || nativeMethods.iframeSrcGetter.call(iframe);
var parsedProxyDocumentLocation = documentLocation && isSupportedProtocol(documentLocation) &&
parseProxyUrl(documentLocation);
var parsedProxySrcLocation = srcLocation && isSupportedProtocol(srcLocation) &&
parseProxyUrl(srcLocation);
return {
documentLocation: parsedProxyDocumentLocation ? parsedProxyDocumentLocation.destUrl : documentLocation,
srcLocation: parsedProxySrcLocation ? parsedProxySrcLocation.destUrl : srcLocation,
};
}
function getFrameElement(win) {
try {
return win.frameElement;
}
catch (e) {
return null;
}
}
function getMapContainer(el) {
var closestMap = closest(el, 'map');
var closestMapName = nativeMethods.getAttribute.call(closestMap, 'name');
var containerSelector = '[usemap="#' + closestMapName + '"]';
return nativeMethods.querySelector.call(findDocument(el), containerSelector);
}
function getParentWindowWithSrc(window) {
var parent = window.parent;
var parentFrameElement = null;
if (window === window.top)
return window;
if (parent === window.top || isCrossDomainWindows(window, parent))
return parent;
try {
parentFrameElement = parent.frameElement;
}
catch (e) {
parentFrameElement = null;
}
if (parentFrameElement === null || !isIframeWithoutSrc(parentFrameElement))
return parent;
return getParentWindowWithSrc(parent);
}
function getScrollbarSize() {
if (!scrollbarSize) {
var scrollDiv = nativeMethods.createElement.call(document, 'div');
scrollDiv.style.height = '100px';
scrollDiv.style.overflow = 'scroll';
scrollDiv.style.position = 'absolute';
scrollDiv.style.top = '-9999px';
scrollDiv.style.width = '100px';
nativeMethods.appendChild.call(document.body, scrollDiv);
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
scrollbarSize = scrollbarWidth;
var parent_1 = nativeMethods.nodeParentNodeGetter.call(scrollDiv);
parent_1.removeChild(scrollDiv);
}
return scrollbarSize;
}
function getSelectParent(child) {
var parent = nativeMethods.nodeParentNodeGetter.call(child);
return closest(parent, 'select');
}
function getSelectVisibleChildren(select) {
var children = nativeMethods.elementQuerySelectorAll.call(select, 'optgroup, option');
var result = [];
var length = nativeMethods.nodeListLengthGetter.call(children);
for (var i = 0; i < length; i++) {
var child = children[i];
// NOTE: Firefox does not display groups without a label and with an empty label.
var shouldAdd = isFirefox ? getTagName(child) !== 'optgroup' || child.label : true;
if (shouldAdd)
result.push(child);
}
return result;
}
function getTopSameDomainWindow(window) {
var result = window;
var currentWindow = window.parent;
if (result === window.top)
return result;
while (currentWindow) {
if (!isCrossDomainWindows(window, currentWindow)) {
var frameElement_1 = getFrameElement(currentWindow);
if (!frameElement_1 || !isIframeWithoutSrc(frameElement_1))
result = currentWindow;
}
currentWindow = currentWindow !== window.top ? currentWindow.parent : null;
}
return result;
}
function find(parent, selector, handler) {
var nodeList = getNativeQuerySelectorAll(parent).call(parent, selector);
if (handler) {
var length_1 = nativeMethods.nodeListLengthGetter.call(nodeList);
for (var i = 0; i < length_1; i++)
handler(nodeList[i]);
}
return nodeList;
}
function findDocument(el) {
if (el.documentElement)
return el;
if (el.ownerDocument && el.ownerDocument.defaultView)
return el.ownerDocument;
var parent = isElementNode(el) && nativeMethods.nodeParentNodeGetter.call(el);
return parent ? findDocument(parent) : document;
}
function isContentEditableElement(el) {
var isContentEditable = false;
var element = null;
if (isTextNode(el))
element = el.parentElement || nativeMethods.nodeParentNodeGetter.call(el);
else
element = el;
if (element) {
isContentEditable = element.isContentEditable && !isAlwaysNotEditableElement(element);
return isRenderedNode(element) && (isContentEditable || findDocument(el).designMode === 'on');
}
return false;
}
function isCrossDomainIframe(iframe, bySrc) {
var iframeLocation = getIframeLocation(iframe);
if (!bySrc && iframeLocation.documentLocation === null)
return true;
var currentLocation = bySrc ? iframeLocation.srcLocation : iframeLocation.documentLocation;
if (currentLocation && isSupportedProtocol(currentLocation))
return !sameOriginCheck(location.toString(), currentLocation);
return false;
}
function isCrossDomainWindows(window1, window2) {
try {
if (window1 === window2)
return false;
var window1Location = window1.location.toString();
var window2Location = window2.location.toString();
if (!isSupportedProtocol(window1Location) || !isSupportedProtocol(window2Location))
return false;
return !sameOriginCheck(window1Location, window2Location);
}
catch (e) {
return true;
}
}
function isIframeWindow(wnd) {
return wnd !== wnd.top;
}
function isDomElement(el) {
if (el instanceof nativeMethods.elementClass)
return true;
return el && IS_HTML_ELEMENT_RE.test(instanceToString(el)) && isElementNode(el) && el.tagName;
}
function getTagName(el) {
// NOTE: Check for tagName being a string, because it may be a function in an Angular app (T175340).
return el && typeof el.tagName === 'string' ? el.tagName.toLowerCase() : '';
}
var SHADOW_ROOT_PARENT_ELEMENT = 'hammerhead|element|shadow-root-parent';
function getNodeShadowRootParent(el) {
var parent = nativeMethods.nodeParentNodeGetter.call(el);
while (parent && parent.nodeType !== Node.DOCUMENT_FRAGMENT_NODE)
parent = nativeMethods.nodeParentNodeGetter.call(parent);
return parent && parent[SHADOW_ROOT_PARENT_ELEMENT];
}
function getParentExceptShadowRoot(el) {
var parent = nativeMethods.nodeParentNodeGetter.call(el);
return parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE && parent[SHADOW_ROOT_PARENT_ELEMENT]
? parent[SHADOW_ROOT_PARENT_ELEMENT]
: parent;
}
function isElementInDocument(el, currentDocument) {
var doc = currentDocument || document;
if (!doc.documentElement)
return false;
if (doc.documentElement.contains(el))
return true;
var shadowRootParent = getNodeShadowRootParent(el);
return shadowRootParent ? isElementInDocument(shadowRootParent) : false;
}
function isElementInIframe(el, currentDocument) {
var doc = currentDocument || findDocument(el);
return window.document !== doc;
}
function isHammerheadAttr(attr) {
return attr === INTERNAL_ATTRIBUTES.focusPseudoClass || attr === INTERNAL_ATTRIBUTES.hoverPseudoClass ||
attr.indexOf(INTERNAL_ATTRIBUTES.storedAttrPostfix) !== -1;
}
function isIframeElement(el) {
return instanceToString(el) === '[object HTMLIFrameElement]';
}
function isFrameElement(el) {
return instanceToString(el) === '[object HTMLFrameElement]';
}
function isIframeWithoutSrc(iframe) {
var iframeLocation = getIframeLocation(iframe);
var iframeSrcLocation = iframeLocation.srcLocation;
var iframeDocumentLocation = iframeLocation.documentLocation;
// NOTE: is a cross-domain iframe
if (iframeDocumentLocation === null)
return false;
// NOTE: after 'document.write' or 'document.open' call for iframe with/without src
// we will process it as iframe without src
if (nativeMethods.contentWindowGetter.call(iframe)[INTERNAL_PROPS.documentWasCleaned])
return true;
var iframeDocumentLocationHaveSupportedProtocol = isSupportedProtocol(iframeDocumentLocation);
// NOTE: When an iframe has an empty src attribute (<iframe src></iframe>) or has no src attribute (<iframe></iframe>),
// the iframe.src property is not empty but has different values in different browsers.
// Its document location is 'about:blank'. Therefore, we should check the src attribute.
if (!iframeDocumentLocationHaveSupportedProtocol && !nativeMethods.getAttribute.call(iframe, 'src'))
return true;
// In Chrome, when an iframe with the src attribute is added to DOM,
// its documentLocation is set to "about:blank" until the iframe has been loaded.
// So, we should check srcLocation in this case.
if (iframeSrcLocation && isSupportedProtocol(iframeSrcLocation))
return false;
return !iframeDocumentLocationHaveSupportedProtocol;
}
function isIframeWithSrcdoc(iframe) {
return nativeMethods.iframeSrcdocGetter && nativeMethods.hasAttribute.call(iframe, 'srcdoc');
}
function isImgElement(el) {
return instanceToString(el) === '[object HTMLImageElement]';
}
function isInputElement(el) {
return instanceToString(el) === '[object HTMLInputElement]';
}
function isTitleElement(el) {
return instanceToString(el) === '[object HTMLTitleElement]';
}
function isButtonElement(el) {
return instanceToString(el) === '[object HTMLButtonElement]';
}
function isFieldSetElement(el) {
return instanceToString(el) === '[object HTMLFieldSetElement]';
}
function isOptGroupElement(el) {
return instanceToString(el) === '[object HTMLOptGroupElement]';
}
function isHtmlElement(el) {
return instanceToString(el) === '[object HTMLHtmlElement]';
}
function isBodyElement(el) {
return instanceToString(el) === '[object HTMLBodyElement]';
}
function isPageBody(el) {
var _a;
var parent = nativeMethods.nodeParentNodeGetter.call(el);
return getTagName(parent) === 'html' && ((_a = nativeMethods.nodeParentNodeGetter.call(parent)) === null || _a === void 0 ? void 0 : _a.nodeName) === '#document';
}
function isHeadElement(el) {
return instanceToString(el) === '[object HTMLHeadElement]';
}
function isHeadOrBodyElement(el) {
var elString = instanceToString(el);
return elString === '[object HTMLHeadElement]' || elString === '[object HTMLBodyElement]';
}
function isHeadOrBodyOrHtmlElement(el) {
var elString = instanceToString(el);
return elString === '[object HTMLHeadElement]' || elString === '[object HTMLBodyElement]' ||
elString === '[object HTMLHtmlElement]';
}
function isBaseElement(el) {
return instanceToString(el) === '[object HTMLBaseElement]';
}
function isScriptElement(el) {
return instanceToString(el) === '[object HTMLScriptElement]';
}
function isStyleElement(el) {
return instanceToString(el) === '[object HTMLStyleElement]';
}
function isLabelElement(el) {
return instanceToString(el) === '[object HTMLLabelElement]';
}
function isTextAreaElement(el) {
return instanceToString(el) === '[object HTMLTextAreaElement]';
}
function isOptionElement(el) {
return instanceToString(el) === '[object HTMLOptionElement]';
}
function isRadioButtonElement(el) {
return isInputElement(el) && el.type.toLowerCase() === 'radio';
}
function isColorInputElement(el) {
return isInputElement(el) && el.type.toLowerCase() === 'color';
}
function isCheckboxElement(el) {
return isInputElement(el) && el.type.toLowerCase() === 'checkbox';
}
function isSelectElement(el) {
return instanceToString(el) === '[object HTMLSelectElement]';
}
function isFormElement(el) {
return instanceToString(el) === '[object HTMLFormElement]';
}
function isFileInput(el) {
return isInputElement(el) && el.type.toLowerCase() === 'file';
}
function isInputWithNativeDialog(el) {
return isInputElement(el) && INPUT_WITH_NATIVE_DIALOG.test(el.type.toLowerCase());
}
function isBodyElementWithChildren(el) {
return isBodyElement(el) && isPageBody(el) && nativeMethods.htmlCollectionLengthGetter.call(nativeMethods.elementChildrenGetter.call(el));
}
function isMapElement(el) {
return NATIVE_MAP_ELEMENT_STRINGS.indexOf(instanceToString(el)) !== -1;
}
function isRenderedNode(node) {
return !(isProcessingInstructionNode(node) || isCommentNode(node) || SCRIPT_OR_STYLE_RE.test(node.nodeName));
}
function getTabIndex(el) {
// NOTE: we obtain the tabIndex value from an attribute because the el.tabIndex
// property returns -1 for some elements (e.g. for body) with no tabIndex assigned
var tabIndex = nativeMethods.getAttribute.call(el, 'tabIndex');
tabIndex = parseInt(tabIndex, 10);
return isNaN(tabIndex) ? null : tabIndex;
}
function isElementDisabled(el) {
return matches(el, ':disabled');
}
function isElementFocusable(el) {
if (!el)
return false;
var tabIndex = getTabIndex(el);
var isDisabledElement = isElementDisabled(el);
var isInvisibleElement = get$1(el, 'visibility') === 'hidden';
var isNotDisplayedElement = get$1(el, 'display') === 'none';
var isHiddenElement = isWebKit ? isHidden(el) && !isOptionElement(el) : isHidden(el);
if (isDisabledElement || isInvisibleElement || isNotDisplayedElement || isHiddenElement)
return false;
if (isOptionElement(el) && isIE)
return false;
if (isAnchorElement(el)) {
if (tabIndex !== null)
return true;
return matches(el, 'a[href]');
}
if (isTableDataCellElement(el) && isIE)
return true;
return matches(el, FOCUSABLE_SELECTOR) || tabIndex !== null;
}
function isShadowUIElement(element) {
// @ts-ignore
return !!element[INTERNAL_PROPS.shadowUIElement];
}
function isWindow(instance) {
try {
// NOTE: The instanceToString call result has a strange values for the MessageEvent.target property:
// * [object DispHTMLWindow2] for IE11
// * [object Object] for MSEdge.
if ((isIE || isMSEdge) && instance && instance === instance.window)
instance = instance.window;
if (!instance || !instance.toString || NATIVE_WINDOW_STR !== instanceToString(instance))
return false;
}
catch (e) {
try {
// NOTE: If a cross-domain object has the 'top' field, this object is a window
// (not a document or location).
return !!instance.top;
}
catch (_a) {
return false;
}
}
try {
nativeMethods.winLocalStorageGetter.call(instance);
}
catch (_b) {
return false;
}
return true;
}
function isDocument(instance) {
if (instance instanceof nativeMethods.documentClass)
return true;
try {
return instance && IS_DOCUMENT_RE.test(instanceToString(instance));
}
catch (e) {
// NOTE: For cross-domain objects (windows, documents or locations), we return false because
// it's impossible to work with them in any case.
return false;
}
}
function isBlob(instance) {
return instance && instanceToString(instance) === '[object Blob]';
}
function isLocation(instance) {
if (!instance)
return false;
if (isIE || isSafari || isChrome || isFirefox)
return isLocationByProto(instance);
return instance instanceof nativeMethods.locationClass ||
nativeMethods.objectToString.call(instance) === '[object Location]';
}
function isSVGElement(instance) {
if (instance instanceof nativeMethods.svgElementClass)
return true;
return instance && IS_SVG_ELEMENT_RE.test(instanceToString(instance));
}
function isSVGElementOrChild(el) {
return !!closest(el, 'svg');
}
function isFetchHeaders(instance) {
if (nativeMethods.Headers && instance instanceof nativeMethods.Headers)
return true;
return instance && instanceToString(instance) === '[object Headers]';
}
function isFetchRequest(instance) {
if (nativeMethods.Request && instance instanceof nativeMethods.Request)
return true;
return instance && instanceToString(instance) === '[object Request]';
}
function isElementReadOnly(el) {
return el.readOnly || el.getAttribute('readonly') === 'readonly';
}
function isTextEditableInput(el) {
var attrType = el.getAttribute('type');
return isInputElement(el) &&
attrType ? EDITABLE_INPUT_TYPES_RE.test(attrType) : EDITABLE_INPUT_TYPES_RE.test(el.type);
}
function isTextEditableElement(el) {
return isTextEditableInput(el) || isTextAreaElement(el);
}
function isTextEditableElementAndEditingAllowed(el) {
return isTextEditableElement(el) && !isElementReadOnly(el);
}
function isElementNode(node) {
return node && node.nodeType === ELEMENT_NODE_TYPE;
}
function isTextNode(node) {
return instanceToString(node) === '[object Text]';
}
function isProcessingInstructionNode(node) {
return IS_PROCESSING_INSTRUCTION_RE.test(instanceToString(node));
}
function isCommentNode(node) {
return instanceToString(node) === '[object Comment]';
}
function isDocumentFragmentNode(node) {
return instanceToString(node) === '[object DocumentFragment]';
}
function isShadowRoot(root) {
return instanceToString(root) === '[object ShadowRoot]';
}
function isAnchorElement(el) {
return instanceToString(el) === '[object HTMLAnchorElement]';
}
function isTableElement(el) {
return instanceToString(el) === '[object HTMLTableElement]';
}
function isTableDataCellElement(el) {
return instanceToString(el) === NATIVE_TABLE_CELL_STR;
}
function isWebSocket(ws) {
return instanceToString(ws) === '[object WebSocket]';
}
function isMessageEvent(e) {
return instanceToString(e) === '[object MessageEvent]';
}
function isPerformanceNavigationTiming(entry) {
return instanceToString(entry) === '[object PerformanceNavigationTiming]';
}
function isArrayBuffer(data) {
if (data instanceof nativeMethods.ArrayBuffer)
return true;
return data && IS_ARRAY_BUFFER_RE.test(instanceToString(data));
}
function isArrayBufferView(data) {
return data && nativeMethods.arrayBufferIsView(data);
}
function isDataView(data) {
if (data instanceof nativeMethods.DataView)
return true;
return data && IS_DATA_VIEW_RE.test(instanceToString(data));
}
function matches(el, selector) {
if (!isElementNode(el))
return false;
return nativeMethods.matches.call(el, selector);
}
function closest(el, selector) {
if (!isElementNode(el))
return null;
if (nativeMethods.closest)
return nativeMethods.closest.call(el, selector);
return closestFallback(el, selector);
}
function addClass(el, className) {
if (!el)
return;
var classNames = className.split(/\s+/);
for (var _i = 0, classNames_1 = classNames; _i < classNames_1.length; _i++) {
var currentClassName = classNames_1[_i];
nativeMethods.tokenListAdd.call(nativeMethods.elementClassListGetter.call(el), currentClassName);
}
}
function removeClass(el, className) {
if (!el)
return;
var classNames = className.split(/\s+/);
for (var _i = 0, classNames_2 = classNames; _i < classNames_2.length; _i++) {
var currentClassName = classNames_2[_i];
nativeMethods.tokenListRemove.call(nativeMethods.elementClassListGetter.call(el), currentClassName);
}
}
function hasClass(el, className) {
if (!el)
return false;
return nativeMethods.tokenListContains.call(nativeMethods.elementClassListGetter.call(el), className);
}
function parseDocumentCharset() {
var metaCharset = nativeMethods.querySelector.call(document, '.' + SHADOW_UI_CLASS_NAME.charset);
return metaCharset && metaCharset.getAttribute('charset');
}
function getParents(el, selector) {
var parents = [];
var parent = getParent(el);
while (parent) {
if (!selector && isElementNode(parent) || selector && matches(parent, selector))
parents.push(parent);
parent = getParent(parent);
}
return parents;
}
function getParent(el) {
el = el.assignedSlot || el;
// eslint-disable-next-line no-restricted-properties
return nativeMethods.nodeParentNodeGetter.call(el) || el.host;
}
function findParent(node, includeSelf, predicate) {
if (includeSelf === void 0) { includeSelf = false; }
if (!includeSelf)
node = getParent(node);
while (node) {
if (!isFunction(predicate) || predicate(node))
return node;
node = getParent(node);
}
return null;
}
function nodeListToArray(nodeList) {
var result = [];
var length = nativeMethods.nodeListLengthGetter.call(nodeList);
for (var i = 0; i < length; i++)
result.push(nodeList[i]);
return result;
}
function getFileInputs(el) {
return isFileInput(el) ? [el] : nodeListToArray(getNativeQuerySelectorAll(el).call(el, 'input[type=file]'));
}
function getIframes(el) {
return isIframeElement(el) ? [el] : nodeListToArray(getNativeQuerySelectorAll(el).call(el, 'iframe,frame'));
}
function getScripts(el) {
return isScriptElement(el) ? [el] : nodeListToArray(getNativeQuerySelectorAll(el).call(el, 'script'));
}
function isNumberOrEmailInput(el) {
return isInputElement(el) && NUMBER_OR_EMAIL_INPUT_RE.test(el.type);
}
function isInputWithoutSelectionProperties(el) {
if (!isNumberOrEmailInput(el))
return false;
var hasSelectionProperties = isNumber(el.selectionStart) && isNumber(el.selectionEnd);
return !hasSelectionProperties;
}
function getAssociatedElement(el) {
if (!isLabelElement(el))
return null;
var doc = findDocument(el);
return el.control || el.htmlFor && nativeMethods.getElementById.call(doc, el.htmlFor);
}
var domUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
instanceToString: instanceToString,
getActiveElement: getActiveElement,
getChildVisibleIndex: getChildVisibleIndex,
getIframeByElement: getIframeByElement,
getIframeLocation: getIframeLocation,
getFrameElement: getFrameElement,
getMapContainer: getMapContainer,
getParentWindowWithSrc: getParentWindowWithSrc,
getScrollbarSize: getScrollbarSize,
getSelectParent: getSelectParent,
getSelectVisibleChildren: getSelectVisibleChildren,
getTopSameDomainWindow: getTopSameDomainWindow,
find: find,
findDocument: findDocument,
isContentEditableElement: isContentEditableElement,
isCrossDomainIframe: isCrossDomainIframe,
isCrossDomainWindows: isCrossDomainWindows,
isIframeWindow: isIframeWindow,
isDomElement: isDomElement,
getTagName: getTagName,
SHADOW_ROOT_PARENT_ELEMENT: SHADOW_ROOT_PARENT_ELEMENT,
getNodeShadowRootParent: getNodeShadowRootParent,
getParentExceptShadowRoot: getParentExceptShadowRoot,
isElementInDocument: isElementInDocument,
isElementInIframe: isElementInIframe,
isHammerheadAttr: isHammerheadAttr,
isIframeElement: isIframeElement,
isFrameElement: isFrameElement,
isIframeWithoutSrc: isIframeWithoutSrc,
isIframeWithSrcdoc: isIframeWithSrcdoc,
isImgElement: isImgElement,
isInputElement: isInputElement,
isTitleElement: isTitleElement,
isButtonElement: isButtonElement,
isFieldSetElement: isFieldSetElement,
isOptGroupElement: isOptGroupElement,
isHtmlElement: isHtmlElement,
isBodyElement: isBodyElement,
isPageBody: isPageBody,
isHeadElement: isHeadElement,
isHeadOrBodyElement: isHeadOrBodyElement,
isHeadOrBodyOrHtmlElement: isHeadOrBodyOrHtmlElement,
isBaseElement: isBaseElement,
isScriptElement: isScriptElement,
isStyleElement: isStyleElement,
isLabelElement: isLabelElement,
isTextAreaElement: isTextAreaElement,
isOptionElement: isOptionElement,
isRadioButtonElement: isRadioButtonElement,
isColorInputElement: isColorInputElement,
isCheckboxElement: isCheckboxElement,
isSelectElement: isSelectElement,
isFormElement: isFormElement,
isFileInput: isFileInput,
isInputWithNativeDialog: isInputWithNativeDialog,
isBodyElementWithChildren: isBodyElementWithChildren,
isMapElement: isMapElement,
isRenderedNode: isRenderedNode,
getTabIndex: getTabIndex,
isElementDisabled: isElementDisabled,
isElementFocusable: isElementFocusable,
isShadowUIElement: isShadowUIElement,
isWindow: isWindow,
isDocument: isDocument,
isBlob: isBlob,
isLocation: isLocation,
isSVGElement: isSVGElement,
isSVGElementOrChild: isSVGElementOrChild,
isFetchHeaders: isFetchHeaders,
isFetchRequest: isFetchRequest,
isElementReadOnly: isElementReadOnly,
isTextEditableInput: isTextEditableInput,
isTextEditableElement: isTextEditableElement,
isTextEditableElementAndEditingAllowed: isTextEditableElementAndEditingAllowed,
isElementNode: isElementNode,
isTextNode: isTextNode,
isProcessingInstructionNode: isProcessingInstructionNode,
isCommentNode: isCommentNode,
isDocumentFragmentNode: isDocumentFragmentNode,
isShadowRoot: isShadowRoot,
isAnchorElement: isAnchorElement,
isTableElement: isTableElement,
isTableDataCellElement: isTableDataCellElement,
isWebSocket: isWebSocket,
isMessageEvent: isMessageEvent,
isPerformanceNavigationTiming: isPerformanceNavigationTiming,
isArrayBuffer: isArrayBuffer,
isArrayBufferView: isArrayBufferView,
isDataView: isDataView,
matches: matches,
closest: closest,
addClass: addClass,
removeClass: removeClass,
hasClass: hasClass,
parseDocumentCharset: parseDocumentCharset,
getParents: getParents,
findParent: findParent,
nodeListToArray: nodeListToArray,
getFileInputs: getFileInputs,
getIframes: getIframes,
getScripts: getScripts,
isNumberOrEmailInput: isNumberOrEmailInput,
isInputWithoutSelectionProperties: isInputWithoutSelectionProperties,
getAssociatedElement: getAssociatedElement
});
var SandboxBase = /** @class */ (function (_super) {
__extends(SandboxBase, _super);
function SandboxBase() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.window = null;
_this.nativeMethods = nativeMethods;
_this.document = null;
_this.proxyless = false;
return _this;
}
// NOTE: The sandbox is deactivated when its window is removed from the DOM.
SandboxBase.prototype.isDeactivated = function () {
try {
// NOTE: In IE11, a situation when the document is not active may occur.
// eslint-disable-next-line no-unused-expressions
this.document.body;
if (this.window[INTERNAL_PROPS.hammerhead]) {
var frameElement_1 = getFrameElement(this.window);
return !!frameElement_1 && !isElementInDocument(frameElement_1, findDocument(frameElement_1));
}
}
catch (e) { // eslint-disable-line no-empty
}
return true;
};
SandboxBase.prototype.attach = function (window, document) {
this.window = window;
this.document = document || window.document;
this.proxyless = !!settings.get().proxyless;
};
return SandboxBase;
}(EventEmitter));
// -------------------------------------------------------------
var isArray,
json$1,
renumber,
hexadecimal,
quotes,
escapeless,
parentheses,
semicolons,
safeConcatenation,
directive,
extra;
var Syntax = {
AssignmentExpression: 'AssignmentExpression',
AssignmentPattern: 'AssignmentPattern',
ArrayExpression: 'ArrayExpression',
ArrayPattern: 'ArrayPattern',
ArrowFunctionExpression: 'ArrowFunctionExpression',
AwaitExpression: 'AwaitExpression',
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
ClassBody: 'ClassBody',
ClassDeclaration: 'ClassDeclaration',
ClassExpression: 'ClassExpression',
ComprehensionBlock: 'ComprehensionBlock',
ComprehensionExpression: 'ComprehensionExpression',
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DirectiveStatement: 'DirectiveStatement',
DoWhileStatement: 'DoWhileStatement',
DebuggerStatement: 'DebuggerStatement',
EmptyStatement: 'EmptyStatement',
ExportAllDeclaration: 'ExportAllDeclaration',
ExportBatchSpecifier: 'ExportBatchSpecifier',
ExportDeclaration: 'ExportDeclaration',
ExportNamedDeclaration: 'ExportNamedDeclaration',
ExportSpecifier: 'ExportSpecifier',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
ForOfStatement: 'ForOfStatement',
FunctionDeclaration: 'FunctionDeclaration',
FunctionExpression: 'FunctionExpression',
GeneratorExpression: 'GeneratorExpression',
Identifier: 'Identifier',
IfStatement: 'IfStatement',
ImportExpression: 'ImportExpression',
ImportSpecifier: 'ImportSpecifier',
ImportDeclaration: 'ImportDeclaration',
ChainExpression: 'ChainExpression',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
MetaProperty: 'MetaProperty',
MethodDefinition: 'MethodDefinition',
ModuleDeclaration: 'ModuleDeclaration',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
ObjectPattern: 'ObjectPattern',
Program: 'Program',
Property: 'Property',
RestElement: 'RestElement',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SpreadElement: 'SpreadElement',
Super: 'Super',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
TaggedTemplateExpression: 'TaggedTemplateExpression',
TemplateElement: 'TemplateElement',
TemplateLiteral: 'TemplateLiteral',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
UnaryExpression: 'UnaryExpression',
UpdateExpression: 'UpdateExpression',
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement',
YieldExpression: 'YieldExpression'
};
var Syntax_1 = Syntax;
var Precedence = {
Sequence: 0,
Yield: 1,
Assignment: 1,
Conditional: 2,
ArrowFunction: 2,
Coalesce: 3,
LogicalOR: 3,
LogicalAND: 4,
BitwiseOR: 5,
BitwiseXOR: 6,
BitwiseAND: 7,
Equality: 8,
Relational: 9,
BitwiseSHIFT: 10,
Additive: 11,
Multiplicative: 12,
Unary: 13,
Exponentiation: 14,
Postfix: 14,
Await: 14,
Call: 15,
New: 16,
TaggedTemplate: 17,
OptionalChaining: 17,
Member: 18,
Primary: 19
};
var BinaryPrecedence = {
'||': Precedence.LogicalOR,
'&&': Precedence.LogicalAND,
'|': Precedence.BitwiseOR,
'^': Precedence.BitwiseXOR,
'&': Precedence.BitwiseAND,
'==': Precedence.Equality,
'!=': Precedence.Equality,
'===': Precedence.Equality,
'!==': Precedence.Equality,
'is': Precedence.Equality,
'isnt': Precedence.Equality,
'<': Precedence.Relational,
'>': Precedence.Relational,
'<=': Precedence.Relational,
'>=': Precedence.Relational,
'in': Precedence.Relational,
'instanceof': Precedence.Relational,
'<<': Precedence.BitwiseSHIFT,
'>>': Precedence.BitwiseSHIFT,
'>>>': Precedence.BitwiseSHIFT,
'+': Precedence.Additive,
'-': Precedence.Additive,
'*': Precedence.Multiplicative,
'%': Precedence.Multiplicative,
'/': Precedence.Multiplicative,
'??': Precedence.Coalesce,
'**': Precedence.Exponentiation
};
function getDefaultOptions () {
// default options
return {
indent: null,
base: null,
parse: null,
format: {
indent: {
style: ' ',
base: 0
},
newline: '\n',
space: ' ',
json: false,
renumber: false,
hexadecimal: false,
quotes: 'single',
escapeless: false,
compact: false,
parentheses: true,
semicolons: true,
safeConcatenation: false
},
directive: false,
raw: true,
verbatim: null
};
}
//-------------------------------------------------===------------------------------------------------------
// Lexical utils
//-------------------------------------------------===------------------------------------------------------
//Const
var NON_ASCII_WHITESPACES = [
0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000,
0xFEFF
];
//Regular expressions
var NON_ASCII_IDENTIFIER_CHARACTERS_REGEXP = new RegExp(
'[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376' +
'\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-' +
'\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA' +
'\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-' +
'\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0\u08A2-\u08AC\u08E4-\u08FE\u0900-' +
'\u0963\u0966-\u096F\u0971-\u0977\u0979-\u097F\u0981-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-' +
'\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-' +
'\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38' +
'\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83' +
'\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9' +
'\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-' +
'\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-' +
'\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E' +
'\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-' +
'\u0BEF\u0C01-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D-\u0C44\u0C46-' +
'\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C82\u0C83\u0C85-\u0C8C\u0C8E-' +
'\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE' +
'\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D02\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44' +
'\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-' +
'\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E01-\u0E3A' +
'\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-' +
'\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9' +
'\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84' +
'\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-' +
'\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5' +
'\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-' +
'\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-' +
'\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD' +
'\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191C\u1920-\u192B' +
'\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E' +
'\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-' +
'\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1D00-\u1DE6\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-' +
'\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-' +
'\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F' +
'\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115' +
'\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188' +
'\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-' +
'\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-' +
'\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A' +
'\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5' +
'\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA697' +
'\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA827\uA840-\uA873' +
'\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-' +
'\uA9D9\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7B\uAA80-\uAAC2\uAADB-\uAADD\uAAE0-' +
'\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABEA\uABEC' +
'\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-' +
'\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D' +
'\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE26\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74' +
'\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-' +
'\uFFD7\uFFDA-\uFFDC]'
);
//Methods
function isIdentifierCh (cp) {
if (cp < 0x80) {
return cp >= 97 && cp <= 122 || // a..z
cp >= 65 && cp <= 90 || // A..Z
cp >= 48 && cp <= 57 || // 0..9
cp === 36 || cp === 95 || // $ (dollar) and _ (underscore)
cp === 92; // \ (backslash)
}
var ch = String.fromCharCode(cp);
return NON_ASCII_IDENTIFIER_CHARACTERS_REGEXP.test(ch);
}
function isLineTerminator (cp) {
return cp === 0x0A || cp === 0x0D || cp === 0x2028 || cp === 0x2029;
}
function isWhitespace (cp) {
return cp === 0x20 || cp === 0x09 || isLineTerminator(cp) || cp === 0x0B || cp === 0x0C || cp === 0xA0 ||
(cp >= 0x1680 && NON_ASCII_WHITESPACES.indexOf(cp) >= 0);
}
function isDecimalDigit (cp) {
return cp >= 48 && cp <= 57;
}
function stringRepeat (str, num) {
var result = '';
for (num |= 0; num > 0; num >>>= 1, str += str) {
if (num & 1) {
result += str;
}
}
return result;
}
isArray = Array.isArray;
if (!isArray) {
isArray = function isArray (array) {
return Object.prototype.toString.call(array) === '[object Array]';
};
}
function updateDeeply (target, override) {
var key, val;
function isHashObject (target) {
return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
}
for (key in override) {
if (override.hasOwnProperty(key)) {
val = override[key];
if (isHashObject(val)) {
if (isHashObject(target[key])) {
updateDeeply(target[key], val);
}
else {
target[key] = updateDeeply({}, val);
}
}
else {
target[key] = val;
}
}
}
return target;
}
function generateNumber (value) {
var result, point, temp, exponent, pos;
if (value === 1 / 0) {
return json$1 ? 'null' : renumber ? '1e400' : '1e+400';
}
result = '' + value;
if (!renumber || result.length < 3) {
return result;
}
point = result.indexOf('.');
//NOTE: 0x30 == '0'
if (!json$1 && result.charCodeAt(0) === 0x30 && point === 1) {
point = 0;
result = result.slice(1);
}
temp = result;
result = result.replace('e+', 'e');
exponent = 0;
if ((pos = temp.indexOf('e')) > 0) {
exponent = +temp.slice(pos + 1);
temp = temp.slice(0, pos);
}
if (point >= 0) {
exponent -= temp.length - point - 1;
temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
}
pos = 0;
//NOTE: 0x30 == '0'
while (temp.charCodeAt(temp.length + pos - 1) === 0x30) {
--pos;
}
if (pos !== 0) {
exponent -= pos;
temp = temp.slice(0, pos);
}
if (exponent !== 0) {
temp += 'e' + exponent;
}
if ((temp.length < result.length ||
(hexadecimal && value > 1e12 && Math.floor(value) === value &&
(temp = '0x' + value.toString(16)).length
< result.length)) &&
+temp === value) {
result = temp;
}
return result;
}
// Generate valid RegExp expression.
// This function is based on https://github.com/Constellation/iv Engine
function escapeRegExpCharacter (ch, previousIsBackslash) {
// not handling '\' and handling \u2028 or \u2029 to unicode escape sequence
if ((ch & ~1) === 0x2028) {
return (previousIsBackslash ? 'u' : '\\u') + ((ch === 0x2028) ? '2028' : '2029');
}
else if (ch === 10 || ch === 13) { // \n, \r
return (previousIsBackslash ? '' : '\\') + ((ch === 10) ? 'n' : 'r');
}
return String.fromCharCode(ch);
}
function generateRegExp (reg) {
var match, result, flags, i, iz, ch, characterInBrack, previousIsBackslash;
result = reg.toString();
if (reg.source) {
// extract flag from toString result
match = result.match(/\/([^/]*)$/);
if (!match) {
return result;
}
flags = match[1];
result = '';
characterInBrack = false;
previousIsBackslash = false;
for (i = 0, iz = reg.source.length; i < iz; ++i) {
ch = reg.source.charCodeAt(i);
if (!previousIsBackslash) {
if (characterInBrack) {
if (ch === 93) { // ]
characterInBrack = false;
}
}
else {
if (ch === 47) { // /
result += '\\';
}
else if (ch === 91) { // [
characterInBrack = true;
}
}
result += escapeRegExpCharacter(ch, previousIsBackslash);
previousIsBackslash = ch === 92; // \
}
else {
// if new RegExp("\\\n') is provided, create /\n/
result += escapeRegExpCharacter(ch, previousIsBackslash);
// prevent like /\\[/]/
previousIsBackslash = false;
}
}
return '/' + result + '/' + flags;
}
return result;
}
function escapeAllowedCharacter (code, next) {
var hex, result = '\\';
switch (code) {
case 0x08: // \b
result += 'b';
break;
case 0x0C: // \f
result += 'f';
break;
case 0x09: // \t
result += 't';
break;
default:
hex = code.toString(16).toUpperCase();
if (json$1 || code > 0xFF) {
result += 'u' + '0000'.slice(hex.length) + hex;
}
else if (code === 0x0000 && !isDecimalDigit(next)) {
result += '0';
}
else if (code === 0x000B) { // \v
result += 'x0B';
}
else {
result += 'x' + '00'.slice(hex.length) + hex;
}
break;
}
return result;
}
function escapeDisallowedCharacter (code) {
var result = '\\';
switch (code) {
case 0x5C // \
:
result += '\\';
break;
case 0x0A // \n
:
result += 'n';
break;
case 0x0D // \r
:
result += 'r';
break;
case 0x2028:
result += 'u2028';
break;
case 0x2029:
result += 'u2029';
break;
}
return result;
}
function escapeDirective (str) {
var i, iz, code, quote;
quote = quotes === 'double' ? '"' : '\'';
for (i = 0, iz = str.length; i < iz; ++i) {
code = str.charCodeAt(i);
if (code === 0x27) { // '
quote = '"';
break;
}
else if (code === 0x22) { // "
quote = '\'';
break;
}
else if (code === 0x5C) { // \
++i;
}
}
return quote + str + quote;
}
function escapeString (str) {
var result = '', i, len, code, singleQuotes = 0, doubleQuotes = 0, single, quote;
//TODO http://jsperf.com/character-counting/8
for (i = 0, len = str.length; i < len; ++i) {
code = str.charCodeAt(i);
if (code === 0x27) { // '
++singleQuotes;
}
else if (code === 0x22) { // "
++doubleQuotes;
}
else if (code === 0x2F && json$1) { // /
result += '\\';
}
else if (isLineTerminator(code) || code === 0x5C) { // \
result += escapeDisallowedCharacter(code);
continue;
}
else if ((json$1 && code < 0x20) || // SP
!(json$1 || escapeless || (code >= 0x20 && code <= 0x7E))) { // SP, ~
result += escapeAllowedCharacter(code, str.charCodeAt(i + 1));
continue;
}
result += String.fromCharCode(code);
}
single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
quote = single ? '\'' : '"';
if (!(single ? singleQuotes : doubleQuotes)) {
return quote + result + quote;
}
str = result;
result = quote;
for (i = 0, len = str.length; i < len; ++i) {
code = str.charCodeAt(i);
if ((code === 0x27 && single) || (code === 0x22 && !single)) { // ', "
result += '\\';
}
result += String.fromCharCode(code);
}
return result + quote;
}
function join (l, r) {
if (!l.length)
return r;
if (!r.length)
return l;
var lCp = l.charCodeAt(l.length - 1),
rCp = r.charCodeAt(0);
if (isIdentifierCh(lCp) && isIdentifierCh(rCp) ||
lCp === rCp && (lCp === 0x2B || lCp === 0x2D) || // + +, - -
lCp === 0x2F && rCp === 0x69) { // /re/ instanceof foo
return l + _.space + r;
}
else if (isWhitespace(lCp) || isWhitespace(rCp))
return l + r;
return l + _.optSpace + r;
}
function shiftIndent () {
var prevIndent = _.indent;
_.indent += _.indentUnit;
return prevIndent;
}
function adoptionPrefix ($stmt) {
if ($stmt.type === Syntax.BlockStatement)
return _.optSpace;
if ($stmt.type === Syntax.EmptyStatement)
return '';
return _.newline + _.indent + _.indentUnit;
}
function adoptionSuffix ($stmt) {
if ($stmt.type === Syntax.BlockStatement)
return _.optSpace;
return _.newline + _.indent;
}
//Subentities generators
function generateVerbatim ($expr, settings) {
var verbatim = $expr[extra.verbatim],
strVerbatim = typeof verbatim === 'string',
precedence = !strVerbatim &&
verbatim.precedence !== void 0 ? verbatim.precedence : Precedence.Sequence,
parenthesize = precedence < settings.precedence,
content = strVerbatim ? verbatim : verbatim.content,
chunks = content.split(/\r\n|\n/),
chunkCount = chunks.length;
if (parenthesize)
_.js += '(';
_.js += chunks[0];
for (var i = 1; i < chunkCount; i++)
_.js += _.newline + _.indent + chunks[i];
if (parenthesize)
_.js += ')';
}
function generateFunctionParams ($node) {
var $params = $node.params,
paramCount = $params.length,
lastParamIdx = paramCount - 1,
arrowFuncWithoutParentheses = $node.type === Syntax.ArrowFunctionExpression && paramCount === 1 &&
$params[0].type === Syntax.Identifier;
//NOTE: arg => { } case
if (arrowFuncWithoutParentheses)
_.js += $params[0].name;
else {
_.js += '(';
for (var i = 0; i < paramCount; ++i) {
var $param = $params[i];
if ($params[i].type === Syntax.Identifier)
_.js += $param.name;
else
ExprGen[$param.type]($param, Preset.e4);
if (i !== lastParamIdx)
_.js += ',' + _.optSpace;
}
_.js += ')';
}
}
function generateFunctionBody ($node) {
var $body = $node.body;
generateFunctionParams($node);
if ($node.type === Syntax.ArrowFunctionExpression)
_.js += _.optSpace + '=>';
if ($node.expression) {
_.js += _.optSpace;
var exprJs = exprToJs($body, Preset.e4);
if (exprJs.charAt(0) === '{')
exprJs = '(' + exprJs + ')';
_.js += exprJs;
}
else {
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s8);
}
}
//-------------------------------------------------===------------------------------------------------------
// Syntactic entities generation presets
//-------------------------------------------------===------------------------------------------------------
var Preset = {
e1: function (allowIn) {
return {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
};
},
e2: function (allowIn) {
return {
precedence: Precedence.LogicalOR,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
};
},
e3: {
precedence: Precedence.Call,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: false
},
e4: {
precedence: Precedence.Assignment,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e5: {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e6: function (allowUnparenthesizedNew) {
return {
precedence: Precedence.New,
allowIn: true,
allowCall: false,
allowUnparenthesizedNew: allowUnparenthesizedNew
};
},
e7: {
precedence: Precedence.Unary,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e8: {
precedence: Precedence.Postfix,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e9: {
precedence: void 0,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e10: {
precedence: Precedence.Call,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e11: function (allowCall) {
return {
precedence: Precedence.Call,
allowIn: true,
allowCall: allowCall,
allowUnparenthesizedNew: false
};
},
e12: {
precedence: Precedence.Primary,
allowIn: false,
allowCall: false,
allowUnparenthesizedNew: true
},
e13: {
precedence: Precedence.Primary,
allowIn: true,
allowCall: true,
allowUnparenthesizedNew: true
},
e14: {
precedence: Precedence.Sequence,
allowIn: false,
allowCall: true,
allowUnparenthesizedNew: true
},
e15: function (allowCall) {
return {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: allowCall,
allowUnparenthesizedNew: true
};
},
e16: function (precedence, allowIn) {
return {
precedence: precedence,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
};
},
e17: function (allowIn) {
return {
precedence: Precedence.Call,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
}
},
e18: function (allowIn) {
return {
precedence: Precedence.Assignment,
allowIn: allowIn,
allowCall: true,
allowUnparenthesizedNew: true
}
},
e19: {
precedence: Precedence.Sequence,
allowIn: true,
allowCall: true,
semicolonOptional: false
},
e20: {
precedence: Precedence.Await,
allowCall: true
},
s1: function (functionBody, semicolonOptional) {
return {
allowIn: true,
functionBody: false,
directiveContext: functionBody,
semicolonOptional: semicolonOptional
};
},
s2: {
allowIn: true,
functionBody: false,
directiveContext: false,
semicolonOptional: true
},
s3: function (allowIn) {
return {
allowIn: allowIn,
functionBody: false,
directiveContext: false,
semicolonOptional: false
};
},
s4: function (semicolonOptional) {
return {
allowIn: true,
functionBody: false,
directiveContext: false,
semicolonOptional: semicolonOptional
};
},
s5: function (semicolonOptional) {
return {
allowIn: true,
functionBody: false,
directiveContext: true,
semicolonOptional: semicolonOptional,
};
},
s6: {
allowIn: false,
functionBody: false,
directiveContext: false,
semicolonOptional: false
},
s7: {
allowIn: true,
functionBody: false,
directiveContext: false,
semicolonOptional: false
},
s8: {
allowIn: true,
functionBody: true,
directiveContext: false,
semicolonOptional: false
}
};
//-------------------------------------------------===-------------------------------------------------------
// Expressions
//-------------------------------------------------===-------------------------------------------------------
//Regular expressions
var FLOATING_OR_OCTAL_REGEXP = /[.eExX]|^0[0-9]+/,
LAST_DECIMAL_DIGIT_REGEXP = /[0-9]$/;
//Common expression generators
function isLogicalExpression(node) {
if (!node)
return false;
return node.type === Syntax.LogicalExpression;
}
function needParensForLogicalExpression (node, parent) {
switch (node.operator) {
case "||":
if (!isLogicalExpression(parent)) return false;
return parent.operator === "??" || parent.operator === "&&";
case "&&":
return isLogicalExpression(parent);
case "??":
return isLogicalExpression(parent) && parent.operator !== "??";
}
}
function generateLogicalOrBinaryExpression ($expr, settings, $parent) {
var op = $expr.operator,
precedence = BinaryPrecedence[$expr.operator],
parenthesize = precedence < settings.precedence,
allowIn = settings.allowIn || parenthesize,
operandGenSettings = Preset.e16(precedence, allowIn),
exprJs = exprToJs($expr.left, operandGenSettings, $expr);
parenthesize |= op === 'in' && !allowIn;
var needParens = needParensForLogicalExpression($expr, $parent);
if (parenthesize || needParens)
_.js += '(';
// 0x2F = '/'
if (exprJs.charCodeAt(exprJs.length - 1) === 0x2F && isIdentifierCh(op.charCodeAt(0)))
exprJs = exprJs + _.space + op;
else
exprJs = join(exprJs, op);
operandGenSettings.precedence++;
var rightJs = exprToJs($expr.right, operandGenSettings, $expr);
//NOTE: If '/' concats with '/' or `<` concats with `!--`, it is interpreted as comment start
if (op === '/' && rightJs.charAt(0) === '/' || op.slice(-1) === '<' && rightJs.slice(0, 3) === '!--')
exprJs += _.space + rightJs;
else
exprJs = join(exprJs, rightJs);
_.js += exprJs;
if (parenthesize || needParens)
_.js += ')';
}
function generateArrayPatternOrExpression ($expr) {
var $elems = $expr.elements,
elemCount = $elems.length;
if (elemCount) {
var lastElemIdx = elemCount - 1,
multiline = elemCount > 1,
prevIndent = shiftIndent(),
itemPrefix = _.newline + _.indent;
_.js += '[';
for (var i = 0; i < elemCount; i++) {
var $elem = $elems[i];
if (multiline)
_.js += itemPrefix;
if ($elem)
ExprGen[$elem.type]($elem, Preset.e4);
if (i !== lastElemIdx || !$elem)
_.js += ',';
}
_.indent = prevIndent;
if (multiline)
_.js += _.newline + _.indent;
_.js += ']';
}
else
_.js += '[]';
}
function generateGeneratorOrComprehensionExpression ($expr) {
//NOTE: GeneratorExpression should be parenthesized with (...), ComprehensionExpression with [...]
var $blocks = $expr.blocks,
$filter = $expr.filter,
isGenerator = $expr.type === Syntax.GeneratorExpression,
exprJs = isGenerator ? '(' : '[',
bodyJs = exprToJs($expr.body, Preset.e4);
if ($blocks) {
var prevIndent = shiftIndent(),
blockCount = $blocks.length;
for (var i = 0; i < blockCount; ++i) {
var blockJs = exprToJs($blocks[i], Preset.e5);
exprJs = i > 0 ? join(exprJs, blockJs) : (exprJs + blockJs);
}
_.indent = prevIndent;
}
if ($filter) {
var filterJs = exprToJs($filter, Preset.e5);
exprJs = join(exprJs, 'if' + _.optSpace);
exprJs = join(exprJs, '(' + filterJs + ')');
}
exprJs = join(exprJs, bodyJs);
exprJs += isGenerator ? ')' : ']';
_.js += exprJs;
}
//Expression raw generator dictionary
var ExprRawGen = {
SequenceExpression: function generateSequenceExpression ($expr, settings) {
var $children = $expr.expressions,
childrenCount = $children.length,
lastChildIdx = childrenCount - 1,
parenthesize = Precedence.Sequence < settings.precedence,
exprGenSettings = Preset.e1(settings.allowIn || parenthesize);
if (parenthesize)
_.js += '(';
for (var i = 0; i < childrenCount; i++) {
var $child = $children[i];
ExprGen[$child.type]($child, exprGenSettings);
if (i !== lastChildIdx)
_.js += ',' + _.optSpace;
}
if (parenthesize)
_.js += ')';
},
AssignmentExpression: function generateAssignmentExpression ($expr, settings) {
var $left = $expr.left,
$right = $expr.right,
parenthesize = Precedence.Assignment < settings.precedence,
allowIn = settings.allowIn || parenthesize;
if (parenthesize)
_.js += '(';
ExprGen[$left.type]($left, Preset.e17(allowIn));
_.js += _.optSpace + $expr.operator + _.optSpace;
ExprGen[$right.type]($right, Preset.e18(allowIn));
if (parenthesize)
_.js += ')';
},
AssignmentPattern: function generateAssignmentPattern ($node) {
var $fakeAssign = {
left: $node.left,
right: $node.right,
operator: '='
};
ExprGen.AssignmentExpression($fakeAssign, Preset.e4);
},
ArrowFunctionExpression: function generateArrowFunctionExpression ($expr, settings) {
var parenthesize = Precedence.ArrowFunction < settings.precedence;
if (parenthesize)
_.js += '(';
if ($expr.async)
_.js += 'async ';
generateFunctionBody($expr);
if (parenthesize)
_.js += ')';
},
AwaitExpression: function generateAwaitExpression ($expr, settings) {
var parenthesize = Precedence.Await < settings.precedence;
if (parenthesize)
_.js += '(';
_.js += $expr.all ? 'await* ' : 'await ';
ExprGen[$expr.argument.type]($expr.argument, Preset.e20);
if (parenthesize)
_.js += ')';
},
ConditionalExpression: function generateConditionalExpression ($expr, settings) {
var $test = $expr.test,
$conseq = $expr.consequent,
$alt = $expr.alternate,
parenthesize = Precedence.Conditional < settings.precedence,
allowIn = settings.allowIn || parenthesize,
testGenSettings = Preset.e2(allowIn),
branchGenSettings = Preset.e1(allowIn);
if (parenthesize)
_.js += '(';
ExprGen[$test.type]($test, testGenSettings);
_.js += _.optSpace + '?' + _.optSpace;
ExprGen[$conseq.type]($conseq, branchGenSettings);
_.js += _.optSpace + ':' + _.optSpace;
ExprGen[$alt.type]($alt, branchGenSettings);
if (parenthesize)
_.js += ')';
},
LogicalExpression: generateLogicalOrBinaryExpression,
BinaryExpression: generateLogicalOrBinaryExpression,
CallExpression: function generateCallExpression ($expr, settings) {
var $callee = $expr.callee,
$args = $expr['arguments'],
argCount = $args.length,
lastArgIdx = argCount - 1,
parenthesize = !settings.allowCall || Precedence.Call < settings.precedence;
if (parenthesize)
_.js += '(';
ExprGen[$callee.type]($callee, Preset.e3);
if ($expr.optional)
_.js += '?.';
_.js += '(';
for (var i = 0; i < argCount; ++i) {
var $arg = $args[i];
ExprGen[$arg.type]($arg, Preset.e4);
if (i !== lastArgIdx)
_.js += ',' + _.optSpace;
}
_.js += ')';
if (parenthesize)
_.js += ')';
},
NewExpression: function generateNewExpression ($expr, settings) {
var $args = $expr['arguments'],
parenthesize = Precedence.New < settings.precedence,
argCount = $args.length,
lastArgIdx = argCount - 1,
withCall = !settings.allowUnparenthesizedNew || parentheses || argCount > 0,
calleeJs = exprToJs($expr.callee, Preset.e6(!withCall));
if (parenthesize)
_.js += '(';
_.js += join('new', calleeJs);
if (withCall) {
_.js += '(';
for (var i = 0; i < argCount; ++i) {
var $arg = $args[i];
ExprGen[$arg.type]($arg, Preset.e4);
if (i !== lastArgIdx)
_.js += ',' + _.optSpace;
}
_.js += ')';
}
if (parenthesize)
_.js += ')';
},
MemberExpression: function generateMemberExpression ($expr, settings) {
var $obj = $expr.object,
$prop = $expr.property,
parenthesize = Precedence.Member < settings.precedence,
isNumObj = !$expr.computed && $obj.type === Syntax.Literal && typeof $obj.value === 'number';
if (parenthesize)
_.js += '(';
if (isNumObj) {
//NOTE: When the following conditions are all true:
// 1. No floating point
// 2. Don't have exponents
// 3. The last character is a decimal digit
// 4. Not hexadecimal OR octal number literal
// then we should add a floating point.
var numJs = exprToJs($obj, Preset.e11(settings.allowCall)),
withPoint = LAST_DECIMAL_DIGIT_REGEXP.test(numJs) && !FLOATING_OR_OCTAL_REGEXP.test(numJs);
_.js += withPoint ? (numJs + '.') : numJs;
}
else
ExprGen[$obj.type]($obj, Preset.e11(settings.allowCall));
if ($expr.computed) {
if ($expr.optional)
_.js += '?.';
_.js += '[';
ExprGen[$prop.type]($prop, Preset.e15(settings.allowCall));
_.js += ']';
}
else
_.js += ($expr.optional ? '?.' : '.') + $prop.name;
if (parenthesize)
_.js += ')';
},
UnaryExpression: function generateUnaryExpression ($expr, settings) {
var parenthesize = Precedence.Unary < settings.precedence,
op = $expr.operator,
argJs = exprToJs($expr.argument, Preset.e7);
if (parenthesize)
_.js += '(';
//NOTE: delete, void, typeof
// get `typeof []`, not `typeof[]`
if (_.optSpace === '' || op.length > 2)
_.js += join(op, argJs);
else {
_.js += op;
//NOTE: Prevent inserting spaces between operator and argument if it is unnecessary
// like, `!cond`
var leftCp = op.charCodeAt(op.length - 1),
rightCp = argJs.charCodeAt(0);
// 0x2B = '+', 0x2D = '-'
if (leftCp === rightCp && (leftCp === 0x2B || leftCp === 0x2D) ||
isIdentifierCh(leftCp) && isIdentifierCh(rightCp)) {
_.js += _.space;
}
_.js += argJs;
}
if (parenthesize)
_.js += ')';
},
YieldExpression: function generateYieldExpression ($expr, settings) {
var $arg = $expr.argument,
js = $expr.delegate ? 'yield*' : 'yield',
parenthesize = Precedence.Yield < settings.precedence;
if (parenthesize)
_.js += '(';
if ($arg) {
var argJs = exprToJs($arg, Preset.e4);
js = join(js, argJs);
}
_.js += js;
if (parenthesize)
_.js += ')';
},
UpdateExpression: function generateUpdateExpression ($expr, settings) {
var $arg = $expr.argument,
$op = $expr.operator,
prefix = $expr.prefix,
precedence = prefix ? Precedence.Unary : Precedence.Postfix,
parenthesize = precedence < settings.precedence;
if (parenthesize)
_.js += '(';
if (prefix) {
_.js += $op;
ExprGen[$arg.type]($arg, Preset.e8);
}
else {
ExprGen[$arg.type]($arg, Preset.e8);
_.js += $op;
}
if (parenthesize)
_.js += ')';
},
FunctionExpression: function generateFunctionExpression ($expr) {
var isGenerator = !!$expr.generator;
if ($expr.async)
_.js += 'async ';
_.js += isGenerator ? 'function*' : 'function';
if ($expr.id) {
_.js += isGenerator ? _.optSpace : _.space;
_.js += $expr.id.name;
}
else
_.js += _.optSpace;
generateFunctionBody($expr);
},
ExportBatchSpecifier: function generateExportBatchSpecifier () {
_.js += '*';
},
ArrayPattern: generateArrayPatternOrExpression,
ArrayExpression: generateArrayPatternOrExpression,
ClassExpression: function generateClassExpression ($expr) {
var $id = $expr.id,
$super = $expr.superClass,
$body = $expr.body,
exprJs = 'class';
if ($id) {
var idJs = exprToJs($id, Preset.e9);
exprJs = join(exprJs, idJs);
}
if ($super) {
var superJs = exprToJs($super, Preset.e4);
superJs = join('extends', superJs);
exprJs = join(exprJs, superJs);
}
_.js += exprJs + _.optSpace;
StmtGen[$body.type]($body, Preset.s2);
},
MetaProperty: function generateMetaProperty ($expr, settings) {
var $meta = $expr.meta,
$property = $expr.property,
parenthesize = Precedence.Member < settings.precedence;
if (parenthesize)
_.js += '(';
_.js += (typeof $meta === "string" ? $meta : $meta.name) +
'.' + (typeof $property === "string" ? $property : $property.name);
if (parenthesize)
_.js += ')';
},
MethodDefinition: function generateMethodDefinition ($expr) {
var exprJs = $expr['static'] ? 'static' + _.optSpace : '',
keyJs = exprToJs($expr.key, Preset.e5);
if ($expr.computed)
keyJs = '[' + keyJs + ']';
if ($expr.kind === 'get' || $expr.kind === 'set') {
keyJs = join($expr.kind, keyJs);
_.js += join(exprJs, keyJs);
}
else {
if ($expr.value.generator)
_.js += exprJs + '*' + keyJs;
else if ($expr.value.async)
_.js += exprJs + 'async ' + keyJs;
else
_.js += join(exprJs, keyJs);
}
generateFunctionBody($expr.value);
},
Property: function generateProperty ($expr) {
var $val = $expr.value,
$kind = $expr.kind,
keyJs = exprToJs($expr.key, Preset.e4);
if ($expr.computed)
keyJs = '[' + keyJs + ']';
if ($kind === 'get' || $kind === 'set') {
_.js += $kind + _.space + keyJs;
generateFunctionBody($val);
}
else {
if ($expr.shorthand)
_.js += keyJs;
else if ($expr.method) {
if ($val.generator)
keyJs = '*' + keyJs;
else if ($val.async)
keyJs = 'async ' + keyJs;
_.js += keyJs;
generateFunctionBody($val);
}
else {
_.js += keyJs + ':' + _.optSpace;
ExprGen[$val.type]($val, Preset.e4);
}
}
},
ObjectExpression: function generateObjectExpression ($expr) {
var $props = $expr.properties,
propCount = $props.length;
if (propCount) {
var lastPropIdx = propCount - 1,
prevIndent = shiftIndent();
_.js += '{';
for (var i = 0; i < propCount; i++) {
var $prop = $props[i],
propType = $prop.type || Syntax.Property;
_.js += _.newline + _.indent;
ExprGen[propType]($prop, Preset.e5);
if (i !== lastPropIdx)
_.js += ',';
}
_.indent = prevIndent;
_.js += _.newline + _.indent + '}';
}
else
_.js += '{}';
},
ObjectPattern: function generateObjectPattern ($expr) {
var $props = $expr.properties,
propCount = $props.length;
if (propCount) {
var lastPropIdx = propCount - 1,
multiline = false;
if (propCount === 1)
multiline = $props[0].value.type !== Syntax.Identifier;
else {
for (var i = 0; i < propCount; i++) {
if (!$props[i].shorthand) {
multiline = true;
break;
}
}
}
_.js += multiline ? ('{' + _.newline) : '{';
var prevIndent = shiftIndent(),
propSuffix = ',' + (multiline ? _.newline : _.optSpace);
for (var i = 0; i < propCount; i++) {
var $prop = $props[i];
if (multiline)
_.js += _.indent;
ExprGen[$prop.type]($prop, Preset.e5);
if (i !== lastPropIdx)
_.js += propSuffix;
}
_.indent = prevIndent;
_.js += multiline ? (_.newline + _.indent + '}') : '}';
}
else
_.js += '{}';
},
ThisExpression: function generateThisExpression () {
_.js += 'this';
},
Identifier: function generateIdentifier ($expr, precedence, flag) {
_.js += $expr.name;
},
ImportExpression: function generateImportExpression ($expr, settings) {
var parenthesize = Precedence.Call < settings.precedence;
var $source = $expr.source;
if (parenthesize)
_.js += '(';
_.js += 'import(';
ExprGen[$source.type]($source, Preset.e4);
_.js += ')';
if (parenthesize)
_.js += ')';
},
ImportSpecifier: function generateImportSpecifier ($expr) {
_.js += $expr.imported.name;
if ($expr.local)
_.js += _.space + 'as' + _.space + $expr.local.name;
},
ExportSpecifier: function generateImportOrExportSpecifier ($expr) {
_.js += $expr.local.name;
if ($expr.exported)
_.js += _.space + 'as' + _.space + $expr.exported.name;
},
ChainExpression: function generateChainExpression ($expr, settings) {
var parenthesize = Precedence.OptionalChaining < settings.precedence;
var $expression = $expr.expression;
settings = settings || {};
var newSettings = {
precedence: Precedence.OptionalChaining,
allowIn: settings.allowIn ,
allowCall: settings.allowCall,
allowUnparenthesizedNew: settings.allowUnparenthesizedNew
};
if (parenthesize) {
newSettings.allowCall = true;
_.js += '(';
}
ExprGen[$expression.type]($expression, newSettings);
if (parenthesize)
_.js += ')';
},
Literal: function generateLiteral ($expr) {
if (extra.raw && $expr.raw !== void 0)
_.js += $expr.raw;
else if ($expr.value === null)
_.js += 'null';
else {
var valueType = typeof $expr.value;
if (valueType === 'string')
_.js += escapeString($expr.value);
else if (valueType === 'number')
_.js += generateNumber($expr.value);
else if (valueType === 'boolean')
_.js += $expr.value ? 'true' : 'false';
else
_.js += generateRegExp($expr.value);
}
},
GeneratorExpression: generateGeneratorOrComprehensionExpression,
ComprehensionExpression: generateGeneratorOrComprehensionExpression,
ComprehensionBlock: function generateComprehensionBlock ($expr) {
var $left = $expr.left,
leftJs = void 0,
rightJs = exprToJs($expr.right, Preset.e5);
if ($left.type === Syntax.VariableDeclaration)
leftJs = $left.kind + _.space + stmtToJs($left.declarations[0], Preset.s6);
else
leftJs = exprToJs($left, Preset.e10);
leftJs = join(leftJs, $expr.of ? 'of' : 'in');
_.js += 'for' + _.optSpace + '(' + join(leftJs, rightJs) + ')';
},
RestElement: function generateRestElement ($node) {
_.js += '...' + $node.argument.name;
},
SpreadElement: function generateSpreadElement ($expr) {
var $arg = $expr.argument;
_.js += '...';
ExprGen[$arg.type]($arg, Preset.e4);
},
TaggedTemplateExpression: function generateTaggedTemplateExpression ($expr, settings) {
var $tag = $expr.tag,
$quasi = $expr.quasi,
parenthesize = Precedence.TaggedTemplate < settings.precedence;
if (parenthesize)
_.js += '(';
ExprGen[$tag.type]($tag, Preset.e11(settings.allowCall));
ExprGen[$quasi.type]($quasi, Preset.e12);
if (parenthesize)
_.js += ')';
},
TemplateElement: function generateTemplateElement ($expr) {
//NOTE: Don't use "cooked". Since tagged template can use raw template
// representation. So if we do so, it breaks the script semantics.
_.js += $expr.value.raw;
},
TemplateLiteral: function generateTemplateLiteral ($expr) {
var $quasis = $expr.quasis,
$childExprs = $expr.expressions,
quasiCount = $quasis.length,
lastQuasiIdx = quasiCount - 1;
_.js += '`';
for (var i = 0; i < quasiCount; ++i) {
var $quasi = $quasis[i];
ExprGen[$quasi.type]($quasi, Preset.e13);
if (i !== lastQuasiIdx) {
var $childExpr = $childExprs[i];
_.js += '${' + _.optSpace;
ExprGen[$childExpr.type]($childExpr, Preset.e5);
_.js += _.optSpace + '}';
}
}
_.js += '`';
},
Super: function generateSuper () {
_.js += 'super';
}
};
//-------------------------------------------------===------------------------------------------------------
// Statements
//-------------------------------------------------===------------------------------------------------------
//Regular expressions
var EXPR_STMT_UNALLOWED_EXPR_REGEXP = /^{|^class(?:\s|{)|^(async )?function(?:\s|\*|\()/;
//Common statement generators
function generateTryStatementHandlers (stmtJs, $finalizer, handlers) {
var handlerCount = handlers.length,
lastHandlerIdx = handlerCount - 1;
for (var i = 0; i < handlerCount; ++i) {
var handlerJs = stmtToJs(handlers[i], Preset.s7);
stmtJs = join(stmtJs, handlerJs);
if ($finalizer || i !== lastHandlerIdx)
stmtJs += adoptionSuffix(handlers[i].body);
}
return stmtJs;
}
function generateForStatementIterator ($op, $stmt, settings) {
var $body = $stmt.body,
$left = $stmt.left,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent1 = shiftIndent(),
awaitStr = $stmt.await ? ' await' : '',
stmtJs = 'for' + awaitStr + _.optSpace + '(';
if ($left.type === Syntax.VariableDeclaration) {
var prevIndent2 = shiftIndent();
stmtJs += $left.kind + _.space + stmtToJs($left.declarations[0], Preset.s6);
_.indent = prevIndent2;
}
else
stmtJs += exprToJs($left, Preset.e10);
stmtJs = join(stmtJs, $op);
var rightJs = exprToJs($stmt.right, Preset.e4);
stmtJs = join(stmtJs, rightJs) + ')';
_.indent = prevIndent1;
_.js += stmtJs + adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
}
//Statement generator dictionary
var StmtRawGen = {
BlockStatement: function generateBlockStatement ($stmt, settings) {
var $body = $stmt.body,
len = $body.length,
lastIdx = len - 1,
prevIndent = shiftIndent();
_.js += '{' + _.newline;
for (var i = 0; i < len; i++) {
var $item = $body[i];
_.js += _.indent;
StmtGen[$item.type]($item, Preset.s1(settings.functionBody, i === lastIdx));
_.js += _.newline;
}
_.indent = prevIndent;
_.js += _.indent + '}';
},
BreakStatement: function generateBreakStatement ($stmt, settings) {
if ($stmt.label)
_.js += 'break ' + $stmt.label.name;
else
_.js += 'break';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
ContinueStatement: function generateContinueStatement ($stmt, settings) {
if ($stmt.label)
_.js += 'continue ' + $stmt.label.name;
else
_.js += 'continue';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
ClassBody: function generateClassBody ($stmt) {
var $body = $stmt.body,
itemCount = $body.length,
lastItemIdx = itemCount - 1,
prevIndent = shiftIndent();
_.js += '{' + _.newline;
for (var i = 0; i < itemCount; i++) {
var $item = $body[i],
itemType = $item.type || Syntax.Property;
_.js += _.indent;
ExprGen[itemType]($item, Preset.e5);
if (i !== lastItemIdx)
_.js += _.newline;
}
_.indent = prevIndent;
_.js += _.newline + _.indent + '}';
},
ClassDeclaration: function generateClassDeclaration ($stmt) {
var $body = $stmt.body,
$super = $stmt.superClass,
js = 'class ' + $stmt.id.name;
if ($super) {
var superJs = exprToJs($super, Preset.e4);
js += _.space + join('extends', superJs);
}
_.js += js + _.optSpace;
StmtGen[$body.type]($body, Preset.s2);
},
DirectiveStatement: function generateDirectiveStatement ($stmt, settings) {
if (extra.raw && $stmt.raw)
_.js += $stmt.raw;
else
_.js += escapeDirective($stmt.directive);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
DoWhileStatement: function generateDoWhileStatement ($stmt, settings) {
var $body = $stmt.body,
$test = $stmt.test,
bodyJs = adoptionPrefix($body) +
stmtToJs($body, Preset.s7) +
adoptionSuffix($body);
//NOTE: Because `do 42 while (cond)` is Syntax Error. We need semicolon.
var stmtJs = join('do', bodyJs);
_.js += join(stmtJs, 'while' + _.optSpace + '(');
ExprGen[$test.type]($test, Preset.e5);
_.js += ')';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
CatchClause: function generateCatchClause ($stmt) {
var $param = $stmt.param,
$guard = $stmt.guard,
$body = $stmt.body,
prevIndent = shiftIndent();
_.js += 'catch' + _.optSpace;
if ($param) {
_.js += '(';
ExprGen[$param.type]($param, Preset.e5);
}
if ($guard) {
_.js += ' if ';
ExprGen[$guard.type]($guard, Preset.e5);
}
_.indent = prevIndent;
if ($param) {
_.js += ')';
}
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s7);
},
DebuggerStatement: function generateDebuggerStatement ($stmt, settings) {
_.js += 'debugger';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
EmptyStatement: function generateEmptyStatement () {
_.js += ';';
},
ExportAllDeclaration: function ($stmt, settings) {
StmtRawGen.ExportDeclaration($stmt, settings, true);
},
ExportDeclaration: function generateExportDeclaration ($stmt, settings, exportAll) {
var $specs = $stmt.specifiers,
$decl = $stmt.declaration,
withSemicolon = semicolons || !settings.semicolonOptional;
// export default AssignmentExpression[In] ;
if ($stmt['default']) {
var declJs = exprToJs($decl, Preset.e4);
_.js += join('export default', declJs);
if (withSemicolon)
_.js += ';';
}
// export * FromClause ;
// export ExportClause[NoReference] FromClause ;
// export ExportClause ;
else if ($specs || exportAll) {
var stmtJs = 'export';
if (exportAll)
stmtJs += _.optSpace + '*';
else if ($specs.length === 0)
stmtJs += _.optSpace + '{' + _.optSpace + '}';
else if ($specs[0].type === Syntax.ExportBatchSpecifier) {
var specJs = exprToJs($specs[0], Preset.e5);
stmtJs = join(stmtJs, specJs);
}
else {
var prevIndent = shiftIndent(),
specCount = $specs.length,
lastSpecIdx = specCount - 1;
stmtJs += _.optSpace + '{';
for (var i = 0; i < specCount; ++i) {
stmtJs += _.newline + _.indent;
stmtJs += exprToJs($specs[i], Preset.e5);
if (i !== lastSpecIdx)
stmtJs += ',';
}
_.indent = prevIndent;
stmtJs += _.newline + _.indent + '}';
}
if ($stmt.source) {
_.js += join(stmtJs, 'from' + _.optSpace);
ExprGen.Literal($stmt.source);
}
else
_.js += stmtJs;
if (withSemicolon)
_.js += ';';
}
// export VariableStatement
// export Declaration[Default]
else if ($decl) {
var declJs = stmtToJs($decl, Preset.s4(!withSemicolon));
_.js += join('export', declJs);
}
},
ExportNamedDeclaration: function ($stmt, settings) {
StmtRawGen.ExportDeclaration($stmt, settings);
},
ExpressionStatement: function generateExpressionStatement ($stmt, settings) {
var exprJs = exprToJs($stmt.expression, Preset.e5),
parenthesize = EXPR_STMT_UNALLOWED_EXPR_REGEXP.test(exprJs) ||
(directive &&
settings.directiveContext &&
$stmt.expression.type === Syntax.Literal &&
typeof $stmt.expression.value === 'string');
//NOTE: '{', 'function', 'class' are not allowed in expression statement.
// Therefore, they should be parenthesized.
if (parenthesize)
_.js += '(' + exprJs + ')';
else
_.js += exprJs;
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
ImportDeclaration: function generateImportDeclaration ($stmt, settings) {
var $specs = $stmt.specifiers,
stmtJs = 'import',
specCount = $specs.length;
//NOTE: If no ImportClause is present,
// this should be `import ModuleSpecifier` so skip `from`
// ModuleSpecifier is StringLiteral.
if (specCount) {
var hasBinding = !!$specs[0]['default'],
firstNamedIdx = hasBinding ? 1 : 0,
lastSpecIdx = specCount - 1;
// ImportedBinding
if (hasBinding)
stmtJs = join(stmtJs, $specs[0].id.name);
// NamedImports
if (firstNamedIdx < specCount) {
if (hasBinding)
stmtJs += ',';
stmtJs += _.optSpace + '{';
// import { ... } from "...";
if (firstNamedIdx === lastSpecIdx)
stmtJs += _.optSpace + exprToJs($specs[firstNamedIdx], Preset.e5) + _.optSpace;
else {
var prevIndent = shiftIndent();
// import {
// ...,
// ...,
// } from "...";
for (var i = firstNamedIdx; i < specCount; i++) {
stmtJs += _.newline + _.indent + exprToJs($specs[i], Preset.e5);
if (i !== lastSpecIdx)
stmtJs += ',';
}
_.indent = prevIndent;
stmtJs += _.newline + _.indent;
}
stmtJs += '}' + _.optSpace;
}
stmtJs = join(stmtJs, 'from');
}
_.js += stmtJs + _.optSpace;
ExprGen.Literal($stmt.source);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
VariableDeclarator: function generateVariableDeclarator ($stmt, settings) {
var $id = $stmt.id,
$init = $stmt.init,
genSettings = Preset.e1(settings.allowIn);
if ($init) {
ExprGen[$id.type]($id, genSettings);
_.js += _.optSpace + '=' + _.optSpace;
ExprGen[$init.type]($init, genSettings, $stmt);
}
else {
if ($id.type === Syntax.Identifier)
_.js += $id.name;
else
ExprGen[$id.type]($id, genSettings);
}
},
VariableDeclaration: function generateVariableDeclaration ($stmt, settings) {
var $decls = $stmt.declarations,
len = $decls.length,
prevIndent = len > 1 ? shiftIndent() : _.indent,
declGenSettings = Preset.s3(settings.allowIn);
_.js += $stmt.kind;
for (var i = 0; i < len; i++) {
var $decl = $decls[i];
_.js += i === 0 ? _.space : (',' + _.optSpace);
StmtGen[$decl.type]($decl, declGenSettings);
}
if (semicolons || !settings.semicolonOptional)
_.js += ';';
_.indent = prevIndent;
},
ThrowStatement: function generateThrowStatement ($stmt, settings) {
var argJs = exprToJs($stmt.argument, Preset.e5);
_.js += join('throw', argJs);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
TryStatement: function generateTryStatement ($stmt) {
var $block = $stmt.block,
$finalizer = $stmt.finalizer,
stmtJs = 'try' +
adoptionPrefix($block) +
stmtToJs($block, Preset.s7) +
adoptionSuffix($block);
var $handlers = $stmt.handlers || $stmt.guardedHandlers;
if ($handlers)
stmtJs = generateTryStatementHandlers(stmtJs, $finalizer, $handlers);
if ($stmt.handler) {
$handlers = isArray($stmt.handler) ? $stmt.handler : [$stmt.handler];
stmtJs = generateTryStatementHandlers(stmtJs, $finalizer, $handlers);
}
if ($finalizer) {
stmtJs = join(stmtJs, 'finally' + adoptionPrefix($finalizer));
stmtJs += stmtToJs($finalizer, Preset.s7);
}
_.js += stmtJs;
},
SwitchStatement: function generateSwitchStatement ($stmt) {
var $cases = $stmt.cases,
$discr = $stmt.discriminant,
prevIndent = shiftIndent();
_.js += 'switch' + _.optSpace + '(';
ExprGen[$discr.type]($discr, Preset.e5);
_.js += ')' + _.optSpace + '{' + _.newline;
_.indent = prevIndent;
if ($cases) {
var caseCount = $cases.length,
lastCaseIdx = caseCount - 1;
for (var i = 0; i < caseCount; i++) {
var $case = $cases[i];
_.js += _.indent;
StmtGen[$case.type]($case, Preset.s4(i === lastCaseIdx));
_.js += _.newline;
}
}
_.js += _.indent + '}';
},
SwitchCase: function generateSwitchCase ($stmt, settings) {
var $conseqs = $stmt.consequent,
$firstConseq = $conseqs[0],
$test = $stmt.test,
i = 0,
conseqSemicolonOptional = !semicolons && settings.semicolonOptional,
conseqCount = $conseqs.length,
lastConseqIdx = conseqCount - 1,
prevIndent = shiftIndent();
if ($test) {
var testJs = exprToJs($test, Preset.e5);
_.js += join('case', testJs) + ':';
}
else
_.js += 'default:';
if (conseqCount && $firstConseq.type === Syntax.BlockStatement) {
i++;
_.js += adoptionPrefix($firstConseq);
StmtGen[$firstConseq.type]($firstConseq, Preset.s7);
}
for (; i < conseqCount; i++) {
var $conseq = $conseqs[i],
semicolonOptional = i === lastConseqIdx && conseqSemicolonOptional;
_.js += _.newline + _.indent;
StmtGen[$conseq.type]($conseq, Preset.s4(semicolonOptional));
}
_.indent = prevIndent;
},
IfStatement: function generateIfStatement ($stmt, settings) {
var $conseq = $stmt.consequent,
$test = $stmt.test,
prevIndent = shiftIndent(),
semicolonOptional = !semicolons && settings.semicolonOptional;
_.js += 'if' + _.optSpace + '(';
ExprGen[$test.type]($test, Preset.e5);
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($conseq);
if ($stmt.alternate) {
var conseq = stmtToJs($conseq, Preset.s7) + adoptionSuffix($conseq),
alt = stmtToJs($stmt.alternate, Preset.s4(semicolonOptional));
if ($stmt.alternate.type === Syntax.IfStatement)
alt = 'else ' + alt;
else
alt = join('else', adoptionPrefix($stmt.alternate) + alt);
_.js += join(conseq, alt);
}
else
StmtGen[$conseq.type]($conseq, Preset.s4(semicolonOptional));
},
ForStatement: function generateForStatement ($stmt, settings) {
var $init = $stmt.init,
$test = $stmt.test,
$body = $stmt.body,
$update = $stmt.update,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = shiftIndent();
_.js += 'for' + _.optSpace + '(';
if ($init) {
if ($init.type === Syntax.VariableDeclaration)
StmtGen[$init.type]($init, Preset.s6);
else {
ExprGen[$init.type]($init, Preset.e14);
_.js += ';';
}
}
else
_.js += ';';
if ($test) {
_.js += _.optSpace;
ExprGen[$test.type]($test, Preset.e5);
}
_.js += ';';
if ($update) {
_.js += _.optSpace;
ExprGen[$update.type]($update, Preset.e5);
}
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
},
ForInStatement: function generateForInStatement ($stmt, settings) {
generateForStatementIterator('in', $stmt, settings);
},
ForOfStatement: function generateForOfStatement ($stmt, settings) {
generateForStatementIterator('of', $stmt, settings);
},
LabeledStatement: function generateLabeledStatement ($stmt, settings) {
var $body = $stmt.body,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = _.indent;
_.js += $stmt.label.name + ':' + adoptionPrefix($body);
if ($body.type !== Syntax.BlockStatement)
prevIndent = shiftIndent();
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
_.indent = prevIndent;
},
ModuleDeclaration: function generateModuleDeclaration ($stmt, settings) {
_.js += 'module' + _.space + $stmt.id.name + _.space + 'from' + _.optSpace;
ExprGen.Literal($stmt.source);
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
Program: function generateProgram ($stmt) {
var $body = $stmt.body,
len = $body.length,
lastIdx = len - 1;
if (safeConcatenation && len > 0)
_.js += '\n';
for (var i = 0; i < len; i++) {
var $item = $body[i];
_.js += _.indent;
StmtGen[$item.type]($item, Preset.s5(!safeConcatenation && i === lastIdx));
if (i !== lastIdx)
_.js += _.newline;
}
},
FunctionDeclaration: function generateFunctionDeclaration ($stmt) {
var isGenerator = !!$stmt.generator;
if ($stmt.async)
_.js += 'async ';
_.js += isGenerator ? ('function*' + _.optSpace) : ('function' + _.space );
_.js += $stmt.id.name;
generateFunctionBody($stmt);
},
ReturnStatement: function generateReturnStatement ($stmt, settings) {
var $arg = $stmt.argument;
if ($arg) {
var argJs = exprToJs($arg, Preset.e5);
_.js += join('return', argJs);
}
else
_.js += 'return';
if (semicolons || !settings.semicolonOptional)
_.js += ';';
},
WhileStatement: function generateWhileStatement ($stmt, settings) {
var $body = $stmt.body,
$test = $stmt.test,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = shiftIndent();
_.js += 'while' + _.optSpace + '(';
ExprGen[$test.type]($test, Preset.e5);
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
},
WithStatement: function generateWithStatement ($stmt, settings) {
var $body = $stmt.body,
$obj = $stmt.object,
bodySemicolonOptional = !semicolons && settings.semicolonOptional,
prevIndent = shiftIndent();
_.js += 'with' + _.optSpace + '(';
ExprGen[$obj.type]($obj, Preset.e5);
_.js += ')';
_.indent = prevIndent;
_.js += adoptionPrefix($body);
StmtGen[$body.type]($body, Preset.s4(bodySemicolonOptional));
}
};
//CodeGen
//-----------------------------------------------------------------------------------
function exprToJs ($expr, settings, $parent) {
var savedJs = _.js;
_.js = '';
ExprGen[$expr.type]($expr, settings, $parent);
var src = _.js;
_.js = savedJs;
return src;
}
function stmtToJs ($stmt, settings) {
var savedJs = _.js;
_.js = '';
StmtGen[$stmt.type]($stmt, settings);
var src = _.js;
_.js = savedJs;
return src;
}
function run ($node) {
_.js = '';
if (StmtGen[$node.type])
StmtGen[$node.type]($node, Preset.s7);
else
ExprGen[$node.type]($node, Preset.e19);
return _.js;
}
function wrapExprGen (gen) {
return function ($expr, settings) {
if (extra.verbatim && $expr.hasOwnProperty(extra.verbatim))
generateVerbatim($expr, settings);
else
gen($expr, settings);
}
}
function createExprGenWithExtras () {
var gens = {};
for (var key in ExprRawGen) {
if (ExprRawGen.hasOwnProperty(key))
gens[key] = wrapExprGen(ExprRawGen[key]);
}
return gens;
}
//Strings
var _ = {
js: '',
newline: '\n',
optSpace: ' ',
space: ' ',
indentUnit: ' ',
indent: ''
};
//Generators
var ExprGen = void 0,
StmtGen = StmtRawGen;
var generate = function ($node, options) {
var defaultOptions = getDefaultOptions();
if (options != null) {
//NOTE: Obsolete options
//
// `options.indent`
// `options.base`
//
// Instead of them, we can use `option.format.indent`.
if (typeof options.indent === 'string') {
defaultOptions.format.indent.style = options.indent;
}
if (typeof options.base === 'number') {
defaultOptions.format.indent.base = options.base;
}
options = updateDeeply(defaultOptions, options);
_.indentUnit = options.format.indent.style;
if (typeof options.base === 'string') {
_.indent = options.base;
}
else {
_.indent = stringRepeat(_.indentUnit, options.format.indent.base);
}
}
else {
options = defaultOptions;
_.indentUnit = options.format.indent.style;
_.indent = stringRepeat(_.indentUnit, options.format.indent.base);
}
json$1 = options.format.json;
renumber = options.format.renumber;
hexadecimal = json$1 ? false : options.format.hexadecimal;
quotes = json$1 ? 'double' : options.format.quotes;
escapeless = options.format.escapeless;
_.newline = options.format.newline;
_.optSpace = options.format.space;
if (options.format.compact)
_.newline = _.optSpace = _.indentUnit = _.indent = '';
_.space = _.optSpace ? _.optSpace : ' ';
parentheses = options.format.parentheses;
semicolons = options.format.semicolons;
safeConcatenation = options.format.safeConcatenation;
directive = options.directive;
json$1 ? null : options.parse;
extra = options;
if (extra.verbatim)
ExprGen = createExprGenWithExtras();
else
ExprGen = ExprRawGen;
return run($node);
};
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
var SCRIPT_PROCESSING_INSTRUCTIONS = {
getLocation: '__get$Loc',
setLocation: '__set$Loc',
getProperty: '__get$',
setProperty: '__set$',
callMethod: '__call$',
processScript: '__proc$Script',
processHtml: '__proc$Html',
getEval: '__get$Eval',
getPostMessage: '__get$PostMessage',
getProxyUrl: '__get$ProxyUrl',
restArray: '__rest$Array',
arrayFrom: '__arrayFrom$',
restObject: '__rest$Object',
swScopeHeaderValue: '__swScopeHeaderValue',
getWorkerSettings: '__getWorkerSettings$',
};
var TEMP_VARIABLE_PREFIX = '_hh$temp';
var TempVariables = /** @class */ (function () {
function TempVariables() {
this._list = [];
}
TempVariables.resetCounter = function () {
TempVariables._counter = 0;
};
TempVariables.generateName = function (baseName, key, index) {
if (!baseName)
return TEMP_VARIABLE_PREFIX + TempVariables._counter++;
if (key) {
if (key.type === Syntax_1.Identifier)
return baseName + '$' + key.name;
if (key.type === Syntax_1.Literal && key.value)
return baseName + '$' + key.value.toString().replace(/[^a-zA-Z0-9]/g, '');
}
return baseName + '$i' + index;
};
TempVariables.isHHTempVariable = function (name) {
return name.indexOf(TEMP_VARIABLE_PREFIX) === 0;
};
TempVariables.prototype.append = function (name) {
this._list.push(name);
};
TempVariables.prototype.get = function () {
return this._list;
};
TempVariables._counter = 0;
return TempVariables;
}());
function createIdentifier(name) {
return { type: Syntax_1.Identifier, name: name };
}
function createExpressionStatement(expression) {
return { type: Syntax_1.ExpressionStatement, expression: expression };
}
function createAssignmentExpression(left, operator, right) {
//@ts-ignore the `right` value can actually be null, but the AssignmentExpression type definition
// does not allow to the `right` value be null
return { type: Syntax_1.AssignmentExpression, operator: operator, left: left, right: right };
}
function createSimpleCallExpression(callee, args) {
return { type: Syntax_1.CallExpression, callee: callee, arguments: args, optional: false };
}
function createArrayExpression(elements) {
return { type: Syntax_1.ArrayExpression, elements: elements };
}
function createMemberExpression(object, property, computed) {
return { type: Syntax_1.MemberExpression, object: object, property: property, computed: computed, optional: false };
}
function createBinaryExpression(left, operator, right) {
return { type: Syntax_1.BinaryExpression, left: left, right: right, operator: operator };
}
function createSequenceExpression(expressions) {
//@ts-ignore SequenceExpression can actually
// TODO: To write to https://github.com/estree/estree that SequenceExpression must include Pattern
return { type: Syntax_1.SequenceExpression, expressions: expressions };
}
function createThisExpression() {
return { type: Syntax_1.ThisExpression };
}
function createLogicalExpression(left, operator, right) {
return { type: Syntax_1.LogicalExpression, left: left, right: right, operator: operator };
}
function createReturnStatement(argument) {
if (argument === void 0) { argument = null; }
return { type: Syntax_1.ReturnStatement, argument: argument };
}
function createFunctionExpression(id, params, body, async, generator) {
if (async === void 0) { async = false; }
if (generator === void 0) { generator = false; }
return { type: Syntax_1.FunctionExpression, id: id, params: params, body: body, async: async, generator: generator };
}
function createUnaryExpression(operator, argument) {
return { type: Syntax_1.UnaryExpression, operator: operator, prefix: true, argument: argument };
}
function createUndefined() {
return createUnaryExpression('void', createSimpleLiteral(0));
}
function createConditionalExpression(test, consequent, alternate) {
return { type: Syntax_1.ConditionalExpression, test: test, consequent: consequent, alternate: alternate };
}
function createSimpleLiteral(value) {
return { type: Syntax_1.Literal, value: value };
}
function createAssignmentExprStmt(left, right) {
return createExpressionStatement(createAssignmentExpression(left, '=', right));
}
function createBlockStatement(body) {
return { type: Syntax_1.BlockStatement, body: body };
}
function createVariableDeclarator(id, init) {
if (init === void 0) { init = null; }
return { type: Syntax_1.VariableDeclarator, id: id, init: init };
}
function createVariableDeclaration(kind, declarations) {
return { type: Syntax_1.VariableDeclaration, declarations: declarations, kind: kind };
}
function createProcessScriptMethodCall(arg, isApply) {
var args = [arg];
var processScriptIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.processScript);
if (isApply)
args.push(createSimpleLiteral(true));
return createSimpleCallExpression(processScriptIdentifier, args);
}
function createLocationGetWrapper(location) {
var getLocationIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.getLocation);
return createSimpleCallExpression(getLocationIdentifier, [location]);
}
function createLocationSetWrapper(locationIdentifier, value, wrapWithSequence) {
var tempIdentifier = createIdentifier(TempVariables.generateName());
var setLocationIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.setLocation);
var setLocationCall = createSimpleCallExpression(setLocationIdentifier, [locationIdentifier, tempIdentifier]);
var locationAssignment = createAssignmentExpression(locationIdentifier, '=', tempIdentifier);
var callIdentifier = createIdentifier('call');
var functionWrapper = createFunctionExpression(null, [], createBlockStatement([
createVariableDeclaration('var', [createVariableDeclarator(tempIdentifier, value)]),
createReturnStatement(createLogicalExpression(setLocationCall, '||', locationAssignment)),
]));
var functionWrapperCallMember = createMemberExpression(functionWrapper, callIdentifier, false);
var functionWrapperCall = createSimpleCallExpression(functionWrapperCallMember, [createThisExpression()]);
if (wrapWithSequence)
return createSequenceExpression([createSimpleLiteral(0), functionWrapperCall]);
return functionWrapperCall;
}
function createPropertySetWrapper(propertyName, obj, value) {
var setPropertyIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.setProperty);
return createSimpleCallExpression(setPropertyIdentifier, [obj, createSimpleLiteral(propertyName), value]);
}
function createMethodCallWrapper(owner, method, methodArgs, optional) {
if (optional === void 0) { optional = false; }
var callMethodIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.callMethod);
var methodArgsArray = createArrayExpression(methodArgs);
var args = [owner, method, methodArgsArray];
if (optional)
args.push(createSimpleLiteral(optional));
return createSimpleCallExpression(callMethodIdentifier, args);
}
function createPropertyGetWrapper(propertyName, owner, optional) {
if (optional === void 0) { optional = false; }
var getPropertyIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty);
var args = [owner, createSimpleLiteral(propertyName)];
if (optional)
args.push(createSimpleLiteral(optional));
return createSimpleCallExpression(getPropertyIdentifier, args);
}
function createComputedPropertyGetWrapper(property, owner, optional) {
if (optional === void 0) { optional = false; }
var getPropertyIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty);
var args = [owner, property];
if (optional)
args.push(createSimpleLiteral(optional));
return createSimpleCallExpression(getPropertyIdentifier, args);
}
function createComputedPropertySetWrapper(property, owner, value) {
var setPropertyIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.setProperty);
return createSimpleCallExpression(setPropertyIdentifier, [owner, property, value]);
}
function createGetEvalMethodCall(node) {
var getEvalIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.getEval);
return createSimpleCallExpression(getEvalIdentifier, [node]);
}
function getProxyUrlLiteral(source, resolver) {
var proxyUrl = resolver(String(source.value), getResourceTypeString({ isScript: true }));
return createSimpleLiteral(proxyUrl);
}
function createGetProxyUrlMethodCall(arg, baseUrl) {
var getProxyUrlIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.getProxyUrl);
var args = [arg];
if (baseUrl)
args.push(createSimpleLiteral(baseUrl));
return createSimpleCallExpression(getProxyUrlIdentifier, args);
}
function createGetPostMessageMethodCall(node) {
var getPostMessageIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage);
var args = node.type === Syntax_1.MemberExpression
? [node.object]
: [createSimpleLiteral(null), node];
return createSimpleCallExpression(getPostMessageIdentifier, args);
}
function createArrayWrapper(array) {
var arrayIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.arrayFrom);
return createSimpleCallExpression(arrayIdentifier, [array]);
}
function createExpandedConcatOperation(left, right) {
return createAssignmentExpression(left, '=', createBinaryExpression(left, '+', right));
}
function createHtmlProcessorWrapper(node) {
var processHtmlIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.processHtml);
var parentIdentifier = createIdentifier('parent');
var windowIdentifier = createIdentifier('window');
var processHtmlThroughParent = createMemberExpression(parentIdentifier, processHtmlIdentifier, false);
var processHtmlCall = createSimpleCallExpression(processHtmlThroughParent, [windowIdentifier, node.expression]);
return createExpressionStatement(processHtmlCall);
}
function createTempVarsDeclaration(tempVars) {
var declarations = [];
for (var _i = 0, tempVars_1 = tempVars; _i < tempVars_1.length; _i++) {
var variable = tempVars_1[_i];
declarations.push(createVariableDeclarator(createIdentifier(variable)));
}
return createVariableDeclaration('var', declarations);
}
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
// NOTE: constants are exported for the testing purposes
var METHODS = [
'postMessage',
'replace',
'assign',
];
var PROPERTIES = [
'href',
'location',
];
var INSTRUMENTED_METHOD_RE = new RegExp("^(".concat(METHODS.join('|'), ")$"));
var INSTRUMENTED_PROPERTY_RE = new RegExp("^(".concat(PROPERTIES.join('|'), ")$"));
// NOTE: Mootools framework contains code that removes the RegExp.prototype.test
// method and restores it later.
// delete z[A]; // z = RegExp.prototype, A = "test"
// __set$(z, A, x.protect()); // x.protect - returns the removed method
// The __set$ function calls the test method of the regular expression. (GH-331)
var reTest = RegExp.prototype.test;
// NOTE: The Function.prototype.call method can also be removed.
// But only one of the methods can be removed at a time.
var test = function (regexp, str) { return regexp.test ? regexp.test(str) : reTest.call(regexp, str); };
// NOTE: we can't use the map approach here, because
// cases like `WRAPPABLE_METHOD['toString']` will fail.
// We could use the hasOwnProperty test, but it is
// significantly slower than the regular expression test
function shouldInstrumentMethod(name) {
return test(INSTRUMENTED_METHOD_RE, String(name));
}
function shouldInstrumentProperty(name) {
return test(INSTRUMENTED_PROPERTY_RE, String(name));
}
var instrumentationProcessingUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
METHODS: METHODS,
PROPERTIES: PROPERTIES,
shouldInstrumentMethod: shouldInstrumentMethod,
shouldInstrumentProperty: shouldInstrumentProperty
});
// -------------------------------------------------------------
// Transform:
// obj[prop] -->
// __get$(obj, prop)
var transformer$l = {
name: 'computed-property-get',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.MemberExpression,
condition: function (node, parent) {
if (!node.computed || !parent)
return false;
if (node.property.type === Syntax_1.Literal && !shouldInstrumentProperty(node.property.value))
return false;
// super[prop]
if (node.object.type === Syntax_1.Super)
return false;
// object[prop] = value
if (parent.type === Syntax_1.AssignmentExpression && parent.left === node)
return false;
// delete object[prop]
if (parent.type === Syntax_1.UnaryExpression && parent.operator === 'delete')
return false;
// object[prop]++ || object[prop]-- || ++object[prop] || --object[prop]
if (parent.type === Syntax_1.UpdateExpression && (parent.operator === '++' || parent.operator === '--'))
return false;
// object[prop]()
if (parent.type === Syntax_1.CallExpression && parent.callee === node)
return false;
// new (object[prop])() || new (object[prop])
if (parent.type === Syntax_1.NewExpression && parent.callee === node)
return false;
// for(object[prop] in source)
if (parent.type === Syntax_1.ForInStatement && parent.left === node)
return false;
return true;
},
run: function (node) { return createComputedPropertyGetWrapper(node.property, node.object, node.optional); },
};
// -------------------------------------------------------------
// Transform:
// obj[prop] = value -->
// __set$(object, prop, value)
var transformer$k = {
name: 'computed-property-set',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.AssignmentExpression,
condition: function (node) {
var left = node.left;
// super[prop] = value
if (left.type === Syntax_1.MemberExpression && left.object.type === Syntax_1.Super)
return false;
if (node.operator === '=' && left.type === Syntax_1.MemberExpression && left.computed)
return left.property.type === Syntax_1.Literal ? shouldInstrumentProperty(left.property.value) : true;
return false;
},
run: function (node) {
var memberExpression = node.left;
return createComputedPropertySetWrapper(memberExpression.property, memberExpression.object, node.right);
},
};
// -------------------------------------------------------------
// Transform:
// val1 += val2
// --> val1 = val1 + val2
var transformer$j = {
name: 'concat-operator',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.AssignmentExpression,
condition: function (node) {
if (node.operator !== '+=')
return false;
var left = node.left;
// location
if (left.type === Syntax_1.Identifier)
return shouldInstrumentProperty(left.name);
if (left.type === Syntax_1.MemberExpression) {
// something['location'] or something[propname]
if (left.computed) {
return left.property.type === Syntax_1.Literal
? shouldInstrumentProperty(left.property.value)
: left.property.type !== Syntax_1.UpdateExpression;
}
// something.location
else if (left.property.type === Syntax_1.Identifier)
return shouldInstrumentProperty(left.property.name);
}
return false;
},
run: function (node) { return createExpandedConcatOperation(node.left, node.right); },
};
function replaceNode(node, newNode, parent, key) {
var oldNode = parent[key];
if (oldNode instanceof Array) {
if (node)
oldNode[oldNode.indexOf(node)] = newNode;
else
oldNode.unshift(newNode);
}
else {
// @ts-ignore
parent[key] = newNode;
}
if (node) {
newNode.originStart = newNode.start = node.start;
newNode.originEnd = newNode.end = node.end;
}
else {
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
newNode.start = newNode.end = newNode.originStart = newNode.originEnd = oldNode[1] ? oldNode[1].start : parent.start + 1;
}
}
// -------------------------------------------------------------
// Transform:
// eval(script); --> eval(__proc$Script(script));
var transformer$i = {
name: 'eval',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.CallExpression,
condition: function (node) {
if (!node.arguments.length)
return false;
var callee = node.callee;
// eval()
if (callee.type === Syntax_1.Identifier && callee.name === 'eval')
return true;
// obj.eval(), obj['eval'](),
return callee.type === Syntax_1.MemberExpression &&
(callee.property.type === Syntax_1.Identifier && callee.property.name ||
callee.property.type === Syntax_1.Literal && callee.property.value) === 'eval';
},
run: function (node) {
var newArgs = createProcessScriptMethodCall(node.arguments[0]);
replaceNode(node.arguments[0], newArgs, node, 'arguments');
return null;
},
};
// -------------------------------------------------------------
// Transform:
// foo = eval.bind(...); -->
// foo = __get$Eval(eval).bind(...);
var transformer$h = {
name: 'eval-bind',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.CallExpression,
condition: function (node) {
if (node.callee.type === Syntax_1.MemberExpression && node.callee.property.type === Syntax_1.Identifier &&
node.callee.property.name === 'bind') {
var obj = node.callee.object;
// obj.eval.bind(), obj[eval].bind()
if (obj.type === Syntax_1.MemberExpression &&
(obj.property.type === Syntax_1.Identifier && obj.property.name ||
obj.property.type === Syntax_1.Literal && obj.property.value) === 'eval')
return true;
// eval.bind()
if (obj.type === Syntax_1.Identifier && obj.name === 'eval')
return true;
}
return false;
},
run: function (node) {
var callee = node.callee;
var getEvalNode = createGetEvalMethodCall(callee.object);
replaceNode(callee.object, getEvalNode, callee, 'object');
return null;
},
};
// -------------------------------------------------------------
var INVOCATION_FUNC_NAME_RE$1 = /^(call|apply)$/;
// Transform:
// eval.call(ctx, script);
// eval.apply(ctx, script); -->
// eval.call(ctx, __proc$Script(script));
// eval.apply(ctx, __proc$Script(script, true));
var transformer$g = {
name: 'eval-call-apply',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.CallExpression,
condition: function (node) {
// eval.<meth>(ctx, script, ...)
if (node.arguments.length < 2)
return false;
if (node.callee.type === Syntax_1.MemberExpression && node.callee.property.type === Syntax_1.Identifier &&
INVOCATION_FUNC_NAME_RE$1.test(node.callee.property.name)) {
var obj = node.callee.object;
// eval.<meth>()
if (obj.type === Syntax_1.Identifier && obj.name === 'eval')
return true;
// obj.eval.<meth>(), obj[eval].<meth>()
if (obj.type === Syntax_1.MemberExpression &&
(obj.property.type === Syntax_1.Identifier && obj.property.name ||
obj.property.type === Syntax_1.Literal && obj.property.value) === 'eval')
return true;
}
return false;
},
run: function (node) {
var callee = node.callee;
var property = callee.property;
var newArg = createProcessScriptMethodCall(node.arguments[1], property.name === 'apply');
replaceNode(node.arguments[1], newArg, node, 'arguments');
return null;
},
};
// -------------------------------------------------------------
// Transform:
// const foo = eval; foo = eval; { _eval: eval }; return eval;
// -->
// const foo = _get$Eval(eval); foo = _get$Eval(eval); { _eval: _get$Eval(eval) }; return _get$Eval(eval);
var transformer$f = {
name: 'eval-get',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.Identifier,
condition: function (node, parent) {
if (node.name === 'eval' && parent) {
// Skip: eval()
if (parent.type === Syntax_1.CallExpression && parent.callee === node)
return false;
// Skip: class X { eval () {} }
if (parent.type === Syntax_1.MethodDefinition)
return false;
// Skip: class eval { x () {} }
if (parent.type === Syntax_1.ClassDeclaration)
return false;
// Skip: window.eval, eval.call
if (parent.type === Syntax_1.MemberExpression)
return false;
// Skip: function eval () { ... }
if ((parent.type === Syntax_1.FunctionExpression || parent.type === Syntax_1.FunctionDeclaration) &&
parent.id === node)
return false;
// Skip: function (eval) { ... } || function func(eval) { ... } || eval => { ... }
if ((parent.type === Syntax_1.FunctionExpression || parent.type === Syntax_1.FunctionDeclaration ||
parent.type === Syntax_1.ArrowFunctionExpression) && parent.params.indexOf(node) !== -1)
return false;
// Skip: { eval: value }
if (parent.type === Syntax_1.Property && parent.key === node)
return false;
// Skip: { eval }
if (parent.type === Syntax_1.Property && parent.value === node && parent.shorthand)
return false;
// Skip: eval = value || function x (eval = value) { ... }
if ((parent.type === Syntax_1.AssignmentExpression || parent.type === Syntax_1.AssignmentPattern) &&
parent.left === node)
return false;
// Skip: const eval = value;
if (parent.type === Syntax_1.VariableDeclarator && parent.id === node)
return false;
// Skip: eval++ || eval-- || ++eval || --eval
if (parent.type === Syntax_1.UpdateExpression && (parent.operator === '++' || parent.operator === '--'))
return false;
// Skip already transformed: __get$Eval(eval)
if (parent.type === Syntax_1.CallExpression && parent.callee.type === Syntax_1.Identifier &&
parent.callee.name === SCRIPT_PROCESSING_INSTRUCTIONS.getEval)
return false;
// Skip: function x (...eval) {}
if (parent.type === Syntax_1.RestElement)
return false;
// Skip: export { eval } from "module";
if (parent.type === Syntax_1.ExportSpecifier)
return false;
// Skip: import { eval } from "module";
if (parent.type === Syntax_1.ImportSpecifier)
return false;
return true;
}
return false;
},
run: createGetEvalMethodCall,
};
// -------------------------------------------------------------
// Transform:
// const foo = window.eval; foo = window.eval; { _eval: window.eval }; return window.eval;
// -->
// const foo = _get$Eval(window.eval); foo = _get$Eval(window.eval); { _eval: _get$Eval(window.eval) }; return _get$Eval(window.eval);
var transformer$e = {
name: 'window-eval-get',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.MemberExpression,
condition: function (node, parent) {
if (!parent)
return false;
// Skip: window.eval.field
if (parent.type === Syntax_1.MemberExpression && (parent.property === node || parent.object === node))
return false;
// Skip: window.eval()
if (parent.type === Syntax_1.CallExpression && parent.callee === node)
return false;
// Skip: window.eval = 1, window["eval"] = 1
if (parent.type === Syntax_1.AssignmentExpression && parent.left === node)
return false;
// Skip already transformed: __get$Eval(window.eval), __get$Eval(window["eval"])
if (parent.type === Syntax_1.CallExpression && parent.callee.type === Syntax_1.Identifier &&
parent.callee.name === SCRIPT_PROCESSING_INSTRUCTIONS.getEval)
return false;
// window.eval
if (node.property.type === Syntax_1.Identifier && node.property.name === 'eval')
return true;
// window['eval']
if (node.property.type === Syntax_1.Literal && node.property.value === 'eval')
return true;
return false;
},
run: createGetEvalMethodCall,
};
// -------------------------------------------------------------
// Transform:
// const foo = postMessage; foo = postMessage; { _postMessage: postMessage }; return postMessage;
// -->
// const foo = _get$PostMessage(postMessage); foo = _get$PostMessage(postMessage); { _postMessage: _get$PostMessage(postMessage) }; return _get$PostMessage(postMessage);
var transformer$d = {
name: 'post-message-get',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.Identifier,
condition: function (node, parent) {
if (node.name !== 'postMessage' || !parent)
return false;
// Skip: window.postMessage, postMessage.call
if (parent.type === Syntax_1.MemberExpression)
return false;
// Skip: class X { postMessage () {} }
if (parent.type === Syntax_1.MethodDefinition)
return false;
// Skip: class postMessage { x () {} }
if (parent.type === Syntax_1.ClassDeclaration)
return false;
// Skip: function postMessage () { ... }
if ((parent.type === Syntax_1.FunctionExpression || parent.type === Syntax_1.FunctionDeclaration) &&
parent.id === node)
return false;
// Skip: function (postMessage) { ... } || function func(postMessage) { ... } || postMessage => { ... }
if ((parent.type === Syntax_1.FunctionExpression || parent.type === Syntax_1.FunctionDeclaration ||
parent.type === Syntax_1.ArrowFunctionExpression) && parent.params.indexOf(node) !== -1)
return false;
// Skip: { postMessage: value }
if (parent.type === Syntax_1.Property && parent.key === node)
return false;
// Skip: { postMessage }
if (parent.type === Syntax_1.Property && parent.value === node && parent.shorthand)
return false;
// Skip: postMessage = value || function x (postMessage = value) { ... }
if ((parent.type === Syntax_1.AssignmentExpression || parent.type === Syntax_1.AssignmentPattern) &&
parent.left === node)
return false;
// Skip: const postMessage = value;
if (parent.type === Syntax_1.VariableDeclarator && parent.id === node)
return false;
// Skip: postMessage++ || postMessage-- || ++postMessage || --postMessage
if (parent.type === Syntax_1.UpdateExpression && (parent.operator === '++' || parent.operator === '--'))
return false;
// Skip already transformed: __get$PostMessage(postMessage) || __call$(obj, postMessage, args...);
if (parent.type === Syntax_1.CallExpression && parent.callee.type === Syntax_1.Identifier &&
(parent.callee.name === SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage ||
parent.callee.name === SCRIPT_PROCESSING_INSTRUCTIONS.callMethod && parent.arguments[1] === node))
return false;
// Skip: function x (...postMessage) {}
if (parent.type === Syntax_1.RestElement)
return false;
// Skip: export { postMessage } from "module";
if (parent.type === Syntax_1.ExportSpecifier)
return false;
// Skip: import { postMessage } from "module";
if (parent.type === Syntax_1.ImportSpecifier)
return false;
return true;
},
run: createGetPostMessageMethodCall,
};
// -------------------------------------------------------------
// Transform:
// const foo = window.postMessage; foo = window.postMessage; { _postMessage: window.postMessage }; return window.postMessage;
// -->
// const foo = _get$PostMessage(window.postMessage); foo = _get$PostMessage(window.postMessage); { _postMessage: _get$PostMessage(window.postMessage) }; return _get$PostMessage(window.postMessage);
var transformer$c = {
name: 'window-post-message-get',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.MemberExpression,
condition: function (node, parent) {
if (!parent)
return false;
// Skip: window.postMessage.field
if (parent.type === Syntax_1.MemberExpression && (parent.property === node || parent.object === node))
return false;
// Skip: window.postMessage()
if (parent.type === Syntax_1.CallExpression && parent.callee === node)
return false;
// Skip: window.postMessage = 1, window["postMessage"] = 1
if (parent.type === Syntax_1.AssignmentExpression && parent.left === node)
return false;
// Skip already transformed: __get$PostMessage(window.postMessage), __get$PostMessage(window["postMessage"])
if (parent.type === Syntax_1.CallExpression && parent.callee.type === Syntax_1.Identifier &&
parent.callee.name === SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage)
return false;
// window.postMessage
if (node.property.type === Syntax_1.Identifier && node.property.name === 'postMessage')
return true;
// window['postMessage']
if (node.property.type === Syntax_1.Literal && node.property.value === 'postMessage')
return true;
return false;
},
run: createGetPostMessageMethodCall,
};
// -------------------------------------------------------------
var INVOCATION_FUNC_NAME_RE = /^(call|apply|bind)$/;
// Transform:
// postMessage.call(ctx, script);
// postMessage.apply(ctx, script);
// postMessage.bind(...); -->
// __get$PostMessage(postMessage).call(ctx, script);
// __get$PostMessage(postMessage).apply(ctx, script);
// __get$PostMessage(postMessage).bind(...);
var transformer$b = {
name: 'post-message-call-apply-bind',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.CallExpression,
condition: function (node) {
if (node.callee.type === Syntax_1.MemberExpression && node.callee.property.type === Syntax_1.Identifier &&
INVOCATION_FUNC_NAME_RE.test(node.callee.property.name)) {
// postMessage.<call|apply>(ctx, script, ...)
if (node.arguments.length < 2 && node.callee.property.name !== 'bind')
return false;
var obj = node.callee.object;
// obj.postMessage.<meth>(), obj[postMessage].<meth>(),
if (obj.type === Syntax_1.MemberExpression &&
(obj.property.type === Syntax_1.Identifier && obj.property.name ||
obj.property.type === Syntax_1.Literal && obj.property.value) === 'postMessage')
return true;
// postMessage.<meth>()
if (obj.type === Syntax_1.Identifier && obj.name === 'postMessage')
return true;
}
return false;
},
run: function (node) {
var callee = node.callee;
var getPostMessageNode = createGetPostMessageMethodCall(callee.object);
replaceNode(callee.object, getPostMessageNode, callee, 'object');
return null;
},
};
// -------------------------------------------------------------
// Transform:
// for(obj[prop] in src), for(obj.prop in src) -->
// for(const _hh$temp0 in src) { obj[prop] = _hh$temp0; }
var transformer$a = {
name: 'for-in',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.ForInStatement,
condition: function (node) { return node.left.type === Syntax_1.MemberExpression; },
run: function (node) {
var tempVarAst = createIdentifier(TempVariables.generateName());
var varDeclaration = createVariableDeclaration('var', [createVariableDeclarator(tempVarAst)]);
var assignmentExprStmt = createAssignmentExprStmt(node.left, tempVarAst);
if (node.body.type !== Syntax_1.BlockStatement)
replaceNode(node.body, createBlockStatement([assignmentExprStmt, node.body]), node, 'body');
else
replaceNode(null, assignmentExprStmt, node.body, 'body');
replaceNode(node.left, varDeclaration, node, 'left');
return null;
},
};
function walkDeclarators(node, action) {
var declarators = [];
var identifiers = [];
for (var _i = 0, _a = node.body; _i < _a.length; _i++) {
var statement = _a[_i];
if (statement.type === Syntax_1.VariableDeclaration)
declarators.push.apply(declarators, statement.declarations);
}
for (var _b = 0, declarators_1 = declarators; _b < declarators_1.length; _b++) {
var declarator = declarators_1[_b];
if (declarator.type === Syntax_1.VariableDeclarator) {
if (declarator.id.type === Syntax_1.Identifier)
identifiers.push(declarator.id);
if (declarator.id.type === Syntax_1.ArrayPattern)
identifiers.push.apply(identifiers, declarator.id.elements);
if (declarator.id.type === Syntax_1.ObjectPattern) {
for (var _c = 0, _d = declarator.id.properties; _c < _d.length; _c++) {
var prop = _d[_c];
if ('value' in prop)
identifiers.push(prop.value);
}
}
}
}
for (var _e = 0, identifiers_1 = identifiers; _e < identifiers_1.length; _e++) {
var identifier = identifiers_1[_e];
if (identifier && identifier.type === Syntax_1.Identifier)
action(identifier);
}
}
function replaceDuplicateDeclarators(forOfNode) {
var _a;
var forOfLeft = forOfNode.left;
var nodesToReplace = [];
var isArrayPatternDeclaration = ((_a = forOfLeft.declarations[0]) === null || _a === void 0 ? void 0 : _a.id.type) === Syntax_1.ArrayPattern;
var isBlockStatement = forOfNode.body.type === Syntax_1.BlockStatement;
if (!isArrayPatternDeclaration || !isBlockStatement)
return;
var leftDeclaration = forOfLeft.declarations[0].id;
var leftIdentifiers = leftDeclaration.elements;
walkDeclarators(forOfNode.body, function (node) {
for (var _i = 0, leftIdentifiers_1 = leftIdentifiers; _i < leftIdentifiers_1.length; _i++) {
var identifier = leftIdentifiers_1[_i];
if (identifier && identifier.name === node.name)
nodesToReplace.push(identifier);
}
});
for (var _i = 0, nodesToReplace_1 = nodesToReplace; _i < nodesToReplace_1.length; _i++) {
var nodeToReplace = nodesToReplace_1[_i];
var destIdentifier = createIdentifier(TempVariables.generateName());
replaceNode(nodeToReplace, destIdentifier, leftDeclaration, 'elements');
}
}
// Transform:
// for (let {href, postMessage} of wins) {} -->
// for (let _hh$temp0 of wins) { let {href, postMessage} = _hh$temp0; }
var forOfTransformer = {
name: 'for-of',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.ForOfStatement,
condition: function (node) {
var left = node.left;
if (left.type === Syntax_1.VariableDeclaration)
left = left.declarations[0].id;
return left.type === Syntax_1.ObjectPattern || left.type === Syntax_1.ArrayPattern;
},
run: function (node) {
var tempIdentifier = createIdentifier(TempVariables.generateName());
var forOfLeft = node.left;
var statementWithTempAssignment;
if (forOfLeft.type === Syntax_1.VariableDeclaration) {
replaceDuplicateDeclarators(node);
statementWithTempAssignment = createVariableDeclaration(forOfLeft.kind, [
createVariableDeclarator(forOfLeft.declarations[0].id, tempIdentifier),
]);
statementWithTempAssignment.reTransform = true;
replaceNode(forOfLeft.declarations[0].id, tempIdentifier, forOfLeft.declarations[0], 'id');
}
else {
var varDeclaration = createVariableDeclaration('var', [createVariableDeclarator(tempIdentifier)]);
statementWithTempAssignment = createAssignmentExprStmt(forOfLeft, tempIdentifier);
replaceNode(forOfLeft, varDeclaration, node, 'left');
}
if (node.body.type === Syntax_1.BlockStatement)
replaceNode(null, statementWithTempAssignment, node.body, 'body');
else
replaceNode(node.body, createBlockStatement([statementWithTempAssignment, node.body]), node, 'body');
return null;
},
};
// -------------------------------------------------------------
// Transform:
// location -->
// __get$Loc(location)
var transformer$9 = {
name: 'location-get',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.Identifier,
condition: function (node, parent) {
if (node.name !== 'location' || !parent)
return false;
// Skip: const location = value;
if (parent.type === Syntax_1.VariableDeclarator && parent.id === node)
return false;
// Skip: location = value || function x (location = value) { ... }
if ((parent.type === Syntax_1.AssignmentExpression || parent.type === Syntax_1.AssignmentPattern) &&
parent.left === node)
return false;
// Skip: function location() {}
if ((parent.type === Syntax_1.FunctionExpression || parent.type === Syntax_1.FunctionDeclaration) &&
parent.id === node)
return false;
// Skip: object.location || location.field
if (parent.type === Syntax_1.MemberExpression && parent.property === node)
return false;
// Skip: { location: value }
if (parent.type === Syntax_1.Property && parent.key === node)
return false;
// Skip: { location }
if (parent.type === Syntax_1.Property && parent.value === node && parent.shorthand)
return false;
// Skip: location++ || location-- || ++location || --location
if (parent.type === Syntax_1.UpdateExpression && (parent.operator === '++' || parent.operator === '--'))
return false;
// Skip: function (location) { ... } || function func(location) { ... } || location => { ... }
if ((parent.type === Syntax_1.FunctionExpression || parent.type === Syntax_1.FunctionDeclaration ||
parent.type === Syntax_1.ArrowFunctionExpression) && parent.params.indexOf(node) !== -1)
return false;
// Skip already transformed: __get$Loc(location)
if (parent.type === Syntax_1.CallExpression && parent.callee.type === Syntax_1.Identifier &&
parent.callee.name === SCRIPT_PROCESSING_INSTRUCTIONS.getLocation)
return false;
// Skip: class X { location () {} }
if (parent.type === Syntax_1.MethodDefinition)
return false;
// Skip: class location { x () {} }
if (parent.type === Syntax_1.ClassDeclaration)
return false;
// Skip: function x (...location) {}
if (parent.type === Syntax_1.RestElement)
return false;
// Skip: export { location } from "module";
if (parent.type === Syntax_1.ExportSpecifier)
return false;
// Skip: import { location } from "module";
if (parent.type === Syntax_1.ImportSpecifier)
return false;
return true;
},
run: createLocationGetWrapper,
};
// -------------------------------------------------------------
// Transform:
// location = value -->
// (function(){ return __set$Loc(location, value) || location = value;}.apply(this))
var transformer$8 = {
name: 'location-set',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.AssignmentExpression,
condition: function (node) { return node.operator === '=' && node.left.type === Syntax_1.Identifier && node.left.name === 'location'; },
run: function (node, parent, key) {
if (!parent)
return null;
var wrapWithSequence = key !== 'arguments' && key !== 'consequent' && key !== 'alternate' &&
// @ts-ignore
(parent.type !== Syntax_1.SequenceExpression || parent.expressions[0] === node);
return createLocationSetWrapper(node.left, node.right, wrapWithSequence);
},
};
// -------------------------------------------------------------
// Transform:
// obj.<wrappable-property> -->
// __get$(obj, '<wrappable-property>')
var transformer$7 = {
name: 'property-get',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.MemberExpression,
condition: function (node, parent) {
if (node.computed || !parent)
return false;
if (node.property.type === Syntax_1.Identifier && !shouldInstrumentProperty(node.property.name))
return false;
// Skip: super.prop
if (node.object.type === Syntax_1.Super)
return false;
// @ts-ignore
var valuableParent = parent.type === Syntax_1.ParenthesizedExpression ? parent.expression : parent;
// Skip: object.prop = value
if (parent.type === Syntax_1.AssignmentExpression && parent.left === node)
return false;
// Skip: delete object.prop
if (parent.type === Syntax_1.UnaryExpression && parent.operator === 'delete')
return false;
// Skip: object.prop()
if (parent.type === Syntax_1.CallExpression && parent.callee === node)
return false;
// Skip: object.prop++ || object.prop-- || ++object.prop || --object.prop
if (parent.type === Syntax_1.UpdateExpression && (parent.operator === '++' || parent.operator === '--'))
return false;
// Skip: new (object.prop)() || new (object.prop)
if (valuableParent.type === Syntax_1.NewExpression && valuableParent.callee === node)
return false;
// Skip: for(object.prop in source)
if (parent.type === Syntax_1.ForInStatement && parent.left === node)
return false;
return true;
},
// eslint-disable-next-line
run: function (node) { return createPropertyGetWrapper(node.property.name, node.object, node.optional); }
};
// -------------------------------------------------------------
// Transform:
// obj.<wrappable-property> = value -->
// __set$(obj, '<wrappable-property>', value)
var transformer$6 = {
name: 'property-set',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.AssignmentExpression,
condition: function (node) {
// super.prop = value
if (node.left.type === Syntax_1.MemberExpression && node.left.object.type === Syntax_1.Super)
return false;
return node.operator === '=' &&
node.left.type === Syntax_1.MemberExpression && !node.left.computed &&
node.left.property.type === Syntax_1.Identifier &&
shouldInstrumentProperty(node.left.property.name);
},
run: function (node) {
var memberExpression = node.left;
var identifier = memberExpression.property;
return createPropertySetWrapper(identifier.name, memberExpression.object, node.right);
},
};
// -------------------------------------------------------------
// Transform:
// obj.method(args...); obj[method](args...); -->
// _call$(obj, 'method', args...); _call$(obj, method, args...);
var transformer$5 = {
name: 'method-call',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.CallExpression,
condition: function (node) {
var callee = node.callee;
if (callee.type === Syntax_1.MemberExpression) {
// Skip: super.meth()
if (callee.object.type === Syntax_1.Super)
return false;
if (callee.computed)
return callee.property.type === Syntax_1.Literal ? shouldInstrumentMethod(callee.property.value) : true;
return callee.property.type === Syntax_1.Identifier && shouldInstrumentMethod(callee.property.name);
}
return false;
},
run: function (node) {
var callee = node.callee;
var method = callee.computed
? callee.property
: createSimpleLiteral(callee.property.name); // eslint-disable-line no-extra-parens
var optional = node.optional;
return createMethodCallWrapper(callee.object, method, node.arguments, optional);
},
};
// -------------------------------------------------------------
// Transform:
// x = 5; "hello" --> x = 5; parent.__proc$Html(window, "hello")
// someAction(); generateHtmlPage() --> someAction(); parent.__proc$Html(window, generateHtmlPage())
var transformer$4 = {
name: 'js-protocol-last-expression',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.ExpressionStatement,
condition: function (node, parent) { return !!transformer$4.wrapLastExpr && !!parent && parent.type === Syntax_1.Program &&
parent.body[parent.body.length - 1] === node; },
run: function (node) {
transformer$4.wrapLastExpr = false;
return createHtmlProcessorWrapper(node);
},
};
// -------------------------------------------------------------
// Transform:
// import something from 'url'; --> import something from 'processed-url';
// export * from 'url'; --> export * from 'processed-url';
// export { x as y } from 'url'; --> export { x as y } from 'processed-url';
var transformer$3 = {
name: 'static-import',
nodeReplacementRequireTransform: false,
nodeTypes: Syntax_1.Literal,
condition: function (node, parent) { return !!parent && (parent.type === Syntax_1.ImportDeclaration ||
parent.type === Syntax_1.ExportAllDeclaration ||
parent.type === Syntax_1.ExportNamedDeclaration) && parent.source === node; },
run: function (node) { return transformer$3.resolver ? getProxyUrlLiteral(node, transformer$3.resolver) : null; },
};
// -------------------------------------------------------------
// Transform:
// import(something).then()
// -->
// import(__get$ProxyUrl(something)).then()
var transformer$2 = {
name: 'dynamic-import',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.ImportExpression,
condition: function () { return true; },
run: function (node) {
var _a;
var newSource = createGetProxyUrlMethodCall(node.source, (_a = transformer$2.getBaseUrl) === null || _a === void 0 ? void 0 : _a.call(transformer$2));
replaceNode(node.source, newSource, node, 'source');
return null;
},
};
function processObjectProperty(prop, temp, build, baseTempName) {
var pattern = prop.value;
var computed = prop.computed || prop.key.type === Syntax_1.Literal;
var value = createMemberExpression(temp, prop.key, computed);
process(pattern, value, build, baseTempName);
}
function createObjectRest(tempIdentifier, keys) {
var restObjectIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.restObject);
return createSimpleCallExpression(restObjectIdentifier, [tempIdentifier, createArrayExpression(keys)]);
}
function createRestArray(array, startIndex) {
var restArrayIdentifier = createIdentifier(SCRIPT_PROCESSING_INSTRUCTIONS.restArray);
return createSimpleCallExpression(restArrayIdentifier, [array, createSimpleLiteral(startIndex)]);
}
function createTempIdentifierOrUseExisting(value, build, baseTempName) {
if (value.type === Syntax_1.Identifier && TempVariables.isHHTempVariable(value.name))
return value;
var tempIdentifier = createIdentifier(baseTempName || TempVariables.generateName(baseTempName));
build(tempIdentifier, value, true);
return tempIdentifier;
}
function processObjectPattern(pattern, value, build, baseTempName) {
if (!value)
return;
var properties = pattern.properties;
var hasRest = properties.length && properties[properties.length - 1].type === Syntax_1.RestElement;
var tempIdentifier = createTempIdentifierOrUseExisting(value, build, baseTempName);
var propNames = [];
var baseTempNames = [];
if (!baseTempName)
baseTempName = tempIdentifier.name;
if (hasRest) {
for (var i = 0; i < properties.length - 1; i++) {
var prop = properties[i];
var key = prop.key;
if (key.type === Syntax_1.Identifier)
propNames.push(prop.computed ? key : createSimpleLiteral(key.name));
else if (key.type === Syntax_1.Literal)
propNames.push(key);
else {
var tempPropKey = createIdentifier(TempVariables.generateName());
build(tempPropKey, key, true);
propNames.push(tempPropKey);
prop.key = tempPropKey;
}
}
}
for (var i = 0; i < properties.length; i++) {
var prop = properties[i];
if (prop.type === Syntax_1.RestElement)
build(prop.argument, createObjectRest(tempIdentifier, propNames));
else {
var assignmentProp = prop;
var newBaseTempName = TempVariables.generateName(baseTempName, assignmentProp.key, i);
if (baseTempNames.indexOf(newBaseTempName) > -1)
newBaseTempName = TempVariables.generateName(newBaseTempName, void 0, i);
baseTempNames.push(newBaseTempName);
processObjectProperty(assignmentProp, tempIdentifier, build, newBaseTempName);
}
}
}
function processArrayPattern(pattern, value, build, baseTempName) {
if (!value)
return;
// NOTE: support iterable objects (GH-2669)
if (value.type !== Syntax_1.ArrayExpression)
value = createArrayWrapper(value);
var tempIdentifier = createTempIdentifierOrUseExisting(value, build, baseTempName);
if (!baseTempName)
baseTempName = tempIdentifier.name;
for (var i = 0; i < pattern.elements.length; i++) {
var elem = pattern.elements[i];
if (!elem)
continue;
if (elem.type === Syntax_1.RestElement) {
value = createRestArray(tempIdentifier, i);
elem = elem.argument;
}
else
value = createMemberExpression(tempIdentifier, createSimpleLiteral(i), true);
process(elem, value, build, TempVariables.generateName(baseTempName, void 0, i));
}
}
function processAssignmentPattern(pattern, value, build, baseTempName) {
if (!value)
return;
var left = pattern.left, right = pattern.right;
var tempIdentifier = createTempIdentifierOrUseExisting(value, build, baseTempName);
var tempCondition = createBinaryExpression(tempIdentifier, '===', createUndefined());
var tempConditional = createConditionalExpression(tempCondition, right, tempIdentifier);
if (!baseTempName)
baseTempName = tempIdentifier.name;
baseTempName += '$assign';
process(left, tempConditional, build, baseTempName);
}
function process(pattern, value, build, baseTempName) {
if (pattern.type === Syntax_1.ObjectPattern)
processObjectPattern(pattern, value, build, baseTempName);
else if (pattern.type === Syntax_1.ArrayPattern)
processArrayPattern(pattern, value, build, baseTempName);
else if (pattern.type === Syntax_1.AssignmentPattern)
processAssignmentPattern(pattern, value, build, baseTempName);
else
build(pattern, value);
}
// -------------------------------------------------------------
// Transform:
// var { location: loc } = window,
// [{ location }, item] = [window, 6],
// -->
// var _hh$temp0 = window,
// loc = _hh$temp0.location,
// _hh$temp1 = [window, 6],
// _hh$temp1$0 = _hh$temp1[0],
// location = _hh$temp1$0.location,
// item = _hh$temp1[1];
// var [a, b] = c;
// -->
// var _hh$temp0 = __arrayFrom$(c),
// a = _hh$temp0[0],
// b = _hh$temp0[1];
var transformer$1 = {
name: 'declaration-destructuring',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.VariableDeclaration,
// @ts-ignore
condition: function (node, parent) {
// Skip: for (let { x } in some);
if ((parent === null || parent === void 0 ? void 0 : parent.type) === Syntax_1.ForInStatement)
return false;
for (var _i = 0, _a = node.declarations; _i < _a.length; _i++) {
var declarator = _a[_i];
if (declarator.id.type === Syntax_1.ObjectPattern || declarator.id.type === Syntax_1.ArrayPattern)
return true;
}
return false;
},
run: function (node) {
var declarations = [];
for (var _i = 0, _a = node.declarations; _i < _a.length; _i++) {
var declarator = _a[_i];
process(declarator.id, declarator.init || null, function (pattern, value) {
return declarations.push(createVariableDeclarator(pattern, value));
});
}
return createVariableDeclaration(node.kind, declarations);
},
};
// -------------------------------------------------------------
// Transform:
// ({ location: loc } = window);
// [{ location }, item] = [window, 6]
// -->
// var _hh$temp0, _hh$temp1, _hh$temp1$0;
//
// (_hh$temp0 = window, loc = _hh$temp0.location, _hh$temp0);
// (_hh$temp1 = [window, 6], _hh$temp1$0 = _hh$temp1[0], location = _hh$temp1$0.location, item = _hh$temp1[1], _hh$temp1);
var transformer = {
name: 'assignment-destructuring',
nodeReplacementRequireTransform: true,
nodeTypes: Syntax_1.AssignmentExpression,
condition: function (node) { return node.operator === '=' && (node.left.type === Syntax_1.ObjectPattern || node.left.type === Syntax_1.ArrayPattern); },
run: function (node, _parent, _key, tempVars) {
var assignments = [];
var isFirstTemp = true;
var firstTemp = null;
process(node.left, node.right, function (pattern, value, isTemp) {
if (isFirstTemp) {
isFirstTemp = false;
if (isTemp)
firstTemp = pattern;
}
assignments.push(createAssignmentExpression(pattern, '=', value));
if (isTemp && tempVars)
tempVars.append(pattern.name);
});
if (firstTemp)
assignments.push(firstTemp);
return createSequenceExpression(assignments);
},
};
// -------------------------------------------------------------
// Transform:
// function x ({a, b}, [c, d]) {}
// -->
// function x (_hh$temp0, _hh$temp1) {
// var {a, b} = _hh$temp0,
// [c, d] = _hh$temp1;
// }
function create$2(type) {
return {
name: 'func-args-destructing',
nodeReplacementRequireTransform: false,
nodeTypes: type,
condition: function (node) {
for (var _i = 0, _a = node.params; _i < _a.length; _i++) {
var param = _a[_i];
if (param.type === Syntax_1.AssignmentPattern)
param = param.left;
if (param.type === Syntax_1.ObjectPattern || param.type === Syntax_1.ArrayPattern)
return true;
}
return false;
},
run: function (node) {
var declarations = [];
for (var _i = 0, _a = node.params; _i < _a.length; _i++) {
var param = _a[_i];
var tempVarParent = node;
var tempVarKey = 'params';
if (param.type === Syntax_1.AssignmentPattern) {
// @ts-ignore
tempVarParent = param;
param = param.left;
tempVarKey = 'left';
}
if (param.type === Syntax_1.ObjectPattern && param.properties.length ||
param.type === Syntax_1.ArrayPattern && param.elements.length) {
var tempVar = createIdentifier(TempVariables.generateName());
// @ts-ignore
replaceNode(param, tempVar, tempVarParent, tempVarKey);
declarations.push(createVariableDeclarator(param, tempVar));
}
}
if (!declarations.length)
return null;
var declaration = createVariableDeclaration('var', declarations);
if (node.body.type !== Syntax_1.BlockStatement) {
// @ts-ignore
var returnStmt = createReturnStatement(node.body);
replaceNode(node.body, createBlockStatement([declaration, returnStmt]), node, 'body');
// @ts-ignore
node.expression = false;
return node;
}
replaceNode(null, declaration, node.body, 'body');
declaration.reTransform = true;
return null;
},
};
}
// -------------------------------------------------------------
var TRANSFORMERS = [
create$2(Syntax_1.FunctionDeclaration),
create$2(Syntax_1.FunctionExpression),
create$2(Syntax_1.ArrowFunctionExpression),
transformer,
transformer$l,
transformer$k,
transformer$j,
transformer$i,
transformer$h,
transformer$g,
transformer$f,
transformer$e,
transformer$d,
transformer$c,
transformer$b,
transformer$a,
forOfTransformer,
transformer$9,
transformer$8,
transformer$7,
transformer$6,
transformer$5,
transformer$4,
transformer$3,
transformer$2,
transformer$1,
];
function createTransformerMap() {
var transformerMap = new Map();
for (var _i = 0, TRANSFORMERS_1 = TRANSFORMERS; _i < TRANSFORMERS_1.length; _i++) {
var transformer = TRANSFORMERS_1[_i];
var nodeType = transformer.nodeTypes;
var transformers = transformerMap.get(nodeType);
if (!transformers) {
transformers = [];
transformerMap.set(nodeType, transformers);
}
transformers.push(transformer);
}
return transformerMap;
}
var transformers = createTransformerMap();
var STACK_FRAME_REG_EXPS = [
/^\s*at .*\((\S+)\)/,
/^\s*at (\S+)/,
/^.*@(\S+)/,
/(.+)/, // Any string
];
var STACK_FRAME_REGEX = /(?:^|\n)(?:\s*at |.*@)(?:.*\()?(\S+?):\d+:\d+\)?/g;
var ROW_COLUMN_NUMBER_REG_EX = /:\d+:\d+$/;
function getDestSource(source) {
var parsedProxiedUrl = parseProxyUrl$1(source);
return parsedProxiedUrl && parsedProxiedUrl.destUrl;
}
function replaceUrlWithProxied(str, source) {
source = source.replace(ROW_COLUMN_NUMBER_REG_EX, '');
var destUrl = getDestSource(source);
return destUrl ? str.replace(source, destUrl) : str;
}
function replaceProxiedUrlsInStack(stack) {
if (!stack)
return stack;
var stackFrames = stack.split('\n');
for (var i = 0; i < stackFrames.length; i++) {
var stackFrame = stackFrames[i];
for (var _i = 0, STACK_FRAME_REG_EXPS_1 = STACK_FRAME_REG_EXPS; _i < STACK_FRAME_REG_EXPS_1.length; _i++) {
var stackFrameRegExp = STACK_FRAME_REG_EXPS_1[_i];
if (stackFrameRegExp.test(stackFrame)) {
stackFrames[i] = stackFrame.replace(stackFrameRegExp, replaceUrlWithProxied);
break;
}
}
}
return stackFrames.join('\n');
}
function getFirstDestUrl(stack) {
if (!stack)
return null;
var searchResult = STACK_FRAME_REGEX.exec(stack);
while (searchResult) {
var destUrl = getDestSource(searchResult[1]);
if (destUrl) {
STACK_FRAME_REGEX.lastIndex = 0;
return destUrl;
}
searchResult = STACK_FRAME_REGEX.exec(stack);
}
return null;
}
var sharedStackProcessingUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
replaceProxiedUrlsInStack: replaceProxiedUrlsInStack,
getFirstDestUrl: getFirstDestUrl
});
var State = /** @class */ (function () {
function State() {
this.hasTransformedAncestor = false;
}
// NOTE: There is an issue with processing `new` expressions. `new a.src.b()` will be transformed
// to `new __get$(a, 'src').b()`, which is wrong. The correct result is `new (__get$(a, 'src')).b()`.
// To solve this problem, we add a 'state' entity. This entity stores the "new" expression, so that
// we can add it to the changes when the transformation is found.
State.create = function (currState, node, parent, key, hasTransformedAncestor) {
if (hasTransformedAncestor === void 0) { hasTransformedAncestor = false; }
var isNewExpression = node.type === Syntax_1.NewExpression;
var isNewExpressionAncestor = isNewExpression && !currState.newExpressionAncestor;
var newState = new State();
newState.hasTransformedAncestor = currState.hasTransformedAncestor || hasTransformedAncestor;
newState.newExpressionAncestor = isNewExpressionAncestor ? node : currState.newExpressionAncestor;
newState.newExpressionAncestorParent = isNewExpressionAncestor ? parent : currState.newExpressionAncestorParent;
// @ts-ignore
newState.newExpressionAncestorKey = isNewExpressionAncestor ? key : currState.newExpressionAncestorKey;
return newState;
};
return State;
}());
// NOTE: We should avoid using native object prototype methods,
// since they can be overriden by the client code. (GH-245)
var objectToString = Object.prototype.toString;
var objectKeys = Object.keys;
function getChange(node, parentType) {
/*eslint-disable @typescript-eslint/no-non-null-assertion*/
var start = node.originStart;
var end = node.originEnd;
/*eslint-disable @typescript-eslint/no-non-null-assertion*/
return { start: start, end: end, node: node, parentType: parentType };
}
function transformChildNodes(node, changes, state, tempVars) {
// @ts-ignore
var nodeKeys = objectKeys(node);
for (var _i = 0, nodeKeys_1 = nodeKeys; _i < nodeKeys_1.length; _i++) {
var key = nodeKeys_1[_i];
var childNode = node[key];
var stringifiedNode = objectToString.call(childNode);
if (stringifiedNode === '[object Array]') {
// @ts-ignore
var childNodes = childNode;
for (var _a = 0, childNodes_1 = childNodes; _a < childNodes_1.length; _a++) {
var nthNode = childNodes_1[_a];
// NOTE: Some items of ArrayExpression can be null
if (nthNode)
transform(nthNode, changes, state, node, key, tempVars);
}
}
else if (stringifiedNode === '[object Object]') {
// @ts-ignore
transform(childNode, changes, state, node, key, tempVars);
}
}
}
function isNodeTransformed(node) {
return node.originStart !== void 0 && node.originEnd !== void 0;
}
function addChangeForTransformedNode(state, changes, replacement, parentType) {
var hasTransformedAncestor = state.hasTransformedAncestor ||
state.newExpressionAncestor && isNodeTransformed(state.newExpressionAncestor);
if (hasTransformedAncestor)
return;
if (state.newExpressionAncestor && state.newExpressionAncestorParent) {
replaceNode(state.newExpressionAncestor, state.newExpressionAncestor, state.newExpressionAncestorParent, state.newExpressionAncestorKey);
changes.push(getChange(state.newExpressionAncestor, state.newExpressionAncestorParent.type));
}
else
changes.push(getChange(replacement, parentType));
}
function addTempVarsDeclaration(node, changes, state, tempVars) {
var names = tempVars.get();
if (!names.length)
return;
var declaration = createTempVarsDeclaration(names);
replaceNode(null, declaration, node, 'body');
addChangeForTransformedNode(state, changes, declaration, node.type);
}
function beforeTransform(wrapLastExprWithProcessHtml, resolver) {
if (wrapLastExprWithProcessHtml === void 0) { wrapLastExprWithProcessHtml = false; }
transformer$4.wrapLastExpr = wrapLastExprWithProcessHtml;
transformer$3.resolver = resolver;
var isServerSide = typeof window === 'undefined';
if (isServerSide) {
transformer$2.getBaseUrl = function () {
if (typeof transformer$2.baseUrl === 'undefined')
transformer$2.baseUrl = resolver ? parseProxyUrl$1(resolver('./')).destUrl : '';
return transformer$2.baseUrl;
};
}
else {
transformer$2.getBaseUrl = function () {
if (typeof transformer$2.baseUrl === 'undefined') {
var currentStack = new Error().stack;
// NOTE: IE11 doesn't give the error stack without the 'throw' statement and doesn't support the 'import' statement
transformer$2.baseUrl = currentStack && getFirstDestUrl(currentStack) || '';
}
return transformer$2.baseUrl;
};
}
}
function afterTransform() {
transformer$4.wrapLastExpr = false;
transformer$3.resolver = void 0;
transformer$2.baseUrl = void 0;
}
function findTransformer(node, parent) {
var nodeTransformers = transformers.get(node.type);
if (nodeTransformers) {
for (var _i = 0, nodeTransformers_1 = nodeTransformers; _i < nodeTransformers_1.length; _i++) {
var transformer = nodeTransformers_1[_i];
if (transformer.condition(node, parent))
return transformer;
}
}
return null;
}
function transform(node, changes, state, parent, key, tempVars) {
var allowTempVarAdd = node.type === Syntax_1.BlockStatement;
var nodeTransformed = false;
if (allowTempVarAdd)
tempVars = new TempVariables();
if (!node.reTransform && isNodeTransformed(node)) {
addChangeForTransformedNode(state, changes, node, parent.type);
nodeTransformed = true;
}
else {
var storedNode = node;
var transformer = findTransformer(node, parent);
var replacement = null;
while (transformer) {
replacement = transformer.run(replacement || node, parent, key, tempVars);
if (!replacement)
break;
nodeTransformed = true;
if (!transformer.nodeReplacementRequireTransform)
break;
transformer = findTransformer(replacement, parent);
node = replacement;
}
if (nodeTransformed && replacement) {
replaceNode(storedNode, replacement, parent, key);
addChangeForTransformedNode(state, changes, replacement, parent.type);
}
}
state = State.create(state, node, parent, key, nodeTransformed);
transformChildNodes(node, changes, state, tempVars);
if (allowTempVarAdd)
addTempVarsDeclaration(node, changes, state, tempVars);
}
function transformProgram(node, wrapLastExprWithProcessHtml, resolver) {
if (wrapLastExprWithProcessHtml === void 0) { wrapLastExprWithProcessHtml = false; }
var changes = [];
var state = new State();
var tempVars = new TempVariables();
TempVariables.resetCounter();
beforeTransform(wrapLastExprWithProcessHtml, resolver);
transformChildNodes(node, changes, state, tempVars);
addTempVarsDeclaration(node, changes, state, tempVars);
afterTransform();
return changes;
}
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
// NOTE: taken from https://github.com/benjamingr/RegExp.escape
function reEscape (str) {
return str.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&');
}
var SERVICE_ROUTES = {
hammerhead: '/hammerhead.js',
task: '/task.js',
iframeTask: '/iframe-task.js',
messaging: '/messaging',
transportWorker: '/transport-worker.js',
workerHammerhead: '/worker-hammerhead.js',
};
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
// NOTE: We should store the methods of the `JSON` object
// since they can be overridden by the client code.
var parse$1 = JSON.parse;
var stringify = JSON.stringify;
function isDOMNode(obj) {
if (typeof Node === 'object')
return obj instanceof Node;
return typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';
}
function isJQueryObj(obj) {
return !!(obj && obj.jquery);
}
function isSerializable(value) {
if (value) {
// NOTE: jquery object, DOM nodes and functions are disallowed obj types because we can't serialize them correctly
if (typeof value === 'function' || isJQueryObj(value) || isDOMNode(value))
return false;
if (typeof value === 'object') {
for (var prop in value) {
if (value.hasOwnProperty(prop) && !isSerializable(value[prop])) // eslint-disable-line no-prototype-builtins
return false;
}
}
}
return true;
}
var json = /*#__PURE__*/Object.freeze({
__proto__: null,
parse: parse$1,
stringify: stringify,
isSerializable: isSerializable
});
// -------------------------------------------------------------
var SCRIPT_PROCESSING_START_COMMENT = '/*hammerhead|script|start*/';
var SCRIPT_PROCESSING_END_COMMENT = '/*hammerhead|script|end*/';
var SCRIPT_PROCESSING_END_HEADER_COMMENT = '/*hammerhead|script|processing-header-end*/';
var STRICT_MODE_PLACEHOLDER = '{strict-placeholder}';
var SW_SCOPE_HEADER_VALUE = '{sw-scope-header-value}';
var WORKER_SETTINGS_PLACEHOLDER = '{worker-settings}';
var IMPORT_WORKER_HAMMERHEAD = "\nif (typeof importScripts !== \"undefined\" && /\\[native code]/g.test(importScripts.toString())) {\n var ".concat(SCRIPT_PROCESSING_INSTRUCTIONS.getWorkerSettings, " = function () {return ").concat(WORKER_SETTINGS_PLACEHOLDER, "};\n importScripts((location.origin || (location.protocol + \"//\" + location.host)) + \"").concat(SERVICE_ROUTES.workerHammerhead, "\");\n}\n");
var PROCESS_DOM_METHOD = "window['".concat(INTERNAL_PROPS.processDomMethodName, "'] && window['").concat(INTERNAL_PROPS.processDomMethodName, "']();");
function trim(val) {
return val.replace(/\n(?!$)\s*/g, '');
}
var PROXYLESS_HEADER = trim("\n ".concat(SCRIPT_PROCESSING_START_COMMENT, "\n ").concat(STRICT_MODE_PLACEHOLDER, "\n\n if (typeof window !== 'undefined' && window) {\n ").concat(PROCESS_DOM_METHOD, "\n }\n\n ").concat(SCRIPT_PROCESSING_END_HEADER_COMMENT, "\n"));
var HEADER = trim("\n ".concat(SCRIPT_PROCESSING_START_COMMENT, "\n ").concat(STRICT_MODE_PLACEHOLDER, "\n ").concat(SW_SCOPE_HEADER_VALUE, "\n\n if (typeof window !== 'undefined' && window){\n ").concat(PROCESS_DOM_METHOD, "\n\n if (window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty, " && typeof ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty, " === 'undefined')\n var ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getLocation, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getLocation, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.setLocation, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.setLocation, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.setProperty, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.setProperty, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.callMethod, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.callMethod, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getEval, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getEval, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.processScript, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.processScript, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.processHtml, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.processHtml, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProxyUrl, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProxyUrl, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.restArray, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.restArray, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.restObject, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.restObject, ",\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.arrayFrom, " = window.").concat(SCRIPT_PROCESSING_INSTRUCTIONS.arrayFrom, ";\n } else {\n if (typeof ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty, " === 'undefined')\n var ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getLocation, " = function(l){return l},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.setLocation, " = function(l,v){return l = v},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.setProperty, " = function(o,p,v){return o[p] = v},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty, " = function(o,p){return o[p]},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.callMethod, " = function(o,p,a){return o[p].apply(o,a)},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getEval, " = function(e){return e},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.processScript, " = function(s){return s},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.processHtml, " = function(h){return h},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage, " = function(w,p){return arguments.length===1?w.postMessage:p},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.getProxyUrl, " = function(u,d){return u},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.restArray, " = function(a,i){return Array.prototype.slice.call(a, i)},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.restObject, " = function(o,p){var k=Object.keys(o),n={};for(var i=0;i<k.length;++i)if(p.indexOf(k[i])<0)n[k[i]]=o[k[i]];return n},\n ").concat(SCRIPT_PROCESSING_INSTRUCTIONS.arrayFrom, " = function(r){if(!r)return r;return!Array.isArray(r)&&\"function\"==typeof r[Symbol.iterator]?Array.from(r):r};\n\n ").concat(IMPORT_WORKER_HAMMERHEAD, "\n }\n ").concat(SCRIPT_PROCESSING_END_HEADER_COMMENT, "\n"));
// NOTE: IE removes trailing newlines in script.textContent,
// so a trailing newline in RegExp is optional
var HEADER_RE = new RegExp("".concat(reEscape(SCRIPT_PROCESSING_START_COMMENT), "[\\S\\s]+?").concat(reEscape(SCRIPT_PROCESSING_END_HEADER_COMMENT), "\n?"), 'gi');
var PROCESSING_END_COMMENT_RE = new RegExp("\n?".concat(reEscape(SCRIPT_PROCESSING_END_COMMENT), "\\s*"), 'gi');
function remove$1(code) {
return code
.replace(HEADER_RE, '')
.replace(PROCESSING_END_COMMENT_RE, '');
}
function add$1(code, isStrictMode, swScopeHeaderValue, proxyless, workerSettings) {
var targetHeader = proxyless ? PROXYLESS_HEADER : HEADER;
var header = targetHeader
.replace(STRICT_MODE_PLACEHOLDER, isStrictMode ? '"use strict";' : '')
.replace(SW_SCOPE_HEADER_VALUE, swScopeHeaderValue ? "var ".concat(SCRIPT_PROCESSING_INSTRUCTIONS.swScopeHeaderValue, " = ").concat(stringify(swScopeHeaderValue), ";") : '')
.replace(WORKER_SETTINGS_PLACEHOLDER, workerSettings ? JSON.stringify(workerSettings) : 'null');
return header + code + '\n' + SCRIPT_PROCESSING_END_COMMENT;
}
var headerProcessingUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
SCRIPT_PROCESSING_START_COMMENT: SCRIPT_PROCESSING_START_COMMENT,
SCRIPT_PROCESSING_END_COMMENT: SCRIPT_PROCESSING_END_COMMENT,
SCRIPT_PROCESSING_END_HEADER_COMMENT: SCRIPT_PROCESSING_END_HEADER_COMMENT,
remove: remove$1,
add: add$1
});
var identifier = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.isIdentifierChar = isIdentifierChar;
exports.isIdentifierStart = isIdentifierStart;
exports.reservedWords = exports.keywords = exports.keywordRelationalOperator = void 0;
// Reserved word lists for various dialects of the language
var reservedWords = {
3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
5: "class enum extends super const export import",
6: "enum",
strict: "implements interface let package private protected public static yield",
strictBind: "eval arguments"
}; // And the keywords
exports.reservedWords = reservedWords;
var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this";
var keywords = {
5: ecma5AndLessKeywords,
"5module": ecma5AndLessKeywords + " export import",
6: ecma5AndLessKeywords + " const class extends export import super"
};
exports.keywords = keywords;
var keywordRelationalOperator = /^in(stanceof)?$/; // ## Character categories
// Big ugly regular expressions that match characters in the
// whitespace, identifier, and identifier-start categories. These
// are only applied when a character is found to actually have a
// code point above 128.
// Generated by `bin/generate-identifier-regex.js`.
exports.keywordRelationalOperator = keywordRelationalOperator;
var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u0870-\u0887\u0889-\u088e\u08a0-\u08c9\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c5d\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cdd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u1711\u171f-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4c\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ca\ua7d0\ua7d1\ua7d3\ua7d5-\ua7d9\ua7f2-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\u
var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u0898-\u089f\u08ca-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3c\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1715\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u180f-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf-\u1ace\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; // These are a run-length and offset encoded representation of the
// >0xffff code points that are a valid part of identifiers. The
// offset starts at 0x10000, and each pair of numbers represents an
// offset to the next range, and then a size of the range. They were
// generated by bin/generate-identifier-regex.js
// eslint-disable-next-line comma-spacing
var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 13, 10, 2, 14, 2, 6, 2, 1, 2, 10, 2, 14, 2, 6, 2, 1, 68, 310, 10, 21, 11, 7, 25, 5, 2, 41, 2, 8, 70, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 43, 17, 47, 20, 28, 22, 13, 52, 58, 1, 3, 0, 14, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 38, 6, 186, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 19, 72, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2637, 96, 16, 1070, 4050, 582, 8634, 568, 8, 30, 18, 78, 18, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8936, 3, 2, 6, 2, 1, 2, 290, 46, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 1845, 30, 482, 44, 11, 6, 17, 0, 322, 29, 19, 43, 1269, 6, 2, 3, 2, 1, 2, 14, 2, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42719, 33, 4152, 8, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; // eslint-disable-next-line comma-spacing
var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 50, 3, 123, 2, 54, 14, 32, 10, 3, 1, 11, 3, 46, 10, 8, 0, 46, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 87, 9, 39, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 4706, 45, 3, 22, 543, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 357, 0, 62, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; // This has a complexity linear to the value of the code. The
// assumption is that looking up astral identifier characters is
// rare.
function isInAstralSet(code, set) {
var pos = 0x10000;
for (var i = 0; i < set.length; i += 2) {
pos += set[i];
if (pos > code)
return false;
pos += set[i + 1];
if (pos >= code)
return true;
}
} // Test whether a given character code starts an identifier.
function isIdentifierStart(code, astral) {
if (code < 65)
return code === 36;
if (code < 91)
return true;
if (code < 97)
return code === 95;
if (code < 123)
return true;
if (code <= 0xffff)
return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));
if (astral === false)
return false;
return isInAstralSet(code, astralIdentifierStartCodes);
} // Test whether a given character is part of an identifier.
function isIdentifierChar(code, astral) {
if (code < 48)
return code === 36;
if (code < 58)
return true;
if (code < 65)
return false;
if (code < 91)
return true;
if (code < 97)
return code === 95;
if (code < 123)
return true;
if (code <= 0xffff)
return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));
if (astral === false)
return false;
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes);
}
});
var tokentype = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.types = exports.keywords = exports.TokenType = void 0;
// ## Token types
// The assignment of fine-grained, information-carrying type objects
// allows the tokenizer to store the information it has about a
// token in a way that is very cheap for the parser to look up.
// All token type variables start with an underscore, to make them
// easy to recognize.
// The `beforeExpr` property is used to disambiguate between regular
// expressions and divisions. It is set on all token types that can
// be followed by an expression (thus, a slash after them would be a
// regular expression).
//
// The `startsExpr` property is used to check if the token ends a
// `yield` expression. It is set on all token types that either can
// directly start an expression (like a quotation mark) or can
// continue an expression (like the body of a string).
//
// `isLoop` marks a keyword as starting a loop, which is important
// to know when parsing a label, in order to allow or disallow
// continue jumps to that label.
var TokenType = /** @class */ (function () {
function TokenType(label, conf) {
if (conf === void 0) { conf = {}; }
this.label = label;
this.keyword = conf.keyword;
this.beforeExpr = !!conf.beforeExpr;
this.startsExpr = !!conf.startsExpr;
this.isLoop = !!conf.isLoop;
this.isAssign = !!conf.isAssign;
this.prefix = !!conf.prefix;
this.postfix = !!conf.postfix;
this.binop = conf.binop || null;
this.updateContext = null;
}
return TokenType;
}());
exports.TokenType = TokenType;
function binop(name, prec) {
return new TokenType(name, {
beforeExpr: true,
binop: prec
});
}
var beforeExpr = {
beforeExpr: true
}, startsExpr = {
startsExpr: true
}; // Map keyword names to token types.
var keywords = {}; // Succinct definitions of keyword token types
exports.keywords = keywords;
function kw(name, options) {
if (options === void 0) { options = {}; }
options.keyword = name;
return keywords[name] = new TokenType(name, options);
}
var types = {
num: new TokenType("num", startsExpr),
regexp: new TokenType("regexp", startsExpr),
string: new TokenType("string", startsExpr),
name: new TokenType("name", startsExpr),
privateId: new TokenType("privateId", startsExpr),
eof: new TokenType("eof"),
// Punctuation token types.
bracketL: new TokenType("[", {
beforeExpr: true,
startsExpr: true
}),
bracketR: new TokenType("]"),
braceL: new TokenType("{", {
beforeExpr: true,
startsExpr: true
}),
braceR: new TokenType("}"),
parenL: new TokenType("(", {
beforeExpr: true,
startsExpr: true
}),
parenR: new TokenType(")"),
comma: new TokenType(",", beforeExpr),
semi: new TokenType(";", beforeExpr),
colon: new TokenType(":", beforeExpr),
dot: new TokenType("."),
question: new TokenType("?", beforeExpr),
questionDot: new TokenType("?."),
arrow: new TokenType("=>", beforeExpr),
template: new TokenType("template"),
invalidTemplate: new TokenType("invalidTemplate"),
ellipsis: new TokenType("...", beforeExpr),
backQuote: new TokenType("`", startsExpr),
dollarBraceL: new TokenType("${", {
beforeExpr: true,
startsExpr: true
}),
// Operators. These carry several kinds of properties to help the
// parser use them properly (the presence of these properties is
// what categorizes them as operators).
//
// `binop`, when present, specifies that this operator is a binary
// operator, and will refer to its precedence.
//
// `prefix` and `postfix` mark the operator as a prefix or postfix
// unary operator.
//
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
// binary operators with a very low precedence, that should result
// in AssignmentExpression nodes.
eq: new TokenType("=", {
beforeExpr: true,
isAssign: true
}),
assign: new TokenType("_=", {
beforeExpr: true,
isAssign: true
}),
incDec: new TokenType("++/--", {
prefix: true,
postfix: true,
startsExpr: true
}),
prefix: new TokenType("!/~", {
beforeExpr: true,
prefix: true,
startsExpr: true
}),
logicalOR: binop("||", 1),
logicalAND: binop("&&", 2),
bitwiseOR: binop("|", 3),
bitwiseXOR: binop("^", 4),
bitwiseAND: binop("&", 5),
equality: binop("==/!=/===/!==", 6),
relational: binop("</>/<=/>=", 7),
bitShift: binop("<</>>/>>>", 8),
plusMin: new TokenType("+/-", {
beforeExpr: true,
binop: 9,
prefix: true,
startsExpr: true
}),
modulo: binop("%", 10),
star: binop("*", 10),
slash: binop("/", 10),
starstar: new TokenType("**", {
beforeExpr: true
}),
coalesce: binop("??", 1),
// Keyword token types.
_break: kw("break"),
_case: kw("case", beforeExpr),
_catch: kw("catch"),
_continue: kw("continue"),
_debugger: kw("debugger"),
_default: kw("default", beforeExpr),
_do: kw("do", {
isLoop: true,
beforeExpr: true
}),
_else: kw("else", beforeExpr),
_finally: kw("finally"),
_for: kw("for", {
isLoop: true
}),
_function: kw("function", startsExpr),
_if: kw("if"),
_return: kw("return", beforeExpr),
_switch: kw("switch"),
_throw: kw("throw", beforeExpr),
_try: kw("try"),
_var: kw("var"),
_const: kw("const"),
_while: kw("while", {
isLoop: true
}),
_with: kw("with"),
_new: kw("new", {
beforeExpr: true,
startsExpr: true
}),
_this: kw("this", startsExpr),
_super: kw("super", startsExpr),
_class: kw("class", startsExpr),
_extends: kw("extends", beforeExpr),
_export: kw("export"),
_import: kw("import", startsExpr),
_null: kw("null", startsExpr),
_true: kw("true", startsExpr),
_false: kw("false", startsExpr),
_in: kw("in", {
beforeExpr: true,
binop: 7
}),
_instanceof: kw("instanceof", {
beforeExpr: true,
binop: 7
}),
_typeof: kw("typeof", {
beforeExpr: true,
prefix: true,
startsExpr: true
}),
_void: kw("void", {
beforeExpr: true,
prefix: true,
startsExpr: true
}),
_delete: kw("delete", {
beforeExpr: true,
prefix: true,
startsExpr: true
})
};
exports.types = types;
});
var whitespace = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.isNewLine = isNewLine;
exports.lineBreakG = exports.lineBreak = void 0;
exports.nextLineBreak = nextLineBreak;
exports.skipWhiteSpace = exports.nonASCIIwhitespace = void 0;
// Matches a whole line break (where CRLF is considered a single
// line break). Used to count lines.
var lineBreak = /\r\n?|\n|\u2028|\u2029/;
exports.lineBreak = lineBreak;
var lineBreakG = new RegExp(lineBreak.source, "g");
exports.lineBreakG = lineBreakG;
function isNewLine(code) {
return code === 10 || code === 13 || code === 0x2028 || code === 0x2029;
}
function nextLineBreak(code, from, end) {
if (end === void 0) { end = code.length; }
for (var i = from; i < end; i++) {
var next = code.charCodeAt(i);
if (isNewLine(next))
return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1;
}
return -1;
}
var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
exports.nonASCIIwhitespace = nonASCIIwhitespace;
var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
exports.skipWhiteSpace = skipWhiteSpace;
});
var util = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.loneSurrogate = exports.isArray = exports.hasOwn = void 0;
exports.wordsRegexp = wordsRegexp;
var _Object$prototype = Object.prototype, hasOwnProperty = _Object$prototype.hasOwnProperty, toString = _Object$prototype.toString;
var hasOwn = Object.hasOwn || (function (obj, propName) { return hasOwnProperty.call(obj, propName); });
exports.hasOwn = hasOwn;
var isArray = Array.isArray || (function (obj) { return toString.call(obj) === "[object Array]"; });
exports.isArray = isArray;
function wordsRegexp(words) {
return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$");
}
var loneSurrogate = /(?:[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/;
exports.loneSurrogate = loneSurrogate;
});
var locutil = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.SourceLocation = exports.Position = void 0;
exports.getLineInfo = getLineInfo;
// These are used when `options.locations` is on, for the
// `startLoc` and `endLoc` properties.
var Position = /** @class */ (function () {
function Position(line, col) {
this.line = line;
this.column = col;
}
Position.prototype.offset = function (n) {
return new Position(this.line, this.column + n);
};
return Position;
}());
exports.Position = Position;
var SourceLocation = /** @class */ (function () {
function SourceLocation(p, start, end) {
this.start = start;
this.end = end;
if (p.sourceFile !== null)
this.source = p.sourceFile;
}
return SourceLocation;
}()); // The `getLineInfo` function is mostly useful when the
// `locations` option is off (for performance reasons) and you
// want to find the line/column position for a given character
// offset. `input` should be the code string that the offset refers
// into.
exports.SourceLocation = SourceLocation;
function getLineInfo(input, offset) {
for (var line = 1, cur = 0;;) {
var nextBreak = (0, whitespace.nextLineBreak)(input, cur, offset);
if (nextBreak < 0)
return new Position(line, offset - cur);
++line;
cur = nextBreak;
}
}
});
var options = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.defaultOptions = void 0;
exports.getOptions = getOptions;
// A second argument must be given to configure the parser process.
// These options are recognized (only `ecmaVersion` is required):
var defaultOptions = {
// `ecmaVersion` indicates the ECMAScript version to parse. Must be
// either 3, 5, 6 (or 2015), 7 (2016), 8 (2017), 9 (2018), 10
// (2019), 11 (2020), 12 (2021), 13 (2022), or `"latest"` (the
// latest version the library supports). This influences support
// for strict mode, the set of reserved words, and support for
// new syntax features.
ecmaVersion: null,
// `sourceType` indicates the mode the code should be parsed in.
// Can be either `"script"` or `"module"`. This influences global
// strict mode and parsing of `import` and `export` declarations.
sourceType: "script",
// `onInsertedSemicolon` can be a callback that will be called
// when a semicolon is automatically inserted. It will be passed
// the position of the comma as an offset, and if `locations` is
// enabled, it is given the location as a `{line, column}` object
// as second argument.
onInsertedSemicolon: null,
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
// trailing commas.
onTrailingComma: null,
// By default, reserved words are only enforced if ecmaVersion >= 5.
// Set `allowReserved` to a boolean value to explicitly turn this on
// an off. When this option has the value "never", reserved words
// and keywords can also not be used as property names.
allowReserved: null,
// When enabled, a return at the top level is not considered an
// error.
allowReturnOutsideFunction: false,
// When enabled, import/export statements are not constrained to
// appearing at the top of the program, and an import.meta expression
// in a script isn't considered an error.
allowImportExportEverywhere: false,
// By default, await identifiers are allowed to appear at the top-level scope only if ecmaVersion >= 2022.
// When enabled, await identifiers are allowed to appear at the top-level scope,
// but they are still not allowed in non-async functions.
allowAwaitOutsideFunction: null,
// When enabled, super identifiers are not constrained to
// appearing in methods and do not raise an error when they appear elsewhere.
allowSuperOutsideMethod: null,
// When enabled, hashbang directive in the beginning of file
// is allowed and treated as a line comment.
allowHashBang: false,
// When `locations` is on, `loc` properties holding objects with
// `start` and `end` properties in `{line, column}` form (with
// line being 1-based and column 0-based) will be attached to the
// nodes.
locations: false,
// A function can be passed as `onToken` option, which will
// cause Acorn to call that function with object in the same
// format as tokens returned from `tokenizer().getToken()`. Note
// that you are not allowed to call the parser from the
// callback—that will corrupt its internal state.
onToken: null,
// A function can be passed as `onComment` option, which will
// cause Acorn to call that function with `(block, text, start,
// end)` parameters whenever a comment is skipped. `block` is a
// boolean indicating whether this is a block (`/* */`) comment,
// `text` is the content of the comment, and `start` and `end` are
// character offsets that denote the start and end of the comment.
// When the `locations` option is on, two more parameters are
// passed, the full `{line, column}` locations of the start and
// end of the comments. Note that you are not allowed to call the
// parser from the callback—that will corrupt its internal state.
onComment: null,
// Nodes have their start and end characters offsets recorded in
// `start` and `end` properties (directly on the node, rather than
// the `loc` object, which holds line/column data. To also add a
// [semi-standardized][range] `range` property holding a `[start,
// end]` array with the same numbers, set the `ranges` option to
// `true`.
//
// [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
ranges: false,
// It is possible to parse multiple files into a single AST by
// passing the tree produced by parsing the first file as
// `program` option in subsequent parses. This will add the
// toplevel forms of the parsed file to the `Program` (top) node
// of an existing parse tree.
program: null,
// When `locations` is on, you can pass this to record the source
// file in every node's `loc` object.
sourceFile: null,
// This value, if given, is stored in every node, whether
// `locations` is on or off.
directSourceFile: null,
// When enabled, parenthesized expressions are represented by
// (non-standard) ParenthesizedExpression nodes
preserveParens: false
}; // Interpret and default an options object
exports.defaultOptions = defaultOptions;
var warnedAboutEcmaVersion = false;
function getOptions(opts) {
var options = {};
for (var opt in defaultOptions)
options[opt] = opts && (0, util.hasOwn)(opts, opt) ? opts[opt] : defaultOptions[opt];
if (options.ecmaVersion === "latest") {
options.ecmaVersion = 1e8;
}
else if (options.ecmaVersion == null) {
if (!warnedAboutEcmaVersion && typeof console === "object" && console.warn) {
warnedAboutEcmaVersion = true;
console.warn("Since Acorn 8.0.0, options.ecmaVersion is required.\nDefaulting to 2020, but this will stop working in the future.");
}
options.ecmaVersion = 11;
}
else if (options.ecmaVersion >= 2015) {
options.ecmaVersion -= 2009;
}
if (options.allowReserved == null)
options.allowReserved = options.ecmaVersion < 5;
if ((0, util.isArray)(options.onToken)) {
var tokens_1 = options.onToken;
options.onToken = function (token) { return tokens_1.push(token); };
}
if ((0, util.isArray)(options.onComment))
options.onComment = pushComment(options, options.onComment);
return options;
}
function pushComment(options, array) {
return function (block, text, start, end, startLoc, endLoc) {
var comment = {
type: block ? "Block" : "Line",
value: text,
start: start,
end: end
};
if (options.locations)
comment.loc = new locutil.SourceLocation(this, startLoc, endLoc);
if (options.ranges)
comment.range = [start, end];
array.push(comment);
};
}
});
var scopeflags = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.SCOPE_VAR = exports.SCOPE_TOP = exports.SCOPE_SUPER = exports.SCOPE_SIMPLE_CATCH = exports.SCOPE_GENERATOR = exports.SCOPE_FUNCTION = exports.SCOPE_DIRECT_SUPER = exports.SCOPE_CLASS_STATIC_BLOCK = exports.SCOPE_ASYNC = exports.SCOPE_ARROW = exports.BIND_VAR = exports.BIND_SIMPLE_CATCH = exports.BIND_OUTSIDE = exports.BIND_NONE = exports.BIND_LEXICAL = exports.BIND_FUNCTION = void 0;
exports.functionFlags = functionFlags;
// Each scope gets a bitset that may contain these flags
var SCOPE_TOP = 1, SCOPE_FUNCTION = 2, SCOPE_ASYNC = 4, SCOPE_GENERATOR = 8, SCOPE_ARROW = 16, SCOPE_SIMPLE_CATCH = 32, SCOPE_SUPER = 64, SCOPE_DIRECT_SUPER = 128, SCOPE_CLASS_STATIC_BLOCK = 256, SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK;
exports.SCOPE_VAR = SCOPE_VAR;
exports.SCOPE_CLASS_STATIC_BLOCK = SCOPE_CLASS_STATIC_BLOCK;
exports.SCOPE_DIRECT_SUPER = SCOPE_DIRECT_SUPER;
exports.SCOPE_SUPER = SCOPE_SUPER;
exports.SCOPE_SIMPLE_CATCH = SCOPE_SIMPLE_CATCH;
exports.SCOPE_ARROW = SCOPE_ARROW;
exports.SCOPE_GENERATOR = SCOPE_GENERATOR;
exports.SCOPE_ASYNC = SCOPE_ASYNC;
exports.SCOPE_FUNCTION = SCOPE_FUNCTION;
exports.SCOPE_TOP = SCOPE_TOP;
function functionFlags(async, generator) {
return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0);
} // Used in checkLVal* and declareName to determine the type of a binding
var BIND_NONE = 0,
// Not a binding
BIND_VAR = 1,
// Var-style binding
BIND_LEXICAL = 2,
// Let- or const-style binding
BIND_FUNCTION = 3,
// Function declaration
BIND_SIMPLE_CATCH = 4,
// Simple (identifier pattern) catch binding
BIND_OUTSIDE = 5; // Special case for function names as bound inside the function
exports.BIND_OUTSIDE = BIND_OUTSIDE;
exports.BIND_SIMPLE_CATCH = BIND_SIMPLE_CATCH;
exports.BIND_FUNCTION = BIND_FUNCTION;
exports.BIND_LEXICAL = BIND_LEXICAL;
exports.BIND_VAR = BIND_VAR;
exports.BIND_NONE = BIND_NONE;
});
var state = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.Parser = void 0;
var Parser = /** @class */ (function () {
function Parser(options$1, input, startPos) {
this.options = options$1 = (0, options.getOptions)(options$1);
this.sourceFile = options$1.sourceFile;
this.keywords = (0, util.wordsRegexp)(identifier.keywords[options$1.ecmaVersion >= 6 ? 6 : options$1.sourceType === "module" ? "5module" : 5]);
var reserved = "";
if (options$1.allowReserved !== true) {
reserved = identifier.reservedWords[options$1.ecmaVersion >= 6 ? 6 : options$1.ecmaVersion === 5 ? 5 : 3];
if (options$1.sourceType === "module")
reserved += " await";
}
this.reservedWords = (0, util.wordsRegexp)(reserved);
var reservedStrict = (reserved ? reserved + " " : "") + identifier.reservedWords.strict;
this.reservedWordsStrict = (0, util.wordsRegexp)(reservedStrict);
this.reservedWordsStrictBind = (0, util.wordsRegexp)(reservedStrict + " " + identifier.reservedWords.strictBind);
this.input = String(input); // Used to signal to callers of `readWord1` whether the word
// contained any escape sequences. This is needed because words with
// escape sequences must not be interpreted as keywords.
this.containsEsc = false; // Set up token state
// The current position of the tokenizer in the input.
if (startPos) {
this.pos = startPos;
this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
this.curLine = this.input.slice(0, this.lineStart).split(whitespace.lineBreak).length;
}
else {
this.pos = this.lineStart = 0;
this.curLine = 1;
} // Properties of the current token:
// Its type
this.type = tokentype.types.eof; // For tokens that include more information than their type, the value
this.value = null; // Its start and end offset
this.start = this.end = this.pos; // And, if locations are used, the {line, column} object
// corresponding to those offsets
this.startLoc = this.endLoc = this.curPosition(); // Position information for the previous token
this.lastTokEndLoc = this.lastTokStartLoc = null;
this.lastTokStart = this.lastTokEnd = this.pos; // The context stack is used to superficially track syntactic
// context to predict whether a regular expression is allowed in a
// given position.
this.context = this.initialContext();
this.exprAllowed = true; // Figure out if it's a module code.
this.inModule = options$1.sourceType === "module";
this.strict = this.inModule || this.strictDirective(this.pos); // Used to signify the start of a potential arrow function
this.potentialArrowAt = -1;
this.potentialArrowInForAwait = false; // Positions to delayed-check that yield/await does not exist in default parameters.
this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; // Labels in scope.
this.labels = []; // Thus-far undefined exports.
this.undefinedExports = Object.create(null); // If enabled, skip leading hashbang line.
if (this.pos === 0 && options$1.allowHashBang && this.input.slice(0, 2) === "#!")
this.skipLineComment(2); // Scope tracking for duplicate variable names (see scope.js)
this.scopeStack = [];
this.enterScope(scopeflags.SCOPE_TOP); // For RegExp validation
this.regexpState = null; // The stack of private names.
// Each element has two properties: 'declared' and 'used'.
// When it exited from the outermost class definition, all used private names must be declared.
this.privateNameStack = [];
}
Parser.prototype.parse = function () {
var node = this.options.program || this.startNode();
this.nextToken();
return this.parseTopLevel(node);
};
Object.defineProperty(Parser.prototype, "inFunction", {
get: function () {
return (this.currentVarScope().flags & scopeflags.SCOPE_FUNCTION) > 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "inGenerator", {
get: function () {
return (this.currentVarScope().flags & scopeflags.SCOPE_GENERATOR) > 0 && !this.currentVarScope().inClassFieldInit;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "inAsync", {
get: function () {
return (this.currentVarScope().flags & scopeflags.SCOPE_ASYNC) > 0 && !this.currentVarScope().inClassFieldInit;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "canAwait", {
get: function () {
for (var i = this.scopeStack.length - 1; i >= 0; i--) {
var scope = this.scopeStack[i];
if (scope.inClassFieldInit || scope.flags & scopeflags.SCOPE_CLASS_STATIC_BLOCK)
return false;
if (scope.flags & scopeflags.SCOPE_FUNCTION)
return (scope.flags & scopeflags.SCOPE_ASYNC) > 0;
}
return this.inModule && this.options.ecmaVersion >= 13 || this.options.allowAwaitOutsideFunction;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "allowSuper", {
get: function () {
var _this$currentThisScop = this.currentThisScope(), flags = _this$currentThisScop.flags, inClassFieldInit = _this$currentThisScop.inClassFieldInit;
return (flags & scopeflags.SCOPE_SUPER) > 0 || inClassFieldInit || this.options.allowSuperOutsideMethod;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "allowDirectSuper", {
get: function () {
return (this.currentThisScope().flags & scopeflags.SCOPE_DIRECT_SUPER) > 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "treatFunctionsAsVar", {
get: function () {
return this.treatFunctionsAsVarInScope(this.currentScope());
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "allowNewDotTarget", {
get: function () {
var _this$currentThisScop2 = this.currentThisScope(), flags = _this$currentThisScop2.flags, inClassFieldInit = _this$currentThisScop2.inClassFieldInit;
return (flags & (scopeflags.SCOPE_FUNCTION | scopeflags.SCOPE_CLASS_STATIC_BLOCK)) > 0 || inClassFieldInit;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "inClassStaticBlock", {
get: function () {
return (this.currentVarScope().flags & scopeflags.SCOPE_CLASS_STATIC_BLOCK) > 0;
},
enumerable: false,
configurable: true
});
Parser.extend = function () {
var plugins = [];
for (var _i = 0; _i < arguments.length; _i++) {
plugins[_i] = arguments[_i];
}
var cls = this;
for (var i = 0; i < plugins.length; i++)
cls = plugins[i](cls);
return cls;
};
Parser.parse = function (input, options) {
return new this(options, input).parse();
};
Parser.parseExpressionAt = function (input, pos, options) {
var parser = new this(options, input, pos);
parser.nextToken();
return parser.parseExpression();
};
Parser.tokenizer = function (input, options) {
return new this(options, input);
};
return Parser;
}());
exports.Parser = Parser;
});
var DestructuringErrors_1 = DestructuringErrors;
var pp$5 = state.Parser.prototype; // ## Parser utilities
var literal = /^(?:'((?:\\.|[^'\\])*?)'|"((?:\\.|[^"\\])*?)")/;
pp$5.strictDirective = function (start) {
for (;;) {
// Try to find string literal.
whitespace.skipWhiteSpace.lastIndex = start;
start += whitespace.skipWhiteSpace.exec(this.input)[0].length;
var match = literal.exec(this.input.slice(start));
if (!match)
return false;
if ((match[1] || match[2]) === "use strict")
return false;
start += match[0].length; // Skip semicolon, if any.
whitespace.skipWhiteSpace.lastIndex = start;
start += whitespace.skipWhiteSpace.exec(this.input)[0].length;
if (this.input[start] === ";")
start++;
}
}; // Predicate that tests whether the next token is of the given
// type, and if yes, consumes it as a side effect.
pp$5.eat = function (type) {
if (this.type === type) {
this.next();
return true;
}
else {
return false;
}
}; // Tests whether parsed token is a contextual keyword.
pp$5.isContextual = function (name) {
return this.type === tokentype.types.name && this.value === name && !this.containsEsc;
}; // Consumes contextual keyword if possible.
pp$5.eatContextual = function (name) {
if (!this.isContextual(name))
return false;
this.next();
return true;
}; // Asserts that following token is given contextual keyword.
pp$5.expectContextual = function (name) {
if (!this.eatContextual(name))
this.unexpected();
}; // Test whether a semicolon can be inserted at the current position.
pp$5.canInsertSemicolon = function () {
return this.type === tokentype.types.eof || this.type === tokentype.types.braceR || whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
};
pp$5.insertSemicolon = function () {
if (this.canInsertSemicolon()) {
if (this.options.onInsertedSemicolon)
this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc);
return true;
}
}; // Consume a semicolon, or, failing that, see if we are allowed to
// pretend that there is a semicolon at this position.
pp$5.semicolon = function () {
if (!this.eat(tokentype.types.semi) && !this.insertSemicolon())
this.unexpected();
};
pp$5.afterTrailingComma = function (tokType, notNext) {
if (this.type === tokType) {
if (this.options.onTrailingComma)
this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc);
if (!notNext)
this.next();
return true;
}
}; // Expect a token of a given type. If found, consume it, otherwise,
// raise an unexpected token error.
pp$5.expect = function (type) {
this.eat(type) || this.unexpected();
}; // Raise an unexpected token error.
pp$5.unexpected = function (pos) {
this.raise(pos != null ? pos : this.start, "Unexpected token");
};
function DestructuringErrors() {
this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = this.doubleProto = -1;
}
pp$5.checkPatternErrors = function (refDestructuringErrors, isAssign) {
if (!refDestructuringErrors)
return;
if (refDestructuringErrors.trailingComma > -1)
this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element");
var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
if (parens > -1)
this.raiseRecoverable(parens, "Parenthesized pattern");
};
pp$5.checkExpressionErrors = function (refDestructuringErrors, andThrow) {
if (!refDestructuringErrors)
return false;
var shorthandAssign = refDestructuringErrors.shorthandAssign, doubleProto = refDestructuringErrors.doubleProto;
if (!andThrow)
return shorthandAssign >= 0 || doubleProto >= 0;
if (shorthandAssign >= 0)
this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns");
if (doubleProto >= 0)
this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property");
};
pp$5.checkYieldAwaitInDefaultParams = function () {
if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
this.raise(this.yieldPos, "Yield expression cannot be a default value");
if (this.awaitPos)
this.raise(this.awaitPos, "Await expression cannot be a default value");
};
pp$5.isSimpleAssignTarget = function (expr) {
if (expr.type === "ParenthesizedExpression")
return this.isSimpleAssignTarget(expr.expression);
return expr.type === "Identifier" || expr.type === "MemberExpression";
};
var parseutil = /*#__PURE__*/Object.defineProperty({
DestructuringErrors: DestructuringErrors_1
}, '__esModule', {value: true});
function _createForOfIteratorHelperLoose$2(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it)
return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray$2(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it)
o = it;
var i = 0;
return function () { if (i >= o.length)
return { done: true }; return { done: false, value: o[i++] }; };
} throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray$2(o, minLen) { if (!o)
return; if (typeof o === "string")
return _arrayLikeToArray$2(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor)
n = o.constructor.name; if (n === "Map" || n === "Set")
return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray$2(o, minLen); }
function _arrayLikeToArray$2(arr, len) { if (len == null || len > arr.length)
len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++)
arr2[i] = arr[i]; return arr2; }
var pp$4 = state.Parser.prototype; // ### Statement parsing
// Parse a program. Initializes the parser, reads any number of
// statements, and wraps them in a Program node. Optionally takes a
// `program` argument. If present, the statements will be appended
// to its body instead of creating a new node.
pp$4.parseTopLevel = function (node) {
var exports = Object.create(null);
if (!node.body)
node.body = [];
while (this.type !== tokentype.types.eof) {
var stmt = this.parseStatement(null, true, exports);
node.body.push(stmt);
}
if (this.inModule)
for (var _i = 0, _Object$keys = Object.keys(this.undefinedExports); _i < _Object$keys.length; _i++) {
var name_1 = _Object$keys[_i];
this.raiseRecoverable(this.undefinedExports[name_1].start, "Export '".concat(name_1, "' is not defined"));
}
this.adaptDirectivePrologue(node.body);
this.next();
node.sourceType = this.options.sourceType;
return this.finishNode(node, "Program");
};
var loopLabel = {
kind: "loop"
}, switchLabel = {
kind: "switch"
};
pp$4.isLet = function (context) {
if (this.options.ecmaVersion < 6 || !this.isContextual("let"))
return false;
whitespace.skipWhiteSpace.lastIndex = this.pos;
var skip = whitespace.skipWhiteSpace.exec(this.input);
var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); // For ambiguous cases, determine if a LexicalDeclaration (or only a
// Statement) is allowed here. If context is not empty then only a Statement
// is allowed. However, `let [` is an explicit negative lookahead for
// ExpressionStatement, so special-case it first.
if (nextCh === 91 || nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00)
return true; // '[', '/', astral
if (context)
return false;
if (nextCh === 123)
return true; // '{'
if ((0, identifier.isIdentifierStart)(nextCh, true)) {
var pos = next + 1;
while ((0, identifier.isIdentifierChar)(nextCh = this.input.charCodeAt(pos), true))
++pos;
if (nextCh === 92 || nextCh > 0xd7ff && nextCh < 0xdc00)
return true;
var ident = this.input.slice(next, pos);
if (!identifier.keywordRelationalOperator.test(ident))
return true;
}
return false;
}; // check 'async [no LineTerminator here] function'
// - 'async /*foo*/ function' is OK.
// - 'async /*\n*/ function' is invalid.
pp$4.isAsyncFunction = function () {
if (this.options.ecmaVersion < 8 || !this.isContextual("async"))
return false;
whitespace.skipWhiteSpace.lastIndex = this.pos;
var skip = whitespace.skipWhiteSpace.exec(this.input);
var next = this.pos + skip[0].length, after;
return !whitespace.lineBreak.test(this.input.slice(this.pos, next)) && this.input.slice(next, next + 8) === "function" && (next + 8 === this.input.length || !((0, identifier.isIdentifierChar)(after = this.input.charCodeAt(next + 8)) || after > 0xd7ff && after < 0xdc00));
}; // Parse a single statement.
//
// If expecting a statement and finding a slash operator, parse a
// regular expression literal. This is to handle cases like
// `if (foo) /blah/.exec(foo)`, where looking at the previous token
// does not help.
pp$4.parseStatement = function (context, topLevel, exports) {
var starttype = this.type, node = this.startNode(), kind;
if (this.isLet(context)) {
starttype = tokentype.types._var;
kind = "let";
} // Most types of statements are recognized by the keyword they
// start with. Many are trivial to parse, some require a bit of
// complexity.
switch (starttype) {
case tokentype.types._break:
case tokentype.types._continue:
return this.parseBreakContinueStatement(node, starttype.keyword);
case tokentype.types._debugger:
return this.parseDebuggerStatement(node);
case tokentype.types._do:
return this.parseDoStatement(node);
case tokentype.types._for:
return this.parseForStatement(node);
case tokentype.types._function:
// Function as sole body of either an if statement or a labeled statement
// works, but not when it is part of a labeled statement that is the sole
// body of an if statement.
if (context && (this.strict || context !== "if" && context !== "label") && this.options.ecmaVersion >= 6)
this.unexpected();
return this.parseFunctionStatement(node, false, !context);
case tokentype.types._class:
if (context)
this.unexpected();
return this.parseClass(node, true);
case tokentype.types._if:
return this.parseIfStatement(node);
case tokentype.types._return:
return this.parseReturnStatement(node);
case tokentype.types._switch:
return this.parseSwitchStatement(node);
case tokentype.types._throw:
return this.parseThrowStatement(node);
case tokentype.types._try:
return this.parseTryStatement(node);
case tokentype.types._const:
case tokentype.types._var:
kind = kind || this.value;
if (context && kind !== "var")
this.unexpected();
return this.parseVarStatement(node, kind);
case tokentype.types._while:
return this.parseWhileStatement(node);
case tokentype.types._with:
return this.parseWithStatement(node);
case tokentype.types.braceL:
return this.parseBlock(true, node);
case tokentype.types.semi:
return this.parseEmptyStatement(node);
case tokentype.types._export:
case tokentype.types._import:
if (this.options.ecmaVersion > 10 && starttype === tokentype.types._import) {
whitespace.skipWhiteSpace.lastIndex = this.pos;
var skip = whitespace.skipWhiteSpace.exec(this.input);
var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
if (nextCh === 40 || nextCh === 46) // '(' or '.'
return this.parseExpressionStatement(node, this.parseExpression());
}
if (!this.options.allowImportExportEverywhere) {
if (!topLevel)
this.raise(this.start, "'import' and 'export' may only appear at the top level");
if (!this.inModule)
this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'");
}
return starttype === tokentype.types._import ? this.parseImport(node) : this.parseExport(node, exports);
// If the statement does not start with a statement keyword or a
// brace, it's an ExpressionStatement or LabeledStatement. We
// simply start parsing an expression, and afterwards, if the
// next token is a colon and the expression was a simple
// Identifier node, we switch to interpreting it as a label.
default:
if (this.isAsyncFunction()) {
if (context)
this.unexpected();
this.next();
return this.parseFunctionStatement(node, true, !context);
}
var maybeName = this.value, expr = this.parseExpression();
if (starttype === tokentype.types.name && expr.type === "Identifier" && this.eat(tokentype.types.colon))
return this.parseLabeledStatement(node, maybeName, expr, context);
else
return this.parseExpressionStatement(node, expr);
}
};
pp$4.parseBreakContinueStatement = function (node, keyword) {
var isBreak = keyword === "break";
this.next();
if (this.eat(tokentype.types.semi) || this.insertSemicolon())
node.label = null;
else if (this.type !== tokentype.types.name)
this.unexpected();
else {
node.label = this.parseIdent();
this.semicolon();
} // Verify that there is an actual destination to break or
// continue to.
var i = 0;
for (; i < this.labels.length; ++i) {
var lab = this.labels[i];
if (node.label == null || lab.name === node.label.name) {
if (lab.kind != null && (isBreak || lab.kind === "loop"))
break;
if (node.label && isBreak)
break;
}
}
if (i === this.labels.length)
this.raise(node.start, "Unsyntactic " + keyword);
return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement");
};
pp$4.parseDebuggerStatement = function (node) {
this.next();
this.semicolon();
return this.finishNode(node, "DebuggerStatement");
};
pp$4.parseDoStatement = function (node) {
this.next();
this.labels.push(loopLabel);
node.body = this.parseStatement("do");
this.labels.pop();
this.expect(tokentype.types._while);
node.test = this.parseParenExpression();
if (this.options.ecmaVersion >= 6)
this.eat(tokentype.types.semi);
else
this.semicolon();
return this.finishNode(node, "DoWhileStatement");
}; // Disambiguating between a `for` and a `for`/`in` or `for`/`of`
// loop is non-trivial. Basically, we have to parse the init `var`
// statement or expression, disallowing the `in` operator (see
// the second parameter to `parseExpression`), and then check
// whether the next token is `in` or `of`. When there is no init
// part (semicolon immediately after the opening parenthesis), it
// is a regular `for` loop.
pp$4.parseForStatement = function (node) {
this.next();
var awaitAt = this.options.ecmaVersion >= 9 && this.canAwait && this.eatContextual("await") ? this.lastTokStart : -1;
this.labels.push(loopLabel);
this.enterScope(0);
this.expect(tokentype.types.parenL);
if (this.type === tokentype.types.semi) {
if (awaitAt > -1)
this.unexpected(awaitAt);
return this.parseFor(node, null);
}
var isLet = this.isLet();
if (this.type === tokentype.types._var || this.type === tokentype.types._const || isLet) {
var init_1 = this.startNode(), kind = isLet ? "let" : this.value;
this.next();
this.parseVar(init_1, true, kind);
this.finishNode(init_1, "VariableDeclaration");
if ((this.type === tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of")) && init_1.declarations.length === 1) {
if (this.options.ecmaVersion >= 9) {
if (this.type === tokentype.types._in) {
if (awaitAt > -1)
this.unexpected(awaitAt);
}
else
node.await = awaitAt > -1;
}
return this.parseForIn(node, init_1);
}
if (awaitAt > -1)
this.unexpected(awaitAt);
return this.parseFor(node, init_1);
}
var startsWithLet = this.isContextual("let"), isForOf = false;
var refDestructuringErrors = new parseutil.DestructuringErrors();
var init = this.parseExpression(awaitAt > -1 ? "await" : true, refDestructuringErrors);
if (this.type === tokentype.types._in || (isForOf = this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
if (this.options.ecmaVersion >= 9) {
if (this.type === tokentype.types._in) {
if (awaitAt > -1)
this.unexpected(awaitAt);
}
else
node.await = awaitAt > -1;
}
if (startsWithLet && isForOf)
this.raise(init.start, "The left-hand side of a for-of loop may not start with 'let'.");
this.toAssignable(init, false, refDestructuringErrors);
this.checkLValPattern(init);
return this.parseForIn(node, init);
}
else {
this.checkExpressionErrors(refDestructuringErrors, true);
}
if (awaitAt > -1)
this.unexpected(awaitAt);
return this.parseFor(node, init);
};
pp$4.parseFunctionStatement = function (node, isAsync, declarationPosition) {
this.next();
return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync);
};
pp$4.parseIfStatement = function (node) {
this.next();
node.test = this.parseParenExpression(); // allow function declarations in branches, but only in non-strict mode
node.consequent = this.parseStatement("if");
node.alternate = this.eat(tokentype.types._else) ? this.parseStatement("if") : null;
return this.finishNode(node, "IfStatement");
};
pp$4.parseReturnStatement = function (node) {
if (!this.inFunction && !this.options.allowReturnOutsideFunction)
this.raise(this.start, "'return' outside of function");
this.next(); // In `return` (and `break`/`continue`), the keywords with
// optional arguments, we eagerly look for a semicolon or the
// possibility to insert one.
if (this.eat(tokentype.types.semi) || this.insertSemicolon())
node.argument = null;
else {
node.argument = this.parseExpression();
this.semicolon();
}
return this.finishNode(node, "ReturnStatement");
};
pp$4.parseSwitchStatement = function (node) {
this.next();
node.discriminant = this.parseParenExpression();
node.cases = [];
this.expect(tokentype.types.braceL);
this.labels.push(switchLabel);
this.enterScope(0); // Statements under must be grouped (by label) in SwitchCase
// nodes. `cur` is used to keep the node that we are currently
// adding statements to.
var cur;
for (var sawDefault = false; this.type !== tokentype.types.braceR;) {
if (this.type === tokentype.types._case || this.type === tokentype.types._default) {
var isCase = this.type === tokentype.types._case;
if (cur)
this.finishNode(cur, "SwitchCase");
node.cases.push(cur = this.startNode());
cur.consequent = [];
this.next();
if (isCase) {
cur.test = this.parseExpression();
}
else {
if (sawDefault)
this.raiseRecoverable(this.lastTokStart, "Multiple default clauses");
sawDefault = true;
cur.test = null;
}
this.expect(tokentype.types.colon);
}
else {
if (!cur)
this.unexpected();
cur.consequent.push(this.parseStatement(null));
}
}
this.exitScope();
if (cur)
this.finishNode(cur, "SwitchCase");
this.next(); // Closing brace
this.labels.pop();
return this.finishNode(node, "SwitchStatement");
};
pp$4.parseThrowStatement = function (node) {
this.next();
if (whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
this.raise(this.lastTokEnd, "Illegal newline after throw");
node.argument = this.parseExpression();
this.semicolon();
return this.finishNode(node, "ThrowStatement");
}; // Reused empty array added for node fields that are always empty.
var empty$1 = [];
pp$4.parseTryStatement = function (node) {
this.next();
node.block = this.parseBlock();
node.handler = null;
if (this.type === tokentype.types._catch) {
var clause = this.startNode();
this.next();
if (this.eat(tokentype.types.parenL)) {
clause.param = this.parseBindingAtom();
var simple = clause.param.type === "Identifier";
this.enterScope(simple ? scopeflags.SCOPE_SIMPLE_CATCH : 0);
this.checkLValPattern(clause.param, simple ? scopeflags.BIND_SIMPLE_CATCH : scopeflags.BIND_LEXICAL);
this.expect(tokentype.types.parenR);
}
else {
if (this.options.ecmaVersion < 10)
this.unexpected();
clause.param = null;
this.enterScope(0);
}
clause.body = this.parseBlock(false);
this.exitScope();
node.handler = this.finishNode(clause, "CatchClause");
}
node.finalizer = this.eat(tokentype.types._finally) ? this.parseBlock() : null;
if (!node.handler && !node.finalizer)
this.raise(node.start, "Missing catch or finally clause");
return this.finishNode(node, "TryStatement");
};
pp$4.parseVarStatement = function (node, kind) {
this.next();
this.parseVar(node, false, kind);
this.semicolon();
return this.finishNode(node, "VariableDeclaration");
};
pp$4.parseWhileStatement = function (node) {
this.next();
node.test = this.parseParenExpression();
this.labels.push(loopLabel);
node.body = this.parseStatement("while");
this.labels.pop();
return this.finishNode(node, "WhileStatement");
};
pp$4.parseWithStatement = function (node) {
if (this.strict)
this.raise(this.start, "'with' in strict mode");
this.next();
node.object = this.parseParenExpression();
node.body = this.parseStatement("with");
return this.finishNode(node, "WithStatement");
};
pp$4.parseEmptyStatement = function (node) {
this.next();
return this.finishNode(node, "EmptyStatement");
};
pp$4.parseLabeledStatement = function (node, maybeName, expr, context) {
for (var _iterator = _createForOfIteratorHelperLoose$2(this.labels), _step; !(_step = _iterator()).done;) {
var label = _step.value;
if (label.name === maybeName)
this.raise(expr.start, "Label '" + maybeName + "' is already declared");
}
var kind = this.type.isLoop ? "loop" : this.type === tokentype.types._switch ? "switch" : null;
for (var i = this.labels.length - 1; i >= 0; i--) {
var label = this.labels[i];
if (label.statementStart === node.start) {
// Update information about previous labels on this node
label.statementStart = this.start;
label.kind = kind;
}
else
break;
}
this.labels.push({
name: maybeName,
kind: kind,
statementStart: this.start
});
node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label");
this.labels.pop();
node.label = expr;
return this.finishNode(node, "LabeledStatement");
};
pp$4.parseExpressionStatement = function (node, expr) {
node.expression = expr;
this.semicolon();
return this.finishNode(node, "ExpressionStatement");
}; // Parse a semicolon-enclosed block of statements, handling `"use
// strict"` declarations when `allowStrict` is true (used for
// function bodies).
pp$4.parseBlock = function (createNewLexicalScope, node, exitStrict) {
if (createNewLexicalScope === void 0) { createNewLexicalScope = true; }
if (node === void 0) { node = this.startNode(); }
node.body = [];
this.expect(tokentype.types.braceL);
if (createNewLexicalScope)
this.enterScope(0);
while (this.type !== tokentype.types.braceR) {
var stmt = this.parseStatement(null);
node.body.push(stmt);
}
if (exitStrict)
this.strict = false;
this.next();
if (createNewLexicalScope)
this.exitScope();
return this.finishNode(node, "BlockStatement");
}; // Parse a regular `for` loop. The disambiguation code in
// `parseStatement` will already have parsed the init statement or
// expression.
pp$4.parseFor = function (node, init) {
node.init = init;
this.expect(tokentype.types.semi);
node.test = this.type === tokentype.types.semi ? null : this.parseExpression();
this.expect(tokentype.types.semi);
node.update = this.type === tokentype.types.parenR ? null : this.parseExpression();
this.expect(tokentype.types.parenR);
node.body = this.parseStatement("for");
this.exitScope();
this.labels.pop();
return this.finishNode(node, "ForStatement");
}; // Parse a `for`/`in` and `for`/`of` loop, which are almost
// same from parser's perspective.
pp$4.parseForIn = function (node, init) {
var isForIn = this.type === tokentype.types._in;
this.next();
if (init.type === "VariableDeclaration" && init.declarations[0].init != null && (!isForIn || this.options.ecmaVersion < 8 || this.strict || init.kind !== "var" || init.declarations[0].id.type !== "Identifier")) {
this.raise(init.start, "".concat(isForIn ? "for-in" : "for-of", " loop variable declaration may not have an initializer"));
}
node.left = init;
node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign();
this.expect(tokentype.types.parenR);
node.body = this.parseStatement("for");
this.exitScope();
this.labels.pop();
return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement");
}; // Parse a list of variable declarations.
pp$4.parseVar = function (node, isFor, kind) {
node.declarations = [];
node.kind = kind;
for (;;) {
var decl = this.startNode();
this.parseVarId(decl, kind);
if (this.eat(tokentype.types.eq)) {
decl.init = this.parseMaybeAssign(isFor);
}
else if (kind === "const" && !(this.type === tokentype.types._in || this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
this.unexpected();
}
else if (decl.id.type !== "Identifier" && !(isFor && (this.type === tokentype.types._in || this.isContextual("of")))) {
this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value");
}
else {
decl.init = null;
}
node.declarations.push(this.finishNode(decl, "VariableDeclarator"));
if (!this.eat(tokentype.types.comma))
break;
}
return node;
};
pp$4.parseVarId = function (decl, kind) {
decl.id = this.parseBindingAtom();
this.checkLValPattern(decl.id, kind === "var" ? scopeflags.BIND_VAR : scopeflags.BIND_LEXICAL, false);
};
var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; // Parse a function declaration or literal (depending on the
// `statement & FUNC_STATEMENT`).
// Remove `allowExpressionBody` for 7.0.0, as it is only called with false
pp$4.parseFunction = function (node, statement, allowExpressionBody, isAsync, forInit) {
this.initFunction(node);
if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) {
if (this.type === tokentype.types.star && statement & FUNC_HANGING_STATEMENT)
this.unexpected();
node.generator = this.eat(tokentype.types.star);
}
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync;
if (statement & FUNC_STATEMENT) {
node.id = statement & FUNC_NULLABLE_ID && this.type !== tokentype.types.name ? null : this.parseIdent();
if (node.id && !(statement & FUNC_HANGING_STATEMENT)) // If it is a regular function declaration in sloppy mode, then it is
// subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding
// mode depends on properties of the current scope (see
// treatFunctionsAsVar).
this.checkLValSimple(node.id, this.strict || node.generator || node.async ? this.treatFunctionsAsVar ? scopeflags.BIND_VAR : scopeflags.BIND_LEXICAL : scopeflags.BIND_FUNCTION);
}
var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
this.yieldPos = 0;
this.awaitPos = 0;
this.awaitIdentPos = 0;
this.enterScope((0, scopeflags.functionFlags)(node.async, node.generator));
if (!(statement & FUNC_STATEMENT))
node.id = this.type === tokentype.types.name ? this.parseIdent() : null;
this.parseFunctionParams(node);
this.parseFunctionBody(node, allowExpressionBody, false, forInit);
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.awaitIdentPos = oldAwaitIdentPos;
return this.finishNode(node, statement & FUNC_STATEMENT ? "FunctionDeclaration" : "FunctionExpression");
};
pp$4.parseFunctionParams = function (node) {
this.expect(tokentype.types.parenL);
node.params = this.parseBindingList(tokentype.types.parenR, false, this.options.ecmaVersion >= 8);
this.checkYieldAwaitInDefaultParams();
}; // Parse a class declaration or literal (depending on the
// `isStatement` parameter).
pp$4.parseClass = function (node, isStatement) {
this.next(); // ecma-262 14.6 Class Definitions
// A class definition is always strict mode code.
var oldStrict = this.strict;
this.strict = true;
this.parseClassId(node, isStatement);
this.parseClassSuper(node);
var privateNameMap = this.enterClassBody();
var classBody = this.startNode();
var hadConstructor = false;
classBody.body = [];
this.expect(tokentype.types.braceL);
while (this.type !== tokentype.types.braceR) {
var element = this.parseClassElement(node.superClass !== null);
if (element) {
classBody.body.push(element);
if (element.type === "MethodDefinition" && element.kind === "constructor") {
if (hadConstructor)
this.raise(element.start, "Duplicate constructor in the same class");
hadConstructor = true;
}
else if (element.key && element.key.type === "PrivateIdentifier" && isPrivateNameConflicted(privateNameMap, element)) {
this.raiseRecoverable(element.key.start, "Identifier '#".concat(element.key.name, "' has already been declared"));
}
}
}
this.strict = oldStrict;
this.next();
node.body = this.finishNode(classBody, "ClassBody");
this.exitClassBody();
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
};
pp$4.parseClassElement = function (constructorAllowsSuper) {
if (this.eat(tokentype.types.semi))
return null;
var ecmaVersion = this.options.ecmaVersion;
var node = this.startNode();
var keyName = "";
var isGenerator = false;
var isAsync = false;
var kind = "method";
var isStatic = false;
if (this.eatContextual("static")) {
// Parse static init block
if (ecmaVersion >= 13 && this.eat(tokentype.types.braceL)) {
this.parseClassStaticBlock(node);
return node;
}
if (this.isClassElementNameStart() || this.type === tokentype.types.star) {
isStatic = true;
}
else {
keyName = "static";
}
}
node.static = isStatic;
if (!keyName && ecmaVersion >= 8 && this.eatContextual("async")) {
if ((this.isClassElementNameStart() || this.type === tokentype.types.star) && !this.canInsertSemicolon()) {
isAsync = true;
}
else {
keyName = "async";
}
}
if (!keyName && (ecmaVersion >= 9 || !isAsync) && this.eat(tokentype.types.star)) {
isGenerator = true;
}
if (!keyName && !isAsync && !isGenerator) {
var lastValue = this.value;
if (this.eatContextual("get") || this.eatContextual("set")) {
if (this.isClassElementNameStart()) {
kind = lastValue;
}
else {
keyName = lastValue;
}
}
} // Parse element name
if (keyName) {
// 'async', 'get', 'set', or 'static' were not a keyword contextually.
// The last token is any of those. Make it the element name.
node.computed = false;
node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc);
node.key.name = keyName;
this.finishNode(node.key, "Identifier");
}
else {
this.parseClassElementName(node);
} // Parse element value
if (ecmaVersion < 13 || this.type === tokentype.types.parenL || kind !== "method" || isGenerator || isAsync) {
var isConstructor = !node.static && checkKeyName(node, "constructor");
var allowsDirectSuper = isConstructor && constructorAllowsSuper; // Couldn't move this check into the 'parseClassMethod' method for backward compatibility.
if (isConstructor && kind !== "method")
this.raise(node.key.start, "Constructor can't have get/set modifier");
node.kind = isConstructor ? "constructor" : kind;
this.parseClassMethod(node, isGenerator, isAsync, allowsDirectSuper);
}
else {
this.parseClassField(node);
}
return node;
};
pp$4.isClassElementNameStart = function () {
return this.type === tokentype.types.name || this.type === tokentype.types.privateId || this.type === tokentype.types.num || this.type === tokentype.types.string || this.type === tokentype.types.bracketL || this.type.keyword;
};
pp$4.parseClassElementName = function (element) {
if (this.type === tokentype.types.privateId) {
if (this.value === "constructor") {
this.raise(this.start, "Classes can't have an element named '#constructor'");
}
element.computed = false;
element.key = this.parsePrivateIdent();
}
else {
this.parsePropertyName(element);
}
};
pp$4.parseClassMethod = function (method, isGenerator, isAsync, allowsDirectSuper) {
// Check key and flags
var key = method.key;
if (method.kind === "constructor") {
if (isGenerator)
this.raise(key.start, "Constructor can't be a generator");
if (isAsync)
this.raise(key.start, "Constructor can't be an async method");
}
else if (method.static && checkKeyName(method, "prototype")) {
this.raise(key.start, "Classes may not have a static property named prototype");
} // Parse value
var value = method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); // Check value
if (method.kind === "get" && value.params.length !== 0)
this.raiseRecoverable(value.start, "getter should have no params");
if (method.kind === "set" && value.params.length !== 1)
this.raiseRecoverable(value.start, "setter should have exactly one param");
if (method.kind === "set" && value.params[0].type === "RestElement")
this.raiseRecoverable(value.params[0].start, "Setter cannot use rest params");
return this.finishNode(method, "MethodDefinition");
};
pp$4.parseClassField = function (field) {
if (checkKeyName(field, "constructor")) {
this.raise(field.key.start, "Classes can't have a field named 'constructor'");
}
else if (field.static && checkKeyName(field, "prototype")) {
this.raise(field.key.start, "Classes can't have a static field named 'prototype'");
}
if (this.eat(tokentype.types.eq)) {
// To raise SyntaxError if 'arguments' exists in the initializer.
var scope = this.currentThisScope();
var inClassFieldInit = scope.inClassFieldInit;
scope.inClassFieldInit = true;
field.value = this.parseMaybeAssign();
scope.inClassFieldInit = inClassFieldInit;
}
else {
field.value = null;
}
this.semicolon();
return this.finishNode(field, "PropertyDefinition");
};
pp$4.parseClassStaticBlock = function (node) {
node.body = [];
var oldLabels = this.labels;
this.labels = [];
this.enterScope(scopeflags.SCOPE_CLASS_STATIC_BLOCK | scopeflags.SCOPE_SUPER);
while (this.type !== tokentype.types.braceR) {
var stmt = this.parseStatement(null);
node.body.push(stmt);
}
this.next();
this.exitScope();
this.labels = oldLabels;
return this.finishNode(node, "StaticBlock");
};
pp$4.parseClassId = function (node, isStatement) {
if (this.type === tokentype.types.name) {
node.id = this.parseIdent();
if (isStatement)
this.checkLValSimple(node.id, scopeflags.BIND_LEXICAL, false);
}
else {
if (isStatement === true)
this.unexpected();
node.id = null;
}
};
pp$4.parseClassSuper = function (node) {
node.superClass = this.eat(tokentype.types._extends) ? this.parseExprSubscripts(false) : null;
};
pp$4.enterClassBody = function () {
var element = {
declared: Object.create(null),
used: []
};
this.privateNameStack.push(element);
return element.declared;
};
pp$4.exitClassBody = function () {
var _this$privateNameStac = this.privateNameStack.pop(), declared = _this$privateNameStac.declared, used = _this$privateNameStac.used;
var len = this.privateNameStack.length;
var parent = len === 0 ? null : this.privateNameStack[len - 1];
for (var i = 0; i < used.length; ++i) {
var id = used[i];
if (!(0, util.hasOwn)(declared, id.name)) {
if (parent) {
parent.used.push(id);
}
else {
this.raiseRecoverable(id.start, "Private field '#".concat(id.name, "' must be declared in an enclosing class"));
}
}
}
};
function isPrivateNameConflicted(privateNameMap, element) {
var name = element.key.name;
var curr = privateNameMap[name];
var next = "true";
if (element.type === "MethodDefinition" && (element.kind === "get" || element.kind === "set")) {
next = (element.static ? "s" : "i") + element.kind;
} // `class { get #a(){}; static set #a(_){} }` is also conflict.
if (curr === "iget" && next === "iset" || curr === "iset" && next === "iget" || curr === "sget" && next === "sset" || curr === "sset" && next === "sget") {
privateNameMap[name] = "true";
return false;
}
else if (!curr) {
privateNameMap[name] = next;
return false;
}
else {
return true;
}
}
function checkKeyName(node, name) {
var computed = node.computed, key = node.key;
return !computed && (key.type === "Identifier" && key.name === name || key.type === "Literal" && key.value === name);
} // Parses module export declaration.
pp$4.parseExport = function (node, exports) {
this.next(); // export * from '...'
if (this.eat(tokentype.types.star)) {
if (this.options.ecmaVersion >= 11) {
if (this.eatContextual("as")) {
node.exported = this.parseModuleExportName();
this.checkExport(exports, node.exported.name, this.lastTokStart);
}
else {
node.exported = null;
}
}
this.expectContextual("from");
if (this.type !== tokentype.types.string)
this.unexpected();
node.source = this.parseExprAtom();
this.semicolon();
return this.finishNode(node, "ExportAllDeclaration");
}
if (this.eat(tokentype.types._default)) {
// export default ...
this.checkExport(exports, "default", this.lastTokStart);
var isAsync = void 0;
if (this.type === tokentype.types._function || (isAsync = this.isAsyncFunction())) {
var fNode = this.startNode();
this.next();
if (isAsync)
this.next();
node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync);
}
else if (this.type === tokentype.types._class) {
var cNode = this.startNode();
node.declaration = this.parseClass(cNode, "nullableID");
}
else {
node.declaration = this.parseMaybeAssign();
this.semicolon();
}
return this.finishNode(node, "ExportDefaultDeclaration");
} // export var|const|let|function|class ...
if (this.shouldParseExportStatement()) {
node.declaration = this.parseStatement(null);
if (node.declaration.type === "VariableDeclaration")
this.checkVariableExport(exports, node.declaration.declarations);
else
this.checkExport(exports, node.declaration.id.name, node.declaration.id.start);
node.specifiers = [];
node.source = null;
}
else {
// export { x, y as z } [from '...']
node.declaration = null;
node.specifiers = this.parseExportSpecifiers(exports);
if (this.eatContextual("from")) {
if (this.type !== tokentype.types.string)
this.unexpected();
node.source = this.parseExprAtom();
}
else {
for (var _iterator2 = _createForOfIteratorHelperLoose$2(node.specifiers), _step2; !(_step2 = _iterator2()).done;) {
var spec = _step2.value;
// check for keywords used as local names
this.checkUnreserved(spec.local); // check if export is defined
this.checkLocalExport(spec.local);
if (spec.local.type === "Literal") {
this.raise(spec.local.start, "A string literal cannot be used as an exported binding without `from`.");
}
}
node.source = null;
}
this.semicolon();
}
return this.finishNode(node, "ExportNamedDeclaration");
};
pp$4.checkExport = function (exports, name, pos) {
if (!exports)
return;
if ((0, util.hasOwn)(exports, name))
this.raiseRecoverable(pos, "Duplicate export '" + name + "'");
exports[name] = true;
};
pp$4.checkPatternExport = function (exports, pat) {
var type = pat.type;
if (type === "Identifier")
this.checkExport(exports, pat.name, pat.start);
else if (type === "ObjectPattern") {
for (var _iterator3 = _createForOfIteratorHelperLoose$2(pat.properties), _step3; !(_step3 = _iterator3()).done;) {
var prop = _step3.value;
this.checkPatternExport(exports, prop);
}
}
else if (type === "ArrayPattern") {
for (var _iterator4 = _createForOfIteratorHelperLoose$2(pat.elements), _step4; !(_step4 = _iterator4()).done;) {
var elt = _step4.value;
if (elt)
this.checkPatternExport(exports, elt);
}
}
else if (type === "Property")
this.checkPatternExport(exports, pat.value);
else if (type === "AssignmentPattern")
this.checkPatternExport(exports, pat.left);
else if (type === "RestElement")
this.checkPatternExport(exports, pat.argument);
else if (type === "ParenthesizedExpression")
this.checkPatternExport(exports, pat.expression);
};
pp$4.checkVariableExport = function (exports, decls) {
if (!exports)
return;
for (var _iterator5 = _createForOfIteratorHelperLoose$2(decls), _step5; !(_step5 = _iterator5()).done;) {
var decl = _step5.value;
this.checkPatternExport(exports, decl.id);
}
};
pp$4.shouldParseExportStatement = function () {
return this.type.keyword === "var" || this.type.keyword === "const" || this.type.keyword === "class" || this.type.keyword === "function" || this.isLet() || this.isAsyncFunction();
}; // Parses a comma-separated list of module exports.
pp$4.parseExportSpecifiers = function (exports) {
var nodes = [], first = true; // export { x, y as z } [from '...']
this.expect(tokentype.types.braceL);
while (!this.eat(tokentype.types.braceR)) {
if (!first) {
this.expect(tokentype.types.comma);
if (this.afterTrailingComma(tokentype.types.braceR))
break;
}
else
first = false;
var node = this.startNode();
node.local = this.parseModuleExportName();
node.exported = this.eatContextual("as") ? this.parseModuleExportName() : node.local;
this.checkExport(exports, node.exported[node.exported.type === "Identifier" ? "name" : "value"], node.exported.start);
nodes.push(this.finishNode(node, "ExportSpecifier"));
}
return nodes;
}; // Parses import declaration.
pp$4.parseImport = function (node) {
this.next(); // import '...'
if (this.type === tokentype.types.string) {
node.specifiers = empty$1;
node.source = this.parseExprAtom();
}
else {
node.specifiers = this.parseImportSpecifiers();
this.expectContextual("from");
node.source = this.type === tokentype.types.string ? this.parseExprAtom() : this.unexpected();
}
this.semicolon();
return this.finishNode(node, "ImportDeclaration");
}; // Parses a comma-separated list of module imports.
pp$4.parseImportSpecifiers = function () {
var nodes = [], first = true;
if (this.type === tokentype.types.name) {
// import defaultObj, { x, y as z } from '...'
var node = this.startNode();
node.local = this.parseIdent();
this.checkLValSimple(node.local, scopeflags.BIND_LEXICAL);
nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
if (!this.eat(tokentype.types.comma))
return nodes;
}
if (this.type === tokentype.types.star) {
var node = this.startNode();
this.next();
this.expectContextual("as");
node.local = this.parseIdent();
this.checkLValSimple(node.local, scopeflags.BIND_LEXICAL);
nodes.push(this.finishNode(node, "ImportNamespaceSpecifier"));
return nodes;
}
this.expect(tokentype.types.braceL);
while (!this.eat(tokentype.types.braceR)) {
if (!first) {
this.expect(tokentype.types.comma);
if (this.afterTrailingComma(tokentype.types.braceR))
break;
}
else
first = false;
var node = this.startNode();
node.imported = this.parseModuleExportName();
if (this.eatContextual("as")) {
node.local = this.parseIdent();
}
else {
this.checkUnreserved(node.imported);
node.local = node.imported;
}
this.checkLValSimple(node.local, scopeflags.BIND_LEXICAL);
nodes.push(this.finishNode(node, "ImportSpecifier"));
}
return nodes;
};
pp$4.parseModuleExportName = function () {
if (this.options.ecmaVersion >= 13 && this.type === tokentype.types.string) {
var stringLiteral = this.parseLiteral(this.value);
if (util.loneSurrogate.test(stringLiteral.value)) {
this.raise(stringLiteral.start, "An export name cannot include a lone surrogate.");
}
return stringLiteral;
}
return this.parseIdent(true);
}; // Set `ExpressionStatement#directive` property for directive prologues.
pp$4.adaptDirectivePrologue = function (statements) {
for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) {
statements[i].directive = statements[i].expression.raw.slice(1, -1);
}
};
pp$4.isDirectiveCandidate = function (statement) {
return statement.type === "ExpressionStatement" && statement.expression.type === "Literal" && typeof statement.expression.value === "string" && ( // Reject parenthesized strings.
this.input[statement.start] === "\"" || this.input[statement.start] === "'");
};
function _createForOfIteratorHelperLoose$1(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it)
return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray$1(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it)
o = it;
var i = 0;
return function () { if (i >= o.length)
return { done: true }; return { done: false, value: o[i++] }; };
} throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray$1(o, minLen) { if (!o)
return; if (typeof o === "string")
return _arrayLikeToArray$1(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor)
n = o.constructor.name; if (n === "Map" || n === "Set")
return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray$1(o, minLen); }
function _arrayLikeToArray$1(arr, len) { if (len == null || len > arr.length)
len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++)
arr2[i] = arr[i]; return arr2; }
var pp$3 = state.Parser.prototype; // Convert existing expression atom to assignable pattern
// if possible.
pp$3.toAssignable = function (node, isBinding, refDestructuringErrors) {
if (this.options.ecmaVersion >= 6 && node) {
switch (node.type) {
case "Identifier":
if (this.inAsync && node.name === "await")
this.raise(node.start, "Cannot use 'await' as identifier inside an async function");
break;
case "ObjectPattern":
case "ArrayPattern":
case "AssignmentPattern":
case "RestElement":
break;
case "ObjectExpression":
node.type = "ObjectPattern";
if (refDestructuringErrors)
this.checkPatternErrors(refDestructuringErrors, true);
for (var _iterator = _createForOfIteratorHelperLoose$1(node.properties), _step; !(_step = _iterator()).done;) {
var prop = _step.value;
this.toAssignable(prop, isBinding); // Early error:
// AssignmentRestProperty[Yield, Await] :
// `...` DestructuringAssignmentTarget[Yield, Await]
//
// It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|.
if (prop.type === "RestElement" && (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern")) {
this.raise(prop.argument.start, "Unexpected token");
}
}
break;
case "Property":
// AssignmentProperty has type === "Property"
if (node.kind !== "init")
this.raise(node.key.start, "Object pattern can't contain getter or setter");
this.toAssignable(node.value, isBinding);
break;
case "ArrayExpression":
node.type = "ArrayPattern";
if (refDestructuringErrors)
this.checkPatternErrors(refDestructuringErrors, true);
this.toAssignableList(node.elements, isBinding);
break;
case "SpreadElement":
node.type = "RestElement";
this.toAssignable(node.argument, isBinding);
if (node.argument.type === "AssignmentPattern")
this.raise(node.argument.start, "Rest elements cannot have a default value");
break;
case "AssignmentExpression":
if (node.operator !== "=")
this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
node.type = "AssignmentPattern";
delete node.operator;
this.toAssignable(node.left, isBinding);
break;
case "ParenthesizedExpression":
this.toAssignable(node.expression, isBinding, refDestructuringErrors);
break;
case "ChainExpression":
this.raiseRecoverable(node.start, "Optional chaining cannot appear in left-hand side");
break;
case "MemberExpression":
if (!isBinding)
break;
default:
this.raise(node.start, "Assigning to rvalue");
}
}
else if (refDestructuringErrors)
this.checkPatternErrors(refDestructuringErrors, true);
return node;
}; // Convert list of expression atoms to binding list.
pp$3.toAssignableList = function (exprList, isBinding) {
var end = exprList.length;
for (var i = 0; i < end; i++) {
var elt = exprList[i];
if (elt)
this.toAssignable(elt, isBinding);
}
if (end) {
var last = exprList[end - 1];
if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
this.unexpected(last.argument.start);
}
return exprList;
}; // Parses spread element.
pp$3.parseSpread = function (refDestructuringErrors) {
var node = this.startNode();
this.next();
node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
return this.finishNode(node, "SpreadElement");
};
pp$3.parseRestBinding = function () {
var node = this.startNode();
this.next(); // RestElement inside of a function parameter must be an identifier
if (this.options.ecmaVersion === 6 && this.type !== tokentype.types.name)
this.unexpected();
node.argument = this.parseBindingAtom();
return this.finishNode(node, "RestElement");
}; // Parses lvalue (assignable) atom.
pp$3.parseBindingAtom = function () {
if (this.options.ecmaVersion >= 6) {
switch (this.type) {
case tokentype.types.bracketL:
var node = this.startNode();
this.next();
node.elements = this.parseBindingList(tokentype.types.bracketR, true, true);
return this.finishNode(node, "ArrayPattern");
case tokentype.types.braceL:
return this.parseObj(true);
}
}
return this.parseIdent();
};
pp$3.parseBindingList = function (close, allowEmpty, allowTrailingComma) {
var elts = [], first = true;
while (!this.eat(close)) {
if (first)
first = false;
else
this.expect(tokentype.types.comma);
if (allowEmpty && this.type === tokentype.types.comma) {
elts.push(null);
}
else if (allowTrailingComma && this.afterTrailingComma(close)) {
break;
}
else if (this.type === tokentype.types.ellipsis) {
var rest = this.parseRestBinding();
this.parseBindingListItem(rest);
elts.push(rest);
if (this.type === tokentype.types.comma)
this.raise(this.start, "Comma is not permitted after the rest element");
this.expect(close);
break;
}
else {
var elem = this.parseMaybeDefault(this.start, this.startLoc);
this.parseBindingListItem(elem);
elts.push(elem);
}
}
return elts;
};
pp$3.parseBindingListItem = function (param) {
return param;
}; // Parses assignment pattern around given atom if possible.
pp$3.parseMaybeDefault = function (startPos, startLoc, left) {
left = left || this.parseBindingAtom();
if (this.options.ecmaVersion < 6 || !this.eat(tokentype.types.eq))
return left;
var node = this.startNodeAt(startPos, startLoc);
node.left = left;
node.right = this.parseMaybeAssign();
return this.finishNode(node, "AssignmentPattern");
}; // The following three functions all verify that a node is an lvalue —
// something that can be bound, or assigned to. In order to do so, they perform
// a variety of checks:
//
// - Check that none of the bound/assigned-to identifiers are reserved words.
// - Record name declarations for bindings in the appropriate scope.
// - Check duplicate argument names, if checkClashes is set.
//
// If a complex binding pattern is encountered (e.g., object and array
// destructuring), the entire pattern is recursively checked.
//
// There are three versions of checkLVal*() appropriate for different
// circumstances:
//
// - checkLValSimple() shall be used if the syntactic construct supports
// nothing other than identifiers and member expressions. Parenthesized
// expressions are also correctly handled. This is generally appropriate for
// constructs for which the spec says
//
// > It is a Syntax Error if AssignmentTargetType of [the production] is not
// > simple.
//
// It is also appropriate for checking if an identifier is valid and not
// defined elsewhere, like import declarations or function/class identifiers.
//
// Examples where this is used include:
// a += …;
// import a from '…';
// where a is the node to be checked.
//
// - checkLValPattern() shall be used if the syntactic construct supports
// anything checkLValSimple() supports, as well as object and array
// destructuring patterns. This is generally appropriate for constructs for
// which the spec says
//
// > It is a Syntax Error if [the production] is neither an ObjectLiteral nor
// > an ArrayLiteral and AssignmentTargetType of [the production] is not
// > simple.
//
// Examples where this is used include:
// (a = …);
// const a = …;
// try { … } catch (a) { … }
// where a is the node to be checked.
//
// - checkLValInnerPattern() shall be used if the syntactic construct supports
// anything checkLValPattern() supports, as well as default assignment
// patterns, rest elements, and other constructs that may appear within an
// object or array destructuring pattern.
//
// As a special case, function parameters also use checkLValInnerPattern(),
// as they also support defaults and rest constructs.
//
// These functions deliberately support both assignment and binding constructs,
// as the logic for both is exceedingly similar. If the node is the target of
// an assignment, then bindingType should be set to BIND_NONE. Otherwise, it
// should be set to the appropriate BIND_* constant, like BIND_VAR or
// BIND_LEXICAL.
//
// If the function is called with a non-BIND_NONE bindingType, then
// additionally a checkClashes object may be specified to allow checking for
// duplicate argument names. checkClashes is ignored if the provided construct
// is an assignment (i.e., bindingType is BIND_NONE).
pp$3.checkLValSimple = function (expr, bindingType, checkClashes) {
if (bindingType === void 0) { bindingType = scopeflags.BIND_NONE; }
var isBind = bindingType !== scopeflags.BIND_NONE;
switch (expr.type) {
case "Identifier":
if (this.strict && this.reservedWordsStrictBind.test(expr.name))
this.raiseRecoverable(expr.start, (isBind ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
if (isBind) {
if (bindingType === scopeflags.BIND_LEXICAL && expr.name === "let")
this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name");
if (checkClashes) {
if ((0, util.hasOwn)(checkClashes, expr.name))
this.raiseRecoverable(expr.start, "Argument name clash");
checkClashes[expr.name] = true;
}
if (bindingType !== scopeflags.BIND_OUTSIDE)
this.declareName(expr.name, bindingType, expr.start);
}
break;
case "ChainExpression":
this.raiseRecoverable(expr.start, "Optional chaining cannot appear in left-hand side");
break;
case "MemberExpression":
if (isBind)
this.raiseRecoverable(expr.start, "Binding member expression");
break;
case "ParenthesizedExpression":
if (isBind)
this.raiseRecoverable(expr.start, "Binding parenthesized expression");
return this.checkLValSimple(expr.expression, bindingType, checkClashes);
default:
this.raise(expr.start, (isBind ? "Binding" : "Assigning to") + " rvalue");
}
};
pp$3.checkLValPattern = function (expr, bindingType, checkClashes) {
if (bindingType === void 0) { bindingType = scopeflags.BIND_NONE; }
switch (expr.type) {
case "ObjectPattern":
for (var _iterator2 = _createForOfIteratorHelperLoose$1(expr.properties), _step2; !(_step2 = _iterator2()).done;) {
var prop = _step2.value;
this.checkLValInnerPattern(prop, bindingType, checkClashes);
}
break;
case "ArrayPattern":
for (var _iterator3 = _createForOfIteratorHelperLoose$1(expr.elements), _step3; !(_step3 = _iterator3()).done;) {
var elem = _step3.value;
if (elem)
this.checkLValInnerPattern(elem, bindingType, checkClashes);
}
break;
default:
this.checkLValSimple(expr, bindingType, checkClashes);
}
};
pp$3.checkLValInnerPattern = function (expr, bindingType, checkClashes) {
if (bindingType === void 0) { bindingType = scopeflags.BIND_NONE; }
switch (expr.type) {
case "Property":
// AssignmentProperty has type === "Property"
this.checkLValInnerPattern(expr.value, bindingType, checkClashes);
break;
case "AssignmentPattern":
this.checkLValPattern(expr.left, bindingType, checkClashes);
break;
case "RestElement":
this.checkLValPattern(expr.argument, bindingType, checkClashes);
break;
default:
this.checkLValPattern(expr, bindingType, checkClashes);
}
};
var tokencontext = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.types = exports.TokContext = void 0;
// The algorithm used to determine whether a regexp can appear at a
// given point in the program is loosely based on sweet.js' approach.
// See https://github.com/mozilla/sweet.js/wiki/design
var TokContext = /** @class */ (function () {
function TokContext(token, isExpr, preserveSpace, override, generator) {
this.token = token;
this.isExpr = !!isExpr;
this.preserveSpace = !!preserveSpace;
this.override = override;
this.generator = !!generator;
}
return TokContext;
}());
exports.TokContext = TokContext;
var types = {
b_stat: new TokContext("{", false),
b_expr: new TokContext("{", true),
b_tmpl: new TokContext("${", false),
p_stat: new TokContext("(", false),
p_expr: new TokContext("(", true),
q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }),
f_stat: new TokContext("function", false),
f_expr: new TokContext("function", true),
f_expr_gen: new TokContext("function", true, false, null, true),
f_gen: new TokContext("function", false, false, null, true)
};
exports.types = types;
var pp = state.Parser.prototype;
pp.initialContext = function () {
return [types.b_stat];
};
pp.curContext = function () {
return this.context[this.context.length - 1];
};
pp.braceIsBlock = function (prevType) {
var parent = this.curContext();
if (parent === types.f_expr || parent === types.f_stat)
return true;
if (prevType === tokentype.types.colon && (parent === types.b_stat || parent === types.b_expr))
return !parent.isExpr; // The check for `tt.name && exprAllowed` detects whether we are
// after a `yield` or `of` construct. See the `updateContext` for
// `tt.name`.
if (prevType === tokentype.types._return || prevType === tokentype.types.name && this.exprAllowed)
return whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
if (prevType === tokentype.types._else || prevType === tokentype.types.semi || prevType === tokentype.types.eof || prevType === tokentype.types.parenR || prevType === tokentype.types.arrow)
return true;
if (prevType === tokentype.types.braceL)
return parent === types.b_stat;
if (prevType === tokentype.types._var || prevType === tokentype.types._const || prevType === tokentype.types.name)
return false;
return !this.exprAllowed;
};
pp.inGeneratorContext = function () {
for (var i = this.context.length - 1; i >= 1; i--) {
var context = this.context[i];
if (context.token === "function")
return context.generator;
}
return false;
};
pp.updateContext = function (prevType) {
var update, type = this.type;
if (type.keyword && prevType === tokentype.types.dot)
this.exprAllowed = false;
else if (update = type.updateContext)
update.call(this, prevType);
else
this.exprAllowed = type.beforeExpr;
}; // Used to handle egde case when token context could not be inferred correctly in tokenize phase
pp.overrideContext = function (tokenCtx) {
if (this.curContext() !== tokenCtx) {
this.context[this.context.length - 1] = tokenCtx;
}
}; // Token-specific context update code
tokentype.types.parenR.updateContext = tokentype.types.braceR.updateContext = function () {
if (this.context.length === 1) {
this.exprAllowed = true;
return;
}
var out = this.context.pop();
if (out === types.b_stat && this.curContext().token === "function") {
out = this.context.pop();
}
this.exprAllowed = !out.isExpr;
};
tokentype.types.braceL.updateContext = function (prevType) {
this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr);
this.exprAllowed = true;
};
tokentype.types.dollarBraceL.updateContext = function () {
this.context.push(types.b_tmpl);
this.exprAllowed = true;
};
tokentype.types.parenL.updateContext = function (prevType) {
var statementParens = prevType === tokentype.types._if || prevType === tokentype.types._for || prevType === tokentype.types._with || prevType === tokentype.types._while;
this.context.push(statementParens ? types.p_stat : types.p_expr);
this.exprAllowed = true;
};
tokentype.types.incDec.updateContext = function () {
};
tokentype.types._function.updateContext = tokentype.types._class.updateContext = function (prevType) {
if (prevType.beforeExpr && prevType !== tokentype.types._else && !(prevType === tokentype.types.semi && this.curContext() !== types.p_stat) && !(prevType === tokentype.types._return && whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && !((prevType === tokentype.types.colon || prevType === tokentype.types.braceL) && this.curContext() === types.b_stat))
this.context.push(types.f_expr);
else
this.context.push(types.f_stat);
this.exprAllowed = false;
};
tokentype.types.backQuote.updateContext = function () {
if (this.curContext() === types.q_tmpl)
this.context.pop();
else
this.context.push(types.q_tmpl);
this.exprAllowed = false;
};
tokentype.types.star.updateContext = function (prevType) {
if (prevType === tokentype.types._function) {
var index = this.context.length - 1;
if (this.context[index] === types.f_expr)
this.context[index] = types.f_expr_gen;
else
this.context[index] = types.f_gen;
}
this.exprAllowed = true;
};
tokentype.types.name.updateContext = function (prevType) {
var allowed = false;
if (this.options.ecmaVersion >= 6 && prevType !== tokentype.types.dot) {
if (this.value === "of" && !this.exprAllowed || this.value === "yield" && this.inGeneratorContext())
allowed = true;
}
this.exprAllowed = allowed;
};
});
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it)
return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it)
o = it;
var i = 0;
return function () { if (i >= o.length)
return { done: true }; return { done: false, value: o[i++] }; };
} throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o)
return; if (typeof o === "string")
return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor)
n = o.constructor.name; if (n === "Map" || n === "Set")
return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length)
len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++)
arr2[i] = arr[i]; return arr2; }
var pp$2 = state.Parser.prototype; // Check if property name clashes with already added.
// Object/class getters and setters are not allowed to clash —
// either with each other or with an init property — and in
// strict mode, init properties are also not allowed to be repeated.
pp$2.checkPropClash = function (prop, propHash, refDestructuringErrors) {
if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement")
return;
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
return;
var key = prop.key, name;
switch (key.type) {
case "Identifier":
name = key.name;
break;
case "Literal":
name = String(key.value);
break;
default:
return;
}
var kind = prop.kind;
if (this.options.ecmaVersion >= 6) {
if (name === "__proto__" && kind === "init") {
if (propHash.proto) {
if (refDestructuringErrors) {
if (refDestructuringErrors.doubleProto < 0) {
refDestructuringErrors.doubleProto = key.start;
}
}
else {
this.raiseRecoverable(key.start, "Redefinition of __proto__ property");
}
}
propHash.proto = true;
}
return;
}
name = "$" + name;
var other = propHash[name];
if (other) {
var redefinition = void 0;
if (kind === "init") {
redefinition = this.strict && other.init || other.get || other.set;
}
else {
redefinition = other.init || other[kind];
}
if (redefinition)
this.raiseRecoverable(key.start, "Redefinition of property");
}
else {
other = propHash[name] = {
init: false,
get: false,
set: false
};
}
other[kind] = true;
}; // ### Expression parsing
// These nest, from the most general expression type at the top to
// 'atomic', nondivisible expression types at the bottom. Most of
// the functions will simply let the function(s) below them parse,
// and, *if* the syntactic construct they handle is present, wrap
// the AST node that the inner parser gave them in another node.
// Parse a full expression. The optional arguments are used to
// forbid the `in` operator (in for loops initalization expressions)
// and provide reference for storing '=' operator inside shorthand
// property assignment in contexts where both object expression
// and object pattern might appear (so it's possible to raise
// delayed syntax error at correct position).
pp$2.parseExpression = function (forInit, refDestructuringErrors) {
var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseMaybeAssign(forInit, refDestructuringErrors);
if (this.type === tokentype.types.comma) {
var node = this.startNodeAt(startPos, startLoc);
node.expressions = [expr];
while (this.eat(tokentype.types.comma))
node.expressions.push(this.parseMaybeAssign(forInit, refDestructuringErrors));
return this.finishNode(node, "SequenceExpression");
}
return expr;
}; // Parse an assignment expression. This includes applications of
// operators like `+=`.
pp$2.parseMaybeAssign = function (forInit, refDestructuringErrors, afterLeftParse) {
if (this.isContextual("yield")) {
if (this.inGenerator)
return this.parseYield(forInit); // The tokenizer will assume an expression is allowed after
// `yield`, but this isn't that kind of yield
else
this.exprAllowed = false;
}
var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldDoubleProto = -1;
if (refDestructuringErrors) {
oldParenAssign = refDestructuringErrors.parenthesizedAssign;
oldTrailingComma = refDestructuringErrors.trailingComma;
oldDoubleProto = refDestructuringErrors.doubleProto;
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1;
}
else {
refDestructuringErrors = new parseutil.DestructuringErrors();
ownDestructuringErrors = true;
}
var startPos = this.start, startLoc = this.startLoc;
if (this.type === tokentype.types.parenL || this.type === tokentype.types.name) {
this.potentialArrowAt = this.start;
this.potentialArrowInForAwait = forInit === "await";
}
var left = this.parseMaybeConditional(forInit, refDestructuringErrors);
if (afterLeftParse)
left = afterLeftParse.call(this, left, startPos, startLoc);
if (this.type.isAssign) {
var node = this.startNodeAt(startPos, startLoc);
node.operator = this.value;
if (this.type === tokentype.types.eq)
left = this.toAssignable(left, false, refDestructuringErrors);
if (!ownDestructuringErrors) {
refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.doubleProto = -1;
}
if (refDestructuringErrors.shorthandAssign >= left.start)
refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
if (this.type === tokentype.types.eq)
this.checkLValPattern(left);
else
this.checkLValSimple(left);
node.left = left;
this.next();
node.right = this.parseMaybeAssign(forInit);
if (oldDoubleProto > -1)
refDestructuringErrors.doubleProto = oldDoubleProto;
return this.finishNode(node, "AssignmentExpression");
}
else {
if (ownDestructuringErrors)
this.checkExpressionErrors(refDestructuringErrors, true);
}
if (oldParenAssign > -1)
refDestructuringErrors.parenthesizedAssign = oldParenAssign;
if (oldTrailingComma > -1)
refDestructuringErrors.trailingComma = oldTrailingComma;
return left;
}; // Parse a ternary conditional (`?:`) operator.
pp$2.parseMaybeConditional = function (forInit, refDestructuringErrors) {
var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseExprOps(forInit, refDestructuringErrors);
if (this.checkExpressionErrors(refDestructuringErrors))
return expr;
if (this.eat(tokentype.types.question)) {
var node = this.startNodeAt(startPos, startLoc);
node.test = expr;
node.consequent = this.parseMaybeAssign();
this.expect(tokentype.types.colon);
node.alternate = this.parseMaybeAssign(forInit);
return this.finishNode(node, "ConditionalExpression");
}
return expr;
}; // Start the precedence parser.
pp$2.parseExprOps = function (forInit, refDestructuringErrors) {
var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseMaybeUnary(refDestructuringErrors, false, false, forInit);
if (this.checkExpressionErrors(refDestructuringErrors))
return expr;
return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, forInit);
}; // Parse binary operators with the operator precedence parsing
// algorithm. `left` is the left-hand side of the operator.
// `minPrec` provides context that allows the function to stop and
// defer further parser to one of its callers when it encounters an
// operator that has a lower precedence than the set it is parsing.
pp$2.parseExprOp = function (left, leftStartPos, leftStartLoc, minPrec, forInit) {
var prec = this.type.binop;
if (prec != null && (!forInit || this.type !== tokentype.types._in)) {
if (prec > minPrec) {
var logical = this.type === tokentype.types.logicalOR || this.type === tokentype.types.logicalAND;
var coalesce = this.type === tokentype.types.coalesce;
if (coalesce) {
// Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
// In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
prec = tokentype.types.logicalAND.binop;
}
var op = this.value;
this.next();
var startPos = this.start, startLoc = this.startLoc;
var right = this.parseExprOp(this.parseMaybeUnary(null, false, false, forInit), startPos, startLoc, prec, forInit);
var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
if (logical && this.type === tokentype.types.coalesce || coalesce && (this.type === tokentype.types.logicalOR || this.type === tokentype.types.logicalAND)) {
this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
}
return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, forInit);
}
}
return left;
};
pp$2.buildBinary = function (startPos, startLoc, left, right, op, logical) {
if (right.type === "PrivateIdentifier")
this.raise(right.start, "Private identifier can only be left side of binary expression");
var node = this.startNodeAt(startPos, startLoc);
node.left = left;
node.operator = op;
node.right = right;
return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression");
}; // Parse unary operators, both prefix and postfix.
pp$2.parseMaybeUnary = function (refDestructuringErrors, sawUnary, incDec, forInit) {
var startPos = this.start, startLoc = this.startLoc, expr;
if (this.isContextual("await") && this.canAwait) {
expr = this.parseAwait(forInit);
sawUnary = true;
}
else if (this.type.prefix) {
var node = this.startNode(), update = this.type === tokentype.types.incDec;
node.operator = this.value;
node.prefix = true;
this.next();
node.argument = this.parseMaybeUnary(null, true, update, forInit);
this.checkExpressionErrors(refDestructuringErrors, true);
if (update)
this.checkLValSimple(node.argument);
else if (this.strict && node.operator === "delete" && node.argument.type === "Identifier")
this.raiseRecoverable(node.start, "Deleting local variable in strict mode");
else if (node.operator === "delete" && isPrivateFieldAccess(node.argument))
this.raiseRecoverable(node.start, "Private fields can not be deleted");
else
sawUnary = true;
expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
}
else if (!sawUnary && this.type === tokentype.types.privateId) {
if (forInit || this.privateNameStack.length === 0)
this.unexpected();
expr = this.parsePrivateIdent(); // only could be private fields in 'in', such as #x in obj
if (this.type !== tokentype.types._in)
this.unexpected();
}
else {
expr = this.parseExprSubscripts(refDestructuringErrors, forInit);
if (this.checkExpressionErrors(refDestructuringErrors))
return expr;
while (this.type.postfix && !this.canInsertSemicolon()) {
var node = this.startNodeAt(startPos, startLoc);
node.operator = this.value;
node.prefix = false;
node.argument = expr;
this.checkLValSimple(expr);
this.next();
expr = this.finishNode(node, "UpdateExpression");
}
}
if (!incDec && this.eat(tokentype.types.starstar)) {
if (sawUnary)
this.unexpected(this.lastTokStart);
else
return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false, false, forInit), "**", false);
}
else {
return expr;
}
};
function isPrivateFieldAccess(node) {
return node.type === "MemberExpression" && node.property.type === "PrivateIdentifier" || node.type === "ChainExpression" && isPrivateFieldAccess(node.expression);
} // Parse call, dot, and `[]`-subscript expressions.
pp$2.parseExprSubscripts = function (refDestructuringErrors, forInit) {
var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseExprAtom(refDestructuringErrors, forInit);
if (expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")")
return expr;
var result = this.parseSubscripts(expr, startPos, startLoc, false, forInit);
if (refDestructuringErrors && result.type === "MemberExpression") {
if (refDestructuringErrors.parenthesizedAssign >= result.start)
refDestructuringErrors.parenthesizedAssign = -1;
if (refDestructuringErrors.parenthesizedBind >= result.start)
refDestructuringErrors.parenthesizedBind = -1;
if (refDestructuringErrors.trailingComma >= result.start)
refDestructuringErrors.trailingComma = -1;
}
return result;
};
pp$2.parseSubscripts = function (base, startPos, startLoc, noCalls, forInit) {
var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && this.potentialArrowAt === base.start;
var optionalChained = false;
while (true) {
var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
if (element.optional)
optionalChained = true;
if (element === base || element.type === "ArrowFunctionExpression") {
if (optionalChained) {
var chainNode = this.startNodeAt(startPos, startLoc);
chainNode.expression = element;
element = this.finishNode(chainNode, "ChainExpression");
}
return element;
}
base = element;
}
};
pp$2.parseSubscript = function (base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
var optionalSupported = this.options.ecmaVersion >= 11;
var optional = optionalSupported && this.eat(tokentype.types.questionDot);
if (noCalls && optional)
this.raise(this.lastTokStart, "Optional chaining cannot appear in the callee of new expressions");
var computed = this.eat(tokentype.types.bracketL);
if (computed || optional && this.type !== tokentype.types.parenL && this.type !== tokentype.types.backQuote || this.eat(tokentype.types.dot)) {
var node = this.startNodeAt(startPos, startLoc);
node.object = base;
if (computed) {
node.property = this.parseExpression();
this.expect(tokentype.types.bracketR);
}
else if (this.type === tokentype.types.privateId && base.type !== "Super") {
node.property = this.parsePrivateIdent();
}
else {
node.property = this.parseIdent(this.options.allowReserved !== "never");
}
node.computed = !!computed;
if (optionalSupported) {
node.optional = optional;
}
base = this.finishNode(node, "MemberExpression");
}
else if (!noCalls && this.eat(tokentype.types.parenL)) {
var refDestructuringErrors = new parseutil.DestructuringErrors(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
this.yieldPos = 0;
this.awaitPos = 0;
this.awaitIdentPos = 0;
var exprList = this.parseExprList(tokentype.types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors);
if (maybeAsyncArrow && !optional && !this.canInsertSemicolon() && this.eat(tokentype.types.arrow)) {
this.checkPatternErrors(refDestructuringErrors, false);
this.checkYieldAwaitInDefaultParams();
if (this.awaitIdentPos > 0)
this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function");
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.awaitIdentPos = oldAwaitIdentPos;
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true, forInit);
}
this.checkExpressionErrors(refDestructuringErrors, true);
this.yieldPos = oldYieldPos || this.yieldPos;
this.awaitPos = oldAwaitPos || this.awaitPos;
this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos;
var node = this.startNodeAt(startPos, startLoc);
node.callee = base;
node.arguments = exprList;
if (optionalSupported) {
node.optional = optional;
}
base = this.finishNode(node, "CallExpression");
}
else if (this.type === tokentype.types.backQuote) {
if (optional || optionalChained) {
this.raise(this.start, "Optional chaining cannot appear in the tag of tagged template expressions");
}
var node = this.startNodeAt(startPos, startLoc);
node.tag = base;
node.quasi = this.parseTemplate({
isTagged: true
});
base = this.finishNode(node, "TaggedTemplateExpression");
}
return base;
}; // Parse an atomic expression — either a single token that is an
// expression, an expression started by a keyword like `function` or
// `new`, or an expression wrapped in punctuation like `()`, `[]`,
// or `{}`.
pp$2.parseExprAtom = function (refDestructuringErrors, forInit) {
// If a division operator appears in an expression position, the
// tokenizer got confused, and we force it to read a regexp instead.
if (this.type === tokentype.types.slash)
this.readRegexp();
var node, canBeArrow = this.potentialArrowAt === this.start;
switch (this.type) {
case tokentype.types._super:
if (!this.allowSuper)
this.raise(this.start, "'super' keyword outside a method");
node = this.startNode();
this.next();
if (this.type === tokentype.types.parenL && !this.allowDirectSuper)
this.raise(node.start, "super() call outside constructor of a subclass"); // The `super` keyword can appear at below:
// SuperProperty:
// super [ Expression ]
// super . IdentifierName
// SuperCall:
// super ( Arguments )
if (this.type !== tokentype.types.dot && this.type !== tokentype.types.bracketL && this.type !== tokentype.types.parenL)
this.unexpected();
return this.finishNode(node, "Super");
case tokentype.types._this:
node = this.startNode();
this.next();
return this.finishNode(node, "ThisExpression");
case tokentype.types.name:
var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc;
var id = this.parseIdent(false);
if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(tokentype.types._function)) {
this.overrideContext(tokencontext.types.f_expr);
return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true, forInit);
}
if (canBeArrow && !this.canInsertSemicolon()) {
if (this.eat(tokentype.types.arrow))
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false, forInit);
if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === tokentype.types.name && !containsEsc && (!this.potentialArrowInForAwait || this.value !== "of" || this.containsEsc)) {
id = this.parseIdent(false);
if (this.canInsertSemicolon() || !this.eat(tokentype.types.arrow))
this.unexpected();
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true, forInit);
}
}
return id;
case tokentype.types.regexp:
var value = this.value;
node = this.parseLiteral(value.value);
node.regex = {
pattern: value.pattern,
flags: value.flags
};
return node;
case tokentype.types.num:
case tokentype.types.string:
return this.parseLiteral(this.value);
case tokentype.types._null:
case tokentype.types._true:
case tokentype.types._false:
node = this.startNode();
node.value = this.type === tokentype.types._null ? null : this.type === tokentype.types._true;
node.raw = this.type.keyword;
this.next();
return this.finishNode(node, "Literal");
case tokentype.types.parenL:
var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow, forInit);
if (refDestructuringErrors) {
if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
refDestructuringErrors.parenthesizedAssign = start;
if (refDestructuringErrors.parenthesizedBind < 0)
refDestructuringErrors.parenthesizedBind = start;
}
return expr;
case tokentype.types.bracketL:
node = this.startNode();
this.next();
node.elements = this.parseExprList(tokentype.types.bracketR, true, true, refDestructuringErrors);
return this.finishNode(node, "ArrayExpression");
case tokentype.types.braceL:
this.overrideContext(tokencontext.types.b_expr);
return this.parseObj(false, refDestructuringErrors);
case tokentype.types._function:
node = this.startNode();
this.next();
return this.parseFunction(node, 0);
case tokentype.types._class:
return this.parseClass(this.startNode(), false);
case tokentype.types._new:
return this.parseNew();
case tokentype.types.backQuote:
return this.parseTemplate();
case tokentype.types._import:
if (this.options.ecmaVersion >= 11) {
return this.parseExprImport();
}
else {
return this.unexpected();
}
default:
this.unexpected();
}
};
pp$2.parseExprImport = function () {
var node = this.startNode(); // Consume `import` as an identifier for `import.meta`.
// Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
if (this.containsEsc)
this.raiseRecoverable(this.start, "Escape sequence in keyword import");
var meta = this.parseIdent(true);
switch (this.type) {
case tokentype.types.parenL:
return this.parseDynamicImport(node);
case tokentype.types.dot:
node.meta = meta;
return this.parseImportMeta(node);
default:
this.unexpected();
}
};
pp$2.parseDynamicImport = function (node) {
this.next(); // skip `(`
// Parse node.source.
node.source = this.parseMaybeAssign(); // Verify ending.
if (!this.eat(tokentype.types.parenR)) {
var errorPos = this.start;
if (this.eat(tokentype.types.comma) && this.eat(tokentype.types.parenR)) {
this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()");
}
else {
this.unexpected(errorPos);
}
}
return this.finishNode(node, "ImportExpression");
};
pp$2.parseImportMeta = function (node) {
this.next(); // skip `.`
var containsEsc = this.containsEsc;
node.property = this.parseIdent(true);
if (node.property.name !== "meta")
this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'");
if (containsEsc)
this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters");
if (this.options.sourceType !== "module" && !this.options.allowImportExportEverywhere)
this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module");
return this.finishNode(node, "MetaProperty");
};
pp$2.parseLiteral = function (value) {
var node = this.startNode();
node.value = value;
node.raw = this.input.slice(this.start, this.end);
if (node.raw.charCodeAt(node.raw.length - 1) === 110)
node.bigint = node.raw.slice(0, -1).replace(/_/g, "");
this.next();
return this.finishNode(node, "Literal");
};
pp$2.parseParenExpression = function () {
this.expect(tokentype.types.parenL);
var val = this.parseExpression();
this.expect(tokentype.types.parenR);
return val;
};
pp$2.parseParenAndDistinguishExpression = function (canBeArrow, forInit) {
var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
if (this.options.ecmaVersion >= 6) {
this.next();
var innerStartPos = this.start, innerStartLoc = this.startLoc;
var exprList = [], first = true, lastIsComma = false;
var refDestructuringErrors = new parseutil.DestructuringErrors(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart = void 0;
this.yieldPos = 0;
this.awaitPos = 0; // Do not save awaitIdentPos to allow checking awaits nested in parameters
while (this.type !== tokentype.types.parenR) {
first ? first = false : this.expect(tokentype.types.comma);
if (allowTrailingComma && this.afterTrailingComma(tokentype.types.parenR, true)) {
lastIsComma = true;
break;
}
else if (this.type === tokentype.types.ellipsis) {
spreadStart = this.start;
exprList.push(this.parseParenItem(this.parseRestBinding()));
if (this.type === tokentype.types.comma)
this.raise(this.start, "Comma is not permitted after the rest element");
break;
}
else {
exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem));
}
}
var innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc;
this.expect(tokentype.types.parenR);
if (canBeArrow && !this.canInsertSemicolon() && this.eat(tokentype.types.arrow)) {
this.checkPatternErrors(refDestructuringErrors, false);
this.checkYieldAwaitInDefaultParams();
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
return this.parseParenArrowList(startPos, startLoc, exprList, forInit);
}
if (!exprList.length || lastIsComma)
this.unexpected(this.lastTokStart);
if (spreadStart)
this.unexpected(spreadStart);
this.checkExpressionErrors(refDestructuringErrors, true);
this.yieldPos = oldYieldPos || this.yieldPos;
this.awaitPos = oldAwaitPos || this.awaitPos;
if (exprList.length > 1) {
val = this.startNodeAt(innerStartPos, innerStartLoc);
val.expressions = exprList;
this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
}
else {
val = exprList[0];
}
}
else {
val = this.parseParenExpression();
}
if (this.options.preserveParens) {
var par = this.startNodeAt(startPos, startLoc);
par.expression = val;
return this.finishNode(par, "ParenthesizedExpression");
}
else {
return val;
}
};
pp$2.parseParenItem = function (item) {
return item;
};
pp$2.parseParenArrowList = function (startPos, startLoc, exprList, forInit) {
return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, false, forInit);
}; // New's precedence is slightly tricky. It must allow its argument to
// be a `[]` or dot subscript expression, but not a call — at least,
// not without wrapping it in parentheses. Thus, it uses the noCalls
// argument to parseSubscripts to prevent it from consuming the
// argument list.
var empty = [];
pp$2.parseNew = function () {
if (this.containsEsc)
this.raiseRecoverable(this.start, "Escape sequence in keyword new");
var node = this.startNode();
var meta = this.parseIdent(true);
if (this.options.ecmaVersion >= 6 && this.eat(tokentype.types.dot)) {
node.meta = meta;
var containsEsc = this.containsEsc;
node.property = this.parseIdent(true);
if (node.property.name !== "target")
this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'");
if (containsEsc)
this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters");
if (!this.allowNewDotTarget)
this.raiseRecoverable(node.start, "'new.target' can only be used in functions and class static block");
return this.finishNode(node, "MetaProperty");
}
var startPos = this.start, startLoc = this.startLoc, isImport = this.type === tokentype.types._import;
node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true, false);
if (isImport && node.callee.type === "ImportExpression") {
this.raise(startPos, "Cannot use new with import()");
}
if (this.eat(tokentype.types.parenL))
node.arguments = this.parseExprList(tokentype.types.parenR, this.options.ecmaVersion >= 8, false);
else
node.arguments = empty;
return this.finishNode(node, "NewExpression");
}; // Parse template expression.
pp$2.parseTemplateElement = function (_a) {
var isTagged = _a.isTagged;
var elem = this.startNode();
if (this.type === tokentype.types.invalidTemplate) {
if (!isTagged) {
this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal");
}
elem.value = {
raw: this.value,
cooked: null
};
}
else {
elem.value = {
raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"),
cooked: this.value
};
}
this.next();
elem.tail = this.type === tokentype.types.backQuote;
return this.finishNode(elem, "TemplateElement");
};
pp$2.parseTemplate = function (_a) {
var _b = _a === void 0 ? {} : _a, _c = _b.isTagged, isTagged = _c === void 0 ? false : _c;
var node = this.startNode();
this.next();
node.expressions = [];
var curElt = this.parseTemplateElement({
isTagged: isTagged
});
node.quasis = [curElt];
while (!curElt.tail) {
if (this.type === tokentype.types.eof)
this.raise(this.pos, "Unterminated template literal");
this.expect(tokentype.types.dollarBraceL);
node.expressions.push(this.parseExpression());
this.expect(tokentype.types.braceR);
node.quasis.push(curElt = this.parseTemplateElement({
isTagged: isTagged
}));
}
this.next();
return this.finishNode(node, "TemplateLiteral");
};
pp$2.isAsyncProp = function (prop) {
return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && (this.type === tokentype.types.name || this.type === tokentype.types.num || this.type === tokentype.types.string || this.type === tokentype.types.bracketL || this.type.keyword || this.options.ecmaVersion >= 9 && this.type === tokentype.types.star) && !whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.start));
}; // Parse an object literal or binding pattern.
pp$2.parseObj = function (isPattern, refDestructuringErrors) {
var node = this.startNode(), first = true, propHash = {};
node.properties = [];
this.next();
while (!this.eat(tokentype.types.braceR)) {
if (!first) {
this.expect(tokentype.types.comma);
if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(tokentype.types.braceR))
break;
}
else
first = false;
var prop = this.parseProperty(isPattern, refDestructuringErrors);
if (!isPattern)
this.checkPropClash(prop, propHash, refDestructuringErrors);
node.properties.push(prop);
}
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression");
};
pp$2.parseProperty = function (isPattern, refDestructuringErrors) {
var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc;
if (this.options.ecmaVersion >= 9 && this.eat(tokentype.types.ellipsis)) {
if (isPattern) {
prop.argument = this.parseIdent(false);
if (this.type === tokentype.types.comma) {
this.raise(this.start, "Comma is not permitted after the rest element");
}
return this.finishNode(prop, "RestElement");
} // To disallow parenthesized identifier via `this.toAssignable()`.
if (this.type === tokentype.types.parenL && refDestructuringErrors) {
if (refDestructuringErrors.parenthesizedAssign < 0) {
refDestructuringErrors.parenthesizedAssign = this.start;
}
if (refDestructuringErrors.parenthesizedBind < 0) {
refDestructuringErrors.parenthesizedBind = this.start;
}
} // Parse argument.
prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); // To disallow trailing comma via `this.toAssignable()`.
if (this.type === tokentype.types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) {
refDestructuringErrors.trailingComma = this.start;
} // Finish
return this.finishNode(prop, "SpreadElement");
}
if (this.options.ecmaVersion >= 6) {
prop.method = false;
prop.shorthand = false;
if (isPattern || refDestructuringErrors) {
startPos = this.start;
startLoc = this.startLoc;
}
if (!isPattern)
isGenerator = this.eat(tokentype.types.star);
}
var containsEsc = this.containsEsc;
this.parsePropertyName(prop);
if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) {
isAsync = true;
isGenerator = this.options.ecmaVersion >= 9 && this.eat(tokentype.types.star);
this.parsePropertyName(prop, refDestructuringErrors);
}
else {
isAsync = false;
}
this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc);
return this.finishNode(prop, "Property");
};
pp$2.parsePropertyValue = function (prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) {
if ((isGenerator || isAsync) && this.type === tokentype.types.colon)
this.unexpected();
if (this.eat(tokentype.types.colon)) {
prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
prop.kind = "init";
}
else if (this.options.ecmaVersion >= 6 && this.type === tokentype.types.parenL) {
if (isPattern)
this.unexpected();
prop.kind = "init";
prop.method = true;
prop.value = this.parseMethod(isGenerator, isAsync);
}
else if (!isPattern && !containsEsc && this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && (prop.key.name === "get" || prop.key.name === "set") && this.type !== tokentype.types.comma && this.type !== tokentype.types.braceR && this.type !== tokentype.types.eq) {
if (isGenerator || isAsync)
this.unexpected();
prop.kind = prop.key.name;
this.parsePropertyName(prop);
prop.value = this.parseMethod(false);
var paramCount = prop.kind === "get" ? 0 : 1;
if (prop.value.params.length !== paramCount) {
var start = prop.value.start;
if (prop.kind === "get")
this.raiseRecoverable(start, "getter should have no params");
else
this.raiseRecoverable(start, "setter should have exactly one param");
}
else {
if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params");
}
}
else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
if (isGenerator || isAsync)
this.unexpected();
this.checkUnreserved(prop.key);
if (prop.key.name === "await" && !this.awaitIdentPos)
this.awaitIdentPos = startPos;
prop.kind = "init";
if (isPattern) {
prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key));
}
else if (this.type === tokentype.types.eq && refDestructuringErrors) {
if (refDestructuringErrors.shorthandAssign < 0)
refDestructuringErrors.shorthandAssign = this.start;
prop.value = this.parseMaybeDefault(startPos, startLoc, this.copyNode(prop.key));
}
else {
prop.value = this.copyNode(prop.key);
}
prop.shorthand = true;
}
else
this.unexpected();
};
pp$2.parsePropertyName = function (prop) {
if (this.options.ecmaVersion >= 6) {
if (this.eat(tokentype.types.bracketL)) {
prop.computed = true;
prop.key = this.parseMaybeAssign();
this.expect(tokentype.types.bracketR);
return prop.key;
}
else {
prop.computed = false;
}
}
return prop.key = this.type === tokentype.types.num || this.type === tokentype.types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never");
}; // Initialize empty function node.
pp$2.initFunction = function (node) {
node.id = null;
if (this.options.ecmaVersion >= 6)
node.generator = node.expression = false;
if (this.options.ecmaVersion >= 8)
node.async = false;
}; // Parse object or class method.
pp$2.parseMethod = function (isGenerator, isAsync, allowDirectSuper) {
var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
this.initFunction(node);
if (this.options.ecmaVersion >= 6)
node.generator = isGenerator;
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync;
this.yieldPos = 0;
this.awaitPos = 0;
this.awaitIdentPos = 0;
this.enterScope((0, scopeflags.functionFlags)(isAsync, node.generator) | scopeflags.SCOPE_SUPER | (allowDirectSuper ? scopeflags.SCOPE_DIRECT_SUPER : 0));
this.expect(tokentype.types.parenL);
node.params = this.parseBindingList(tokentype.types.parenR, false, this.options.ecmaVersion >= 8);
this.checkYieldAwaitInDefaultParams();
this.parseFunctionBody(node, false, true, false);
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.awaitIdentPos = oldAwaitIdentPos;
return this.finishNode(node, "FunctionExpression");
}; // Parse arrow function expression with given parameters.
pp$2.parseArrowExpression = function (node, params, isAsync, forInit) {
var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos;
this.enterScope((0, scopeflags.functionFlags)(isAsync, false) | scopeflags.SCOPE_ARROW);
this.initFunction(node);
if (this.options.ecmaVersion >= 8)
node.async = !!isAsync;
this.yieldPos = 0;
this.awaitPos = 0;
this.awaitIdentPos = 0;
node.params = this.toAssignableList(params, true);
this.parseFunctionBody(node, true, false, forInit);
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.awaitIdentPos = oldAwaitIdentPos;
return this.finishNode(node, "ArrowFunctionExpression");
}; // Parse function body and check parameters.
pp$2.parseFunctionBody = function (node, isArrowFunction, isMethod, forInit) {
var isExpression = isArrowFunction && this.type !== tokentype.types.braceL;
var oldStrict = this.strict, useStrict = false;
if (isExpression) {
node.body = this.parseMaybeAssign(forInit);
node.expression = true;
this.checkParams(node, false);
}
else {
var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
if (!oldStrict || nonSimple) {
useStrict = this.strictDirective(this.end); // If this is a strict mode function, verify that argument names
// are not repeated, and it does not try to bind the words `eval`
// or `arguments`.
if (useStrict && nonSimple)
this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list");
} // Start a new scope with regard to labels and the `inFunction`
// flag (restore them to their old value afterwards).
var oldLabels = this.labels;
this.labels = [];
if (useStrict)
this.strict = true; // Add the params to varDeclaredNames to ensure that an error is thrown
// if a let/const declaration in the function clashes with one of the params.
this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
if (this.strict && node.id)
this.checkLValSimple(node.id, scopeflags.BIND_OUTSIDE);
node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
node.expression = false;
this.adaptDirectivePrologue(node.body.body);
this.labels = oldLabels;
}
this.exitScope();
};
pp$2.isSimpleParamList = function (params) {
for (var _iterator = _createForOfIteratorHelperLoose(params), _step; !(_step = _iterator()).done;) {
var param = _step.value;
if (param.type !== "Identifier")
return false;
}
return true;
}; // Checks function params for various disallowed patterns such as using "eval"
// or "arguments" and duplicate parameters.
pp$2.checkParams = function (node, allowDuplicates) {
var nameHash = Object.create(null);
for (var _iterator2 = _createForOfIteratorHelperLoose(node.params), _step2; !(_step2 = _iterator2()).done;) {
var param = _step2.value;
this.checkLValInnerPattern(param, scopeflags.BIND_VAR, allowDuplicates ? null : nameHash);
}
}; // Parses a comma-separated list of expressions, and returns them as
// an array. `close` is the token type that ends the list, and
// `allowEmpty` can be turned on to allow subsequent commas with
// nothing in between them to be parsed as `null` (which is needed
// for array literals).
pp$2.parseExprList = function (close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
var elts = [], first = true;
while (!this.eat(close)) {
if (!first) {
this.expect(tokentype.types.comma);
if (allowTrailingComma && this.afterTrailingComma(close))
break;
}
else
first = false;
var elt = void 0;
if (allowEmpty && this.type === tokentype.types.comma)
elt = null;
else if (this.type === tokentype.types.ellipsis) {
elt = this.parseSpread(refDestructuringErrors);
if (refDestructuringErrors && this.type === tokentype.types.comma && refDestructuringErrors.trailingComma < 0)
refDestructuringErrors.trailingComma = this.start;
}
else {
elt = this.parseMaybeAssign(false, refDestructuringErrors);
}
elts.push(elt);
}
return elts;
};
pp$2.checkUnreserved = function (_a) {
var start = _a.start, end = _a.end, name = _a.name;
if (this.inGenerator && name === "yield")
this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator");
if (this.inAsync && name === "await")
this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function");
if (this.currentThisScope().inClassFieldInit && name === "arguments")
this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer");
if (this.inClassStaticBlock && (name === "arguments" || name === "await"))
this.raise(start, "Cannot use ".concat(name, " in class static initialization block"));
if (this.keywords.test(name))
this.raise(start, "Unexpected keyword '".concat(name, "'"));
if (this.options.ecmaVersion < 6 && this.input.slice(start, end).indexOf("\\") !== -1)
return;
var re = this.strict ? this.reservedWordsStrict : this.reservedWords;
if (re.test(name)) {
if (!this.inAsync && name === "await")
this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function");
this.raiseRecoverable(start, "The keyword '".concat(name, "' is reserved"));
}
}; // Parse the next token as an identifier. If `liberal` is true (used
// when parsing properties), it will also convert keywords into
// identifiers.
pp$2.parseIdent = function (liberal, isBinding) {
var node = this.startNode();
if (this.type === tokentype.types.name) {
node.name = this.value;
}
else if (this.type.keyword) {
node.name = this.type.keyword; // To fix https://github.com/acornjs/acorn/issues/575
// `class` and `function` keywords push new context into this.context.
// But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name.
// If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword
if ((node.name === "class" || node.name === "function") && (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) {
this.context.pop();
}
}
else {
this.unexpected();
}
this.next(!!liberal);
this.finishNode(node, "Identifier");
if (!liberal) {
this.checkUnreserved(node);
if (node.name === "await" && !this.awaitIdentPos)
this.awaitIdentPos = node.start;
}
return node;
};
pp$2.parsePrivateIdent = function () {
var node = this.startNode();
if (this.type === tokentype.types.privateId) {
node.name = this.value;
}
else {
this.unexpected();
}
this.next();
this.finishNode(node, "PrivateIdentifier"); // For validating existence
if (this.privateNameStack.length === 0) {
this.raise(node.start, "Private field '#".concat(node.name, "' must be declared in an enclosing class"));
}
else {
this.privateNameStack[this.privateNameStack.length - 1].used.push(node);
}
return node;
}; // Parses yield expression inside generator.
pp$2.parseYield = function (forInit) {
if (!this.yieldPos)
this.yieldPos = this.start;
var node = this.startNode();
this.next();
if (this.type === tokentype.types.semi || this.canInsertSemicolon() || this.type !== tokentype.types.star && !this.type.startsExpr) {
node.delegate = false;
node.argument = null;
}
else {
node.delegate = this.eat(tokentype.types.star);
node.argument = this.parseMaybeAssign(forInit);
}
return this.finishNode(node, "YieldExpression");
};
pp$2.parseAwait = function (forInit) {
if (!this.awaitPos)
this.awaitPos = this.start;
var node = this.startNode();
this.next();
node.argument = this.parseMaybeUnary(null, true, false, forInit);
return this.finishNode(node, "AwaitExpression");
};
var pp$1 = state.Parser.prototype; // This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.
pp$1.raise = function (pos, message) {
var loc = (0, locutil.getLineInfo)(this.input, pos);
message += " (" + loc.line + ":" + loc.column + ")";
var err = new SyntaxError(message);
err.pos = pos;
err.loc = loc;
err.raisedAt = this.pos;
throw err;
};
pp$1.raiseRecoverable = pp$1.raise;
pp$1.curPosition = function () {
if (this.options.locations) {
return new locutil.Position(this.curLine, this.pos - this.lineStart);
}
};
var pp = state.Parser.prototype;
var Scope = /** @class */ (function () {
function Scope(flags) {
this.flags = flags; // A list of var-declared names in the current lexical scope
this.var = []; // A list of lexically-declared names in the current lexical scope
this.lexical = []; // A list of lexically-declared FunctionDeclaration names in the current lexical scope
this.functions = []; // A switch to disallow the identifier reference 'arguments'
this.inClassFieldInit = false;
}
return Scope;
}()); // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names.
pp.enterScope = function (flags) {
this.scopeStack.push(new Scope(flags));
};
pp.exitScope = function () {
this.scopeStack.pop();
}; // The spec says:
// > At the top level of a function, or script, function declarations are
// > treated like var declarations rather than like lexical declarations.
pp.treatFunctionsAsVarInScope = function (scope) {
return scope.flags & scopeflags.SCOPE_FUNCTION || !this.inModule && scope.flags & scopeflags.SCOPE_TOP;
};
pp.declareName = function (name, bindingType, pos) {
var redeclared = false;
if (bindingType === scopeflags.BIND_LEXICAL) {
var scope = this.currentScope();
redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
scope.lexical.push(name);
if (this.inModule && scope.flags & scopeflags.SCOPE_TOP)
delete this.undefinedExports[name];
}
else if (bindingType === scopeflags.BIND_SIMPLE_CATCH) {
var scope = this.currentScope();
scope.lexical.push(name);
}
else if (bindingType === scopeflags.BIND_FUNCTION) {
var scope = this.currentScope();
if (this.treatFunctionsAsVar)
redeclared = scope.lexical.indexOf(name) > -1;
else
redeclared = scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1;
scope.functions.push(name);
}
else {
for (var i = this.scopeStack.length - 1; i >= 0; --i) {
var scope = this.scopeStack[i];
if (scope.lexical.indexOf(name) > -1 && !(scope.flags & scopeflags.SCOPE_SIMPLE_CATCH && scope.lexical[0] === name) || !this.treatFunctionsAsVarInScope(scope) && scope.functions.indexOf(name) > -1) {
redeclared = true;
break;
}
scope.var.push(name);
if (this.inModule && scope.flags & scopeflags.SCOPE_TOP)
delete this.undefinedExports[name];
if (scope.flags & scopeflags.SCOPE_VAR)
break;
}
}
if (redeclared)
this.raiseRecoverable(pos, "Identifier '".concat(name, "' has already been declared"));
};
pp.checkLocalExport = function (id) {
// scope.functions must be empty as Module code is always strict.
if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && this.scopeStack[0].var.indexOf(id.name) === -1) {
this.undefinedExports[id.name] = id;
}
};
pp.currentScope = function () {
return this.scopeStack[this.scopeStack.length - 1];
};
pp.currentVarScope = function () {
for (var i = this.scopeStack.length - 1;; i--) {
var scope = this.scopeStack[i];
if (scope.flags & scopeflags.SCOPE_VAR)
return scope;
}
}; // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`.
pp.currentThisScope = function () {
for (var i = this.scopeStack.length - 1;; i--) {
var scope = this.scopeStack[i];
if (scope.flags & scopeflags.SCOPE_VAR && !(scope.flags & scopeflags.SCOPE_ARROW))
return scope;
}
};
var node = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.Node = void 0;
var Node = /** @class */ (function () {
function Node(parser, pos, loc) {
this.type = "";
this.start = pos;
this.end = 0;
if (parser.options.locations)
this.loc = new locutil.SourceLocation(parser, loc);
if (parser.options.directSourceFile)
this.sourceFile = parser.options.directSourceFile;
if (parser.options.ranges)
this.range = [pos, 0];
}
return Node;
}()); // Start an AST node, attaching a start offset.
exports.Node = Node;
var pp = state.Parser.prototype;
pp.startNode = function () {
return new Node(this, this.start, this.startLoc);
};
pp.startNodeAt = function (pos, loc) {
return new Node(this, pos, loc);
}; // Finish an AST node, adding `type` and `end` properties.
function finishNodeAt(node, type, pos, loc) {
node.type = type;
node.end = pos;
if (this.options.locations)
node.loc.end = loc;
if (this.options.ranges)
node.range[1] = pos;
return node;
}
pp.finishNode = function (node, type) {
return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc);
}; // Finish node at given position
pp.finishNodeAt = function (node, type, pos, loc) {
return finishNodeAt.call(this, node, type, pos, loc);
};
pp.copyNode = function (node) {
var newNode = new Node(this, node.start, this.startLoc);
for (var prop in node)
newNode[prop] = node[prop];
return newNode;
};
});
var unicodePropertyData = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.default = void 0;
// This file contains Unicode properties extracted from the ECMAScript
// specification. The lists are extracted like so:
// $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText)
// #table-binary-unicode-properties
var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS";
var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic";
var ecma11BinaryProperties = ecma10BinaryProperties;
var ecma12BinaryProperties = ecma11BinaryProperties + " EBase EComp EMod EPres ExtPict";
var ecma13BinaryProperties = ecma12BinaryProperties;
var unicodeBinaryProperties = {
9: ecma9BinaryProperties,
10: ecma10BinaryProperties,
11: ecma11BinaryProperties,
12: ecma12BinaryProperties,
13: ecma13BinaryProperties
}; // #table-unicode-general-category-values
var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; // #table-unicode-script-values
var ecma9ScriptValues = "Adlam Adlm Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb";
var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd";
var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho";
var ecma12ScriptValues = ecma11ScriptValues + " Chorasmian Chrs Diak Dives_Akuru Khitan_Small_Script Kits Yezi Yezidi";
var ecma13ScriptValues = ecma12ScriptValues + " Cypro_Minoan Cpmn Old_Uyghur Ougr Tangsa Tnsa Toto Vithkuqi Vith";
var unicodeScriptValues = {
9: ecma9ScriptValues,
10: ecma10ScriptValues,
11: ecma11ScriptValues,
12: ecma12ScriptValues,
13: ecma13ScriptValues
};
var data = {};
function buildUnicodeData(ecmaVersion) {
var d = data[ecmaVersion] = {
binary: (0, util.wordsRegexp)(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues),
nonBinary: {
General_Category: (0, util.wordsRegexp)(unicodeGeneralCategoryValues),
Script: (0, util.wordsRegexp)(unicodeScriptValues[ecmaVersion])
}
};
d.nonBinary.Script_Extensions = d.nonBinary.Script;
d.nonBinary.gc = d.nonBinary.General_Category;
d.nonBinary.sc = d.nonBinary.Script;
d.nonBinary.scx = d.nonBinary.Script_Extensions;
}
for (var _i = 0, _arr = [9, 10, 11, 12, 13]; _i < _arr.length; _i++) {
var ecmaVersion = _arr[_i];
buildUnicodeData(ecmaVersion);
}
var _default = data;
exports.default = _default;
module.exports = exports["default"];
});
var regexp = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.RegExpValidationState = void 0;
var _unicodePropertyData = _interopRequireDefault(unicodePropertyData);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it)
return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it)
o = it;
var i = 0;
return function () { if (i >= o.length)
return { done: true }; return { done: false, value: o[i++] }; };
} throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o)
return; if (typeof o === "string")
return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor)
n = o.constructor.name; if (n === "Map" || n === "Set")
return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length)
len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++)
arr2[i] = arr[i]; return arr2; }
var pp = state.Parser.prototype;
var RegExpValidationState = /** @class */ (function () {
function RegExpValidationState(parser) {
this.parser = parser;
this.validFlags = "gim".concat(parser.options.ecmaVersion >= 6 ? "uy" : "").concat(parser.options.ecmaVersion >= 9 ? "s" : "").concat(parser.options.ecmaVersion >= 13 ? "d" : "");
this.unicodeProperties = _unicodePropertyData.default[parser.options.ecmaVersion >= 13 ? 13 : parser.options.ecmaVersion];
this.source = "";
this.flags = "";
this.start = 0;
this.switchU = false;
this.switchN = false;
this.pos = 0;
this.lastIntValue = 0;
this.lastStringValue = "";
this.lastAssertionIsQuantifiable = false;
this.numCapturingParens = 0;
this.maxBackReference = 0;
this.groupNames = [];
this.backReferenceNames = [];
}
RegExpValidationState.prototype.reset = function (start, pattern, flags) {
var unicode = flags.indexOf("u") !== -1;
this.start = start | 0;
this.source = pattern + "";
this.flags = flags;
this.switchU = unicode && this.parser.options.ecmaVersion >= 6;
this.switchN = unicode && this.parser.options.ecmaVersion >= 9;
};
RegExpValidationState.prototype.raise = function (message) {
this.parser.raiseRecoverable(this.start, "Invalid regular expression: /".concat(this.source, "/: ").concat(message));
}; // If u flag is given, this returns the code point at the index (it combines a surrogate pair).
// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
RegExpValidationState.prototype.at = function (i, forceU) {
if (forceU === void 0) { forceU = false; }
var s = this.source;
var l = s.length;
if (i >= l) {
return -1;
}
var c = s.charCodeAt(i);
if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
return c;
}
var next = s.charCodeAt(i + 1);
return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c;
};
RegExpValidationState.prototype.nextIndex = function (i, forceU) {
if (forceU === void 0) { forceU = false; }
var s = this.source;
var l = s.length;
if (i >= l) {
return l;
}
var c = s.charCodeAt(i), next;
if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
return i + 1;
}
return i + 2;
};
RegExpValidationState.prototype.current = function (forceU) {
if (forceU === void 0) { forceU = false; }
return this.at(this.pos, forceU);
};
RegExpValidationState.prototype.lookahead = function (forceU) {
if (forceU === void 0) { forceU = false; }
return this.at(this.nextIndex(this.pos, forceU), forceU);
};
RegExpValidationState.prototype.advance = function (forceU) {
if (forceU === void 0) { forceU = false; }
this.pos = this.nextIndex(this.pos, forceU);
};
RegExpValidationState.prototype.eat = function (ch, forceU) {
if (forceU === void 0) { forceU = false; }
if (this.current(forceU) === ch) {
this.advance(forceU);
return true;
}
return false;
};
return RegExpValidationState;
}());
exports.RegExpValidationState = RegExpValidationState;
function codePointToString(ch) {
if (ch <= 0xFFFF)
return String.fromCharCode(ch);
ch -= 0x10000;
return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00);
}
/**
* Validate the flags part of a given RegExpLiteral.
*
* @param {RegExpValidationState} state The state to validate RegExp.
* @returns {void}
*/
pp.validateRegExpFlags = function (state) {
var validFlags = state.validFlags;
var flags = state.flags;
for (var i = 0; i < flags.length; i++) {
var flag = flags.charAt(i);
if (validFlags.indexOf(flag) === -1) {
this.raise(state.start, "Invalid regular expression flag");
}
if (flags.indexOf(flag, i + 1) > -1) {
this.raise(state.start, "Duplicate regular expression flag");
}
}
};
/**
* Validate the pattern part of a given RegExpLiteral.
*
* @param {RegExpValidationState} state The state to validate RegExp.
* @returns {void}
*/
pp.validateRegExpPattern = function (state) {
this.regexp_pattern(state); // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of
// parsing contains a |GroupName|, reparse with the goal symbol
// |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError*
// exception if _P_ did not conform to the grammar, if any elements of _P_
// were not matched by the parse, or if any Early Error conditions exist.
if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) {
state.switchN = true;
this.regexp_pattern(state);
}
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern
pp.regexp_pattern = function (state) {
state.pos = 0;
state.lastIntValue = 0;
state.lastStringValue = "";
state.lastAssertionIsQuantifiable = false;
state.numCapturingParens = 0;
state.maxBackReference = 0;
state.groupNames.length = 0;
state.backReferenceNames.length = 0;
this.regexp_disjunction(state);
if (state.pos !== state.source.length) {
// Make the same messages as V8.
if (state.eat(0x29
/* ) */
)) {
state.raise("Unmatched ')'");
}
if (state.eat(0x5D
/* ] */
) || state.eat(0x7D
/* } */
)) {
state.raise("Lone quantifier brackets");
}
}
if (state.maxBackReference > state.numCapturingParens) {
state.raise("Invalid escape");
}
for (var _iterator = _createForOfIteratorHelperLoose(state.backReferenceNames), _step; !(_step = _iterator()).done;) {
var name_1 = _step.value;
if (state.groupNames.indexOf(name_1) === -1) {
state.raise("Invalid named capture referenced");
}
}
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction
pp.regexp_disjunction = function (state) {
this.regexp_alternative(state);
while (state.eat(0x7C
/* | */
)) {
this.regexp_alternative(state);
} // Make the same message as V8.
if (this.regexp_eatQuantifier(state, true)) {
state.raise("Nothing to repeat");
}
if (state.eat(0x7B
/* { */
)) {
state.raise("Lone quantifier brackets");
}
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative
pp.regexp_alternative = function (state) {
while (state.pos < state.source.length && this.regexp_eatTerm(state))
;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term
pp.regexp_eatTerm = function (state) {
if (this.regexp_eatAssertion(state)) {
// Handle `QuantifiableAssertion Quantifier` alternative.
// `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion
// is a QuantifiableAssertion.
if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) {
// Make the same message as V8.
if (state.switchU) {
state.raise("Invalid quantifier");
}
}
return true;
}
if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) {
this.regexp_eatQuantifier(state);
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion
pp.regexp_eatAssertion = function (state) {
var start = state.pos;
state.lastAssertionIsQuantifiable = false; // ^, $
if (state.eat(0x5E
/* ^ */
) || state.eat(0x24
/* $ */
)) {
return true;
} // \b \B
if (state.eat(0x5C
/* \ */
)) {
if (state.eat(0x42
/* B */
) || state.eat(0x62
/* b */
)) {
return true;
}
state.pos = start;
} // Lookahead / Lookbehind
if (state.eat(0x28
/* ( */
) && state.eat(0x3F
/* ? */
)) {
var lookbehind = false;
if (this.options.ecmaVersion >= 9) {
lookbehind = state.eat(0x3C
/* < */
);
}
if (state.eat(0x3D
/* = */
) || state.eat(0x21
/* ! */
)) {
this.regexp_disjunction(state);
if (!state.eat(0x29
/* ) */
)) {
state.raise("Unterminated group");
}
state.lastAssertionIsQuantifiable = !lookbehind;
return true;
}
}
state.pos = start;
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier
pp.regexp_eatQuantifier = function (state, noError) {
if (noError === void 0) { noError = false; }
if (this.regexp_eatQuantifierPrefix(state, noError)) {
state.eat(0x3F
/* ? */
);
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix
pp.regexp_eatQuantifierPrefix = function (state, noError) {
return state.eat(0x2A
/* * */
) || state.eat(0x2B
/* + */
) || state.eat(0x3F
/* ? */
) || this.regexp_eatBracedQuantifier(state, noError);
};
pp.regexp_eatBracedQuantifier = function (state, noError) {
var start = state.pos;
if (state.eat(0x7B
/* { */
)) {
var min = 0, max = -1;
if (this.regexp_eatDecimalDigits(state)) {
min = state.lastIntValue;
if (state.eat(0x2C
/* , */
) && this.regexp_eatDecimalDigits(state)) {
max = state.lastIntValue;
}
if (state.eat(0x7D
/* } */
)) {
// SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term
if (max !== -1 && max < min && !noError) {
state.raise("numbers out of order in {} quantifier");
}
return true;
}
}
if (state.switchU && !noError) {
state.raise("Incomplete quantifier");
}
state.pos = start;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom
pp.regexp_eatAtom = function (state) {
return this.regexp_eatPatternCharacters(state) || state.eat(0x2E
/* . */
) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state);
};
pp.regexp_eatReverseSolidusAtomEscape = function (state) {
var start = state.pos;
if (state.eat(0x5C
/* \ */
)) {
if (this.regexp_eatAtomEscape(state)) {
return true;
}
state.pos = start;
}
return false;
};
pp.regexp_eatUncapturingGroup = function (state) {
var start = state.pos;
if (state.eat(0x28
/* ( */
)) {
if (state.eat(0x3F
/* ? */
) && state.eat(0x3A
/* : */
)) {
this.regexp_disjunction(state);
if (state.eat(0x29
/* ) */
)) {
return true;
}
state.raise("Unterminated group");
}
state.pos = start;
}
return false;
};
pp.regexp_eatCapturingGroup = function (state) {
if (state.eat(0x28
/* ( */
)) {
if (this.options.ecmaVersion >= 9) {
this.regexp_groupSpecifier(state);
}
else if (state.current() === 0x3F
/* ? */
) {
state.raise("Invalid group");
}
this.regexp_disjunction(state);
if (state.eat(0x29
/* ) */
)) {
state.numCapturingParens += 1;
return true;
}
state.raise("Unterminated group");
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom
pp.regexp_eatExtendedAtom = function (state) {
return state.eat(0x2E
/* . */
) || this.regexp_eatReverseSolidusAtomEscape(state) || this.regexp_eatCharacterClass(state) || this.regexp_eatUncapturingGroup(state) || this.regexp_eatCapturingGroup(state) || this.regexp_eatInvalidBracedQuantifier(state) || this.regexp_eatExtendedPatternCharacter(state);
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier
pp.regexp_eatInvalidBracedQuantifier = function (state) {
if (this.regexp_eatBracedQuantifier(state, true)) {
state.raise("Nothing to repeat");
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter
pp.regexp_eatSyntaxCharacter = function (state) {
var ch = state.current();
if (isSyntaxCharacter(ch)) {
state.lastIntValue = ch;
state.advance();
return true;
}
return false;
};
function isSyntaxCharacter(ch) {
return ch === 0x24
/* $ */
|| ch >= 0x28
/* ( */
&& ch <= 0x2B
/* + */
|| ch === 0x2E
/* . */
|| ch === 0x3F
/* ? */
|| ch >= 0x5B
/* [ */
&& ch <= 0x5E
/* ^ */
|| ch >= 0x7B
/* { */
&& ch <= 0x7D;
} // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter
// But eat eager.
pp.regexp_eatPatternCharacters = function (state) {
var start = state.pos;
var ch = 0;
while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) {
state.advance();
}
return state.pos !== start;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter
pp.regexp_eatExtendedPatternCharacter = function (state) {
var ch = state.current();
if (ch !== -1 && ch !== 0x24
/* $ */
&& !(ch >= 0x28
/* ( */
&& ch <= 0x2B
/* + */
) && ch !== 0x2E
/* . */
&& ch !== 0x3F
/* ? */
&& ch !== 0x5B
/* [ */
&& ch !== 0x5E
/* ^ */
&& ch !== 0x7C
/* | */
) {
state.advance();
return true;
}
return false;
}; // GroupSpecifier ::
// [empty]
// `?` GroupName
pp.regexp_groupSpecifier = function (state) {
if (state.eat(0x3F
/* ? */
)) {
if (this.regexp_eatGroupName(state)) {
if (state.groupNames.indexOf(state.lastStringValue) !== -1) {
state.raise("Duplicate capture group name");
}
state.groupNames.push(state.lastStringValue);
return;
}
state.raise("Invalid group");
}
}; // GroupName ::
// `<` RegExpIdentifierName `>`
// Note: this updates `state.lastStringValue` property with the eaten name.
pp.regexp_eatGroupName = function (state) {
state.lastStringValue = "";
if (state.eat(0x3C
/* < */
)) {
if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E
/* > */
)) {
return true;
}
state.raise("Invalid capture group name");
}
return false;
}; // RegExpIdentifierName ::
// RegExpIdentifierStart
// RegExpIdentifierName RegExpIdentifierPart
// Note: this updates `state.lastStringValue` property with the eaten name.
pp.regexp_eatRegExpIdentifierName = function (state) {
state.lastStringValue = "";
if (this.regexp_eatRegExpIdentifierStart(state)) {
state.lastStringValue += codePointToString(state.lastIntValue);
while (this.regexp_eatRegExpIdentifierPart(state)) {
state.lastStringValue += codePointToString(state.lastIntValue);
}
return true;
}
return false;
}; // RegExpIdentifierStart ::
// UnicodeIDStart
// `$`
// `_`
// `\` RegExpUnicodeEscapeSequence[+U]
pp.regexp_eatRegExpIdentifierStart = function (state) {
var start = state.pos;
var forceU = this.options.ecmaVersion >= 11;
var ch = state.current(forceU);
state.advance(forceU);
if (ch === 0x5C
/* \ */
&& this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
ch = state.lastIntValue;
}
if (isRegExpIdentifierStart(ch)) {
state.lastIntValue = ch;
return true;
}
state.pos = start;
return false;
};
function isRegExpIdentifierStart(ch) {
return (0, identifier.isIdentifierStart)(ch, true) || ch === 0x24
/* $ */
|| ch === 0x5F;
/* _ */
} // RegExpIdentifierPart ::
// UnicodeIDContinue
// `$`
// `_`
// `\` RegExpUnicodeEscapeSequence[+U]
// <ZWNJ>
// <ZWJ>
pp.regexp_eatRegExpIdentifierPart = function (state) {
var start = state.pos;
var forceU = this.options.ecmaVersion >= 11;
var ch = state.current(forceU);
state.advance(forceU);
if (ch === 0x5C
/* \ */
&& this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
ch = state.lastIntValue;
}
if (isRegExpIdentifierPart(ch)) {
state.lastIntValue = ch;
return true;
}
state.pos = start;
return false;
};
function isRegExpIdentifierPart(ch) {
return (0, identifier.isIdentifierChar)(ch, true) || ch === 0x24
/* $ */
|| ch === 0x5F
/* _ */
|| ch === 0x200C
/* <ZWNJ> */
|| ch === 0x200D;
/* <ZWJ> */
} // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape
pp.regexp_eatAtomEscape = function (state) {
if (this.regexp_eatBackReference(state) || this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state) || state.switchN && this.regexp_eatKGroupName(state)) {
return true;
}
if (state.switchU) {
// Make the same message as V8.
if (state.current() === 0x63
/* c */
) {
state.raise("Invalid unicode escape");
}
state.raise("Invalid escape");
}
return false;
};
pp.regexp_eatBackReference = function (state) {
var start = state.pos;
if (this.regexp_eatDecimalEscape(state)) {
var n = state.lastIntValue;
if (state.switchU) {
// For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape
if (n > state.maxBackReference) {
state.maxBackReference = n;
}
return true;
}
if (n <= state.numCapturingParens) {
return true;
}
state.pos = start;
}
return false;
};
pp.regexp_eatKGroupName = function (state) {
if (state.eat(0x6B
/* k */
)) {
if (this.regexp_eatGroupName(state)) {
state.backReferenceNames.push(state.lastStringValue);
return true;
}
state.raise("Invalid named reference");
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape
pp.regexp_eatCharacterEscape = function (state) {
return this.regexp_eatControlEscape(state) || this.regexp_eatCControlLetter(state) || this.regexp_eatZero(state) || this.regexp_eatHexEscapeSequence(state) || this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || !state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state) || this.regexp_eatIdentityEscape(state);
};
pp.regexp_eatCControlLetter = function (state) {
var start = state.pos;
if (state.eat(0x63
/* c */
)) {
if (this.regexp_eatControlLetter(state)) {
return true;
}
state.pos = start;
}
return false;
};
pp.regexp_eatZero = function (state) {
if (state.current() === 0x30
/* 0 */
&& !isDecimalDigit(state.lookahead())) {
state.lastIntValue = 0;
state.advance();
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape
pp.regexp_eatControlEscape = function (state) {
var ch = state.current();
if (ch === 0x74
/* t */
) {
state.lastIntValue = 0x09;
/* \t */
state.advance();
return true;
}
if (ch === 0x6E
/* n */
) {
state.lastIntValue = 0x0A;
/* \n */
state.advance();
return true;
}
if (ch === 0x76
/* v */
) {
state.lastIntValue = 0x0B;
/* \v */
state.advance();
return true;
}
if (ch === 0x66
/* f */
) {
state.lastIntValue = 0x0C;
/* \f */
state.advance();
return true;
}
if (ch === 0x72
/* r */
) {
state.lastIntValue = 0x0D;
/* \r */
state.advance();
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter
pp.regexp_eatControlLetter = function (state) {
var ch = state.current();
if (isControlLetter(ch)) {
state.lastIntValue = ch % 0x20;
state.advance();
return true;
}
return false;
};
function isControlLetter(ch) {
return ch >= 0x41
/* A */
&& ch <= 0x5A
/* Z */
|| ch >= 0x61
/* a */
&& ch <= 0x7A;
} // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
pp.regexp_eatRegExpUnicodeEscapeSequence = function (state, forceU) {
if (forceU === void 0) { forceU = false; }
var start = state.pos;
var switchU = forceU || state.switchU;
if (state.eat(0x75
/* u */
)) {
if (this.regexp_eatFixedHexDigits(state, 4)) {
var lead = state.lastIntValue;
if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
var leadSurrogateEnd = state.pos;
if (state.eat(0x5C
/* \ */
) && state.eat(0x75
/* u */
) && this.regexp_eatFixedHexDigits(state, 4)) {
var trail = state.lastIntValue;
if (trail >= 0xDC00 && trail <= 0xDFFF) {
state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
return true;
}
}
state.pos = leadSurrogateEnd;
state.lastIntValue = lead;
}
return true;
}
if (switchU && state.eat(0x7B
/* { */
) && this.regexp_eatHexDigits(state) && state.eat(0x7D
/* } */
) && isValidUnicode(state.lastIntValue)) {
return true;
}
if (switchU) {
state.raise("Invalid unicode escape");
}
state.pos = start;
}
return false;
};
function isValidUnicode(ch) {
return ch >= 0 && ch <= 0x10FFFF;
} // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape
pp.regexp_eatIdentityEscape = function (state) {
if (state.switchU) {
if (this.regexp_eatSyntaxCharacter(state)) {
return true;
}
if (state.eat(0x2F
/* / */
)) {
state.lastIntValue = 0x2F;
/* / */
return true;
}
return false;
}
var ch = state.current();
if (ch !== 0x63
/* c */
&& (!state.switchN || ch !== 0x6B
/* k */
)) {
state.lastIntValue = ch;
state.advance();
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape
pp.regexp_eatDecimalEscape = function (state) {
state.lastIntValue = 0;
var ch = state.current();
if (ch >= 0x31
/* 1 */
&& ch <= 0x39
/* 9 */
) {
do {
state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30
/* 0 */
);
state.advance();
} while ((ch = state.current()) >= 0x30
/* 0 */
&& ch <= 0x39
/* 9 */
);
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape
pp.regexp_eatCharacterClassEscape = function (state) {
var ch = state.current();
if (isCharacterClassEscape(ch)) {
state.lastIntValue = -1;
state.advance();
return true;
}
if (state.switchU && this.options.ecmaVersion >= 9 && (ch === 0x50
/* P */
|| ch === 0x70
/* p */
)) {
state.lastIntValue = -1;
state.advance();
if (state.eat(0x7B
/* { */
) && this.regexp_eatUnicodePropertyValueExpression(state) && state.eat(0x7D
/* } */
)) {
return true;
}
state.raise("Invalid property name");
}
return false;
};
function isCharacterClassEscape(ch) {
return ch === 0x64
/* d */
|| ch === 0x44
/* D */
|| ch === 0x73
/* s */
|| ch === 0x53
/* S */
|| ch === 0x77
/* w */
|| ch === 0x57;
} // UnicodePropertyValueExpression ::
// UnicodePropertyName `=` UnicodePropertyValue
// LoneUnicodePropertyNameOrValue
pp.regexp_eatUnicodePropertyValueExpression = function (state) {
var start = state.pos; // UnicodePropertyName `=` UnicodePropertyValue
if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D
/* = */
)) {
var name_2 = state.lastStringValue;
if (this.regexp_eatUnicodePropertyValue(state)) {
var value = state.lastStringValue;
this.regexp_validateUnicodePropertyNameAndValue(state, name_2, value);
return true;
}
}
state.pos = start; // LoneUnicodePropertyNameOrValue
if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) {
var nameOrValue = state.lastStringValue;
this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue);
return true;
}
return false;
};
pp.regexp_validateUnicodePropertyNameAndValue = function (state, name, value) {
if (!(0, util.hasOwn)(state.unicodeProperties.nonBinary, name))
state.raise("Invalid property name");
if (!state.unicodeProperties.nonBinary[name].test(value))
state.raise("Invalid property value");
};
pp.regexp_validateUnicodePropertyNameOrValue = function (state, nameOrValue) {
if (!state.unicodeProperties.binary.test(nameOrValue))
state.raise("Invalid property name");
}; // UnicodePropertyName ::
// UnicodePropertyNameCharacters
pp.regexp_eatUnicodePropertyName = function (state) {
var ch = 0;
state.lastStringValue = "";
while (isUnicodePropertyNameCharacter(ch = state.current())) {
state.lastStringValue += codePointToString(ch);
state.advance();
}
return state.lastStringValue !== "";
};
function isUnicodePropertyNameCharacter(ch) {
return isControlLetter(ch) || ch === 0x5F;
/* _ */
} // UnicodePropertyValue ::
// UnicodePropertyValueCharacters
pp.regexp_eatUnicodePropertyValue = function (state) {
var ch = 0;
state.lastStringValue = "";
while (isUnicodePropertyValueCharacter(ch = state.current())) {
state.lastStringValue += codePointToString(ch);
state.advance();
}
return state.lastStringValue !== "";
};
function isUnicodePropertyValueCharacter(ch) {
return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch);
} // LoneUnicodePropertyNameOrValue ::
// UnicodePropertyValueCharacters
pp.regexp_eatLoneUnicodePropertyNameOrValue = function (state) {
return this.regexp_eatUnicodePropertyValue(state);
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass
pp.regexp_eatCharacterClass = function (state) {
if (state.eat(0x5B
/* [ */
)) {
state.eat(0x5E
/* ^ */
);
this.regexp_classRanges(state);
if (state.eat(0x5D
/* ] */
)) {
return true;
} // Unreachable since it threw "unterminated regular expression" error before.
state.raise("Unterminated character class");
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges
// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges
// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash
pp.regexp_classRanges = function (state) {
while (this.regexp_eatClassAtom(state)) {
var left = state.lastIntValue;
if (state.eat(0x2D
/* - */
) && this.regexp_eatClassAtom(state)) {
var right = state.lastIntValue;
if (state.switchU && (left === -1 || right === -1)) {
state.raise("Invalid character class");
}
if (left !== -1 && right !== -1 && left > right) {
state.raise("Range out of order in character class");
}
}
}
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom
// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash
pp.regexp_eatClassAtom = function (state) {
var start = state.pos;
if (state.eat(0x5C
/* \ */
)) {
if (this.regexp_eatClassEscape(state)) {
return true;
}
if (state.switchU) {
// Make the same message as V8.
var ch_1 = state.current();
if (ch_1 === 0x63
/* c */
|| isOctalDigit(ch_1)) {
state.raise("Invalid class escape");
}
state.raise("Invalid escape");
}
state.pos = start;
}
var ch = state.current();
if (ch !== 0x5D
/* ] */
) {
state.lastIntValue = ch;
state.advance();
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape
pp.regexp_eatClassEscape = function (state) {
var start = state.pos;
if (state.eat(0x62
/* b */
)) {
state.lastIntValue = 0x08;
/* <BS> */
return true;
}
if (state.switchU && state.eat(0x2D
/* - */
)) {
state.lastIntValue = 0x2D;
/* - */
return true;
}
if (!state.switchU && state.eat(0x63
/* c */
)) {
if (this.regexp_eatClassControlLetter(state)) {
return true;
}
state.pos = start;
}
return this.regexp_eatCharacterClassEscape(state) || this.regexp_eatCharacterEscape(state);
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter
pp.regexp_eatClassControlLetter = function (state) {
var ch = state.current();
if (isDecimalDigit(ch) || ch === 0x5F
/* _ */
) {
state.lastIntValue = ch % 0x20;
state.advance();
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
pp.regexp_eatHexEscapeSequence = function (state) {
var start = state.pos;
if (state.eat(0x78
/* x */
)) {
if (this.regexp_eatFixedHexDigits(state, 2)) {
return true;
}
if (state.switchU) {
state.raise("Invalid escape");
}
state.pos = start;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits
pp.regexp_eatDecimalDigits = function (state) {
var start = state.pos;
var ch = 0;
state.lastIntValue = 0;
while (isDecimalDigit(ch = state.current())) {
state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30
/* 0 */
);
state.advance();
}
return state.pos !== start;
};
function isDecimalDigit(ch) {
return ch >= 0x30
/* 0 */
&& ch <= 0x39;
/* 9 */
} // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits
pp.regexp_eatHexDigits = function (state) {
var start = state.pos;
var ch = 0;
state.lastIntValue = 0;
while (isHexDigit(ch = state.current())) {
state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
state.advance();
}
return state.pos !== start;
};
function isHexDigit(ch) {
return ch >= 0x30
/* 0 */
&& ch <= 0x39
/* 9 */
|| ch >= 0x41
/* A */
&& ch <= 0x46
/* F */
|| ch >= 0x61
/* a */
&& ch <= 0x66;
}
function hexToInt(ch) {
if (ch >= 0x41
/* A */
&& ch <= 0x46
/* F */
) {
return 10 + (ch - 0x41
/* A */
);
}
if (ch >= 0x61
/* a */
&& ch <= 0x66
/* f */
) {
return 10 + (ch - 0x61
/* a */
);
}
return ch - 0x30;
/* 0 */
} // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence
// Allows only 0-377(octal) i.e. 0-255(decimal).
pp.regexp_eatLegacyOctalEscapeSequence = function (state) {
if (this.regexp_eatOctalDigit(state)) {
var n1 = state.lastIntValue;
if (this.regexp_eatOctalDigit(state)) {
var n2 = state.lastIntValue;
if (n1 <= 3 && this.regexp_eatOctalDigit(state)) {
state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue;
}
else {
state.lastIntValue = n1 * 8 + n2;
}
}
else {
state.lastIntValue = n1;
}
return true;
}
return false;
}; // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit
pp.regexp_eatOctalDigit = function (state) {
var ch = state.current();
if (isOctalDigit(ch)) {
state.lastIntValue = ch - 0x30;
/* 0 */
state.advance();
return true;
}
state.lastIntValue = 0;
return false;
};
function isOctalDigit(ch) {
return ch >= 0x30
/* 0 */
&& ch <= 0x37;
/* 7 */
} // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits
// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit
// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence
pp.regexp_eatFixedHexDigits = function (state, length) {
var start = state.pos;
state.lastIntValue = 0;
for (var i = 0; i < length; ++i) {
var ch = state.current();
if (!isHexDigit(ch)) {
state.pos = start;
return false;
}
state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch);
state.advance();
}
return true;
};
});
var tokenize = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.Token = void 0;
// Object type used to represent tokens. Note that normally, tokens
// simply exist as properties on the parser object. This is only
// used for the onToken callback and the external tokenizer.
var Token = /** @class */ (function () {
function Token(p) {
this.type = p.type;
this.value = p.value;
this.start = p.start;
this.end = p.end;
if (p.options.locations)
this.loc = new locutil.SourceLocation(p, p.startLoc, p.endLoc);
if (p.options.ranges)
this.range = [p.start, p.end];
}
return Token;
}()); // ## Tokenizer
exports.Token = Token;
var pp = state.Parser.prototype; // Move to the next token
pp.next = function (ignoreEscapeSequenceInKeyword) {
if (!ignoreEscapeSequenceInKeyword && this.type.keyword && this.containsEsc)
this.raiseRecoverable(this.start, "Escape sequence in keyword " + this.type.keyword);
if (this.options.onToken)
this.options.onToken(new Token(this));
this.lastTokEnd = this.end;
this.lastTokStart = this.start;
this.lastTokEndLoc = this.endLoc;
this.lastTokStartLoc = this.startLoc;
this.nextToken();
};
pp.getToken = function () {
this.next();
return new Token(this);
}; // If we're in an ES6 environment, make parsers iterable
if (typeof Symbol !== "undefined")
pp[Symbol.iterator] = function () {
var _this = this;
return {
next: function () {
var token = _this.getToken();
return {
done: token.type === tokentype.types.eof,
value: token
};
}
};
}; // Toggle strict mode. Re-reads the next number or string to please
// pedantic tests (`"use strict"; 010;` should fail).
// Read a single token, updating the parser object's token-related
// properties.
pp.nextToken = function () {
var curContext = this.curContext();
if (!curContext || !curContext.preserveSpace)
this.skipSpace();
this.start = this.pos;
if (this.options.locations)
this.startLoc = this.curPosition();
if (this.pos >= this.input.length)
return this.finishToken(tokentype.types.eof);
if (curContext.override)
return curContext.override(this);
else
this.readToken(this.fullCharCodeAtPos());
};
pp.readToken = function (code) {
// Identifier or keyword. '\uXXXX' sequences are allowed in
// identifiers, so '\' also dispatches to that.
if ((0, identifier.isIdentifierStart)(code, this.options.ecmaVersion >= 6) || code === 92
/* '\' */
)
return this.readWord();
return this.getTokenFromCode(code);
};
pp.fullCharCodeAtPos = function () {
var code = this.input.charCodeAt(this.pos);
if (code <= 0xd7ff || code >= 0xdc00)
return code;
var next = this.input.charCodeAt(this.pos + 1);
return next <= 0xdbff || next >= 0xe000 ? code : (code << 10) + next - 0x35fdc00;
};
pp.skipBlockComment = function () {
var startLoc = this.options.onComment && this.curPosition();
var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
if (end === -1)
this.raise(this.pos - 2, "Unterminated comment");
this.pos = end + 2;
if (this.options.locations) {
for (var nextBreak = void 0, pos = start; (nextBreak = (0, whitespace.nextLineBreak)(this.input, pos, this.pos)) > -1;) {
++this.curLine;
pos = this.lineStart = nextBreak;
}
}
if (this.options.onComment)
this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, startLoc, this.curPosition());
};
pp.skipLineComment = function (startSkip) {
var start = this.pos;
var startLoc = this.options.onComment && this.curPosition();
var ch = this.input.charCodeAt(this.pos += startSkip);
while (this.pos < this.input.length && !(0, whitespace.isNewLine)(ch)) {
ch = this.input.charCodeAt(++this.pos);
}
if (this.options.onComment)
this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, startLoc, this.curPosition());
}; // Called at the start of the parse and after every token. Skips
// whitespace and comments, and.
pp.skipSpace = function () {
loop: while (this.pos < this.input.length) {
var ch = this.input.charCodeAt(this.pos);
switch (ch) {
case 32:
case 160:
// ' '
++this.pos;
break;
case 13:
if (this.input.charCodeAt(this.pos + 1) === 10) {
++this.pos;
}
case 10:
case 8232:
case 8233:
++this.pos;
if (this.options.locations) {
++this.curLine;
this.lineStart = this.pos;
}
break;
case 47:
// '/'
switch (this.input.charCodeAt(this.pos + 1)) {
case 42:
// '*'
this.skipBlockComment();
break;
case 47:
this.skipLineComment(2);
break;
default:
break loop;
}
break;
default:
if (ch > 8 && ch < 14 || ch >= 5760 && whitespace.nonASCIIwhitespace.test(String.fromCharCode(ch))) {
++this.pos;
}
else {
break loop;
}
}
}
}; // Called at the end of every token. Sets `end`, `val`, and
// maintains `context` and `exprAllowed`, and skips the space after
// the token, so that the next one's `start` will point at the
// right position.
pp.finishToken = function (type, val) {
this.end = this.pos;
if (this.options.locations)
this.endLoc = this.curPosition();
var prevType = this.type;
this.type = type;
this.value = val;
this.updateContext(prevType);
}; // ### Token reading
// This is the function that is called to fetch the next token. It
// is somewhat obscure, because it works in character codes rather
// than characters, and because operator parsing has been inlined
// into it.
//
// All in the name of speed.
//
pp.readToken_dot = function () {
var next = this.input.charCodeAt(this.pos + 1);
if (next >= 48 && next <= 57)
return this.readNumber(true);
var next2 = this.input.charCodeAt(this.pos + 2);
if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) {
// 46 = dot '.'
this.pos += 3;
return this.finishToken(tokentype.types.ellipsis);
}
else {
++this.pos;
return this.finishToken(tokentype.types.dot);
}
};
pp.readToken_slash = function () {
// '/'
var next = this.input.charCodeAt(this.pos + 1);
if (this.exprAllowed) {
++this.pos;
return this.readRegexp();
}
if (next === 61)
return this.finishOp(tokentype.types.assign, 2);
return this.finishOp(tokentype.types.slash, 1);
};
pp.readToken_mult_modulo_exp = function (code) {
// '%*'
var next = this.input.charCodeAt(this.pos + 1);
var size = 1;
var tokentype$1 = code === 42 ? tokentype.types.star : tokentype.types.modulo; // exponentiation operator ** and **=
if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) {
++size;
tokentype$1 = tokentype.types.starstar;
next = this.input.charCodeAt(this.pos + 2);
}
if (next === 61)
return this.finishOp(tokentype.types.assign, size + 1);
return this.finishOp(tokentype$1, size);
};
pp.readToken_pipe_amp = function (code) {
// '|&'
var next = this.input.charCodeAt(this.pos + 1);
if (next === code) {
if (this.options.ecmaVersion >= 12) {
var next2 = this.input.charCodeAt(this.pos + 2);
if (next2 === 61)
return this.finishOp(tokentype.types.assign, 3);
}
return this.finishOp(code === 124 ? tokentype.types.logicalOR : tokentype.types.logicalAND, 2);
}
if (next === 61)
return this.finishOp(tokentype.types.assign, 2);
return this.finishOp(code === 124 ? tokentype.types.bitwiseOR : tokentype.types.bitwiseAND, 1);
};
pp.readToken_caret = function () {
// '^'
var next = this.input.charCodeAt(this.pos + 1);
if (next === 61)
return this.finishOp(tokentype.types.assign, 2);
return this.finishOp(tokentype.types.bitwiseXOR, 1);
};
pp.readToken_plus_min = function (code) {
// '+-'
var next = this.input.charCodeAt(this.pos + 1);
if (next === code) {
if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && (this.lastTokEnd === 0 || whitespace.lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) {
// A `-->` line comment
this.skipLineComment(3);
this.skipSpace();
return this.nextToken();
}
return this.finishOp(tokentype.types.incDec, 2);
}
if (next === 61)
return this.finishOp(tokentype.types.assign, 2);
return this.finishOp(tokentype.types.plusMin, 1);
};
pp.readToken_lt_gt = function (code) {
// '<>'
var next = this.input.charCodeAt(this.pos + 1);
var size = 1;
if (next === code) {
size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
if (this.input.charCodeAt(this.pos + size) === 61)
return this.finishOp(tokentype.types.assign, size + 1);
return this.finishOp(tokentype.types.bitShift, size);
}
if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && this.input.charCodeAt(this.pos + 3) === 45) {
// `<!--`, an XML-style comment that should be interpreted as a line comment
this.skipLineComment(4);
this.skipSpace();
return this.nextToken();
}
if (next === 61)
size = 2;
return this.finishOp(tokentype.types.relational, size);
};
pp.readToken_eq_excl = function (code) {
// '=!'
var next = this.input.charCodeAt(this.pos + 1);
if (next === 61)
return this.finishOp(tokentype.types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2);
if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) {
// '=>'
this.pos += 2;
return this.finishToken(tokentype.types.arrow);
}
return this.finishOp(code === 61 ? tokentype.types.eq : tokentype.types.prefix, 1);
};
pp.readToken_question = function () {
// '?'
var ecmaVersion = this.options.ecmaVersion;
if (ecmaVersion >= 11) {
var next = this.input.charCodeAt(this.pos + 1);
if (next === 46) {
var next2 = this.input.charCodeAt(this.pos + 2);
if (next2 < 48 || next2 > 57)
return this.finishOp(tokentype.types.questionDot, 2);
}
if (next === 63) {
if (ecmaVersion >= 12) {
var next2 = this.input.charCodeAt(this.pos + 2);
if (next2 === 61)
return this.finishOp(tokentype.types.assign, 3);
}
return this.finishOp(tokentype.types.coalesce, 2);
}
}
return this.finishOp(tokentype.types.question, 1);
};
pp.readToken_numberSign = function () {
// '#'
var ecmaVersion = this.options.ecmaVersion;
var code = 35; // '#'
if (ecmaVersion >= 13) {
++this.pos;
code = this.fullCharCodeAtPos();
if ((0, identifier.isIdentifierStart)(code, true) || code === 92
/* '\' */
) {
return this.finishToken(tokentype.types.privateId, this.readWord1());
}
}
this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};
pp.getTokenFromCode = function (code) {
switch (code) {
// The interpretation of a dot depends on whether it is followed
// by a digit or another two dots.
case 46:
// '.'
return this.readToken_dot();
// Punctuation tokens.
case 40:
++this.pos;
return this.finishToken(tokentype.types.parenL);
case 41:
++this.pos;
return this.finishToken(tokentype.types.parenR);
case 59:
++this.pos;
return this.finishToken(tokentype.types.semi);
case 44:
++this.pos;
return this.finishToken(tokentype.types.comma);
case 91:
++this.pos;
return this.finishToken(tokentype.types.bracketL);
case 93:
++this.pos;
return this.finishToken(tokentype.types.bracketR);
case 123:
++this.pos;
return this.finishToken(tokentype.types.braceL);
case 125:
++this.pos;
return this.finishToken(tokentype.types.braceR);
case 58:
++this.pos;
return this.finishToken(tokentype.types.colon);
case 96:
// '`'
if (this.options.ecmaVersion < 6)
break;
++this.pos;
return this.finishToken(tokentype.types.backQuote);
case 48:
// '0'
var next = this.input.charCodeAt(this.pos + 1);
if (next === 120 || next === 88)
return this.readRadixNumber(16); // '0x', '0X' - hex number
if (this.options.ecmaVersion >= 6) {
if (next === 111 || next === 79)
return this.readRadixNumber(8); // '0o', '0O' - octal number
if (next === 98 || next === 66)
return this.readRadixNumber(2); // '0b', '0B' - binary number
}
// Anything else beginning with a digit is an integer, octal
// number, or float.
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
// 1-9
return this.readNumber(false);
// Quotes produce strings.
case 34:
case 39:
// '"', "'"
return this.readString(code);
// Operators are parsed inline in tiny state machines. '=' (61) is
// often referred to. `finishOp` simply skips the amount of
// characters it is given as second argument, and returns a token
// of the type given by its first argument.
case 47:
// '/'
return this.readToken_slash();
case 37:
case 42:
// '%*'
return this.readToken_mult_modulo_exp(code);
case 124:
case 38:
// '|&'
return this.readToken_pipe_amp(code);
case 94:
// '^'
return this.readToken_caret();
case 43:
case 45:
// '+-'
return this.readToken_plus_min(code);
case 60:
case 62:
// '<>'
return this.readToken_lt_gt(code);
case 61:
case 33:
// '=!'
return this.readToken_eq_excl(code);
case 63:
// '?'
return this.readToken_question();
case 126:
// '~'
return this.finishOp(tokentype.types.prefix, 1);
case 35:
// '#'
return this.readToken_numberSign();
}
this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");
};
pp.finishOp = function (type, size) {
var str = this.input.slice(this.pos, this.pos + size);
this.pos += size;
return this.finishToken(type, str);
};
pp.readRegexp = function () {
var escaped, inClass, start = this.pos;
for (;;) {
if (this.pos >= this.input.length)
this.raise(start, "Unterminated regular expression");
var ch = this.input.charAt(this.pos);
if (whitespace.lineBreak.test(ch))
this.raise(start, "Unterminated regular expression");
if (!escaped) {
if (ch === "[")
inClass = true;
else if (ch === "]" && inClass)
inClass = false;
else if (ch === "/" && !inClass)
break;
escaped = ch === "\\";
}
else
escaped = false;
++this.pos;
}
var pattern = this.input.slice(start, this.pos);
++this.pos;
var flagsStart = this.pos;
var flags = this.readWord1();
if (this.containsEsc)
this.unexpected(flagsStart); // Validate pattern
var state = this.regexpState || (this.regexpState = new regexp.RegExpValidationState(this));
state.reset(start, pattern, flags);
this.validateRegExpFlags(state);
this.validateRegExpPattern(state); // Create Literal#value property value.
var value = null;
try {
value = new RegExp(pattern, flags);
}
catch (e) { // ESTree requires null if it failed to instantiate RegExp object.
// https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral
}
return this.finishToken(tokentype.types.regexp, {
pattern: pattern,
flags: flags,
value: value
});
}; // Read an integer in the given radix. Return null if zero digits
// were read, the integer value otherwise. When `len` is given, this
// will return `null` unless the integer has exactly `len` digits.
pp.readInt = function (radix, len, maybeLegacyOctalNumericLiteral) {
// `len` is used for character escape sequences. In that case, disallow separators.
var allowSeparators = this.options.ecmaVersion >= 12 && len === undefined; // `maybeLegacyOctalNumericLiteral` is true if it doesn't have prefix (0x,0o,0b)
// and isn't fraction part nor exponent part. In that case, if the first digit
// is zero then disallow separators.
var isLegacyOctalNumericLiteral = maybeLegacyOctalNumericLiteral && this.input.charCodeAt(this.pos) === 48;
var start = this.pos, total = 0, lastCode = 0;
for (var i = 0, e = len == null ? Infinity : len; i < e; ++i, ++this.pos) {
var code = this.input.charCodeAt(this.pos), val = void 0;
if (allowSeparators && code === 95) {
if (isLegacyOctalNumericLiteral)
this.raiseRecoverable(this.pos, "Numeric separator is not allowed in legacy octal numeric literals");
if (lastCode === 95)
this.raiseRecoverable(this.pos, "Numeric separator must be exactly one underscore");
if (i === 0)
this.raiseRecoverable(this.pos, "Numeric separator is not allowed at the first of digits");
lastCode = code;
continue;
}
if (code >= 97)
val = code - 97 + 10; // a
else if (code >= 65)
val = code - 65 + 10; // A
else if (code >= 48 && code <= 57)
val = code - 48; // 0-9
else
val = Infinity;
if (val >= radix)
break;
lastCode = code;
total = total * radix + val;
}
if (allowSeparators && lastCode === 95)
this.raiseRecoverable(this.pos - 1, "Numeric separator is not allowed at the last of digits");
if (this.pos === start || len != null && this.pos - start !== len)
return null;
return total;
};
function stringToNumber(str, isLegacyOctalNumericLiteral) {
if (isLegacyOctalNumericLiteral) {
return parseInt(str, 8);
} // `parseFloat(value)` stops parsing at the first numeric separator then returns a wrong value.
return parseFloat(str.replace(/_/g, ""));
}
function stringToBigInt(str) {
if (typeof BigInt !== "function") {
return null;
} // `BigInt(value)` throws syntax error if the string contains numeric separators.
return BigInt(str.replace(/_/g, ""));
}
pp.readRadixNumber = function (radix) {
var start = this.pos;
this.pos += 2; // 0x
var val = this.readInt(radix);
if (val == null)
this.raise(this.start + 2, "Expected number in radix " + radix);
if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) {
val = stringToBigInt(this.input.slice(start, this.pos));
++this.pos;
}
else if ((0, identifier.isIdentifierStart)(this.fullCharCodeAtPos()))
this.raise(this.pos, "Identifier directly after number");
return this.finishToken(tokentype.types.num, val);
}; // Read an integer, octal integer, or floating-point number.
pp.readNumber = function (startsWithDot) {
var start = this.pos;
if (!startsWithDot && this.readInt(10, undefined, true) === null)
this.raise(start, "Invalid number");
var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48;
if (octal && this.strict)
this.raise(start, "Invalid number");
var next = this.input.charCodeAt(this.pos);
if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) {
var val_1 = stringToBigInt(this.input.slice(start, this.pos));
++this.pos;
if ((0, identifier.isIdentifierStart)(this.fullCharCodeAtPos()))
this.raise(this.pos, "Identifier directly after number");
return this.finishToken(tokentype.types.num, val_1);
}
if (octal && /[89]/.test(this.input.slice(start, this.pos)))
octal = false;
if (next === 46 && !octal) {
// '.'
++this.pos;
this.readInt(10);
next = this.input.charCodeAt(this.pos);
}
if ((next === 69 || next === 101) && !octal) {
// 'eE'
next = this.input.charCodeAt(++this.pos);
if (next === 43 || next === 45)
++this.pos; // '+-'
if (this.readInt(10) === null)
this.raise(start, "Invalid number");
}
if ((0, identifier.isIdentifierStart)(this.fullCharCodeAtPos()))
this.raise(this.pos, "Identifier directly after number");
var val = stringToNumber(this.input.slice(start, this.pos), octal);
return this.finishToken(tokentype.types.num, val);
}; // Read a string value, interpreting backslash-escapes.
pp.readCodePoint = function () {
var ch = this.input.charCodeAt(this.pos), code;
if (ch === 123) {
// '{'
if (this.options.ecmaVersion < 6)
this.unexpected();
var codePos = ++this.pos;
code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos);
++this.pos;
if (code > 0x10FFFF)
this.invalidStringToken(codePos, "Code point out of bounds");
}
else {
code = this.readHexChar(4);
}
return code;
};
function codePointToString(code) {
// UTF-16 Decoding
if (code <= 0xFFFF)
return String.fromCharCode(code);
code -= 0x10000;
return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00);
}
pp.readString = function (quote) {
var out = "", chunkStart = ++this.pos;
for (;;) {
if (this.pos >= this.input.length)
this.raise(this.start, "Unterminated string constant");
var ch = this.input.charCodeAt(this.pos);
if (ch === quote)
break;
if (ch === 92) {
// '\'
out += this.input.slice(chunkStart, this.pos);
out += this.readEscapedChar(false);
chunkStart = this.pos;
}
else if (ch === 0x2028 || ch === 0x2029) {
if (this.options.ecmaVersion < 10)
this.raise(this.start, "Unterminated string constant");
++this.pos;
if (this.options.locations) {
this.curLine++;
this.lineStart = this.pos;
}
}
else {
if ((0, whitespace.isNewLine)(ch))
this.raise(this.start, "Unterminated string constant");
++this.pos;
}
}
out += this.input.slice(chunkStart, this.pos++);
return this.finishToken(tokentype.types.string, out);
}; // Reads template string tokens.
var INVALID_TEMPLATE_ESCAPE_ERROR = {};
pp.tryReadTemplateToken = function () {
this.inTemplateElement = true;
try {
this.readTmplToken();
}
catch (err) {
if (err === INVALID_TEMPLATE_ESCAPE_ERROR) {
this.readInvalidTemplateToken();
}
else {
throw err;
}
}
this.inTemplateElement = false;
};
pp.invalidStringToken = function (position, message) {
if (this.inTemplateElement && this.options.ecmaVersion >= 9) {
throw INVALID_TEMPLATE_ESCAPE_ERROR;
}
else {
this.raise(position, message);
}
};
pp.readTmplToken = function () {
var out = "", chunkStart = this.pos;
for (;;) {
if (this.pos >= this.input.length)
this.raise(this.start, "Unterminated template");
var ch = this.input.charCodeAt(this.pos);
if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) {
// '`', '${'
if (this.pos === this.start && (this.type === tokentype.types.template || this.type === tokentype.types.invalidTemplate)) {
if (ch === 36) {
this.pos += 2;
return this.finishToken(tokentype.types.dollarBraceL);
}
else {
++this.pos;
return this.finishToken(tokentype.types.backQuote);
}
}
out += this.input.slice(chunkStart, this.pos);
return this.finishToken(tokentype.types.template, out);
}
if (ch === 92) {
// '\'
out += this.input.slice(chunkStart, this.pos);
out += this.readEscapedChar(true);
chunkStart = this.pos;
}
else if ((0, whitespace.isNewLine)(ch)) {
out += this.input.slice(chunkStart, this.pos);
++this.pos;
switch (ch) {
case 13:
if (this.input.charCodeAt(this.pos) === 10)
++this.pos;
case 10:
out += "\n";
break;
default:
out += String.fromCharCode(ch);
break;
}
if (this.options.locations) {
++this.curLine;
this.lineStart = this.pos;
}
chunkStart = this.pos;
}
else {
++this.pos;
}
}
}; // Reads a template token to search for the end, without validating any escape sequences
pp.readInvalidTemplateToken = function () {
for (; this.pos < this.input.length; this.pos++) {
switch (this.input[this.pos]) {
case "\\":
++this.pos;
break;
case "$":
if (this.input[this.pos + 1] !== "{") {
break;
}
// falls through
case "`":
return this.finishToken(tokentype.types.invalidTemplate, this.input.slice(this.start, this.pos));
// no default
}
}
this.raise(this.start, "Unterminated template");
}; // Used to read escaped characters
pp.readEscapedChar = function (inTemplate) {
var ch = this.input.charCodeAt(++this.pos);
++this.pos;
switch (ch) {
case 110:
return "\n";
// 'n' -> '\n'
case 114:
return "\r";
// 'r' -> '\r'
case 120:
return String.fromCharCode(this.readHexChar(2));
// 'x'
case 117:
return codePointToString(this.readCodePoint());
// 'u'
case 116:
return "\t";
// 't' -> '\t'
case 98:
return "\b";
// 'b' -> '\b'
case 118:
return "\u000b";
// 'v' -> '\u000b'
case 102:
return "\f";
// 'f' -> '\f'
case 13:
if (this.input.charCodeAt(this.pos) === 10)
++this.pos;
// '\r\n'
case 10:
// ' \n'
if (this.options.locations) {
this.lineStart = this.pos;
++this.curLine;
}
return "";
case 56:
case 57:
if (this.strict) {
this.invalidStringToken(this.pos - 1, "Invalid escape sequence");
}
if (inTemplate) {
var codePos = this.pos - 1;
this.invalidStringToken(codePos, "Invalid escape sequence in template string");
return null;
}
default:
if (ch >= 48 && ch <= 55) {
var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
var octal = parseInt(octalStr, 8);
if (octal > 255) {
octalStr = octalStr.slice(0, -1);
octal = parseInt(octalStr, 8);
}
this.pos += octalStr.length - 1;
ch = this.input.charCodeAt(this.pos);
if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) {
this.invalidStringToken(this.pos - 1 - octalStr.length, inTemplate ? "Octal literal in template string" : "Octal literal in strict mode");
}
return String.fromCharCode(octal);
}
if ((0, whitespace.isNewLine)(ch)) {
// Unicode new line characters after \ get removed from output in both
// template literals and strings
return "";
}
return String.fromCharCode(ch);
}
}; // Used to read character escape sequences ('\x', '\u', '\U').
pp.readHexChar = function (len) {
var codePos = this.pos;
var n = this.readInt(16, len);
if (n === null)
this.invalidStringToken(codePos, "Bad character escape sequence");
return n;
}; // Read an identifier, and return it as a string. Sets `this.containsEsc`
// to whether the word contained a '\u' escape.
//
// Incrementally adds only escaped chars, adding other chunks as-is
// as a micro-optimization.
pp.readWord1 = function () {
this.containsEsc = false;
var word = "", first = true, chunkStart = this.pos;
var astral = this.options.ecmaVersion >= 6;
while (this.pos < this.input.length) {
var ch = this.fullCharCodeAtPos();
if ((0, identifier.isIdentifierChar)(ch, astral)) {
this.pos += ch <= 0xffff ? 1 : 2;
}
else if (ch === 92) {
// "\"
this.containsEsc = true;
word += this.input.slice(chunkStart, this.pos);
var escStart = this.pos;
if (this.input.charCodeAt(++this.pos) !== 117) // "u"
this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX");
++this.pos;
var esc = this.readCodePoint();
if (!(first ? identifier.isIdentifierStart : identifier.isIdentifierChar)(esc, astral))
this.invalidStringToken(escStart, "Invalid Unicode escape");
word += this.input.substr(this.pos - 6, 6);
chunkStart = this.pos;
}
else {
break;
}
first = false;
}
return word + this.input.slice(chunkStart, this.pos);
}; // Read an identifier or keyword token. Will check for reserved
// words when necessary.
pp.readWord = function () {
var word = this.readWord1();
var type = tokentype.types.name;
if (this.keywords.test(word)) {
type = tokentype.keywords[word];
}
return this.finishToken(type, word);
};
});
var lib = createCommonjsModule(function (module, exports) {
exports.__esModule = true;
exports.parse = parse;
exports.parseExpressionAt = parseExpressionAt;
exports.tokenizer = tokenizer;
exports.version = void 0;
exports.Parser = state.Parser;
exports.defaultOptions = options.defaultOptions;
exports.Position = locutil.Position;
exports.SourceLocation = locutil.SourceLocation;
exports.getLineInfo = locutil.getLineInfo;
exports.Node = node.Node;
exports.TokenType = tokentype.TokenType;
exports.tokTypes = tokentype.types;
exports.keywordTypes = tokentype.keywords;
exports.TokContext = tokencontext.TokContext;
exports.tokContexts = tokencontext.types;
exports.isIdentifierChar = identifier.isIdentifierChar;
exports.isIdentifierStart = identifier.isIdentifierStart;
exports.Token = tokenize.Token;
exports.isNewLine = whitespace.isNewLine;
exports.lineBreak = whitespace.lineBreak;
exports.lineBreakG = whitespace.lineBreakG;
exports.nonASCIIwhitespace = whitespace.nonASCIIwhitespace;
var utils = _interopRequireWildcard(util);
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function")
return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) {
return obj;
} if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return { default: obj };
} var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) {
return cache.get(obj);
} var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) {
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
}
else {
newObj[key] = obj[key];
}
}
} newObj.default = obj; if (cache) {
cache.set(obj, newObj);
} return newObj; }
// Acorn is a tiny, fast JavaScript parser written in JavaScript.
//
// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and
// various contributors and released under an MIT license.
//
// Git repositories for Acorn are available at
//
// http://marijnhaverbeke.nl/git/acorn
// https://github.com/acornjs/acorn.git
//
// Please use the [github bug tracker][ghbt] to report issues.
//
// [ghbt]: https://github.com/acornjs/acorn/issues
//
// [walk]: util/walk.js
var version = "8.7.0";
exports.version = version;
state.Parser.acorn = {
Parser: state.Parser,
version: version,
defaultOptions: options.defaultOptions,
Position: locutil.Position,
SourceLocation: locutil.SourceLocation,
getLineInfo: locutil.getLineInfo,
Node: node.Node,
TokenType: tokentype.TokenType,
tokTypes: tokentype.types,
keywordTypes: tokentype.keywords,
TokContext: tokencontext.TokContext,
tokContexts: tokencontext.types,
isIdentifierChar: identifier.isIdentifierChar,
isIdentifierStart: identifier.isIdentifierStart,
Token: tokenize.Token,
isNewLine: whitespace.isNewLine,
lineBreak: whitespace.lineBreak,
lineBreakG: whitespace.lineBreakG,
nonASCIIwhitespace: whitespace.nonASCIIwhitespace
}; // The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and
// returns an abstract syntax tree as specified by [Mozilla parser
// API][api].
//
// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
function parse(input, options) {
return state.Parser.parse(input, options);
} // This function tries to parse a single expression at a given
// offset in a string. Useful for parsing mixed-language formats
// that embed JavaScript expressions.
function parseExpressionAt(input, pos, options) {
return state.Parser.parseExpressionAt(input, pos, options);
} // Acorn is organized as a tokenizer and a recursive-descent parser.
// The `tokenizer` export provides an interface to the tokenizer.
function tokenizer(input, options) {
return state.Parser.tokenizer(input, options);
} // =============================================================================
// =============================================================================
// ===================== TestCafe performance patch ============================
// =====================||||||||||||||||||||||||||||============================
// =====================vvvvvvvvvvvvvvvvvvvvvvvvvvvv============================
var storedWordsRegexp = utils.wordsRegexp;
var wordsRegexpCache = {};
utils.wordsRegexp = function (words) {
if (!wordsRegexpCache[words])
wordsRegexpCache[words] = storedWordsRegexp(words);
return wordsRegexpCache[words];
}; // =====================^^^^^^^^^^^^^^^^^^^^^^^^^^^^============================
});
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
var BOM_RE = /^(\xEF\xBB\xBF|\xFE\xFF|\xFF\xFE|\x00\x00\xFE\xFF|\xFF\xFE\x00\x00|\x2B\x2F\x76\x38|\x2B\x2F\x76\x39|\x2B\x2F\x76\x2B|\x2B\x2F\x76\x2F|\xF7\x64\x4C|\xDD\x73\x66\x73|\x0E\xFE\xFF|\xFB\xEE\x28|\x84\x31\x95\x33)/; // eslint-disable-line no-control-regex
function getBOM (str) {
var match = str.match(BOM_RE);
return match ? match[0] : null;
}
var HTML_COMMENT_RE = /(^|\n)\s*<!--[^\n]*(\n|$)/g;
var OBJECT_RE = /^\s*\{.*\}\s*$/;
var TRAILING_SEMICOLON_RE = /;\s*$/;
var OBJECT_WRAPPER_RE = /^\s*\((.*)\);\s*$/;
var SOURCEMAP_RE = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)/gm;
var PROCESSED_SCRIPT_RE = new RegExp([
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.getLocation),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.setLocation),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.getProperty),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.setProperty),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.callMethod),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.processScript),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.processHtml),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage),
reEscape(SCRIPT_PROCESSING_INSTRUCTIONS.getProxyUrl),
].join('|'));
var PARSING_OPTIONS = {
allowReturnOutsideFunction: true,
allowImportExportEverywhere: true,
ecmaVersion: 13,
};
// Code pre/post-processing
function removeHtmlComments(code) {
// NOTE: The JS parser removes the line that follows'<!--'. (T226589)
do
code = code.replace(HTML_COMMENT_RE, '\n');
while (HTML_COMMENT_RE.test(code));
return code;
}
function preprocess(code) {
var bom = getBOM(code);
var preprocessed = bom ? code.substring(bom.length) : code;
preprocessed = remove$1(preprocessed);
preprocessed = removeSourceMap(preprocessed);
return { bom: bom, preprocessed: preprocessed };
}
function removeSourceMap(code) {
return code.replace(SOURCEMAP_RE, '');
}
function postprocess(processed, withHeader, bom, strictMode, swScopeHeaderValue, proxyless, workerSettings) {
// NOTE: If the 'use strict' directive is not in the beginning of the file, it is ignored.
// As we insert our header in the beginning of the script, we must put a new 'use strict'
// before the header, otherwise it will be ignored.
if (withHeader)
processed = add$1(processed, strictMode, swScopeHeaderValue, proxyless, workerSettings);
return bom ? bom + processed : processed;
}
// Parse/generate code
function removeTrailingSemicolon(processed, src) {
return TRAILING_SEMICOLON_RE.test(src) ? processed : processed.replace(TRAILING_SEMICOLON_RE, '');
}
function getAst(src, isObject) {
// NOTE: In case of objects (e.g.eval('{ 1: 2}')) without wrapping
// object will be parsed as label. To avoid this we parenthesize src
src = isObject ? "(".concat(src, ")") : src;
try {
return lib.parse(src, PARSING_OPTIONS);
}
catch (err) {
return null;
}
}
function getCode(ast, src) {
var code = generate(ast, {
format: {
quotes: 'double',
escapeless: true,
compact: true,
},
});
return src ? removeTrailingSemicolon(code, src) : code;
}
// Analyze code
function analyze(code) {
var isObject = OBJECT_RE.test(code);
var ast = getAst(code, isObject);
// NOTE: `{ const a = 'foo'; }` edge case
if (!ast && isObject) {
ast = getAst(code, false);
isObject = false;
}
return { ast: ast, isObject: isObject };
}
function isArrayDataScript(ast) {
var firstChild = ast.body[0];
return ast.body.length === 1 &&
firstChild.type === Syntax_1.ExpressionStatement &&
firstChild.expression.type === Syntax_1.ArrayExpression;
}
function isStrictMode(ast) {
if (ast.body.length) {
var firstChild = ast.body[0];
if (firstChild.type === Syntax_1.ExpressionStatement && firstChild.expression.type === Syntax_1.Literal)
return firstChild.expression.value === 'use strict';
}
return false;
}
function applyChanges(script, changes, isObject) {
var indexOffset = isObject ? -1 : 0;
var chunks = [];
var index = 0;
if (!changes.length)
return script;
changes.sort(function (a, b) { return (a.start - b.start) || (a.end - b.end) || // eslint-disable-line @typescript-eslint/no-extra-parens
((a.node.type === Syntax_1.VariableDeclaration ? 0 : 1) - (b.node.type === Syntax_1.VariableDeclaration ? 0 : 1)); }); // eslint-disable-line @typescript-eslint/no-extra-parens
for (var _i = 0, changes_1 = changes; _i < changes_1.length; _i++) {
var change = changes_1[_i];
var changeStart = change.start + indexOffset;
var changeEnd = change.end + indexOffset;
var parentheses = change.node.type === Syntax_1.SequenceExpression &&
change.parentType !== Syntax_1.ExpressionStatement &&
change.parentType !== Syntax_1.SequenceExpression;
chunks.push(script.substring(index, changeStart));
chunks.push(parentheses ? '(' : ' ');
chunks.push(getCode(change.node, script.substring(changeStart, changeEnd)));
chunks.push(parentheses ? ')' : ' ');
index += changeEnd - index;
}
chunks.push(script.substring(index));
return chunks.join('');
}
function isScriptProcessed(code) {
return PROCESSED_SCRIPT_RE.test(code);
}
function processScript(src, withHeader, wrapLastExprWithProcessHtml, resolver, swScopeHeaderValue, proxyless, workerSettings) {
if (withHeader === void 0) { withHeader = false; }
if (wrapLastExprWithProcessHtml === void 0) { wrapLastExprWithProcessHtml = false; }
var _a = preprocess(src), bom = _a.bom, preprocessed = _a.preprocessed;
var withoutHtmlComments = removeHtmlComments(preprocessed);
var _b = analyze(withoutHtmlComments), ast = _b.ast, isObject = _b.isObject;
if (!ast)
return src;
withHeader = withHeader && !isObject && !isArrayDataScript(ast);
var changes = proxyless ? [] : transformProgram(ast, wrapLastExprWithProcessHtml, resolver);
var processed = changes.length ? applyChanges(withoutHtmlComments, changes, isObject) : preprocessed;
processed = postprocess(processed, withHeader, bom, isStrictMode(ast), swScopeHeaderValue, proxyless, workerSettings);
if (isObject)
processed = processed.replace(OBJECT_WRAPPER_RE, '$1');
return processed;
}
var scriptProcessingUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
isScriptProcessed: isScriptProcessed,
processScript: processScript
});
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
var URL_ATTR_TAGS = {
href: ['a', 'link', 'image', 'area', 'base'],
src: ['img', 'embed', 'script', 'source', 'video', 'audio', 'input', 'frame', 'iframe'],
srcset: ['img', 'source'],
action: ['form'],
formaction: ['button', 'input'],
manifest: ['html'],
data: ['object'],
};
var URL_ATTRS = ['href', 'src', 'action', 'formaction', 'manifest', 'data'];
var TARGET_ATTR_TAGS = {
target: ['a', 'form', 'area', 'base'],
formtarget: ['input', 'button'],
};
var TARGET_ATTRS = ['target', 'formtarget'];
var ATTRS_WITH_SPECIAL_PROXYING_LOGIC = ['sandbox', 'autocomplete', 'target', 'formtarget', 'style'];
// -------------------------------------------------------------
var SOURCE_MAP_RE = /\/\*\s*[#@]\s*sourceMappingURL\s*=[\s\S]*?\*\/|\/\/[\t ]*[#@][\t ]*sourceMappingURL[\t ]*=.*/ig;
var CSS_URL_PROPERTY_VALUE_RE = /(url\s*\(\s*(['"]?))([^\s]*?)(\2\s*\))|(@import\s+(['"]))([^\s]*?)(\6)/g;
var ATTRIBUTE_SELECTOR_RE = /((?:(\W?)(\w+))?\[\s*)(\w+)(\s*\^?=)/g;
var STYLESHEET_PROCESSING_START_COMMENT = '/*hammerhead|stylesheet|start*/';
var STYLESHEET_PROCESSING_END_COMMENT = '/*hammerhead|stylesheet|end*/';
var HOVER_PSEUDO_CLASS_RE = /:\s*hover(\W)/gi;
var PSEUDO_CLASS_RE = new RegExp("\\[".concat(INTERNAL_ATTRIBUTES.hoverPseudoClass, "\\](\\W)"), 'ig');
var IS_STYLE_SHEET_PROCESSED_RE = new RegExp("\\s*".concat(reEscape(STYLESHEET_PROCESSING_START_COMMENT)), 'gi');
var STYLESHEET_PROCESSING_COMMENTS_RE = new RegExp("".concat(reEscape(STYLESHEET_PROCESSING_START_COMMENT), "\n?|") +
"\n?".concat(reEscape(STYLESHEET_PROCESSING_END_COMMENT), "\\s*"), 'gi');
var StyleProcessor = /** @class */ (function () {
function StyleProcessor() {
this.STYLESHEET_PROCESSING_START_COMMENT = STYLESHEET_PROCESSING_START_COMMENT;
this.STYLESHEET_PROCESSING_END_COMMENT = STYLESHEET_PROCESSING_END_COMMENT;
this.proxyless = false;
}
StyleProcessor.prototype.process = function (css, urlReplacer, shouldIncludeProcessingComments) {
if (!css || typeof css !== 'string' || shouldIncludeProcessingComments && IS_STYLE_SHEET_PROCESSED_RE.test(css))
return css;
// NOTE: Replace the :hover pseudo-class.
css = css.replace(HOVER_PSEUDO_CLASS_RE, '[' + INTERNAL_ATTRIBUTES.hoverPseudoClass + ']$1');
// NOTE: Remove all 'source map' directives.
css = css.replace(SOURCE_MAP_RE, '');
// NOTE: Replace URLs in CSS rules with proxy URLs.
if (!this.proxyless)
css = this._replaceStylesheetUrls(css, urlReplacer);
// NOTE: Replace url attributes to stored attributes
css = this._replaceUrlAttributes(css);
if (shouldIncludeProcessingComments)
css = "".concat(STYLESHEET_PROCESSING_START_COMMENT, "\n").concat(css, "\n").concat(STYLESHEET_PROCESSING_END_COMMENT);
return css;
};
StyleProcessor.prototype.cleanUp = function (css, parseProxyUrl) {
if (typeof css !== 'string')
return css;
css = css
.replace(PSEUDO_CLASS_RE, ':hover$1')
.replace(INTERNAL_ATTRIBUTES.storedAttrPostfix, '');
css = this._removeStylesheetProcessingComments(css);
if (!this.proxyless) {
css = this._replaceStylesheetUrls(css, function (url) {
var parsedProxyUrl = parseProxyUrl(url);
return parsedProxyUrl ? parsedProxyUrl.destUrl : url;
});
}
return css;
};
StyleProcessor.prototype._removeStylesheetProcessingComments = function (css) {
var parts = css.split(STYLESHEET_PROCESSING_COMMENTS_RE);
var stylesheetPartsFound = parts.length >= 3;
if (!stylesheetPartsFound)
return css;
for (var i = 0; i < parts.length; i += 2) {
var whiteSpaceCount = 0;
// NOTE: search for whitespaces from the end of the string
// we do not use /\s*$/ regex intentionally to improve performance
for (var j = parts[i].length - 1; j >= 0; j--) {
if (!(/\s/.test(parts[i][j]))) // eslint-disable-line @typescript-eslint/no-extra-parens
break;
whiteSpaceCount++;
}
parts[i] = parts[i].substring(0, parts[i].length - whiteSpaceCount);
}
return parts.join('');
};
StyleProcessor.prototype._replaceStylesheetUrls = function (css, processor) {
return css.replace(CSS_URL_PROPERTY_VALUE_RE, function (match, prefix1, _q1, url1, postfix1, prefix2, _q2, url2, postfix2) {
var prefix = prefix1 || prefix2;
var url = url1 || url2;
var processedUrl = isSpecialPage$1(url) ? url : processor(url);
var postfix = postfix1 || postfix2;
return url ? prefix + processedUrl + postfix : match;
});
};
StyleProcessor.prototype._replaceUrlAttributes = function (css) {
return css.replace(ATTRIBUTE_SELECTOR_RE, function (match, prefix, prev, possibleTag, attribute, postfix) {
var tagName = prev === '.' || prev === '#' ? '' : possibleTag;
if (!tagName || !URL_ATTR_TAGS[attribute] || URL_ATTR_TAGS[attribute].indexOf(tagName) === -1)
return match;
return prefix + DomProcessor.getStoredAttrName(attribute) + postfix;
});
};
return StyleProcessor;
}());
var styleProcessor = new StyleProcessor();
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
var BUILTIN_HEADERS = {
authorization: 'authorization',
wwwAuthenticate: 'www-authenticate',
proxyAuthorization: 'proxy-authorization',
proxyAuthenticate: 'proxy-authenticate',
host: 'host',
referer: 'referer',
origin: 'origin',
contentLength: 'content-length',
cookie: 'cookie',
setCookie: 'set-cookie',
ifModifiedSince: 'if-modified-since',
ifNoneMatch: 'if-none-match',
contentType: 'content-type',
location: 'location',
xFrameOptions: 'x-frame-options',
sourceMap: 'sourcemap',
referrerPolicy: 'referrer-policy',
refresh: 'refresh',
link: 'link',
cacheControl: 'cache-control',
pragma: 'pragma',
eTag: 'etag',
contentDisposition: 'content-disposition',
accept: 'accept',
contentEncoding: 'content-encoding',
expires: 'expires',
trailer: 'trailer',
transferEncoding: 'transfer-encoding',
serviceWorkerAllowed: 'service-worker-allowed',
accessControlAllowOrigin: 'access-control-allow-origin',
accessControlAllowCredentials: 'access-control-allow-credentials',
contentSecurityPolicy: 'content-security-policy',
contentSecurityPolicyReportOnly: 'content-security-policy-report-only',
xContentSecurityPolicy: 'x-content-security-policy',
xContentSecurityPolicyReportOnly: 'x-content-security-policy-report-only',
xWebkitCsp: 'x-webkit-csp',
isApiRequest: 'is-api-request',
userAgent: 'user-agent',
};
var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace';
var XLINK_NAMESPACE = 'http://www.w3.org/1999/xlink';
// -------------------------------------------------------------
var CDATA_REG_EX = /^(\s)*\/\/<!\[CDATA\[([\s\S]*)\/\/\]\]>(\s)*$/;
var HTML_COMMENT_POSTFIX_REG_EX = /(\/\/[^\n]*|\n\s*)-->[^\n]*([\n\s]*)?$/;
var HTML_COMMENT_PREFIX_REG_EX = /^(\s)*<!--[^\n]*\n/;
var HTML_COMMENT_SIMPLE_POSTFIX_REG_EX = /-->\s*$/;
var JAVASCRIPT_PROTOCOL_REG_EX = /^\s*javascript\s*:/i;
var EXECUTABLE_SCRIPT_TYPES_REG_EX = /^\s*(application\/(x-)?(ecma|java)script|text\/(javascript(1\.[0-5])?|((x-)?ecma|x-java|js|live)script)|module)\s*$/i;
var SVG_XLINK_HREF_TAGS = [
'animate', 'animateColor', 'animateMotion', 'animateTransform', 'mpath', 'set',
'linearGradient', 'radialGradient', 'stop',
'a', 'altglyph', 'color-profile', 'cursor', 'feimage', 'filter', 'font-face-uri', 'glyphref', 'image',
'mpath', 'pattern', 'script', 'textpath', 'use', 'tref',
];
var INTEGRITY_ATTR_TAGS = ['script', 'link'];
var IFRAME_FLAG_TAGS = ['a', 'form', 'area', 'input', 'button'];
var PROCESSED_PRELOAD_LINK_CONTENT_TYPE = 'script';
var MODULE_PRELOAD_LINK_REL = 'modulepreload';
var ELEMENT_PROCESSED = 'hammerhead|element-processed';
var AUTOCOMPLETE_ATTRIBUTE_ABSENCE_MARKER = 'hammerhead|autocomplete-attribute-absence-marker';
var DomProcessor = /** @class */ (function () {
function DomProcessor(adapter) {
this.adapter = adapter;
this.HTML_PROCESSING_REQUIRED_EVENT = 'hammerhead|event|html-processing-required';
this.SVG_XLINK_HREF_TAGS = SVG_XLINK_HREF_TAGS;
this.AUTOCOMPLETE_ATTRIBUTE_ABSENCE_MARKER = AUTOCOMPLETE_ATTRIBUTE_ABSENCE_MARKER;
this.PROCESSED_PRELOAD_LINK_CONTENT_TYPE = PROCESSED_PRELOAD_LINK_CONTENT_TYPE;
this.MODULE_PRELOAD_LINK_REL = MODULE_PRELOAD_LINK_REL;
this.forceProxySrcForImage = false;
this.allowMultipleWindows = false;
this.proxyless = false;
this.EVENTS = this.adapter.EVENTS;
this.elementProcessorPatterns = this._createProcessorPatterns(this.adapter);
}
DomProcessor.isTagWithTargetAttr = function (tagName) {
return !!tagName && TARGET_ATTR_TAGS.target.indexOf(tagName) > -1;
};
DomProcessor.isTagWithFormTargetAttr = function (tagName) {
return !!tagName && TARGET_ATTR_TAGS.formtarget.indexOf(tagName) > -1;
};
DomProcessor.isTagWithIntegrityAttr = function (tagName) {
return !!tagName && INTEGRITY_ATTR_TAGS.indexOf(tagName) !== -1;
};
DomProcessor.isIframeFlagTag = function (tagName) {
return !!tagName && IFRAME_FLAG_TAGS.indexOf(tagName) !== -1;
};
DomProcessor.isAddedAutocompleteAttr = function (attrName, storedAttrValue) {
return attrName === 'autocomplete' && storedAttrValue === AUTOCOMPLETE_ATTRIBUTE_ABSENCE_MARKER;
};
DomProcessor.processJsAttrValue = function (value, _a) {
var isJsProtocol = _a.isJsProtocol, isEventAttr = _a.isEventAttr;
if (isJsProtocol)
value = value.replace(JAVASCRIPT_PROTOCOL_REG_EX, '');
value = processScript(value, false, isJsProtocol && !isEventAttr, void 0);
if (isJsProtocol)
value = 'javascript:' + value; // eslint-disable-line no-script-url
return value;
};
DomProcessor.getStoredAttrName = function (attr) {
return attr + INTERNAL_ATTRIBUTES.storedAttrPostfix;
};
DomProcessor.isJsProtocol = function (value) {
return JAVASCRIPT_PROTOCOL_REG_EX.test(value);
};
DomProcessor._isHtmlImportLink = function (tagName, relAttr) {
return !!tagName && !!relAttr && tagName === 'link' && relAttr === 'import';
};
DomProcessor.isElementProcessed = function (el) {
// @ts-ignore
return el[ELEMENT_PROCESSED];
};
DomProcessor.setElementProcessed = function (el, processed) {
// @ts-ignore
el[ELEMENT_PROCESSED] = processed;
};
DomProcessor.prototype._getRelAttribute = function (el) {
return String(this.adapter.getAttr(el, 'rel')).toLowerCase();
};
DomProcessor.prototype._getAsAttribute = function (el) {
return String(this.adapter.getAttr(el, 'as')).toLowerCase();
};
DomProcessor.prototype._createProcessorPatterns = function (adapter) {
var _this = this;
var selectors = {
HAS_HREF_ATTR: function (el) { return _this.isUrlAttr(el, 'href'); },
HAS_SRC_ATTR: function (el) { return _this.isUrlAttr(el, 'src'); },
HAS_SRCSET_ATTR: function (el) { return _this.isUrlAttr(el, 'srcset'); },
HAS_ACTION_ATTR: function (el) { return _this.isUrlAttr(el, 'action'); },
HAS_FORMACTION_ATTR: function (el) { return _this.isUrlAttr(el, 'formaction'); },
HAS_FORMTARGET_ATTR: function (el) {
return DomProcessor.isTagWithFormTargetAttr(adapter.getTagName(el)) && adapter.hasAttr(el, 'formtarget');
},
HAS_MANIFEST_ATTR: function (el) { return _this.isUrlAttr(el, 'manifest'); },
HAS_DATA_ATTR: function (el) { return _this.isUrlAttr(el, 'data'); },
HAS_SRCDOC_ATTR: function (el) {
var tagName = _this.adapter.getTagName(el);
return (tagName === 'iframe' || tagName === 'frame') && adapter.hasAttr(el, 'srcdoc');
},
HTTP_EQUIV_META: function (el) {
var tagName = adapter.getTagName(el);
return tagName === 'meta' && adapter.hasAttr(el, 'http-equiv');
},
ALL: function () { return true; },
IS_SCRIPT: function (el) { return adapter.getTagName(el) === 'script'; },
IS_LINK: function (el) { return adapter.getTagName(el) === 'link'; },
IS_INPUT: function (el) { return adapter.getTagName(el) === 'input'; },
IS_FILE_INPUT: function (el) {
return adapter.getTagName(el) === 'input' &&
adapter.hasAttr(el, 'type') &&
adapter.getAttr(el, 'type').toLowerCase() === 'file';
},
IS_STYLE: function (el) { return adapter.getTagName(el) === 'style'; },
HAS_EVENT_HANDLER: function (el) { return adapter.hasEventHandler(el); },
IS_SANDBOXED_IFRAME: function (el) {
var tagName = adapter.getTagName(el);
return (tagName === 'iframe' || tagName === 'frame') && adapter.hasAttr(el, 'sandbox');
},
IS_SVG_ELEMENT_WITH_XLINK_HREF_ATTR: function (el) {
return adapter.isSVGElement(el) &&
adapter.hasAttr(el, 'xlink:href') &&
SVG_XLINK_HREF_TAGS.indexOf(adapter.getTagName(el)) !== -1;
},
IS_SVG_ELEMENT_WITH_XML_BASE_ATTR: function (el) { return adapter.isSVGElement(el) && adapter.hasAttr(el, 'xml:base'); },
};
return [
{
selector: selectors.HAS_FORMTARGET_ATTR,
targetAttr: 'formtarget',
elementProcessors: [this._processTargetBlank],
},
{
selector: selectors.HAS_HREF_ATTR,
urlAttr: 'href',
targetAttr: 'target',
elementProcessors: [this._processTargetBlank, this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_SRC_ATTR,
urlAttr: 'src',
targetAttr: 'target',
elementProcessors: [this._processTargetBlank, this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_SRCSET_ATTR,
urlAttr: 'srcset',
targetAttr: 'target',
elementProcessors: [this._processTargetBlank, this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_ACTION_ATTR,
urlAttr: 'action',
targetAttr: 'target',
elementProcessors: [this._processTargetBlank, this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_FORMACTION_ATTR,
urlAttr: 'formaction',
targetAttr: 'formtarget',
elementProcessors: [this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_MANIFEST_ATTR,
urlAttr: 'manifest',
elementProcessors: [this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_DATA_ATTR,
urlAttr: 'data',
elementProcessors: [this._processUrlAttrs, this._processUrlJsAttr],
},
{
selector: selectors.HAS_SRCDOC_ATTR,
elementProcessors: [this._processSrcdocAttr],
},
{
selector: selectors.HTTP_EQUIV_META,
urlAttr: 'content',
elementProcessors: [this._processMetaElement],
},
{
selector: selectors.IS_SCRIPT,
elementProcessors: [this._processScriptElement, this._processIntegrityAttr],
},
{ selector: selectors.ALL, elementProcessors: [this._processStyleAttr] },
{
selector: selectors.IS_LINK,
relAttr: 'rel',
elementProcessors: [this._processIntegrityAttr, this._processRelPrefetch],
},
{ selector: selectors.IS_STYLE, elementProcessors: [this._processStylesheetElement] },
{ selector: selectors.IS_INPUT, elementProcessors: [this._processAutoComplete] },
{ selector: selectors.IS_FILE_INPUT, elementProcessors: [this._processRequired] },
{ selector: selectors.HAS_EVENT_HANDLER, elementProcessors: [this._processEvtAttr] },
{ selector: selectors.IS_SANDBOXED_IFRAME, elementProcessors: [this._processSandboxedIframe] },
{
selector: selectors.IS_SVG_ELEMENT_WITH_XLINK_HREF_ATTR,
urlAttr: 'xlink:href',
elementProcessors: [this._processSVGXLinkHrefAttr, this._processUrlAttrs],
},
{
selector: selectors.IS_SVG_ELEMENT_WITH_XML_BASE_ATTR,
urlAttr: 'xml:base',
elementProcessors: [this._processUrlAttrs],
},
];
};
// API
DomProcessor.prototype.processElement = function (el, urlReplacer) {
if (DomProcessor.isElementProcessed(el))
return;
for (var _i = 0, _a = this.elementProcessorPatterns; _i < _a.length; _i++) {
var pattern = _a[_i];
if (pattern.selector(el) && !this._isShadowElement(el)) {
for (var _b = 0, _c = pattern.elementProcessors; _b < _c.length; _b++) {
var processor = _c[_b];
processor.call(this, el, urlReplacer, pattern);
}
DomProcessor.setElementProcessed(el, true);
}
}
};
// Utils
DomProcessor.prototype.getElementResourceType = function (el) {
var tagName = this.adapter.getTagName(el);
if (tagName === 'link' && (this._getAsAttribute(el) === PROCESSED_PRELOAD_LINK_CONTENT_TYPE ||
this._getRelAttribute(el) === MODULE_PRELOAD_LINK_REL))
return getResourceTypeString({ isScript: true });
return getResourceTypeString({
isIframe: tagName === 'iframe' || tagName === 'frame' || this._isOpenLinkInIframe(el),
isForm: tagName === 'form' || tagName === 'input' || tagName === 'button',
isScript: tagName === 'script',
isHtmlImport: tagName === 'link' && this._getRelAttribute(el) === 'import',
isObject: tagName === 'object',
});
};
DomProcessor.prototype.isUrlAttr = function (el, attr, ns) {
var tagName = this.adapter.getTagName(el);
attr = attr ? attr.toLowerCase() : attr;
// @ts-ignore
if (URL_ATTR_TAGS[attr] && URL_ATTR_TAGS[attr].indexOf(tagName) !== -1)
return true;
return this.adapter.isSVGElement(el) && (attr === 'xml:base' || attr === 'base' && ns === XML_NAMESPACE);
};
DomProcessor.prototype.getUrlAttr = function (el) {
var tagName = this.adapter.getTagName(el);
for (var _i = 0, URL_ATTRS_1 = URL_ATTRS; _i < URL_ATTRS_1.length; _i++) {
var urlAttr = URL_ATTRS_1[_i];
// @ts-ignore
if (URL_ATTR_TAGS[urlAttr].indexOf(tagName) !== -1)
return urlAttr;
}
return null;
};
DomProcessor.prototype.getTargetAttr = function (el) {
var tagName = this.adapter.getTagName(el);
for (var _i = 0, TARGET_ATTRS_1 = TARGET_ATTRS; _i < TARGET_ATTRS_1.length; _i++) {
var targetAttr = TARGET_ATTRS_1[_i];
// @ts-ignore
if (TARGET_ATTR_TAGS[targetAttr].indexOf(tagName) > -1)
return targetAttr;
}
return null;
};
DomProcessor.prototype._isOpenLinkInIframe = function (el) {
var tagName = this.adapter.getTagName(el);
var targetAttr = this.getTargetAttr(el);
var target = targetAttr ? this.adapter.getAttr(el, targetAttr) : null;
var rel = this._getRelAttribute(el);
if (target !== '_top') {
var isImageInput = tagName === 'input' && this.adapter.getAttr(el, 'type') === 'image';
var mustProcessTag = !isImageInput && DomProcessor.isIframeFlagTag(tagName) ||
DomProcessor._isHtmlImportLink(tagName, rel);
var isNameTarget = target ? target[0] !== '_' : false;
if (target === '_parent')
return mustProcessTag && !this.adapter.isTopParentIframe(el);
if (mustProcessTag && (this.adapter.hasIframeParent(el) || isNameTarget && this.adapter.isExistingTarget(target, el)))
return true;
}
return false;
};
DomProcessor.prototype._isShadowElement = function (el) {
var className = this.adapter.getClassName(el);
return typeof className === 'string' && className.indexOf(SHADOW_UI_CLASS_NAME.postfix) > -1;
};
// Element processors
DomProcessor.prototype._processAutoComplete = function (el) {
var storedUrlAttr = DomProcessor.getStoredAttrName('autocomplete');
var processed = this.adapter.hasAttr(el, storedUrlAttr);
var attrValue = this.adapter.getAttr(el, processed ? storedUrlAttr : 'autocomplete');
if (!processed) {
this.adapter.setAttr(el, storedUrlAttr, attrValue || attrValue ===
''
? attrValue
: AUTOCOMPLETE_ATTRIBUTE_ABSENCE_MARKER);
}
this.adapter.setAttr(el, 'autocomplete', 'off');
};
DomProcessor.prototype._processRequired = function (el) {
var storedRequired = DomProcessor.getStoredAttrName('required');
var processed = this.adapter.hasAttr(el, storedRequired);
if (!processed && this.adapter.hasAttr(el, 'required')) {
var attrValue = this.adapter.getAttr(el, 'required');
this.adapter.setAttr(el, storedRequired, attrValue);
this.adapter.removeAttr(el, 'required');
}
};
// NOTE: We simply remove the 'integrity' attribute because its value will not be relevant after the script
// content changes (http://www.w3.org/TR/SRI/). If this causes problems in the future, we will need to generate
// the correct SHA for the changed script.
// In addition, we create stored 'integrity' attribute with the current 'integrity' attribute value. (GH-235)
DomProcessor.prototype._processIntegrityAttr = function (el) {
var storedIntegrityAttr = DomProcessor.getStoredAttrName('integrity');
var processed = this.adapter.hasAttr(el, storedIntegrityAttr) && !this.adapter.hasAttr(el, 'integrity');
var attrValue = this.adapter.getAttr(el, processed ? storedIntegrityAttr : 'integrity');
if (attrValue)
this.adapter.setAttr(el, storedIntegrityAttr, attrValue);
if (!processed)
this.adapter.removeAttr(el, 'integrity');
};
// NOTE: We simply remove the 'rel' attribute if rel='prefetch' and use stored 'rel' attribute, because the prefetch
// resource type is unknown. https://github.com/DevExpress/testcafe/issues/2528
DomProcessor.prototype._processRelPrefetch = function (el, _urlReplacer, pattern) {
if (!pattern.relAttr)
return;
var storedRelAttr = DomProcessor.getStoredAttrName(pattern.relAttr);
var processed = this.adapter.hasAttr(el, storedRelAttr) && !this.adapter.hasAttr(el, pattern.relAttr);
var attrValue = this.adapter.getAttr(el, processed ? storedRelAttr : pattern.relAttr);
if (attrValue) {
var formatedValue = trim$1(attrValue.toLowerCase());
if (formatedValue === 'prefetch') {
this.adapter.setAttr(el, storedRelAttr, attrValue);
if (!processed)
this.adapter.removeAttr(el, pattern.relAttr);
}
}
};
DomProcessor.prototype._processJsAttr = function (el, attrName, _a) {
var isJsProtocol = _a.isJsProtocol, isEventAttr = _a.isEventAttr;
var storedUrlAttr = DomProcessor.getStoredAttrName(attrName);
var processed = this.adapter.hasAttr(el, storedUrlAttr);
var attrValue = this.adapter.getAttr(el, processed ? storedUrlAttr : attrName) || '';
var processedValue = DomProcessor.processJsAttrValue(attrValue, { isJsProtocol: isJsProtocol, isEventAttr: isEventAttr });
if (attrValue !== processedValue) {
this.adapter.setAttr(el, storedUrlAttr, attrValue);
this.adapter.setAttr(el, attrName, processedValue);
}
};
DomProcessor.prototype._processEvtAttr = function (el) {
var events = this.adapter.EVENTS;
for (var i = 0; i < events.length; i++) {
var attrValue = this.adapter.getAttr(el, events[i]);
if (attrValue) {
this._processJsAttr(el, events[i], {
isJsProtocol: DomProcessor.isJsProtocol(attrValue),
isEventAttr: true,
});
}
}
};
DomProcessor.prototype._processMetaElement = function (el, urlReplacer, pattern) {
var httpEquivAttrValue = (this.adapter.getAttr(el, 'http-equiv') || '').toLowerCase();
if (httpEquivAttrValue === BUILTIN_HEADERS.refresh && pattern.urlAttr) {
var attr = this.adapter.getAttr(el, pattern.urlAttr) || '';
attr = processMetaRefreshContent(attr, urlReplacer);
this.adapter.setAttr(el, pattern.urlAttr, attr);
}
// TODO: remove after https://github.com/DevExpress/testcafe-hammerhead/issues/244 implementation
else if (httpEquivAttrValue === BUILTIN_HEADERS.contentSecurityPolicy) {
this.adapter.removeAttr(el, 'http-equiv');
this.adapter.removeAttr(el, 'content');
}
};
DomProcessor.prototype._processSandboxedIframe = function (el) {
var attrValue = this.adapter.getAttr(el, 'sandbox') || '';
var allowSameOrigin = attrValue.indexOf('allow-same-origin') !== -1;
var allowScripts = attrValue.indexOf('allow-scripts') !== -1;
var storedAttr = DomProcessor.getStoredAttrName('sandbox');
this.adapter.setAttr(el, storedAttr, attrValue);
if (!allowSameOrigin || !allowScripts) {
attrValue += !allowSameOrigin ? ' allow-same-origin' : '';
attrValue += !allowScripts ? ' allow-scripts' : '';
}
this.adapter.setAttr(el, 'sandbox', attrValue);
};
DomProcessor.prototype._processScriptElement = function (script, urlReplacer) {
var scriptContent = this.adapter.getScriptContent(script);
if (!scriptContent || !this.adapter.needToProcessContent(script))
return;
var scriptProcessedOnServer = isScriptProcessed(scriptContent);
if (scriptProcessedOnServer)
return;
// NOTE: We do not process scripts that are not executed during page load. We process scripts of types like
// text/javascript, application/javascript etc. (a complete list of MIME types is specified in the w3c.org
// html5 specification). If the type is not set, it is considered 'text/javascript' by default.
var scriptType = this.adapter.getAttr(script, 'type');
var isExecutableScript = !scriptType || EXECUTABLE_SCRIPT_TYPES_REG_EX.test(scriptType);
if (isExecutableScript) {
var result = scriptContent;
var commentPrefix = '';
var commentPrefixMatch = result.match(HTML_COMMENT_PREFIX_REG_EX);
var commentPostfix = '';
var commentPostfixMatch = null;
var hasCDATA = CDATA_REG_EX.test(result);
if (commentPrefixMatch) {
commentPrefix = commentPrefixMatch[0];
commentPostfixMatch = result.match(HTML_COMMENT_POSTFIX_REG_EX);
if (commentPostfixMatch)
commentPostfix = commentPostfixMatch[0];
else if (!HTML_COMMENT_SIMPLE_POSTFIX_REG_EX.test(commentPrefix))
commentPostfix = '//-->';
result = result.replace(commentPrefix, '').replace(commentPostfix, '');
}
if (hasCDATA)
result = result.replace(CDATA_REG_EX, '$2');
result = commentPrefix + processScript(result, true, false, urlReplacer) + commentPostfix;
if (hasCDATA)
result = '\n//<![CDATA[\n' + result + '//]]>';
this.adapter.setScriptContent(script, result);
}
};
DomProcessor.prototype._processStyleAttr = function (el, urlReplacer) {
var style = this.adapter.getAttr(el, 'style');
if (style)
this.adapter.setAttr(el, 'style', styleProcessor.process(style, urlReplacer, false));
};
DomProcessor.prototype._processStylesheetElement = function (el, urlReplacer) {
var content = this.adapter.getStyleContent(el);
if (content && urlReplacer && this.adapter.needToProcessContent(el)) {
content = styleProcessor.process(content, urlReplacer, true);
this.adapter.setStyleContent(el, content);
}
};
DomProcessor.prototype._processTargetBlank = function (el, _urlReplacer, pattern) {
if (this.allowMultipleWindows || !pattern.targetAttr)
return;
var storedTargetAttr = DomProcessor.getStoredAttrName(pattern.targetAttr);
var processed = this.adapter.hasAttr(el, storedTargetAttr);
if (processed)
return;
var attrValue = this.adapter.getAttr(el, pattern.targetAttr);
// NOTE: Value may have whitespace.
attrValue = attrValue && attrValue.replace(/\s/g, '');
if (attrValue === '_blank') {
this.adapter.setAttr(el, pattern.targetAttr, '_top');
this.adapter.setAttr(el, storedTargetAttr, attrValue);
}
};
DomProcessor.prototype._processUrlAttrs = function (el, urlReplacer, pattern) {
if (!pattern.urlAttr || this.proxyless)
return;
var storedUrlAttr = DomProcessor.getStoredAttrName(pattern.urlAttr);
var resourceUrl = this.adapter.getAttr(el, pattern.urlAttr);
var isSpecialPageUrl = !!resourceUrl && isSpecialPage$1(resourceUrl);
var processedOnServer = this.adapter.hasAttr(el, storedUrlAttr);
if ((!resourceUrl && resourceUrl !== '' || processedOnServer) || //eslint-disable-line @typescript-eslint/no-extra-parens
!isSupportedProtocol$1(resourceUrl) && !isSpecialPageUrl)
return;
var elTagName = this.adapter.getTagName(el);
var isIframe = elTagName === 'iframe' || elTagName === 'frame';
var isScript = elTagName === 'script';
var isAnchor = elTagName === 'a';
var isUrlsSet = pattern.urlAttr === 'srcset';
var target = pattern.targetAttr ? this.adapter.getAttr(el, pattern.targetAttr) : null;
// NOTE: Elements with target=_parent shouldnt be processed on the server,because we don't
// know what is the parent of the processed page (an iframe or the top window).
if (!this.adapter.needToProcessUrl(elTagName, target || ''))
return;
var resourceType = this.getElementResourceType(el) || '';
var parsedResourceUrl = parseUrl$1(resourceUrl);
var isRelativePath = parsedResourceUrl.protocol !== 'file:' && !parsedResourceUrl.host;
var charsetAttrValue = isScript && this.adapter.getAttr(el, 'charset') || '';
var isImgWithoutSrc = elTagName === 'img' && resourceUrl === '';
var isIframeWithEmptySrc = isIframe && resourceUrl === '';
var parsedProxyUrl = parseProxyUrl$1(urlReplacer('/'));
var isCrossDomainSrc = false;
var proxyUrl = resourceUrl;
// NOTE: Only a non-relative iframe src can be cross-domain.
if (isIframe && !isSpecialPageUrl && !isRelativePath && parsedProxyUrl)
isCrossDomainSrc = !this.adapter.sameOriginCheck(parsedProxyUrl.destUrl, resourceUrl);
if ((!isSpecialPageUrl || isAnchor) && !isImgWithoutSrc && !isIframeWithEmptySrc) {
proxyUrl = elTagName === 'img' && !this.forceProxySrcForImage && !isUrlsSet
? resolveUrlAsDest$1(resourceUrl, urlReplacer)
: urlReplacer(resourceUrl, resourceType, charsetAttrValue, isCrossDomainSrc, isUrlsSet);
}
this.adapter.setAttr(el, storedUrlAttr, resourceUrl);
this.adapter.setAttr(el, pattern.urlAttr, proxyUrl);
};
DomProcessor.prototype._processSrcdocAttr = function (el) {
var storedAttr = DomProcessor.getStoredAttrName('srcdoc');
var html = this.adapter.getAttr(el, 'srcdoc') || '';
var processedHtml = this.adapter.processSrcdocAttr(html);
this.adapter.setAttr(el, storedAttr, html);
this.adapter.setAttr(el, 'srcdoc', processedHtml);
};
DomProcessor.prototype._processUrlJsAttr = function (el, _urlReplacer, pattern) {
if (pattern.urlAttr && DomProcessor.isJsProtocol(this.adapter.getAttr(el, pattern.urlAttr) || ''))
this._processJsAttr(el, pattern.urlAttr, { isJsProtocol: true, isEventAttr: false });
};
DomProcessor.prototype._processSVGXLinkHrefAttr = function (el, _urlReplacer, pattern) {
if (!pattern.urlAttr)
return;
var attrValue = this.adapter.getAttr(el, pattern.urlAttr) || '';
if (HASH_RE$1.test(attrValue)) {
var storedUrlAttr = DomProcessor.getStoredAttrName(pattern.urlAttr);
this.adapter.setAttr(el, storedUrlAttr, attrValue);
}
};
return DomProcessor;
}());
var lengthWeakMap = new WeakMap();
function updateOrigin(ancestorOrigins, wrapper, index, origin) {
var descriptor = createOverriddenDescriptor(ancestorOrigins, index, { value: origin });
nativeMethods.objectDefineProperty(wrapper, index, descriptor);
}
var DOMStringListInheritor = /** @class */ (function () {
function DOMStringListInheritor() {
}
return DOMStringListInheritor;
}());
DOMStringListInheritor.prototype = DOMStringList.prototype;
var DOMStringListWrapper = /** @class */ (function (_super) {
__extends(DOMStringListWrapper, _super);
function DOMStringListWrapper(window, getCrossDomainOrigin) {
var _this = _super.call(this) || this;
var nativeOrigins = window.location.ancestorOrigins;
var length = nativeOrigins.length;
var parentWindow = window.parent;
lengthWeakMap.set(_this, length);
var _loop_1 = function (i) {
var parentLocationWrapper = LocationAccessorsInstrumentation.getLocationWrapper(parentWindow);
var isCrossDomainParent = parentLocationWrapper === parentWindow.location;
// eslint-disable-next-line no-restricted-properties
updateOrigin(nativeOrigins, this_1, i.toString(), isCrossDomainParent ? '' : parentLocationWrapper.origin);
if (isCrossDomainParent && getCrossDomainOrigin)
//@ts-ignore
getCrossDomainOrigin(parentWindow, function (origin) { return updateOrigin(nativeOrigins, _this, i, origin); });
parentWindow = parentWindow.parent;
};
var this_1 = this;
for (var i = 0; i < length; i++) {
_loop_1(i);
}
return _this;
}
DOMStringListWrapper.prototype.item = function (index) {
return this[index];
};
DOMStringListWrapper.prototype.contains = function (origin) {
if (typeof origin !== 'string')
origin = String(origin);
var length = lengthWeakMap.get(this) || 0;
for (var i = 0; i < length; i++) {
if (this[i] === origin)
return true;
}
return false;
};
Object.defineProperty(DOMStringListWrapper.prototype, "length", {
get: function () {
return lengthWeakMap.get(this);
},
enumerable: false,
configurable: true
});
return DOMStringListWrapper;
}(DOMStringListInheritor));
var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;
var MIN_SAFE_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991;
var IntegerIdGenerator = /** @class */ (function () {
function IntegerIdGenerator() {
this._id = MIN_SAFE_INTEGER;
}
IntegerIdGenerator.prototype.increment = function () {
this._id = this._id === MAX_SAFE_INTEGER ? MIN_SAFE_INTEGER : this._id + 1;
return this._id;
};
Object.defineProperty(IntegerIdGenerator.prototype, "value", {
get: function () {
return this._id;
},
enumerable: false,
configurable: true
});
return IntegerIdGenerator;
}());
var GET_ORIGIN_CMD = 'hammerhead|command|get-origin';
var ORIGIN_RECEIVED_CMD = 'hammerhead|command|origin-received';
function getLocationUrl(window) {
try {
return window.location.toString();
}
catch (e) {
return void 0;
}
}
var LocationInheritor = /** @class */ (function () {
function LocationInheritor() {
}
return LocationInheritor;
}());
LocationInheritor.prototype = Location.prototype;
var LocationWrapper = /** @class */ (function (_super) {
__extends(LocationWrapper, _super);
function LocationWrapper(window, messageSandbox, onChanged) {
var _this = _super.call(this) || this;
var parsedLocation = parseProxyUrl(getLocationUrl(window));
var locationResourceType = parsedLocation ? parsedLocation.resourceType : '';
var parsedResourceType = parseResourceType(locationResourceType);
// @ts-ignore
var isLocationPropsInProto = nativeMethods.objectHasOwnProperty.call(window.Location.prototype, 'href');
// @ts-ignore
var locationPropsOwner = isLocationPropsInProto ? window.Location.prototype : window.location;
var locationProps = {};
parsedResourceType.isIframe = parsedResourceType.isIframe || isIframeWindow(window);
var resourceType = getResourceTypeString({
isIframe: parsedResourceType.isIframe,
isForm: parsedResourceType.isForm,
});
var getHref = function () {
// eslint-disable-next-line no-restricted-properties
if (isIframeWindow(window) && window.location.href === SPECIAL_BLANK_PAGE)
return SPECIAL_BLANK_PAGE;
var locationUrl = get$2();
var resolveElement = urlResolver.getResolverElement(window.document);
nativeMethods.anchorHrefSetter.call(resolveElement, locationUrl);
var href = nativeMethods.anchorHrefGetter.call(resolveElement);
return ensureTrailingSlash(href, locationUrl);
};
var getProxiedHref = function (href) {
if (typeof href !== 'string')
href = String(href);
href = prepareUrl(href);
if (DomProcessor.isJsProtocol(href))
return DomProcessor.processJsAttrValue(href, { isJsProtocol: true, isEventAttr: false });
var locationUrl = getLocationUrl(window);
var proxyPort = null;
if (window !== window.parent) {
var parentLocationUrl = getLocationUrl(window.parent);
var parsedParentLocationUrl = parseProxyUrl(parentLocationUrl);
if (parsedParentLocationUrl && parsedParentLocationUrl.proxy) {
// eslint-disable-next-line no-restricted-properties
var parentProxyPort = parsedParentLocationUrl.proxy.port;
proxyPort = sameOriginCheck(parentLocationUrl, href)
? parentProxyPort
: getCrossDomainProxyPort(parentProxyPort);
}
}
var changedOnlyHash = locationUrl && isChangedOnlyHash(locationUrl, href);
var currentResourceType = changedOnlyHash ? locationResourceType : resourceType;
return getProxyUrl(href, { resourceType: currentResourceType, proxyPort: proxyPort });
};
// eslint-disable-next-line no-restricted-properties
locationProps.href = createOverriddenDescriptor(locationPropsOwner, 'href', {
getter: getHref,
setter: function (href) {
var proxiedHref = getProxiedHref(href);
// eslint-disable-next-line no-restricted-properties
window.location.href = proxiedHref;
onChanged(proxiedHref);
return href;
},
});
// eslint-disable-next-line no-restricted-properties
locationProps.search = createOverriddenDescriptor(locationPropsOwner, 'search', {
// eslint-disable-next-line no-restricted-properties
getter: function () { return window.location.search; },
setter: function (search) {
var newLocation = changeDestUrlPart(window.location.toString(), nativeMethods.anchorSearchSetter, search, resourceType);
// @ts-ignore
window.location = newLocation;
onChanged(newLocation);
return search;
},
});
// eslint-disable-next-line no-restricted-properties
locationProps.origin = createOverriddenDescriptor(locationPropsOwner, 'origin', {
getter: function () { return getDomain(getParsed()); },
setter: function (origin) { return origin; },
});
locationProps.hash = createOverriddenDescriptor(locationPropsOwner, 'hash', {
getter: function () { return window.location.hash; },
setter: function (hash) {
window.location.hash = hash;
return hash;
},
});
if (window.location.ancestorOrigins) {
var callbacks_1 = nativeMethods.objectCreate(null);
var idGenerator_1 = new IntegerIdGenerator();
var getCrossDomainOrigin = function (win, callback) {
var id = idGenerator_1.increment();
callbacks_1[id] = callback;
messageSandbox.sendServiceMsg({ id: id, cmd: GET_ORIGIN_CMD }, win);
};
if (messageSandbox) {
messageSandbox.on(messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (_a) {
var message = _a.message, source = _a.source;
if (message.cmd === GET_ORIGIN_CMD) {
// @ts-ignore
messageSandbox.sendServiceMsg({ id: message.id, cmd: ORIGIN_RECEIVED_CMD, origin: _this.origin }, source); // eslint-disable-line no-restricted-properties
}
else if (message.cmd === ORIGIN_RECEIVED_CMD) {
var callback = callbacks_1[message.id];
if (callback)
callback(message.origin); // eslint-disable-line no-restricted-properties
}
});
}
var ancestorOrigins_1 = new DOMStringListWrapper(window, messageSandbox ? getCrossDomainOrigin : void 0);
locationProps.ancestorOrigins = createOverriddenDescriptor(locationPropsOwner, 'ancestorOrigins', {
getter: function () { return ancestorOrigins_1; },
});
}
var createLocationPropertyDesc = function (property, nativePropSetter) {
locationProps[property] = createOverriddenDescriptor(locationPropsOwner, property, {
getter: function () {
var frameElement = getFrameElement(window);
var inIframeWithoutSrc = frameElement && isIframeWithoutSrc(frameElement);
var parsedDestLocation = inIframeWithoutSrc ? window.location : getParsed();
return parsedDestLocation[property];
},
setter: function (value) {
var newLocation = changeDestUrlPart(window.location.toString(), nativePropSetter, value, resourceType);
// @ts-ignore
window.location = newLocation;
onChanged(newLocation);
return value;
},
});
};
createLocationPropertyDesc('port', nativeMethods.anchorPortSetter);
createLocationPropertyDesc('host', nativeMethods.anchorHostSetter);
createLocationPropertyDesc('hostname', nativeMethods.anchorHostnameSetter);
createLocationPropertyDesc('pathname', nativeMethods.anchorPathnameSetter);
createLocationPropertyDesc('protocol', nativeMethods.anchorProtocolSetter);
locationProps.assign = createOverriddenDescriptor(locationPropsOwner, 'assign', {
value: function (url) {
var proxiedHref = getProxiedHref(url);
var result = window.location.assign(proxiedHref);
onChanged(proxiedHref);
return result;
},
});
locationProps.replace = createOverriddenDescriptor(locationPropsOwner, 'replace', {
value: function (url) {
var proxiedHref = getProxiedHref(url);
var result = window.location.replace(proxiedHref);
onChanged(proxiedHref);
return result;
},
});
locationProps.reload = createOverriddenDescriptor(locationPropsOwner, 'reload', {
value: function () {
var result = window.location.reload();
onChanged(window.location.toString());
return result;
},
});
locationProps.toString = createOverriddenDescriptor(locationPropsOwner, 'toString', { value: getHref });
if (!isLocationPropsInProto && nativeMethods.objectHasOwnProperty.call(window.location, 'valueOf'))
locationProps.valueOf = createOverriddenDescriptor(locationPropsOwner, 'valueOf', { value: function () { return _this; } });
nativeMethods.objectDefineProperties(_this, locationProps);
// NOTE: We shouldn't break the client script if the browser add the new API. For example:
// > From Chrome 80 to Chrome 85, the fragmentDirective property was defined on Location.prototype.
if (isIE11)
return _this;
var protoKeys = nativeMethods.objectKeys(Location.prototype);
var locWrapper = _this;
var rewriteDescriptorFn = function (descriptor, key) {
if (!isFunction(descriptor[key]))
return;
var nativeMethod = descriptor[key];
descriptor[key] = function () {
var ctx = this === locWrapper ? window.location : this;
return nativeMethod.apply(ctx, arguments);
};
};
for (var _i = 0, protoKeys_1 = protoKeys; _i < protoKeys_1.length; _i++) {
var protoKey = protoKeys_1[_i];
if (protoKey in locationProps)
continue;
var protoKeyDescriptor = nativeMethods.objectGetOwnPropertyDescriptor(Location.prototype, protoKey);
rewriteDescriptorFn(protoKeyDescriptor, 'get');
rewriteDescriptorFn(protoKeyDescriptor, 'set');
rewriteDescriptorFn(protoKeyDescriptor, 'value');
nativeMethods.objectDefineProperty(locWrapper, protoKey, protoKeyDescriptor);
// NOTE: We hide errors with a new browser API and we should know about it.
nativeMethods.consoleMeths.log("testcafe-hammerhead: unwrapped Location.prototype.".concat(protoKey, " descriptor!"));
}
return _this;
}
return LocationWrapper;
}(LocationInheritor));
// NOTE: window.Location in IE11 is object
if (!isFunction(Location))
LocationWrapper.toString = function () { return Location.toString(); };
else
overrideStringRepresentation(LocationWrapper, Location);
var LOCATION_WRAPPER = 'hammerhead|location-wrapper';
var LocationAccessorsInstrumentation = /** @class */ (function (_super) {
__extends(LocationAccessorsInstrumentation, _super);
function LocationAccessorsInstrumentation(_messageSandbox) {
var _this = _super.call(this) || this;
_this._messageSandbox = _messageSandbox;
_this.LOCATION_CHANGED_EVENT = 'hammerhead|event|location-changed';
_this._locationChangedEventCallback = function (e) { return _this.emit(_this.LOCATION_CHANGED_EVENT, e); };
return _this;
}
LocationAccessorsInstrumentation.isLocationWrapper = function (obj) {
return obj instanceof LocationWrapper;
};
LocationAccessorsInstrumentation.getLocationWrapper = function (owner) {
// NOTE: IE11 case. We can get cross-domain location wrapper without any exceptions.
// We return owner.location in this case, as in other browsers.
if (isIE && isCrossDomainWindows(window, owner))
return owner.location;
// NOTE: When the owner is cross-domain, we cannot get its location wrapper, so we return the original
// location, which cannot be accessed but behaves like a real one. Cross-domain location retains the 'replace'
// and 'assign' methods, so we intercept calls to them through MethodCallInstrumentation.
try {
return owner[LOCATION_WRAPPER];
}
catch (e) {
return owner.location;
}
};
LocationAccessorsInstrumentation.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
var document = window.document;
var locationWrapper = new LocationWrapper(window, this._messageSandbox, this._locationChangedEventCallback);
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
nativeMethods.objectDefineProperty(window, LOCATION_WRAPPER, { value: locationWrapper, configurable: true });
nativeMethods.objectDefineProperty(document, LOCATION_WRAPPER, { value: locationWrapper, configurable: true });
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.getLocation, {
value: function (location) { return isLocation(location) ? locationWrapper : location; },
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.setLocation, {
value: function (location, value) {
if (isLocation(location) && typeof value === 'string') {
// @ts-ignore
locationWrapper.href = value; // eslint-disable-line no-restricted-properties
return value;
}
return null;
},
configurable: true,
});
};
return LocationAccessorsInstrumentation;
}(SandboxBase));
var IFRAME_WINDOW_INITED = 'hammerhead|iframe-window-inited';
var IframeSandbox = /** @class */ (function (_super) {
__extends(IframeSandbox, _super);
function IframeSandbox(_nodeMutation, _cookieSandbox) {
var _this = _super.call(this) || this;
_this._nodeMutation = _nodeMutation;
_this._cookieSandbox = _cookieSandbox;
_this.RUN_TASK_SCRIPT_EVENT = 'hammerhead|event|run-task-script';
_this.EVAL_HAMMERHEAD_SCRIPT_EVENT = 'hammerhead|event|eval-hammerhead-script';
_this.EVAL_EXTERNAL_SCRIPT_EVENT = 'hammerhead|event|eval-external-script';
_this.IFRAME_DOCUMENT_CREATED_EVENT = 'hammerhead|event|iframe-document-created';
_this.on(_this.RUN_TASK_SCRIPT_EVENT, _this.iframeReadyToInitHandler);
_this._nodeMutation.on(_this._nodeMutation.IFRAME_ADDED_TO_DOM_EVENT, function (iframe) { return _this.processIframe(iframe); });
_this.iframeNativeMethodsBackup = null;
return _this;
}
IframeSandbox.prototype._shouldSaveIframeNativeMethods = function (iframe) {
if (!isWebKit)
return false;
var iframeSrc = this.nativeMethods.getAttribute.call(iframe, 'src');
return DomProcessor.isJsProtocol(iframeSrc);
};
IframeSandbox.prototype._ensureIframeNativeMethodsForChrome = function (iframe) {
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
if (this.iframeNativeMethodsBackup) {
this.iframeNativeMethodsBackup.restoreDocumentMeths(contentWindow, contentDocument);
this.iframeNativeMethodsBackup = null;
}
else if (this._shouldSaveIframeNativeMethods(iframe))
// @ts-ignore
this.iframeNativeMethodsBackup = new this.nativeMethods.constructor(contentDocument, contentWindow);
};
IframeSandbox.prototype._ensureIframeNativeMethodsForIE = function (iframe) {
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
var iframeNativeMethods = contentWindow[INTERNAL_PROPS.iframeNativeMethods];
if (iframeNativeMethods) {
iframeNativeMethods.restoreDocumentMeths(contentWindow, contentDocument);
delete contentWindow[INTERNAL_PROPS.iframeNativeMethods];
}
};
IframeSandbox.prototype._ensureIframeNativeMethods = function (iframe) {
// NOTE: In Chrome, iframe with javascript protocol src raises the load event twice.
// As a result, when the second load event is raised, we write the overridden methods to the native methods.
// So, we need to save the native methods when the first load event is raised.
// https://code.google.com/p/chromium/issues/detail?id=578812
this._ensureIframeNativeMethodsForChrome(iframe);
// NOTE: Restore native document methods for the iframe's document if it overrided earlier (IE9, IE10 only)
// https://github.com/DevExpress/testcafe-hammerhead/issues/279
this._ensureIframeNativeMethodsForIE(iframe);
};
IframeSandbox.prototype._emitEvents = function (iframe) {
// NOTE: Raise this internal event to eval the Hammerhead code script.
this.emit(this.EVAL_HAMMERHEAD_SCRIPT_EVENT, { iframe: iframe });
// NOTE: Raise this event to eval external code script.
this.emit(this.EVAL_EXTERNAL_SCRIPT_EVENT, { iframe: iframe });
// NOTE: Raise this event to eval the "task" script and to call the Hammerhead initialization method
// and external script initialization code.
this.emit(this.RUN_TASK_SCRIPT_EVENT, iframe);
};
IframeSandbox.prototype._raiseReadyToInitEvent = function (iframe) {
if (!isIframeWithoutSrc(iframe))
return;
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
if (!IframeSandbox.isIframeInitialized(iframe)) {
// NOTE: Even if iframe is not loaded (iframe.contentDocument.documentElement does not exist), we
// still need to override the document.write method without initializing Hammerhead. This method can
// be called before iframe is fully loaded, we should override it now.
if (isNativeFunction(contentDocument.write))
this.emit(this.IFRAME_DOCUMENT_CREATED_EVENT, { iframe: iframe });
}
else if (!contentWindow[IFRAME_WINDOW_INITED] && !contentWindow[INTERNAL_PROPS.hammerhead]) {
this._ensureIframeNativeMethods(iframe);
// NOTE: Ok, the iframe is fully loaded now, but Hammerhead is not injected.
nativeMethods.objectDefineProperty(contentWindow, IFRAME_WINDOW_INITED, { value: true });
this._emitEvents(iframe);
contentWindow[INTERNAL_PROPS.processDomMethodName]();
}
};
IframeSandbox.isIframeInitialized = function (iframe) {
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
if (isFirefox)
return contentDocument.readyState !== 'uninitialized';
if (isIE)
return !!contentDocument.documentElement || contentWindow[INTERNAL_PROPS.documentWasCleaned];
if (!contentWindow[INTERNAL_PROPS.documentWasCleaned] && isIframeWithSrcdoc(iframe))
// eslint-disable-next-line no-restricted-properties
return contentWindow.location.href === 'about:srcdoc';
return true;
};
IframeSandbox.isWindowInited = function (window) {
return window[IFRAME_WINDOW_INITED];
};
IframeSandbox.prototype.iframeReadyToInitHandler = function (iframe) {
// NOTE: We are using String.replace in order to avoid adding Mustache scripts on the client side.
// If it is needed elsewhere in a certain place, we should consider using Mustache.
var taskScriptTemplate = settings.get().iframeTaskScriptTemplate;
var escapeStringPatterns = function (str) { return str.replace(/\$/g, '$$$$'); };
var cookie = stringify(this._cookieSandbox.getCookie());
var referer = settings.get().referer || this.window.location.toString();
var iframeTaskScriptTemplate = stringify(taskScriptTemplate);
var taskScript = taskScriptTemplate
.replace('{{{cookie}}}', escapeStringPatterns(cookie))
.replace('{{{referer}}}', escapeStringPatterns(stringify(referer)))
.replace('{{{iframeTaskScriptTemplate}}}', escapeStringPatterns(iframeTaskScriptTemplate));
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
contentWindow.eval.call(contentWindow, taskScript);
};
IframeSandbox.prototype.onIframeBeganToRun = function (iframe) {
this._raiseReadyToInitEvent(iframe);
};
IframeSandbox.prototype.processIframe = function (el) {
var _this = this;
if (isShadowUIElement(el))
return;
if (isIframeElement(el) && nativeMethods.contentWindowGetter.call(el) ||
isFrameElement(el) && nativeMethods.frameContentWindowGetter.call(el))
this._raiseReadyToInitEvent(el);
// NOTE: This handler exists for iframes without the src attribute. In some the browsers (e.g. Chrome)
// the load event is triggering immediately after an iframe added to DOM. In other browsers,
// the _raiseReadyToInitEvent function is calling in our function wrapper after an iframe added to DOM.
this.nativeMethods.addEventListener.call(el, 'load', function () { return _this._raiseReadyToInitEvent(el); });
};
return IframeSandbox;
}(SandboxBase));
var BaseDomAdapter = /** @class */ (function () {
function BaseDomAdapter() {
this.EVENTS = ['onblur', 'onchange', 'onclick', 'oncontextmenu', 'oncopy', 'oncut',
'ondblclick', 'onerror', 'onfocus', 'onfocusin', 'onfocusout', 'onhashchange', 'onkeydown',
'onkeypress', 'onkeyup', 'onload', 'onmousedown', 'onmouseenter', 'onmouseleave',
'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onpaste', 'onreset',
'onresize', 'onscroll', 'onselect', 'onsubmit', 'ontextinput', 'onunload', 'onwheel',
'onpointerdown', 'onpointerup', 'onpointercancel', 'onpointermove', 'onpointerover', 'onpointerout',
'onpointerenter', 'onpointerleave', 'ongotpointercapture', 'onlostpointercapture',
'onmspointerdown', 'onmspointerup', 'onmspointercancel', 'onmspointermove', 'onmspointerover',
'onmspointerout', 'onmspointerenter', 'onmspointerleave', 'onmsgotpointercapture', 'onmslostpointercapture',
];
}
return BaseDomAdapter;
}());
// -------------------------------------------------------------
var CLEANUP_FORMATTING_REGEXP = /\n\s*|\/\*[\S\s]*?\*\//g;
function create$1(script) {
return "\n <script class=\"".concat(SHADOW_UI_CLASS_NAME.selfRemovingScript, "\">\n (function () {\n var currentScript = document.currentScript;\n\n /* NOTE: IE11 doesn't support the 'currentScript' property */\n if (!currentScript) {\n var scripts = document.scripts;\n var scriptsLength = scripts.length;\n\n currentScript = scripts[scriptsLength - 1];\n }\n\n currentScript.parentNode.removeChild(currentScript);\n\n ").concat(script, "\n })();\n </script>\n ").replace(CLEANUP_FORMATTING_REGEXP, '');
}
var sharedSelfRemovingScripts = {
iframeInit: create$1("\n var parentHammerhead = null;\n\n if (!window[\"".concat(INTERNAL_PROPS.hammerhead, "\"])\n Object.defineProperty(window, \"").concat(INTERNAL_PROPS.documentWasCleaned, "\", { value: true, configurable: true });\n\n try {\n parentHammerhead = window.parent[\"").concat(INTERNAL_PROPS.hammerhead, "\"];\n } catch(e) {}\n\n if (parentHammerhead)\n parentHammerhead.sandbox.onIframeDocumentRecreated(window.frameElement);\n ")),
onWindowRecreation: create$1("\n var hammerhead = window[\"".concat(INTERNAL_PROPS.hammerhead, "\"];\n var sandbox = hammerhead && hammerhead.sandbox;\n\n if (!sandbox) {\n try {\n sandbox = window.parent[\"").concat(INTERNAL_PROPS.hammerhead, "\"].sandboxUtils.backup.get(window);\n } catch(e) {}\n }\n\n if (sandbox) {\n Object.defineProperty(window, \"").concat(INTERNAL_PROPS.documentWasCleaned, "\", { value: true, configurable: true });\n\n sandbox.node.mutation.onDocumentCleaned(window, document);\n\n /* NOTE: B234357 */\n sandbox.node.processNodes(null, document);\n }\n ")),
onBodyCreated: create$1("\n if (window[\"".concat(INTERNAL_PROPS.hammerhead, "\"])\n window[\"").concat(INTERNAL_PROPS.hammerhead, "\"].sandbox.node.raiseBodyCreatedEvent();\n ")),
onOriginFirstTitleLoaded: create$1("\n window[\"".concat(INTERNAL_PROPS.hammerhead, "\"].sandbox.node.onOriginFirstTitleElementInHeadLoaded();\n ")),
restoreStorages: create$1("\n window.localStorage.setItem(\"%s\", %s);\n window.sessionStorage.setItem(\"%s\", %s);\n "),
};
var InsertPosition;
(function (InsertPosition) {
InsertPosition["beforeBegin"] = "beforebegin";
InsertPosition["afterBegin"] = "afterbegin";
InsertPosition["beforeEnd"] = "beforeend";
InsertPosition["afterEnd"] = "afterend";
})(InsertPosition || (InsertPosition = {}));
var InsertPosition$1 = InsertPosition;
function removeElement (element) {
var parent = nativeMethods.nodeParentNodeGetter.call(element);
if (parent)
nativeMethods.removeChild.call(parent, element);
return element;
}
var FAKE_TAG_NAME_PREFIX = 'hh_fake_tag_name_';
var FAKE_DOCTYPE_TAG_NAME = 'hh_fake_doctype';
var FAKE_HEAD_TAG_NAME = "".concat(FAKE_TAG_NAME_PREFIX, "head");
var FAKE_BODY_TAG_NAME = "".concat(FAKE_TAG_NAME_PREFIX, "body");
var FAKE_ATTR_WITH_TAG_NAME = 'hh_fake_attr';
var FAKE_TAG_NAME_RE = new RegExp('(<\\/?)' + FAKE_TAG_NAME_PREFIX, 'ig');
var WRAP_TAGS_RE = /(<\/?)(html|head|body|table|tbody|tfoot|thead|tr|td|th|caption|colgroup)((?:\s[^>]*)?>)/ig;
var WRAP_TAGS_TEMPLATE = "$1".concat(FAKE_TAG_NAME_PREFIX, "$2$3");
var WRAP_COL_NOSCRIPT_TAGS_RE = /<(\/?(?:col|noscript))(\s[^>]*?)?(\s?\/)?>/ig;
var WRAP_COL_NOSCRIPT_TAGS_TEMPLATE = "<br ".concat(FAKE_ATTR_WITH_TAG_NAME, "=\"$1|$3\"$2>");
var UNWRAP_COL_NOSCRIPT_TAGS_RE = new RegExp("<br([^>]*?) ".concat(FAKE_ATTR_WITH_TAG_NAME, "=\"([^|]+)\\|([^\"]*)\"([^>]*)"), 'ig');
var WRAP_DOCTYPE_RE = /<!doctype([^>]*)>/ig;
var WRAP_DOCTYPE_TEMPLATE = "<".concat(FAKE_DOCTYPE_TAG_NAME, ">$1</").concat(FAKE_DOCTYPE_TAG_NAME, ">");
var UNWRAP_DOCTYPE_RE = new RegExp("<".concat(FAKE_DOCTYPE_TAG_NAME, ">([\\S\\s]*?)</").concat(FAKE_DOCTYPE_TAG_NAME, ">"), 'ig');
var FIND_SVG_RE = /<svg\s?[^>]*>/ig;
var FIND_NS_ATTRS_RE = /\s(?:NS[0-9]+:[^"']+('|")[\S\s]*?\1|[^:]+:NS[0-9]+=(?:""|''))/g;
var STORED_ATTRS_SELECTOR = (function () {
var storedAttrs = [];
for (var _i = 0, URL_ATTRS_1 = URL_ATTRS; _i < URL_ATTRS_1.length; _i++) {
var attr = URL_ATTRS_1[_i];
storedAttrs.push(DomProcessor.getStoredAttrName(attr));
}
for (var _a = 0, ATTRS_WITH_SPECIAL_PROXYING_LOGIC_1 = ATTRS_WITH_SPECIAL_PROXYING_LOGIC; _a < ATTRS_WITH_SPECIAL_PROXYING_LOGIC_1.length; _a++) {
var attr = ATTRS_WITH_SPECIAL_PROXYING_LOGIC_1[_a];
storedAttrs.push(DomProcessor.getStoredAttrName(attr));
}
return '[' + storedAttrs.join('],[') + ']';
})();
var SHADOW_UI_ELEMENTS_SELECTOR = "[class*=\"".concat(SHADOW_UI_CLASS_NAME.postfix, "\"]");
var HOVER_AND_FOCUS_PSEUDO_CLASS_ELEMENTS_SELECTOR = "[".concat(INTERNAL_ATTRIBUTES.hoverPseudoClass, "],[").concat(INTERNAL_ATTRIBUTES.focusPseudoClass, "]");
var FAKE_ELEMENTS_SELECTOR = "".concat(FAKE_HEAD_TAG_NAME, ", ").concat(FAKE_BODY_TAG_NAME);
var HTML_PARSER_ELEMENT_FLAG = 'hammerhead|html-parser-element-flag';
var SCRIPT_AND_STYLE_SELECTOR = 'script,link[rel="stylesheet"]';
var htmlDocument = nativeMethods.createHTMLDocument.call(document.implementation, 'title');
var htmlParser = nativeMethods.createDocumentFragment.call(htmlDocument);
htmlParser[HTML_PARSER_ELEMENT_FLAG] = true;
function getHtmlDocument() {
try {
// NOTE: IE bug: access denied.
if (htmlDocument.location)
htmlDocument.location.toString();
}
catch (e) {
htmlDocument = nativeMethods.createHTMLDocument.call(document.implementation, 'title');
htmlParser = nativeMethods.createDocumentFragment.call(htmlDocument);
htmlParser[HTML_PARSER_ELEMENT_FLAG] = true;
}
return htmlDocument;
}
function wrapHtmlText(html) {
return html
.replace(WRAP_DOCTYPE_RE, WRAP_DOCTYPE_TEMPLATE)
.replace(WRAP_COL_NOSCRIPT_TAGS_RE, WRAP_COL_NOSCRIPT_TAGS_TEMPLATE)
.replace(WRAP_TAGS_RE, WRAP_TAGS_TEMPLATE);
}
function unwrapHtmlText(html) {
return html
.replace(UNWRAP_DOCTYPE_RE, '<!doctype$1>')
.replace(UNWRAP_COL_NOSCRIPT_TAGS_RE, '<$2$1$4$3')
.replace(FAKE_TAG_NAME_RE, '$1');
}
function isPageHtml(html) {
return /^\s*(<\s*(!doctype|html|head|body)[^>]*>)/i.test(html);
}
function processHtmlInternal(html, process) {
var container = nativeMethods.createElement.call(getHtmlDocument(), 'div');
html = wrapHtmlText(html);
nativeMethods.appendChild.call(htmlParser, container);
nativeMethods.elementInnerHTMLSetter.call(container, html);
var processedHtml = process(container) ? nativeMethods.elementInnerHTMLGetter.call(container) : html;
removeElement(container);
processedHtml = unwrapHtmlText(processedHtml);
// NOTE: hack for IE (GH-1083)
if (isIE && !isMSEdge && html !== processedHtml)
processedHtml = removeExtraSvgNamespaces(html, processedHtml);
return processedHtml;
}
function cleanUpUrlAttr(el) {
var urlAttr = domProcessor.getUrlAttr(el);
if (!urlAttr || !nativeMethods.hasAttribute.call(el, urlAttr))
return;
var storedAttr = DomProcessor.getStoredAttrName(urlAttr);
if (nativeMethods.hasAttribute.call(el, storedAttr)) {
nativeMethods.setAttribute.call(el, urlAttr, nativeMethods.getAttribute.call(el, storedAttr));
nativeMethods.removeAttribute.call(el, storedAttr);
}
}
function cleanUpAutocompleteAttr(el) {
if (!nativeMethods.hasAttribute.call(el, 'autocomplete'))
return;
var storedAttr = DomProcessor.getStoredAttrName('autocomplete');
if (nativeMethods.hasAttribute.call(el, storedAttr)) {
var storedAttrValue = nativeMethods.getAttribute.call(el, storedAttr);
if (DomProcessor.isAddedAutocompleteAttr('autocomplete', storedAttrValue))
nativeMethods.removeAttribute.call(el, 'autocomplete');
else
nativeMethods.setAttribute.call(el, 'autocomplete', storedAttrValue);
nativeMethods.removeAttribute.call(el, storedAttr);
}
}
function cleanUpTargetAttr(el) {
var targetAttr = domProcessor.getTargetAttr(el);
if (!targetAttr || !nativeMethods.hasAttribute.call(el, targetAttr))
return;
var storedAttr = DomProcessor.getStoredAttrName(targetAttr);
if (nativeMethods.hasAttribute.call(el, storedAttr)) {
nativeMethods.setAttribute.call(el, targetAttr, nativeMethods.getAttribute.call(el, storedAttr));
nativeMethods.removeAttribute.call(el, storedAttr);
}
}
function cleanUpSandboxAttr(el) {
if (domProcessor.adapter.getTagName(el) !== 'iframe' || !nativeMethods.hasAttribute.call(el, 'sandbox'))
return;
var storedAttr = DomProcessor.getStoredAttrName('sandbox');
if (nativeMethods.hasAttribute.call(el, storedAttr)) {
nativeMethods.setAttribute.call(el, 'sandbox', nativeMethods.getAttribute.call(el, storedAttr));
nativeMethods.removeAttribute.call(el, storedAttr);
}
}
function cleanUpStyleAttr(el) {
if (!nativeMethods.hasAttribute.call(el, 'style'))
return;
var storedAttr = DomProcessor.getStoredAttrName('style');
if (nativeMethods.hasAttribute.call(el, storedAttr)) {
nativeMethods.setAttribute.call(el, 'style', nativeMethods.getAttribute.call(el, storedAttr));
nativeMethods.removeAttribute.call(el, storedAttr);
}
}
function cleanUpHtml(html) {
return processHtmlInternal(html, function (container) {
var changed = false;
find(container, STORED_ATTRS_SELECTOR, function (el) {
cleanUpUrlAttr(el);
cleanUpAutocompleteAttr(el);
cleanUpTargetAttr(el);
cleanUpSandboxAttr(el);
cleanUpStyleAttr(el);
changed = true;
});
find(container, SHADOW_UI_ELEMENTS_SELECTOR, function (el) {
var parent = nativeMethods.nodeParentNodeGetter.call(el);
if (parent) {
nativeMethods.removeChild.call(parent, el);
changed = true;
}
});
find(container, 'script', function (el) {
var textContent = nativeMethods.nodeTextContentGetter.call(el);
var cleanedTextContent = remove$1(textContent);
if (textContent !== cleanedTextContent) {
nativeMethods.nodeTextContentSetter.call(el, cleanedTextContent);
changed = true;
}
});
find(container, 'style', function (el) {
var textContent = nativeMethods.nodeTextContentGetter.call(el);
var cleanedTextContent = styleProcessor.cleanUp(textContent, parseProxyUrl);
if (textContent !== cleanedTextContent) {
nativeMethods.nodeTextContentSetter.call(el, cleanedTextContent);
changed = true;
}
});
find(container, HOVER_AND_FOCUS_PSEUDO_CLASS_ELEMENTS_SELECTOR, function (el) {
nativeMethods.removeAttribute.call(el, INTERNAL_ATTRIBUTES.hoverPseudoClass);
nativeMethods.removeAttribute.call(el, INTERNAL_ATTRIBUTES.focusPseudoClass);
changed = true;
});
find(container, FAKE_ELEMENTS_SELECTOR, function (el) {
var innerHtml = nativeMethods.elementInnerHTMLGetter.call(el);
if (innerHtml.indexOf(sharedSelfRemovingScripts.iframeInit) !== -1) {
nativeMethods.elementInnerHTMLSetter.call(el, innerHtml.replace(sharedSelfRemovingScripts.iframeInit, ''));
changed = true;
}
});
return changed;
});
}
function processHtml(html, options) {
if (options === void 0) { options = {}; }
var parentTag = options.parentTag, prepareDom = options.prepareDom, processedContext = options.processedContext, isPage = options.isPage;
return processHtmlInternal(html, function (container) {
var doctypeElement = null;
var htmlElements = [];
var children = [];
var length = 0;
var storedBaseUrl = urlResolver.getBaseUrl(document);
if (prepareDom)
prepareDom(container);
if (nativeMethods.htmlCollectionLengthGetter.call(nativeMethods.elementChildrenGetter.call(container))) {
children = nativeMethods.elementQuerySelectorAll.call(container, '*');
length = nativeMethods.nodeListLengthGetter.call(children);
}
var base = nativeMethods.elementQuerySelector.call(container, 'base');
if (base)
urlResolver.updateBase(nativeMethods.getAttribute.call(base, 'href'), document);
for (var i = 0; i < length; i++) {
var child = children[i];
if (isScriptElement(child)) {
var scriptContent = nativeMethods.nodeTextContentGetter.call(child);
nativeMethods.nodeTextContentSetter.call(child, unwrapHtmlText(scriptContent));
}
child[INTERNAL_PROPS.processedContext] = processedContext;
domProcessor.processElement(child, convertToProxyUrl);
var elTagName = getTagName(child);
if (elTagName === FAKE_HEAD_TAG_NAME || elTagName === FAKE_BODY_TAG_NAME)
htmlElements.push(child);
else if (elTagName === FAKE_DOCTYPE_TAG_NAME)
doctypeElement = child;
}
if (!parentTag) {
if (htmlElements.length) {
for (var _i = 0, htmlElements_1 = htmlElements; _i < htmlElements_1.length; _i++) {
var htmlElement = htmlElements_1[_i];
var firstScriptOrStyle = nativeMethods.elementQuerySelector.call(htmlElement, SCRIPT_AND_STYLE_SELECTOR);
if (firstScriptOrStyle)
nativeMethods.insertAdjacentHTML.call(firstScriptOrStyle, InsertPosition$1.beforeBegin, sharedSelfRemovingScripts.iframeInit);
else
nativeMethods.insertAdjacentHTML.call(htmlElement, InsertPosition$1.beforeEnd, sharedSelfRemovingScripts.iframeInit);
}
}
else if (doctypeElement && isIE)
nativeMethods.insertAdjacentHTML.call(doctypeElement, InsertPosition$1.afterEnd, sharedSelfRemovingScripts.iframeInit);
else if (isPage)
nativeMethods.insertAdjacentHTML.call(container, InsertPosition$1.afterBegin, sharedSelfRemovingScripts.iframeInit);
}
urlResolver.updateBase(storedBaseUrl, document);
return true;
});
}
function dispose$1() {
htmlParser = null;
htmlDocument = null;
}
function isInternalHtmlParserElement(el) {
while (nativeMethods.nodeParentNodeGetter.call(el))
el = nativeMethods.nodeParentNodeGetter.call(el);
return !!el[HTML_PARSER_ELEMENT_FLAG];
}
function removeExtraSvgNamespaces(html, processedHtml) {
var initialSvgStrs = html.match(FIND_SVG_RE);
var index = 0;
if (!initialSvgStrs)
return processedHtml;
return processedHtml.replace(FIND_SVG_RE, function (svgStr) {
var initialSvgStr = initialSvgStrs[index];
var initialNSAttrs = initialSvgStr ? initialSvgStr.match(FIND_NS_ATTRS_RE) : null;
if (initialSvgStr)
index++;
return initialSvgStr ? svgStr.replace(FIND_NS_ATTRS_RE, function () {
var replacement = initialNSAttrs ? initialNSAttrs.join('') : '';
if (initialNSAttrs)
initialNSAttrs = null;
return replacement;
}) : svgStr;
});
}
var htmlUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
isPageHtml: isPageHtml,
cleanUpHtml: cleanUpHtml,
processHtml: processHtml,
dispose: dispose$1,
isInternalHtmlParserElement: isInternalHtmlParserElement
});
var BEGIN_MARKER_TAG_NAME = 'hammerhead_write_marker_begin';
var END_MARKER_TAG_NAME = 'hammerhead_write_marker_end';
var BEGIN_MARKER_MARKUP = "<".concat(BEGIN_MARKER_TAG_NAME, "></").concat(BEGIN_MARKER_TAG_NAME, ">");
var END_MARKER_MARKUP = "<".concat(END_MARKER_TAG_NAME, "></").concat(END_MARKER_TAG_NAME, ">");
var BEGIN_REMOVE_RE = new RegExp("^[\\S\\s]*".concat(BEGIN_MARKER_MARKUP), 'g');
var END_REMOVE_RE = new RegExp("".concat(END_MARKER_MARKUP, "[\\S\\s]*$"), 'g');
var REMOVE_OPENING_TAG_RE = /^<[^>]+>/g;
var REMOVE_CLOSING_TAG_RE = /<\/[^<>]+>$/g;
var PENDING_RE = /<\/?(?:[A-Za-z][^>]*)?$/g;
var UNCLOSED_ELEMENT_FLAG = 'hammerhead|unclosed-element-flag';
var DocumentWriter = /** @class */ (function () {
function DocumentWriter(window, document) {
this.window = window;
this.document = document;
this.pending = '';
this.parentTagChain = [];
this.isBeginMarkerInDOM = false;
this.isEndMarkerInDOM = false;
this.isClosingContentEl = false;
this.isNonClosedComment = false;
this.isAddContentToEl = false;
this.contentForProcessing = '';
this.nonClosedEl = null;
this.cachedStartsWithClosingTagRegExps = {};
}
DocumentWriter.prototype._cutPending = function (htmlChunk) {
var match = htmlChunk.match(PENDING_RE);
this.pending = match ? match[0] : '';
return this.pending ? htmlChunk.substring(0, htmlChunk.length - this.pending.length) : htmlChunk;
};
DocumentWriter.prototype._wrapHtmlChunk = function (htmlChunk) {
var parentTagChainMarkup = this.parentTagChain.length ? '<' + this.parentTagChain.join('><') + '>' : '';
if (this.isNonClosedComment)
parentTagChainMarkup += '<!--';
return parentTagChainMarkup + BEGIN_MARKER_MARKUP + htmlChunk + END_MARKER_MARKUP;
};
DocumentWriter.prototype._unwrapHtmlChunk = function (htmlChunk) {
if (!htmlChunk)
return htmlChunk;
htmlChunk = htmlChunk
.replace(BEGIN_REMOVE_RE, '')
.replace(END_REMOVE_RE, '');
if (!this.isBeginMarkerInDOM)
htmlChunk = this.isNonClosedComment ? htmlChunk.slice(4) : htmlChunk.replace(REMOVE_OPENING_TAG_RE, '');
if (!this.isEndMarkerInDOM)
htmlChunk = this.isNonClosedComment ? htmlChunk.slice(0, -3) : htmlChunk.replace(REMOVE_CLOSING_TAG_RE, '');
if (!this.isBeginMarkerInDOM && this.isEndMarkerInDOM)
this.isNonClosedComment = false;
return htmlChunk;
};
DocumentWriter._setUnclosedElementFlag = function (el) {
if (isScriptElement(el) || isStyleElement(el))
el[UNCLOSED_ELEMENT_FLAG] = true;
};
DocumentWriter.hasUnclosedElementFlag = function (el) {
return !!el[UNCLOSED_ELEMENT_FLAG];
};
DocumentWriter._searchBeginMarker = function (container) {
var beginMarker = nativeMethods.elementQuerySelector.call(container, BEGIN_MARKER_TAG_NAME);
if (beginMarker)
return beginMarker;
beginMarker = container;
while (nativeMethods.elementFirstElementChildGetter.call(beginMarker))
beginMarker = nativeMethods.elementFirstElementChildGetter.call(beginMarker);
var beginMarkerParent = nativeMethods.nodeParentNodeGetter.call(beginMarker);
if (nativeMethods.nodeFirstChildGetter.call(beginMarkerParent) !== beginMarker)
beginMarker = nativeMethods.nodeFirstChildGetter.call(beginMarkerParent);
else if (isCommentNode(nativeMethods.nodeFirstChildGetter.call(beginMarker)))
beginMarker = nativeMethods.nodeFirstChildGetter.call(beginMarker);
return beginMarker;
};
DocumentWriter._searchEndMarker = function (container) {
var endMarker = nativeMethods.elementQuerySelector.call(container, END_MARKER_TAG_NAME);
if (endMarker)
return endMarker;
endMarker = container;
while (nativeMethods.elementLastElementChildGetter.call(endMarker))
endMarker = nativeMethods.elementLastElementChildGetter.call(endMarker);
var endMarkerParent = nativeMethods.nodeParentNodeGetter.call(endMarker);
if (nativeMethods.nodeLastChildGetter.call(endMarkerParent) !== endMarker)
endMarker = nativeMethods.nodeLastChildGetter.call(endMarkerParent);
else if (isCommentNode(nativeMethods.nodeLastChildGetter.call(endMarker)))
endMarker = nativeMethods.nodeLastChildGetter.call(endMarker);
return endMarker;
};
DocumentWriter.prototype._updateParentTagChain = function (container, endMarker) {
var endMarkerParent = getTagName(endMarker) !== END_MARKER_TAG_NAME ? endMarker : nativeMethods.nodeParentNodeGetter.call(endMarker);
if (isCommentNode(endMarker)) {
this.isNonClosedComment = true;
endMarkerParent = nativeMethods.nodeParentNodeGetter.call(endMarker);
}
this.parentTagChain = [];
while (endMarkerParent !== container) {
this.parentTagChain.unshift(getTagName(endMarkerParent));
endMarkerParent = nativeMethods.nodeParentNodeGetter.call(endMarkerParent);
}
};
DocumentWriter.prototype._processBeginMarkerInContent = function (beginMarker) {
var elWithContent = beginMarker;
DocumentWriter._setUnclosedElementFlag(elWithContent);
if (this.isClosingContentEl && (isScriptElement(elWithContent) || isStyleElement(elWithContent))) {
this.contentForProcessing = nativeMethods.nodeTextContentGetter.call(this.nonClosedEl) +
nativeMethods.nodeTextContentGetter.call(elWithContent).replace(BEGIN_REMOVE_RE, '');
nativeMethods.nodeTextContentSetter.call(elWithContent, '');
}
else {
var textContent = nativeMethods.nodeTextContentGetter.call(elWithContent);
nativeMethods.nodeTextContentSetter.call(elWithContent, textContent.replace(BEGIN_REMOVE_RE, ''));
}
beginMarker = nativeMethods.createElement.call(document, BEGIN_MARKER_TAG_NAME);
var elWithContentParent = nativeMethods.nodeParentNodeGetter.call(elWithContent);
nativeMethods.insertBefore.call(elWithContentParent, beginMarker, elWithContent);
};
DocumentWriter._createStartsWithClosingTagRegExp = function (tagName) {
var regExpStrParts = [tagName.charAt(tagName.length - 1), '?'];
for (var i = tagName.length - 2; i > -1; i--) {
regExpStrParts.unshift('(?:', tagName.charAt(i));
regExpStrParts.push(')?');
}
regExpStrParts.unshift('^</');
regExpStrParts.push('$');
return new RegExp(regExpStrParts.join(''), 'i');
};
DocumentWriter.prototype._getStartsWithClosingTagRegExp = function (tagName) {
tagName = tagName.toLowerCase();
if (!this.cachedStartsWithClosingTagRegExps[tagName])
this.cachedStartsWithClosingTagRegExps[tagName] = DocumentWriter._createStartsWithClosingTagRegExp(tagName);
return this.cachedStartsWithClosingTagRegExps[tagName];
};
DocumentWriter.prototype._processEndMarkerInContent = function (endMarker) {
var elWithContent = endMarker;
var textContent = nativeMethods.nodeTextContentGetter.call(elWithContent);
DocumentWriter._setUnclosedElementFlag(elWithContent);
nativeMethods.nodeTextContentSetter.call(elWithContent, textContent.replace(END_REMOVE_RE, ''));
endMarker = nativeMethods.createElement.call(document, END_MARKER_TAG_NAME);
if (this.pending) {
var startsWithClosingTagRegExp = this._getStartsWithClosingTagRegExp(elWithContent.tagName);
var isPendingStartsWithClosingTagPart = startsWithClosingTagRegExp.test(this.pending);
if (!isPendingStartsWithClosingTagPart) {
var newContent = nativeMethods.nodeTextContentGetter.call(elWithContent) + this.pending;
nativeMethods.nodeTextContentSetter.call(elWithContent, newContent);
this.pending = '';
}
}
var elWithContentParent = nativeMethods.nodeParentNodeGetter.call(elWithContent);
nativeMethods.appendChild.call(elWithContentParent, endMarker);
};
DocumentWriter._addOnDocumentRecreationScript = function (endMarker) {
var span = nativeMethods.createElement.call(endMarker.ownerDocument, 'span');
var endMarkerParent = nativeMethods.nodeParentNodeGetter.call(endMarker);
nativeMethods.insertBefore.call(endMarkerParent, span, endMarker);
nativeMethods.elementOuterHTMLSetter.call(span, sharedSelfRemovingScripts.onWindowRecreation);
};
DocumentWriter.prototype._prepareDom = function (container, isDocumentCleaned) {
var beginMarker = DocumentWriter._searchBeginMarker(container);
var endMarker = DocumentWriter._searchEndMarker(container);
this.isBeginMarkerInDOM = getTagName(beginMarker) === BEGIN_MARKER_TAG_NAME;
this.isEndMarkerInDOM = getTagName(endMarker) === END_MARKER_TAG_NAME;
this.isAddContentToEl = beginMarker === endMarker;
this.isClosingContentEl = !this.isBeginMarkerInDOM && !this.isAddContentToEl;
if (!this.isAddContentToEl) {
this._updateParentTagChain(container, endMarker);
if (isDocumentCleaned)
DocumentWriter._addOnDocumentRecreationScript(endMarker);
}
if (!this.isBeginMarkerInDOM && !this.isEndMarkerInDOM) {
this._processBeginMarkerInContent(beginMarker);
this._processEndMarkerInContent(endMarker);
}
else if (this.isBeginMarkerInDOM && !this.isEndMarkerInDOM)
this._processEndMarkerInContent(endMarker);
else if (!this.isBeginMarkerInDOM && this.isEndMarkerInDOM)
this._processBeginMarkerInContent(beginMarker);
};
DocumentWriter.prototype._processHtmlChunk = function (htmlChunk, isDocumentCleaned) {
var _this = this;
htmlChunk = this._cutPending(this.pending + htmlChunk);
htmlChunk = this._wrapHtmlChunk(htmlChunk);
htmlChunk = processHtml(htmlChunk, {
prepareDom: function (container) { return _this._prepareDom(container, isDocumentCleaned); },
processedContext: this.window,
});
htmlChunk = this._unwrapHtmlChunk(htmlChunk);
// NOTE: Firefox and IE recreate a window instance during the document.write function execution (T213930).
if (htmlChunk && this.isBeginMarkerInDOM && (isFirefox || isIE) && !isPageHtml(htmlChunk))
htmlChunk = sharedSelfRemovingScripts.iframeInit + htmlChunk;
return htmlChunk;
};
DocumentWriter.prototype.write = function (args, ln, isDocumentCleaned) {
var htmlChunk = this._processHtmlChunk(nativeMethods.arrayJoin.call(args, ''), isDocumentCleaned);
if (this.nonClosedEl && this.contentForProcessing) {
var processedContent = this.contentForProcessing;
if (isScriptElement(this.nonClosedEl))
processedContent = processScript(this.contentForProcessing, true, false, convertToProxyUrl, void 0, settings.get().proxyless);
else if (isStyleElement(this.nonClosedEl))
processedContent = styleProcessor.process(this.contentForProcessing, getProxyUrl, true);
nativeMethods.nodeTextContentSetter.call(this.nonClosedEl, processedContent);
this.contentForProcessing = '';
}
var nativeWriteMethod = ln ? nativeMethods.documentWriteLn : nativeMethods.documentWrite;
var result = nativeWriteMethod.call(this.document, htmlChunk);
if (isDocumentCleaned && isIE)
return result;
if (!this.isEndMarkerInDOM && !this.isAddContentToEl) {
var el = this.document.documentElement;
while (nativeMethods.elementLastElementChildGetter.call(el))
el = nativeMethods.elementLastElementChildGetter.call(el);
this.nonClosedEl = el;
}
return result;
};
return DocumentWriter;
}());
var WINDOWS_STORAGE = 'hammerhead|windows-storage';
function getStorage() {
var topSameDomainWindow = getTopSameDomainWindow(window);
var storage = topSameDomainWindow[WINDOWS_STORAGE];
if (!storage) {
storage = [];
nativeMethods.objectDefineProperty(topSameDomainWindow, WINDOWS_STORAGE, { value: storage });
}
return storage;
}
function add(wnd) {
var storage = getStorage();
for (var i = storage.length - 1; i >= 0; i--) {
try {
if (storage[i] === wnd)
return;
}
catch (e) {
storage.splice(i, 1);
}
}
storage.push(wnd);
}
function remove(wnd) {
var storage = getStorage();
var index = storage.indexOf(wnd);
if (index !== -1)
storage.splice(index, 1);
}
function findByName(name) {
var storage = getStorage();
for (var i = 0; i < storage.length; i++) {
try {
if (storage[i].name === name)
return storage[i];
}
catch (e) {
// NOTE: During loading, an iframe can be changed from same-domain to cross-domain.
// Iframe's window is reinitialized, and we add 2 windows to the window storages:
// one to the same-domain storage and another one to the cross-domain storage.
// We remove the cross-domain window from this storage
// because it is already added to the cross-domain window storage.
storage.splice(i, 1);
i--;
}
}
return null;
}
var windowStorage = /*#__PURE__*/Object.freeze({
__proto__: null,
add: add,
remove: remove,
findByName: findByName
});
var ClientDomAdapter = /** @class */ (function (_super) {
__extends(ClientDomAdapter, _super);
function ClientDomAdapter() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._srcdocMode = false;
return _this;
}
ClientDomAdapter.prototype.removeAttr = function (el, attr) {
return nativeMethods.removeAttribute.call(el, attr);
};
ClientDomAdapter.prototype.getAttr = function (el, attr) {
return nativeMethods.getAttribute.call(el, attr);
};
ClientDomAdapter.prototype.hasAttr = function (el, attr) {
return el.hasAttribute(attr);
};
ClientDomAdapter.prototype.isSVGElement = function (el) {
return isSVGElement(el);
};
ClientDomAdapter.prototype.getClassName = function (el) {
return el.className;
};
ClientDomAdapter.prototype.hasEventHandler = function (el) {
var attributes = nativeMethods.elementAttributesGetter.call(el);
for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
var attr = attributes_1[_i];
if (this.EVENTS.indexOf(attr.name) !== -1)
return true;
}
return false;
};
ClientDomAdapter.prototype.getTagName = function (el) {
return getTagName(el);
};
ClientDomAdapter.prototype.setAttr = function (el, attr, value) {
return nativeMethods.setAttribute.call(el, attr, value);
};
ClientDomAdapter.prototype.setScriptContent = function (script, content) {
nativeMethods.nodeTextContentSetter.call(script, content);
};
ClientDomAdapter.prototype.getScriptContent = function (script) {
return nativeMethods.nodeTextContentGetter.call(script);
};
ClientDomAdapter.prototype.getStyleContent = function (style) {
return nativeMethods.elementInnerHTMLGetter.call(style);
};
ClientDomAdapter.prototype.setStyleContent = function (style, content) {
nativeMethods.elementInnerHTMLSetter.call(style, content);
};
ClientDomAdapter.prototype.needToProcessContent = function (el) {
return !DocumentWriter.hasUnclosedElementFlag(el);
};
ClientDomAdapter.prototype.needToProcessUrl = function () {
return true;
};
ClientDomAdapter.prototype.hasIframeParent = function (el) {
if (this._srcdocMode)
return true;
try {
if (el[INTERNAL_PROPS.processedContext])
return window.top !== el[INTERNAL_PROPS.processedContext];
return window.top.document !== findDocument(el);
}
catch (e) {
return true;
}
};
ClientDomAdapter.prototype.getProxyUrl = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return getProxyUrl.apply(void 0, args);
};
ClientDomAdapter.prototype.isTopParentIframe = function (el) {
var elWindow = el[INTERNAL_PROPS.processedContext];
return elWindow && window.top === elWindow.parent;
};
ClientDomAdapter.prototype.sameOriginCheck = function (location, checkedUrl) {
return sameOriginCheck(location, checkedUrl);
};
ClientDomAdapter.prototype.isExistingTarget = function (target) {
return !!findByName(target);
};
ClientDomAdapter.prototype.processSrcdocAttr = function (html) {
this._srcdocMode = true;
var processedHtml = processHtml(html, { isPage: true });
this._srcdocMode = false;
return processedHtml;
};
return ClientDomAdapter;
}(BaseDomAdapter));
var domProcessor = new DomProcessor(new ClientDomAdapter());
var DocumentSandbox = /** @class */ (function (_super) {
__extends(DocumentSandbox, _super);
function DocumentSandbox(_nodeSandbox, _shadowUI, _cookieSandbox, _iframeSandbox, _documentTitleStorageInitializer) {
var _this = _super.call(this) || this;
_this._nodeSandbox = _nodeSandbox;
_this._shadowUI = _shadowUI;
_this._cookieSandbox = _cookieSandbox;
_this._iframeSandbox = _iframeSandbox;
_this._documentTitleStorageInitializer = _documentTitleStorageInitializer;
_this.writers = new Map();
return _this;
}
DocumentSandbox.forceProxySrcForImageIfNecessary = function (element) {
if (settings.get().proxyless)
return;
if (isImgElement(element) && settings.get().forceProxySrcForImage)
element[INTERNAL_PROPS.forceProxySrcForImage] = true;
};
DocumentSandbox._isDocumentInDesignMode = function (doc) {
return doc.designMode === 'on';
};
DocumentSandbox.prototype._isUninitializedIframeWithoutSrc = function (win) {
var frameElement = getFrameElement(win);
return win !== win.top && frameElement && isIframeWithoutSrc(frameElement) &&
!IframeSandbox.isIframeInitialized(frameElement);
};
DocumentSandbox.prototype._beforeDocumentCleaned = function () {
this._nodeSandbox.mutation.onBeforeDocumentCleaned(this.document);
};
DocumentSandbox.prototype._onDocumentClosed = function () {
this._nodeSandbox.mutation.onDocumentClosed(this.document);
};
DocumentSandbox._shouldEmitDocumentCleanedEvents = function (doc) {
if (isIE) {
if (doc.readyState !== 'loading')
return true;
var window_1 = doc.defaultView;
if (window_1[INTERNAL_PROPS.documentWasCleaned])
return false;
var iframe = window_1 && getFrameElement(window_1);
return iframe && isIframeWithoutSrc(iframe);
}
return doc.readyState !== 'loading' && doc.readyState !== 'uninitialized';
};
DocumentSandbox.prototype._performDocumentWrite = function (doc, args, ln) {
var shouldEmitEvents = DocumentSandbox._shouldEmitDocumentCleanedEvents(this.document);
if (shouldEmitEvents)
this._beforeDocumentCleaned();
var result = this.writers.get(doc).write(args, ln, shouldEmitEvents);
// NOTE: B234357
if (!shouldEmitEvents)
this._nodeSandbox.processNodes(null, this.document);
return result;
};
DocumentSandbox._definePropertyDescriptor = function (owner, childOfOwner, prop, overriddenDescriptor) {
// NOTE: The 'URL', 'domain' and 'referrer' properties are non configurable in IE and Edge
if (!overriddenDescriptor.configurable) {
// NOTE: property doesn't redefined yet
if (!childOfOwner.hasOwnProperty(prop)) // eslint-disable-line no-prototype-builtins
nativeMethods.objectDefineProperty(childOfOwner, prop, overriddenDescriptor);
}
else
nativeMethods.objectDefineProperty(owner, prop, overriddenDescriptor);
};
DocumentSandbox.prototype.iframeDocumentOpen = function (window, document, args) {
var iframe = window.frameElement;
var result = nativeMethods.documentOpen.apply(document, args);
nativeMethods.objectDefineProperty(window, INTERNAL_PROPS.documentWasCleaned, { value: true, configurable: true });
this._nodeSandbox.iframeSandbox.onIframeBeganToRun(iframe);
return result;
};
DocumentSandbox.prototype.attach = function (window, document, partialInitializationForNotLoadedIframe) {
var _this = this;
if (partialInitializationForNotLoadedIframe === void 0) { partialInitializationForNotLoadedIframe = false; }
if (!this.writers.size)
_super.prototype.attach.call(this, window, document);
if (!this.writers.has(document)) {
this.writers.set(document, new DocumentWriter(window, document));
this._nodeSandbox.mutation.on(this._nodeSandbox.mutation.BEFORE_DOCUMENT_CLEANED_EVENT, function () {
_this.writers.set(document, new DocumentWriter(window, document));
});
}
var documentSandbox = this;
var docPrototype = window.Document.prototype;
var overriddenMethods = {
open: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var isUninitializedIframe = documentSandbox._isUninitializedIframeWithoutSrc(window);
if (!isUninitializedIframe)
documentSandbox._beforeDocumentCleaned();
if (isIE)
return window.parent[INTERNAL_PROPS.hammerhead].sandbox.node.doc.iframeDocumentOpen(window, this, args);
var result = nativeMethods.documentOpen.apply(this, args);
// NOTE: Chrome does not remove the "%hammerhead%" property from window
// after document.open call
var objectDefinePropertyFn = window[INTERNAL_PROPS.hammerhead]
? window[INTERNAL_PROPS.hammerhead].nativeMethods.objectDefineProperty
: window.Object.defineProperty;
objectDefinePropertyFn(window, INTERNAL_PROPS.documentWasCleaned, { value: true, configurable: true });
if (!isUninitializedIframe)
documentSandbox._nodeSandbox.mutation.onDocumentCleaned(window, this);
else {
var iframe = getFrameElement(window);
if (iframe)
documentSandbox._iframeSandbox.processIframe(iframe);
}
return result;
},
close: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
// NOTE: IE11 raise the "load" event only when the document.close method is called. We need to
// restore the overridden document.open and document.write methods before Hammerhead injection, if the
// window is not initialized.
if (isIE && !IframeSandbox.isWindowInited(window))
nativeMethods.restoreDocumentMeths(window, this);
// NOTE: IE doesn't run scripts in iframe if iframe.documentContent.designMode equals 'on' (GH-871)
if (DocumentSandbox._isDocumentInDesignMode(this))
ShadowUISandbox.removeSelfRemovingScripts(this);
var result = nativeMethods.documentClose.apply(this, args);
if (!documentSandbox._isUninitializedIframeWithoutSrc(window))
documentSandbox._onDocumentClosed();
var iframe = getFrameElement(window);
// NOTE: Firefox misses the Hammerhead instance after the iframe.contentDocument.close function calling (GH-1821)
if (iframe)
documentSandbox._nodeSandbox.iframeSandbox.onIframeBeganToRun(iframe);
return result;
},
write: function () {
return documentSandbox._performDocumentWrite(this, arguments);
},
writeln: function () {
return documentSandbox._performDocumentWrite(this, arguments, true);
},
};
overrideFunction(window[nativeMethods.documentOpenPropOwnerName].prototype, 'open', overriddenMethods.open);
overrideFunction(window[nativeMethods.documentClosePropOwnerName].prototype, 'close', overriddenMethods.close);
overrideFunction(window[nativeMethods.documentWritePropOwnerName].prototype, 'write', overriddenMethods.write);
overrideFunction(window[nativeMethods.documentWriteLnPropOwnerName].prototype, 'writeln', overriddenMethods.writeln);
overrideFunction(document, 'open', overriddenMethods.open);
overrideFunction(document, 'close', overriddenMethods.close);
overrideFunction(document, 'write', overriddenMethods.write);
overrideFunction(document, 'writeln', overriddenMethods.writeln);
if (document.open !== overriddenMethods.open)
overrideFunction(document, 'open', overriddenMethods.open);
overrideFunction(docPrototype, 'createElement', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var el = nativeMethods.createElement.apply(this, args);
DocumentSandbox.forceProxySrcForImageIfNecessary(el);
domProcessor.processElement(el, convertToProxyUrl);
documentSandbox._nodeSandbox.processNodes(el);
return el;
});
overrideFunction(docPrototype, 'createElementNS', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var el = nativeMethods.createElementNS.apply(this, args);
DocumentSandbox.forceProxySrcForImageIfNecessary(el);
domProcessor.processElement(el, convertToProxyUrl);
documentSandbox._nodeSandbox.processNodes(el);
return el;
});
overrideFunction(docPrototype, 'createDocumentFragment', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var fragment = nativeMethods.createDocumentFragment.apply(this, args);
documentSandbox._nodeSandbox.processNodes(fragment);
return fragment;
});
var htmlDocPrototype = window.HTMLDocument.prototype;
var storedDomain = '';
if (nativeMethods.documentDocumentURIGetter) {
overrideDescriptor(docPrototype, 'documentURI', {
getter: function () {
return getDestinationUrl(nativeMethods.documentDocumentURIGetter.call(this));
},
});
}
var referrerOverriddenDescriptor = createOverriddenDescriptor(docPrototype, 'referrer', {
getter: function () {
var referrer = getDestinationUrl(nativeMethods.documentReferrerGetter.call(this));
if (referrer === getCrossDomainProxyOrigin() + '/')
return getReferrer();
return isSpecialPage(referrer) ? '' : referrer;
},
});
DocumentSandbox._definePropertyDescriptor(docPrototype, htmlDocPrototype, 'referrer', referrerOverriddenDescriptor);
var urlOverriddenDescriptor = createOverriddenDescriptor(docPrototype, 'URL', {
getter: function () {
// eslint-disable-next-line no-restricted-properties
return LocationAccessorsInstrumentation.getLocationWrapper(this).href;
},
});
DocumentSandbox._definePropertyDescriptor(docPrototype, htmlDocPrototype, 'URL', urlOverriddenDescriptor);
var domainPropertyOwner = nativeMethods.objectHasOwnProperty.call(docPrototype, 'domain')
? docPrototype
: htmlDocPrototype;
var domainOverriddenDescriptor = createOverriddenDescriptor(domainPropertyOwner, 'domain', {
getter: function () {
// eslint-disable-next-line no-restricted-properties
return storedDomain || LocationAccessorsInstrumentation.getLocationWrapper(window).hostname;
},
setter: function (value) {
storedDomain = value;
},
});
DocumentSandbox._definePropertyDescriptor(domainPropertyOwner, htmlDocPrototype, 'domain', domainOverriddenDescriptor);
overrideDescriptor(docPrototype, 'styleSheets', {
getter: function () {
var styleSheets = nativeMethods.documentStyleSheetsGetter.call(this);
return documentSandbox._shadowUI._filterStyleSheetList(styleSheets, styleSheets.length);
},
});
var documentCookiePropOwnerPrototype = window[nativeMethods.documentCookiePropOwnerName].prototype;
if (!this.proxyless) {
overrideDescriptor(documentCookiePropOwnerPrototype, 'cookie', {
getter: function () { return documentSandbox._cookieSandbox.getCookie(); },
setter: function (value) { return documentSandbox._cookieSandbox.setCookie(String(value)); },
});
}
overrideDescriptor(docPrototype, 'activeElement', {
getter: function () {
var activeElement = nativeMethods.documentActiveElementGetter.call(this);
if (activeElement && isShadowUIElement(activeElement))
return documentSandbox._shadowUI.getLastActiveElement() || this.body;
return activeElement;
},
});
if (this._documentTitleStorageInitializer && !partialInitializationForNotLoadedIframe) {
overrideDescriptor(docPrototype, 'title', {
getter: function () {
return documentSandbox._documentTitleStorageInitializer.storage.getTitle();
},
setter: function (value) {
documentSandbox._documentTitleStorageInitializer.storage.setTitle(value);
},
});
}
};
return DocumentSandbox;
}(SandboxBase));
function createInput(form) {
var hiddenInput = nativeMethods.createElement.call(document, 'input');
hiddenInput.type = 'hidden';
hiddenInput.name = INTERNAL_ATTRIBUTES.uploadInfoHiddenInputName;
ShadowUISandbox.markElementAsShadow(hiddenInput);
nativeMethods.inputValueSetter.call(hiddenInput, '[]');
nativeMethods.appendChild.call(form, hiddenInput);
ShadowUISandbox.markFormAsShadow(form);
return hiddenInput;
}
function getInput(form) {
var inputSelector = '[name="' + INTERNAL_ATTRIBUTES.uploadInfoHiddenInputName + '"]';
return nativeMethods.elementQuerySelector.call(form, inputSelector) || createInput(form);
}
function indexOf(info, input) {
for (var index = 0; index < info.length; index++) {
if (info[index].id === input.id || info[index].name === input.name)
return index;
}
return -1;
}
function addInputInfo(input, fileList, value) {
var formInfo = getFormInfo(input);
if (formInfo) {
var files = [];
fileList = nativeMethods.arraySlice.call(fileList);
for (var i = 0, len = fileList.length; i < len; i++) {
var file = fileList[i];
files.push({
name: file.name,
type: file.type,
data: file.base64,
});
}
var inputInfoIndex = indexOf(formInfo, input);
var inputInfo = {
id: input.id,
name: input.name,
files: files,
value: value,
};
if (inputInfoIndex === -1)
formInfo.push(inputInfo);
else
formInfo[inputInfoIndex] = inputInfo;
setFormInfo(input, formInfo);
}
}
function getFormInfo(input) {
return input.form ? parse$1(nativeMethods.inputValueGetter.call(getInput(input.form))) : null;
}
function setFormInfo(input, info) {
if (input.form) {
var hiddenInput = getInput(input.form);
nativeMethods.inputValueSetter.call(hiddenInput, stringify(info));
}
}
function removeInputInfo(input) {
var uploadInfo = getFormInfo(input);
if (uploadInfo) {
var inputInfoIndex = indexOf(uploadInfo, input);
if (inputInfoIndex !== -1) {
uploadInfo.splice(inputInfoIndex, 1);
setFormInfo(input, uploadInfo);
return true;
}
}
return false;
}
var hiddenInfoUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
addInputInfo: addInputInfo,
getFormInfo: getFormInfo,
setFormInfo: setFormInfo,
removeInputInfo: removeInputInfo
});
var COMPOSED_EVENTS = [
'blur',
'focus',
'focusin',
'focusout',
'click',
'dblclick',
'mousedown',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'beforeinput',
'input',
'keydown',
'keyup',
];
var BUTTON = {
left: 0,
middle: 1,
right: 2,
};
var BUTTONS_PARAMETER = {
noButton: 0,
leftButton: 1,
rightButton: 2,
};
var WHICH_PARAMETER = {
noButton: 0,
leftButton: 1,
middleButton: 2,
rightButton: 3,
};
var KEYBOARD_MODIFIERS_PARAMETER = {
altKey: 'Alt',
ctrlKey: 'Control',
shiftKey: 'Shift',
metaKey: 'Meta',
};
var DOM_EVENTS = [
'click', 'dblclick', 'contextmenu',
'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave',
'touchstart', 'touchmove', 'touchend',
'keydown', 'keypress', 'keyup',
'textInput', 'textinput', 'input', 'change',
'focus', 'blur',
'MSPointerDown', 'MSPointerMove', 'MSPointerOver', 'MSPointerOut', 'MSPointerUp',
'pointerdown', 'pointermove', 'pointerover', 'pointerout', 'pointerup', 'pointerenter', 'pointerleave',
'dragstart', 'drop',
'focusin', 'focusout',
];
function preventDefault(ev, allowBubbling) {
if (ev.preventDefault)
ev.preventDefault();
else
ev.returnValue = false;
if (!allowBubbling)
stopPropagation(ev);
}
function stopPropagation(ev) {
if (ev.stopImmediatePropagation)
ev.stopImmediatePropagation();
else if (ev.stopPropagation)
ev.stopPropagation();
ev.cancelBubble = true;
}
function isObjectEventListener(listener) {
return typeof listener === 'object' && listener && isFunction(listener.handleEvent);
}
function isValidEventListener(listener) {
return isFunction(listener) || isObjectEventListener(listener);
}
function callEventListener(ctx, listener, e) {
if (isObjectEventListener(listener))
return listener.handleEvent.call(listener, e);
return listener.call(ctx, e);
}
function isComposedEvent(event) {
return COMPOSED_EVENTS.indexOf(event) !== -1;
}
var hasPointerEvents = !!(nativeMethods.WindowPointerEvent || nativeMethods.WindowMSPointerEvent);
var eventUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
BUTTON: BUTTON,
BUTTONS_PARAMETER: BUTTONS_PARAMETER,
WHICH_PARAMETER: WHICH_PARAMETER,
KEYBOARD_MODIFIERS_PARAMETER: KEYBOARD_MODIFIERS_PARAMETER,
DOM_EVENTS: DOM_EVENTS,
preventDefault: preventDefault,
stopPropagation: stopPropagation,
isObjectEventListener: isObjectEventListener,
isValidEventListener: isValidEventListener,
callEventListener: callEventListener,
isComposedEvent: isComposedEvent,
hasPointerEvents: hasPointerEvents
});
// OPTIMIZATION: http://jsperf.com/bind-apply
function fnBind(func, thisObj) {
return function () {
return func.apply(thisObj, arguments);
};
}
var ATTRIBUTES_METHODS = ['setNamedItem', 'setNamedItemNS', 'removeNamedItem', 'removeNamedItemNS', 'getNamedItem', 'getNamedItemNS'];
function createMethodWrapper(el, attributes, method) {
return function () {
var result = attributes[method].apply(attributes, arguments);
refreshAttributesWrapper(el);
return result;
};
}
var AttributesWrapper = /** @class */ (function () {
function AttributesWrapper(el, attributes) {
var _this = this;
assignAttributes(this, attributes);
this.item = function (index) { return _this[index]; };
for (var field in attributes) {
if (typeof this[field] === 'function' && field !== 'item') {
this[field] = ATTRIBUTES_METHODS.indexOf(field) !== -1
? createMethodWrapper(el, attributes, field)
: fnBind(attributes[field], attributes);
}
}
if (attrGetNamedItemIsNotEnumerable)
this['getNamedItem'] = createMethodWrapper(el, attributes, 'getNamedItem');
}
return AttributesWrapper;
}());
var ATTRIBUTES_WRAPPER = 'hammerhead|element-attribute-wrappers';
function cleanAttributes(wrapper) {
if (wrapper.length) {
for (var i = 0; i < wrapper.length; i++) {
delete wrapper[wrapper[i].name];
delete wrapper[i];
}
}
}
function assignAttributes(wrapper, attributes) {
var length = 0;
var properties = {};
for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
var attr = attributes_1[_i];
if (!isHammerheadAttr(attr.name)) {
var storedAttr = attributes[DomProcessor.getStoredAttrName(attr.name)];
if (storedAttr) {
// eslint-disable-next-line no-restricted-properties
if (DomProcessor.isAddedAutocompleteAttr(attr.name, storedAttr.value))
continue;
attr = nativeMethods.cloneNode.call(attr);
// eslint-disable-next-line no-restricted-properties
attr.value = storedAttr.value;
}
properties[attr.name] = { value: attr, configurable: true, enumerable: true };
properties[length] = { value: attr, configurable: true };
length++;
}
}
properties['length'] = { value: length, configurable: true };
nativeMethods.objectDefineProperties(wrapper, properties);
}
function getAttributes(el) {
if (el[ATTRIBUTES_WRAPPER]) {
refreshAttributesWrapper(el);
return el[ATTRIBUTES_WRAPPER];
}
var attributes = nativeMethods.elementAttributesGetter.call(el);
if (!attributes)
return attributes;
for (var _i = 0, attributes_2 = attributes; _i < attributes_2.length; _i++) {
var attr = attributes_2[_i];
if (isHammerheadAttr(attr.name)) {
AttributesWrapper.prototype = attributes;
el[ATTRIBUTES_WRAPPER] = new AttributesWrapper(el, attributes);
return el[ATTRIBUTES_WRAPPER];
}
}
return attributes;
}
function refreshAttributesWrapper(el) {
var attributesWrapper = el[ATTRIBUTES_WRAPPER];
if (attributesWrapper) {
cleanAttributes(attributesWrapper);
assignAttributes(attributesWrapper, nativeMethods.elementAttributesGetter.call(el));
}
}
var DOMMutationTracker = /** @class */ (function () {
function DOMMutationTracker() {
var _this = this;
this._mutations = nativeMethods.objectCreate(null);
this._isDomContentLoaded = false;
nativeMethods.addEventListener.call(document, 'DOMContentLoaded', function () {
for (var _i = 0, _a = nativeMethods.objectKeys(_this._mutations); _i < _a.length; _i++) {
var tagName = _a[_i];
_this._updateVersion(tagName);
}
_this._isDomContentLoaded = true;
});
}
DOMMutationTracker.prototype._updateVersion = function (tagName) {
if (tagName in this._mutations)
this._mutations[tagName].increment();
};
DOMMutationTracker.prototype._processElement = function (el) {
if (!el.tagName || isShadowUIElement(el))
return;
var tagName = getTagName(el);
this._updateVersion('*');
this._updateVersion(tagName);
};
DOMMutationTracker.prototype._processChildren = function (el) {
if (!el.querySelectorAll)
return;
var children = getNativeQuerySelectorAll(el).call(el, '*');
var length = nativeMethods.nodeListLengthGetter.call(children);
for (var i = 0; i < length; i++)
this._processElement(children[i]);
};
DOMMutationTracker.prototype.onElementChanged = function (el) {
this._processElement(el);
this._processChildren(el);
};
DOMMutationTracker.prototype.onChildrenChanged = function (el) {
this._processChildren(el);
};
DOMMutationTracker.prototype.isDomContentLoaded = function () {
return this._isDomContentLoaded;
};
DOMMutationTracker.prototype.isOutdated = function (tagName, version) {
var isTagTracked = tagName in this._mutations;
if (!isTagTracked)
this._mutations[tagName] = new IntegerIdGenerator();
var lastVersion = this._mutations[tagName].value; // eslint-disable-line no-restricted-properties
return version < lastVersion;
};
DOMMutationTracker.prototype.getVersion = function (tagName) {
if (tagName in this._mutations)
return this._mutations[tagName].value; // eslint-disable-line no-restricted-properties
return -Infinity;
};
return DOMMutationTracker;
}());
var domMutationTracker = new DOMMutationTracker();
var KEYWORD_TARGETS = ['_blank', '_self', '_parent', '_top'];
function isKeywordTarget (value) {
if (value === void 0) { value = ''; }
value = value.toLowerCase();
return KEYWORD_TARGETS.indexOf(value) !== -1;
}
var KEBAB_CASE_REGEX = /[A-Z]/g;
function toKebabCase (s) {
return s.replace(KEBAB_CASE_REGEX, function (match) { return "-".concat(match.toLowerCase()); });
}
var RESTRICTED_META_HTTP_EQUIV_VALUES = [BUILTIN_HEADERS.refresh, BUILTIN_HEADERS.contentSecurityPolicy];
var AttributeType;
(function (AttributeType) {
AttributeType[AttributeType["Ns"] = 0] = "Ns";
AttributeType[AttributeType["Node"] = 1] = "Node";
})(AttributeType || (AttributeType = {}));
var ElementSandbox = /** @class */ (function (_super) {
__extends(ElementSandbox, _super);
function ElementSandbox(_nodeSandbox, _uploadSandbox, _iframeSandbox, _shadowUI, _eventSandbox, _childWindowSandbox) {
var _this = _super.call(this) || this;
_this._nodeSandbox = _nodeSandbox;
_this._uploadSandbox = _uploadSandbox;
_this._iframeSandbox = _iframeSandbox;
_this._shadowUI = _shadowUI;
_this._eventSandbox = _eventSandbox;
_this._childWindowSandbox = _childWindowSandbox;
_this.BEFORE_FORM_SUBMIT_EVENT = 'hammerhead|event|before-form-submit';
_this.SCRIPT_ELEMENT_ADDED_EVENT = 'hammerhead|event|script-added';
_this.overriddenMethods = null;
return _this;
}
ElementSandbox._onTargetChanged = function (el) {
var tagName = getTagName(el);
var targetAttr = domProcessor.getTargetAttr(el);
if (!DomProcessor.isIframeFlagTag(tagName))
return;
var urlAttr = '';
if (targetAttr === 'target')
urlAttr = tagName === 'form' ? 'action' : 'href';
else if (targetAttr === 'formtarget')
urlAttr = 'formaction';
var storedUrlAttr = DomProcessor.getStoredAttrName(urlAttr);
if (el.hasAttribute(storedUrlAttr)) {
var url = el.getAttribute(storedUrlAttr);
if (isSupportedProtocol(url))
el.setAttribute(urlAttr, url);
}
};
ElementSandbox._setProxiedSrc = function (img) {
if (img[INTERNAL_PROPS.forceProxySrcForImage])
return;
var imgSrc = nativeMethods.imageSrcGetter.call(img);
var imgSrcset = isIE ? null : nativeMethods.imageSrcsetGetter.call(img); // NOTE: IE11 doesn't support the 'srcset' property
var skipNextLoadEvent = !!imgSrc && img.complete && !img[INTERNAL_PROPS.cachedImage];
img[INTERNAL_PROPS.forceProxySrcForImage] = true;
if (imgSrc)
img.setAttribute('src', imgSrc);
if (imgSrcset)
img.setAttribute('srcset', imgSrcset);
img[INTERNAL_PROPS.skipNextLoadEventForImage] = skipNextLoadEvent;
};
ElementSandbox.prototype.getAttributeCore = function (el, args, isNs) {
var attr = String(args[isNs ? 1 : 0]);
var loweredAttr = attr.toLowerCase();
var ns = isNs ? args[0] : null;
var getAttrMeth = isNs ? nativeMethods.getAttributeNS : nativeMethods.getAttribute;
var tagName = getTagName(el);
if (loweredAttr === 'style')
return styleProcessor.cleanUp(getAttrMeth.apply(el, args), parseProxyUrl);
// OPTIMIZATION: The hasAttribute method is very slow.
if (domProcessor.isUrlAttr(el, loweredAttr, ns) ||
domProcessor.EVENTS.indexOf(loweredAttr) !== -1 ||
ATTRS_WITH_SPECIAL_PROXYING_LOGIC.indexOf(loweredAttr) !== -1) {
var storedAttrName = DomProcessor.getStoredAttrName(attr);
var storedAttrValue = getAttrMeth.apply(el, isNs ? [ns, storedAttrName] : [storedAttrName]);
if (DomProcessor.isAddedAutocompleteAttr(loweredAttr, storedAttrValue))
return null;
else if (el.hasAttribute(storedAttrName))
args[isNs ? 1 : 0] = storedAttrName;
}
else if (!isNs && (
// NOTE: We simply remove the 'integrity' attribute because its value will not be relevant after the script
// content changes (http://www.w3.org/TR/SRI/). If this causes problems in the future, we will need to generate
// the correct SHA for the changed script. (GH-235)
loweredAttr === 'integrity' && DomProcessor.isTagWithIntegrityAttr(tagName) ||
// NOTE: We simply remove the 'rel' attribute if rel='prefetch' and use stored 'rel' attribute, because the prefetch
// resource type is unknown. https://github.com/DevExpress/testcafe/issues/2528
loweredAttr === 'rel' && tagName === 'link' ||
loweredAttr === 'required' && isFileInput(el) ||
loweredAttr === 'srcdoc' && tagName === 'iframe')) {
var storedAttr = DomProcessor.getStoredAttrName(attr);
if (nativeMethods.hasAttribute.call(el, storedAttr))
args[0] = storedAttr;
}
return getAttrMeth.apply(el, args);
};
ElementSandbox.prototype.setAttributeCore = function (el, args, isNs) {
var ns = isNs ? args[0] : null;
var attr = String(args[isNs ? 1 : 0]);
var loweredAttr = attr.toLowerCase();
var valueIndex = isNs ? 2 : 1;
var value = String(args[valueIndex]);
var setAttrMeth = isNs ? nativeMethods.setAttributeNS : nativeMethods.setAttribute;
var tagName = getTagName(el);
var isUrlAttr = domProcessor.isUrlAttr(el, attr, ns);
var isEventAttr = domProcessor.EVENTS.indexOf(attr) !== -1;
var isUrlsSet = attr === 'srcset';
var needToCallTargetChanged = false;
var needToRecalcHref = false;
var isSpecialPage$1 = isSpecialPage(value);
var isSupportedProtocol$1 = isSupportedProtocol(value);
if (isUrlAttr && !isSupportedProtocol$1 && !isSpecialPage$1 || isEventAttr) {
var isJsProtocol = DomProcessor.isJsProtocol(value);
var storedJsAttr = DomProcessor.getStoredAttrName(attr);
if (isUrlAttr && isJsProtocol || isEventAttr)
args[valueIndex] = DomProcessor.processJsAttrValue(value, { isJsProtocol: isJsProtocol, isEventAttr: isEventAttr });
setAttrMeth.apply(el, isNs ? [ns, storedJsAttr, value] : [storedJsAttr, value]);
}
else if (isUrlAttr && (isSupportedProtocol$1 || isSpecialPage$1)) {
var storedUrlAttr = DomProcessor.getStoredAttrName(attr);
setAttrMeth.apply(el, isNs ? [ns, storedUrlAttr, value] : [storedUrlAttr, value]);
if (tagName !== 'img' || el[INTERNAL_PROPS.forceProxySrcForImage]) {
if (tagName === 'img')
el[INTERNAL_PROPS.skipNextLoadEventForImage] = false;
if (value !== '' && (!isSpecialPage$1 || tagName === 'a')) {
var isIframe = tagName === 'iframe' || tagName === 'frame';
var isScript = tagName === 'script';
var isCrossDomainUrl = !this.proxyless && isSupportedProtocol$1 && !sameOriginCheck(this.window.location.toString(), value);
var resourceType = domProcessor.getElementResourceType(el);
var elCharset = isScript && el.charset; // eslint-disable-line no-extra-parens
var currentDocument = el.ownerDocument || this.document;
if (loweredAttr === 'formaction' && !nativeMethods.hasAttribute.call(el, 'formtarget')) {
resourceType = stringifyResourceType({ isForm: true });
if (el.form && nativeMethods.hasAttribute.call(el.form, 'action')) { // eslint-disable-line no-extra-parens
var parsedFormAction = parseProxyUrl(nativeMethods.formActionGetter.call(el.form)); // eslint-disable-line no-extra-parens
if (parsedFormAction)
resourceType = parsedFormAction.resourceType;
}
}
if (ElementSandbox._isHrefAttrForBaseElement(el, attr) &&
isElementInDocument(el, currentDocument))
urlResolver.updateBase(value, currentDocument);
if (this.proxyless)
args[valueIndex] = value;
else {
args[valueIndex] = isIframe && isCrossDomainUrl
? getCrossDomainIframeProxyUrl(value)
: getProxyUrl(value, { resourceType: resourceType, charset: elCharset, doc: currentDocument, isUrlsSet: isUrlsSet });
}
}
}
else if (value && !isSpecialPage$1 && !parseProxyUrl(value))
args[valueIndex] = resolveUrlAsDest(value, isUrlsSet);
if (!nativeMethods.nodeParentNodeGetter.call(el)) {
nativeMethods.objectDefineProperty(el, INTERNAL_PROPS.currentBaseUrl, {
value: urlResolver.getBaseUrl(document),
configurable: true,
writable: true,
});
}
}
else if (loweredAttr === 'autocomplete') {
var storedAutocompleteAttr = DomProcessor.getStoredAttrName(attr);
setAttrMeth.apply(el, isNs ? [ns, storedAutocompleteAttr, value] : [storedAutocompleteAttr, value]);
args[valueIndex] = 'off';
}
else if (loweredAttr === 'target' && DomProcessor.isTagWithTargetAttr(tagName) ||
loweredAttr === 'formtarget' && DomProcessor.isTagWithFormTargetAttr(tagName)) {
var currentTarget = nativeMethods.getAttribute.call(el, loweredAttr);
var newTarget = this.getCorrectedTarget(value);
if (newTarget !== currentTarget) {
var storedTargetAttr = DomProcessor.getStoredAttrName(attr);
setAttrMeth.apply(el, isNs ? [ns, storedTargetAttr, value] : [storedTargetAttr, value]);
args[valueIndex] = newTarget;
needToCallTargetChanged = true;
}
else
return null;
}
else if (attr === 'sandbox') {
var storedSandboxAttr = DomProcessor.getStoredAttrName(attr);
var allowSameOrigin = value.indexOf('allow-same-origin') !== -1;
var allowScripts = value.indexOf('allow-scripts') !== -1;
setAttrMeth.apply(el, isNs ? [ns, storedSandboxAttr, value] : [storedSandboxAttr, value]);
if (!allowSameOrigin || !allowScripts) {
args[valueIndex] += !allowSameOrigin ? ' allow-same-origin' : '';
args[valueIndex] += !allowScripts ? ' allow-scripts' : '';
}
if (el[this._nodeSandbox.win.SANDBOX_DOM_TOKEN_LIST_UPDATE_FN])
el[this._nodeSandbox.win.SANDBOX_DOM_TOKEN_LIST_UPDATE_FN](value);
}
// TODO: remove after https://github.com/DevExpress/testcafe-hammerhead/issues/244 implementation
else if (tagName === 'meta' && toKebabCase(attr) === 'http-equiv') {
var loweredValue = value.toLowerCase();
if (RESTRICTED_META_HTTP_EQUIV_VALUES.indexOf(loweredValue) !== -1)
return null;
}
else if (loweredAttr === 'xlink:href' &&
domProcessor.SVG_XLINK_HREF_TAGS.indexOf(tagName) !== -1 &&
isSVGElement(el)) {
var storedXLinkHrefAttr = DomProcessor.getStoredAttrName(attr);
setAttrMeth.apply(el, isNs ? [ns, storedXLinkHrefAttr, value] : [storedXLinkHrefAttr, value]);
if (!HASH_RE$1.test(value))
args[valueIndex] = getProxyUrl(value);
}
else if (loweredAttr === 'style')
args[valueIndex] = styleProcessor.process(value, getProxyUrl);
else if (!isNs && loweredAttr === 'integrity' && DomProcessor.isTagWithIntegrityAttr(tagName)) {
var storedIntegrityAttr = DomProcessor.getStoredAttrName(attr);
return setAttrMeth.apply(el, [storedIntegrityAttr, value]);
}
else if (!isNs && loweredAttr === 'rel' && tagName === 'link') {
var currentValue = nativeMethods.getAttribute.call(el, 'rel');
var formatedValue = trim$1(value.toLowerCase());
var storedRelAttr = DomProcessor.getStoredAttrName(attr);
needToRecalcHref = value !== currentValue && (value === domProcessor.MODULE_PRELOAD_LINK_REL ||
currentValue === domProcessor.MODULE_PRELOAD_LINK_REL);
if (formatedValue === 'prefetch') {
nativeMethods.removeAttribute.call(el, attr);
args[0] = storedRelAttr;
}
else
nativeMethods.removeAttribute.call(el, storedRelAttr);
}
else if (!isNs && loweredAttr === 'as' && tagName === 'link') {
var currentValue = nativeMethods.getAttribute.call(el, 'as');
needToRecalcHref = value !== currentValue && (value === domProcessor.PROCESSED_PRELOAD_LINK_CONTENT_TYPE ||
currentValue === domProcessor.PROCESSED_PRELOAD_LINK_CONTENT_TYPE);
}
else if (!isNs && loweredAttr === 'required' && isFileInput(el)) {
var storedRequiredAttr = DomProcessor.getStoredAttrName(attr);
nativeMethods.removeAttribute.call(el, attr);
args[0] = storedRequiredAttr;
}
else if (!isNs && loweredAttr === 'type' && isInputElement(el)) {
var currentType = nativeMethods.getAttribute.call(el, loweredAttr);
var newType = value.toLowerCase();
var storedRequiredAttr = DomProcessor.getStoredAttrName('required');
var currentRequired = nativeMethods.hasAttribute.call(el, storedRequiredAttr)
? nativeMethods.getAttribute.call(el, storedRequiredAttr)
: nativeMethods.getAttribute.call(el, 'required');
var typeIsChanged = !currentType || newType !== currentType.toLowerCase();
if (typeIsChanged && currentRequired !== null) {
if (newType === 'file') {
nativeMethods.setAttribute.call(el, storedRequiredAttr, currentRequired);
nativeMethods.removeAttribute.call(el, 'required');
}
else if (currentType === 'file') {
nativeMethods.setAttribute.call(el, 'required', currentRequired);
nativeMethods.removeAttribute.call(el, storedRequiredAttr);
}
}
}
else if (!isNs && loweredAttr === 'srcdoc' && tagName === 'iframe') {
var storedAttr = DomProcessor.getStoredAttrName(attr);
setAttrMeth.apply(el, [storedAttr, value]);
args[valueIndex] = domProcessor.adapter.processSrcdocAttr(value);
}
var result = setAttrMeth.apply(el, args);
if (tagName === 'img' && !el[INTERNAL_PROPS.forceProxySrcForImage] && el.complete && !isFirefox) // eslint-disable-line no-extra-parens
el[INTERNAL_PROPS.cachedImage] = true;
if (needToCallTargetChanged)
ElementSandbox._onTargetChanged(el);
if (needToRecalcHref && nativeMethods.hasAttribute.call(el, 'href'))
this.setAttributeCore(el, ['href', nativeMethods.getAttribute.call(el, 'href')]);
return result;
};
ElementSandbox.prototype._hasAttributeCore = function (el, args, isNs) {
var attributeNameArgIndex = isNs ? 1 : 0;
var hasAttrMeth = isNs ? nativeMethods.hasAttributeNS : nativeMethods.hasAttribute;
var storedAutocompleteAttrName = DomProcessor.getStoredAttrName('autocomplete');
var storedAutocompleteAttrValue = nativeMethods.getAttribute.call(el, storedAutocompleteAttrName);
var tagName = getTagName(el);
if (typeof args[attributeNameArgIndex] === 'string' &&
DomProcessor.isAddedAutocompleteAttr(args[attributeNameArgIndex], storedAutocompleteAttrValue))
return false;
// NOTE: We simply remove the 'integrity' attribute because its value will not be relevant after the script
// content changes (http://www.w3.org/TR/SRI/). If this causes problems in the future, we will need to generate
// the correct SHA for the changed script.
// _hasAttributeCore returns true for 'integrity' attribute if the stored attribute is exists. (GH-235)
else if (!isNs && args[0] === 'integrity' &&
DomProcessor.isTagWithIntegrityAttr(tagName))
args[0] = DomProcessor.getStoredAttrName('integrity');
// NOTE: We simply remove the 'rel' attribute if rel='prefetch' and use stored 'rel' attribute, because the prefetch
// resource type is unknown.
// _hasAttributeCore returns true for 'rel' attribute if the original 'rel' or stored attribute is exists.
// https://github.com/DevExpress/testcafe/issues/2528
else if (!isNs && args[0] === 'rel' && tagName === 'link') {
var storedRelAttr = DomProcessor.getStoredAttrName(args[0]);
return hasAttrMeth.apply(el, args) || hasAttrMeth.apply(el, [storedRelAttr]);
}
else if (!isNs && args[0] === 'required' && isFileInput(el)) {
var storedRequiredAttr = DomProcessor.getStoredAttrName(args[0]);
return hasAttrMeth.apply(el, args) || hasAttrMeth.call(el, storedRequiredAttr);
}
return hasAttrMeth.apply(el, args);
};
ElementSandbox._removeStoredAttrNode = function (node) {
var storedNode;
var storedAttr = DomProcessor.getStoredAttrName(node.name);
if (node.namespaceURI)
storedNode = nativeMethods.getAttributeNodeNS.call(this, node.namespaceURI, storedAttr);
else
storedNode = nativeMethods.getAttributeNode.call(this, storedAttr);
if (storedNode)
nativeMethods.removeAttributeNode.call(this, storedNode);
};
ElementSandbox.prototype.removeAttributeCore = function (el, args, isNsNode) {
var attr;
var node;
var removeStoredAttrFunc;
var isNs = isNsNode === AttributeType.Ns;
var isNode = isNsNode === AttributeType.Node;
if (isNode) {
node = args[0];
attr = node.name;
removeStoredAttrFunc = ElementSandbox._removeStoredAttrNode;
}
else {
attr = String(args[isNs ? 1 : 0]);
removeStoredAttrFunc = isNs ? nativeMethods.removeAttributeNS : nativeMethods.removeAttribute;
}
var formatedAttr = attr.toLowerCase();
var tagName = getTagName(el);
var result = void 0;
if (domProcessor.isUrlAttr(el, formatedAttr, isNs ? args[0] : null) || formatedAttr === 'sandbox' ||
formatedAttr === 'autocomplete' ||
domProcessor.EVENTS.indexOf(formatedAttr) !== -1 ||
formatedAttr === 'target' && DomProcessor.isTagWithTargetAttr(tagName) ||
formatedAttr === 'formtarget' && DomProcessor.isTagWithFormTargetAttr(tagName)) {
var storedAttr = DomProcessor.getStoredAttrName(attr);
if (formatedAttr === 'autocomplete')
nativeMethods.setAttribute.call(el, storedAttr, domProcessor.AUTOCOMPLETE_ATTRIBUTE_ABSENCE_MARKER);
else
removeStoredAttrFunc.apply(el, isNs ? [args[0], storedAttr] : [isNode ? node : storedAttr]);
}
else if (!isNs && formatedAttr === 'rel' && tagName === 'link') {
var storedRelAttr = DomProcessor.getStoredAttrName(attr);
removeStoredAttrFunc.apply(el, [isNode ? node : storedRelAttr]);
}
else if (!isNs && formatedAttr === 'required' && isFileInput(el)) {
var storedRequiredAttr = DomProcessor.getStoredAttrName(attr);
removeStoredAttrFunc.call(el, isNode ? node : storedRequiredAttr);
}
else if (!isNs && formatedAttr === 'type' && isInputElement(el)) {
var storedRequiredAttr = DomProcessor.getStoredAttrName('required');
if (nativeMethods.hasAttribute.call(el, storedRequiredAttr)) {
var currentRequired = nativeMethods.getAttribute.call(el, storedRequiredAttr);
nativeMethods.setAttribute.call(el, 'required', currentRequired);
nativeMethods.removeAttribute.call(el, storedRequiredAttr);
}
}
if (ElementSandbox._isHrefAttrForBaseElement(el, formatedAttr))
urlResolver.updateBase(get$2(), this.document);
if (formatedAttr !== 'autocomplete') {
if (isNode) {
var removeArgs = [nativeMethods.getAttributeNodeNS.call(el, node.namespaceURI, node.name)];
for (var i = 1, ilen = args.length; i < ilen; ++i)
removeArgs.push(args[i]);
result = nativeMethods.removeAttributeNode.apply(el, removeArgs);
}
else {
var removeAttrFunc = isNs ? nativeMethods.removeAttributeNS : nativeMethods.removeAttribute;
result = removeAttrFunc.apply(el, args);
}
}
if (formatedAttr === 'target' && DomProcessor.isTagWithTargetAttr(tagName) ||
formatedAttr === 'formtarget' && DomProcessor.isTagWithFormTargetAttr(tagName))
ElementSandbox._onTargetChanged(el);
return result;
};
ElementSandbox._getChildNodesArray = function (args, range) {
var result = [];
var start = range[0], end = range[1];
if (args.length === 0)
return result;
for (var i = start; i < end; i++) {
var node = args[i];
if (isDocumentFragmentNode(node)) {
var childNodes = nativeMethods.nodeChildNodesGetter.call(node);
result.push.apply(result, nodeListToArray(childNodes));
}
else if (typeof node !== 'string')
result.push(node);
}
return result;
};
ElementSandbox._ensureStringArguments = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var result = [];
for (var i = 0; i < args.length; i++)
result.push(String(args[i]));
return result;
};
ElementSandbox.prototype._addNodeCore = function (parent, context, newNodesRange, args, nativeFn, checkBody, stringifyNode) {
if (checkBody === void 0) { checkBody = true; }
if (stringifyNode === void 0) { stringifyNode = false; }
this._prepareNodesForInsertion(args, newNodesRange, parent, stringifyNode);
var result = null;
var childNodesArray = ElementSandbox._getChildNodesArray(args, newNodesRange);
// NOTE: Before the page's <body> is processed and added to DOM,
// some javascript frameworks create their own body element, perform
// certain manipulations and then remove it.
// Therefore, we need to check if the body element is present in DOM
if (checkBody && isBodyElementWithChildren(parent) && isElementInDocument(parent)) {
var newNodes = nativeMethods.arraySlice.apply(args, newNodesRange);
result = this._shadowUI.insertBeforeRoot(newNodes);
}
else
result = nativeFn.apply(context, args);
for (var _i = 0, childNodesArray_1 = childNodesArray; _i < childNodesArray_1.length; _i++) {
var child = childNodesArray_1[_i];
this._onElementAdded(child);
}
return result;
};
ElementSandbox.prototype._removeNodeCore = function (context, args, removingNode, nativeFn) {
this._onRemoveFileInputInfo(removingNode);
this._onRemoveIframe(removingNode);
var result = nativeFn.apply(context, args);
this._onElementRemoved(removingNode);
return result;
};
ElementSandbox.prototype._prepareNodesForInsertion = function (args, newNodesRange, parentNode, stringifyNode) {
if (stringifyNode === void 0) { stringifyNode = false; }
if (args.length === 0)
return;
var start = newNodesRange[0], end = newNodesRange[1];
for (var i = start; i < end; i++) {
var node = args[i];
if (isTextNode(node))
node.data = ElementSandbox._processTextContent(node.data, parentNode);
else if (isDomElement(node) ||
isDocumentFragmentNode(node) ||
isCommentNode(node))
this._nodeSandbox.processNodes(node);
else {
if (stringifyNode)
node = String(node);
if (typeof node === 'string')
args[i] = ElementSandbox._processTextContent(node, parentNode);
}
}
};
ElementSandbox.prototype._insertAdjacentTextOrElement = function (context, args, nativeFn) {
var _a, _b;
var position = (_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase) === null || _b === void 0 ? void 0 : _b.call(_a);
var parent = position === InsertPosition$1.beforeBegin || position === InsertPosition$1.afterEnd
? nativeMethods.nodeParentNodeGetter.call(context)
: context;
if (!parent)
return nativeMethods.insertAdjacentElement.apply(context, args);
return this._addNodeCore(parent, context, [1, 2], args, nativeFn, position === InsertPosition$1.beforeEnd);
};
ElementSandbox.prototype._createOverriddenMethods = function () {
// NOTE: We need the closure because a context of overridden methods is an html element
var sandbox = this;
this.overriddenMethods = {
appendData: function (text) {
var parentNode = nativeMethods.nodeParentNodeGetter.call(this);
nativeMethods.nodeTextContentSetter.call(this, nativeMethods.nodeTextContentGetter.call(this) + text);
if (parentNode)
this.data = ElementSandbox._processTextContent(this.data, parentNode);
},
insertRow: function () {
var nativeMeth = isTableElement(this)
? nativeMethods.insertTableRow
: nativeMethods.insertTBodyRow;
var row = nativeMeth.apply(this, arguments);
sandbox._nodeSandbox.processNodes(row);
return row;
},
insertCell: function () {
var cell = nativeMethods.insertCell.apply(this, arguments);
sandbox._nodeSandbox.processNodes(cell);
return cell;
},
insertAdjacentHTML: function () {
var _a, _b;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var position = (_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase) === null || _b === void 0 ? void 0 : _b.call(_a);
var html = args[1];
var parent = position === InsertPosition$1.beforeBegin || position === InsertPosition$1.afterEnd
? nativeMethods.nodeParentNodeGetter.call(this)
: this;
if (args.length > 1 && html !== null && parent) {
args[1] = processHtml(String(html), {
parentTag: parent['tagName'],
processedContext: parent[INTERNAL_PROPS.processedContext],
});
}
nativeMethods.insertAdjacentHTML.apply(this, args);
if (!parent)
return;
sandbox._nodeSandbox.processNodes(parent);
domMutationTracker.onChildrenChanged(parent);
},
insertAdjacentElement: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._insertAdjacentTextOrElement(this, args, nativeMethods.insertAdjacentElement);
},
insertAdjacentText: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var _a = ElementSandbox._ensureStringArguments.apply(ElementSandbox, args), where = _a[0], data = _a[1];
return sandbox._insertAdjacentTextOrElement(this, [where, data], nativeMethods.insertAdjacentText);
},
formSubmit: function () {
sandbox._ensureTargetContainsExistingBrowsingContext(this);
var args = { form: this, preventSubmit: false };
sandbox.emit(sandbox.BEFORE_FORM_SUBMIT_EVENT, args);
// HACK: For https://github.com/DevExpress/testcafe/issues/3560
// We have to cancel every form submit after a test is done
// to prevent requests to a closed session
if (!args.preventSubmit)
return nativeMethods.formSubmit.apply(this, arguments);
return null;
},
insertBefore: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._addNodeCore(this, this, [0, 1], args, nativeMethods.insertBefore, !args[1]);
},
appendChild: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._addNodeCore(this, this, [0, 1], args, nativeMethods.appendChild);
},
append: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._addNodeCore(this, this, [0, args.length], args, nativeMethods.append, true, true);
},
prepend: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._addNodeCore(this, this, [0, args.length], args, nativeMethods.prepend, false);
},
after: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var parent = nativeMethods.nodeParentNodeGetter.call(this);
if (!parent)
return nativeMethods.after.apply(this, args);
return sandbox._addNodeCore(parent, this, [0, args.length], args, nativeMethods.after, false);
},
removeChild: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._removeNodeCore(this, args, args[0], nativeMethods.removeChild);
},
remove: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return sandbox._removeNodeCore(this, args, this, nativeMethods.remove);
},
elementReplaceWith: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var parentNode = nativeMethods.nodeParentNodeGetter.call(this);
if (!parentNode)
return nativeMethods.elementReplaceWith.apply(this, args);
var newNodesRange = [0, args.length];
sandbox._prepareNodesForInsertion(args, newNodesRange, parentNode);
var childNodesArray = ElementSandbox._getChildNodesArray(args, newNodesRange);
sandbox._onRemoveFileInputInfo(this);
sandbox._onRemoveIframe(this);
var result = nativeMethods.elementReplaceWith.apply(this, args);
sandbox._onElementRemoved(this);
for (var _a = 0, childNodesArray_2 = childNodesArray; _a < childNodesArray_2.length; _a++) {
var child = childNodesArray_2[_a];
sandbox._onElementAdded(child);
}
return result;
},
replaceChild: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var newChild = args[0], oldChild = args[1];
if (isTextNode(newChild))
newChild.data = ElementSandbox._processTextContent(newChild.data, this);
sandbox._onRemoveFileInputInfo(oldChild);
var result = nativeMethods.replaceChild.apply(this, arguments);
sandbox._onAddFileInputInfo(newChild);
domMutationTracker.onElementChanged(newChild);
domMutationTracker.onElementChanged(oldChild);
return result;
},
cloneNode: function () {
var clone = nativeMethods.cloneNode.apply(this, arguments);
sandbox._nodeSandbox.processNodes(clone);
return clone;
},
attachShadow: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var root = nativeMethods.attachShadow.apply(this, args);
nativeMethods.objectDefineProperty(root, SHADOW_ROOT_PARENT_ELEMENT, { value: this });
return root;
},
getAttribute: function () {
return sandbox.getAttributeCore(this, arguments);
},
getAttributeNS: function () {
return sandbox.getAttributeCore(this, arguments, true);
},
setAttribute: function () {
var result = sandbox.setAttributeCore(this, arguments);
refreshAttributesWrapper(this);
return result;
},
setAttributeNS: function () {
var result = sandbox.setAttributeCore(this, arguments, true);
refreshAttributesWrapper(this);
return result;
},
removeAttribute: function () {
var result = sandbox.removeAttributeCore(this, arguments);
refreshAttributesWrapper(this);
return result;
},
removeAttributeNS: function () {
var result = sandbox.removeAttributeCore(this, arguments, AttributeType.Ns);
refreshAttributesWrapper(this);
return result;
},
removeAttributeNode: function () {
var result = sandbox.removeAttributeCore(this, arguments, AttributeType.Node);
refreshAttributesWrapper(this);
return result;
},
querySelector: function () {
if (typeof arguments[0] === 'string')
arguments[0] = NodeSandbox$1.processSelector(arguments[0]);
return getNativeQuerySelector(this).apply(this, arguments);
},
querySelectorAll: function () {
if (typeof arguments[0] === 'string')
arguments[0] = NodeSandbox$1.processSelector(arguments[0]);
return getNativeQuerySelectorAll(this).apply(this, arguments);
},
hasAttribute: function () {
return sandbox._hasAttributeCore(this, arguments, false);
},
hasAttributeNS: function () {
return sandbox._hasAttributeCore(this, arguments, true);
},
hasAttributes: function () {
if (nativeMethods.elementAttributesGetter.call(this).length === 2 &&
nativeMethods.elementAttributesGetter.call(this).getNamedItem('autocomplete') &&
nativeMethods.elementAttributesGetter.call(this).getNamedItem(DomProcessor.getStoredAttrName('autocomplete')))
return sandbox._hasAttributeCore(this, ['autocomplete'], false);
return nativeMethods.hasAttributes.apply(this, arguments);
},
anchorToString: function () {
return getDestinationUrl(nativeMethods.anchorToString.call(this));
},
registerElement: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var opts = args[1];
if (opts && opts.prototype && opts.prototype.createdCallback) {
var storedCreatedCallback_1 = opts.prototype.createdCallback;
opts.prototype.createdCallback = function () {
if (!isInternalHtmlParserElement(this))
storedCreatedCallback_1.call(this);
};
}
return nativeMethods.registerElement.apply(this, args);
},
};
};
ElementSandbox._processTextContent = function (str, parentNode) {
if (!parentNode['tagName'])
return str;
if (isScriptElement(parentNode))
return processScript(str, true, false, convertToProxyUrl, void 0, settings.get().proxyless);
if (isStyleElement(parentNode))
return styleProcessor.process(str, getProxyUrl);
return str;
};
ElementSandbox._isHrefAttrForBaseElement = function (el, attr) {
return isBaseElement(el) && attr === 'href';
};
ElementSandbox._removeFileInputInfo = function (el) {
removeInputInfo(el);
};
ElementSandbox._hasShadowUIParentOrContainsShadowUIClassPostfix = function (el) {
var parent = nativeMethods.nodeParentNodeGetter.call(el);
return parent && isShadowUIElement(parent) || ShadowUISandbox.containsShadowUIClassPostfix(el);
};
ElementSandbox.prototype._isFirstBaseTagOnPage = function (el) {
var doc = el.ownerDocument || this.document;
return nativeMethods.querySelector.call(doc, 'base') === el;
};
ElementSandbox.prototype._onAddFileInputInfo = function (el) {
if (!isDomElement(el))
return;
var fileInputs = getFileInputs(el);
for (var _i = 0, fileInputs_1 = fileInputs; _i < fileInputs_1.length; _i++) {
var fileInput = fileInputs_1[_i];
this.addFileInputInfo(fileInput);
}
};
ElementSandbox.prototype._onRemoveFileInputInfo = function (el) {
if (!isDomElement(el))
return;
if (isFileInput(el))
ElementSandbox._removeFileInputInfo(el);
else
find(el, 'input[type=file]', ElementSandbox._removeFileInputInfo);
};
ElementSandbox.prototype._onRemoveIframe = function (el) {
if (isDomElement(el) && isIframeElement(el))
remove(nativeMethods.contentWindowGetter.call(el));
};
ElementSandbox.prototype._onElementAdded = function (el) {
if (ElementSandbox._hasShadowUIParentOrContainsShadowUIClassPostfix(el))
ShadowUISandbox.markElementAndChildrenAsShadow(el);
if ((isDomElement(el) || isDocument(el)) && isElementInDocument(el)) {
var iframes = getIframes(el);
for (var _i = 0, iframes_1 = iframes; _i < iframes_1.length; _i++) {
var iframe = iframes_1[_i];
this.onIframeAddedToDOM(iframe);
}
var scripts = getScripts(el);
for (var _a = 0, scripts_1 = scripts; _a < scripts_1.length; _a++) {
var script = scripts_1[_a];
this.emit(this.SCRIPT_ELEMENT_ADDED_EVENT, { el: script });
}
domMutationTracker.onElementChanged(el);
}
// NOTE: recalculate `formaction` attribute value if it placed in the dom
if ((isInputElement(el) || isButtonElement(el)) && el.form &&
nativeMethods.hasAttribute.call(el, 'formaction'))
el.setAttribute('formaction', el.getAttribute('formaction'));
if (isBodyElement(el))
this._shadowUI.onBodyElementMutation();
this._onAddFileInputInfo(el);
if (isBaseElement(el) && this._isFirstBaseTagOnPage(el)) {
var storedHrefAttrName = DomProcessor.getStoredAttrName('href');
var storedHrefAttrValue = el.getAttribute(storedHrefAttrName);
if (storedHrefAttrValue !== null)
urlResolver.updateBase(storedHrefAttrValue, this.document);
}
};
ElementSandbox.prototype._onElementRemoved = function (el) {
if (isBodyElement(el))
this._shadowUI.onBodyElementMutation();
else if (isBaseElement(el)) {
var firstBaseEl = nativeMethods.querySelector.call(this.document, 'base');
var storedHrefAttr = firstBaseEl && firstBaseEl.getAttribute(DomProcessor.getStoredAttrName('href'));
urlResolver.updateBase(storedHrefAttr || get$2(), this.document);
}
domMutationTracker.onElementChanged(el);
};
ElementSandbox.prototype._reprocessElementsAssociatedWithIframe = function (iframe) {
if (!iframe.name)
return;
var escapedIframeName = iframe.name.replace(/"/g, '\\"');
var elementsWithTarget = nativeMethods.querySelectorAll.call(this.document, "*[target=\"".concat(escapedIframeName, "\"]"));
for (var _i = 0, elementsWithTarget_1 = elementsWithTarget; _i < elementsWithTarget_1.length; _i++) {
var el = elementsWithTarget_1[_i];
this._reprocessElementAssociatedWithIframe(el);
}
};
ElementSandbox.prototype._reprocessElementAssociatedWithIframe = function (el) {
var urlAttrName = domProcessor.getUrlAttr(el);
var storedUrlAttrName = DomProcessor.getStoredAttrName(urlAttrName);
nativeMethods.removeAttribute.call(el, storedUrlAttrName);
DomProcessor.setElementProcessed(el, false);
domProcessor.processElement(el, convertToProxyUrl);
};
ElementSandbox.prototype.addFileInputInfo = function (el) {
var infoManager = this._uploadSandbox.infoManager;
addInputInfo(el, infoManager.getFiles(el), infoManager.getValue(el));
};
ElementSandbox.prototype.onIframeAddedToDOM = function (iframe) {
if (!isCrossDomainIframe(iframe, true))
this._nodeSandbox.mutation.onIframeAddedToDOM(iframe);
add(nativeMethods.contentWindowGetter.call(iframe));
this._reprocessElementsAssociatedWithIframe(iframe);
};
ElementSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
this._createOverriddenMethods();
overrideFunction(window.Element.prototype, 'setAttribute', this.overriddenMethods.setAttribute);
overrideFunction(window.Element.prototype, 'setAttributeNS', this.overriddenMethods.setAttributeNS);
overrideFunction(window.Element.prototype, 'getAttribute', this.overriddenMethods.getAttribute);
overrideFunction(window.Element.prototype, 'getAttributeNS', this.overriddenMethods.getAttributeNS);
overrideFunction(window.Element.prototype, 'removeAttribute', this.overriddenMethods.removeAttribute);
overrideFunction(window.Element.prototype, 'removeAttributeNS', this.overriddenMethods.removeAttributeNS);
overrideFunction(window.Element.prototype, 'removeAttributeNode', this.overriddenMethods.removeAttributeNode);
overrideFunction(window.Element.prototype, 'cloneNode', this.overriddenMethods.cloneNode);
overrideFunction(window.Element.prototype, 'querySelector', this.overriddenMethods.querySelector);
overrideFunction(window.Element.prototype, 'querySelectorAll', this.overriddenMethods.querySelectorAll);
overrideFunction(window.Element.prototype, 'hasAttribute', this.overriddenMethods.hasAttribute);
overrideFunction(window.Element.prototype, 'hasAttributeNS', this.overriddenMethods.hasAttributeNS);
overrideFunction(window.Element.prototype, 'hasAttributes', this.overriddenMethods.hasAttributes);
if (nativeMethods.attachShadow)
overrideFunction(window.Element.prototype, 'attachShadow', this.overriddenMethods.attachShadow);
overrideFunction(window.Node.prototype, 'cloneNode', this.overriddenMethods.cloneNode);
overrideFunction(window.Node.prototype, 'appendChild', this.overriddenMethods.appendChild);
overrideFunction(window.Node.prototype, 'removeChild', this.overriddenMethods.removeChild);
overrideFunction(window.Node.prototype, 'insertBefore', this.overriddenMethods.insertBefore);
overrideFunction(window.Node.prototype, 'replaceChild', this.overriddenMethods.replaceChild);
if (nativeMethods.append)
overrideFunction(window.Element.prototype, 'append', this.overriddenMethods.append);
if (nativeMethods.prepend)
overrideFunction(window.Element.prototype, 'prepend', this.overriddenMethods.prepend);
if (nativeMethods.after)
overrideFunction(window.Element.prototype, 'after', this.overriddenMethods.after);
if (nativeMethods.remove)
overrideFunction(window.Element.prototype, 'remove', this.overriddenMethods.remove);
if (nativeMethods.elementReplaceWith)
overrideFunction(window.Element.prototype, 'replaceWith', this.overriddenMethods.elementReplaceWith);
overrideFunction(window.DocumentFragment.prototype, 'querySelector', this.overriddenMethods.querySelector);
overrideFunction(window.DocumentFragment.prototype, 'querySelectorAll', this.overriddenMethods.querySelectorAll);
overrideFunction(window.HTMLTableElement.prototype, 'insertRow', this.overriddenMethods.insertRow);
overrideFunction(window.HTMLTableSectionElement.prototype, 'insertRow', this.overriddenMethods.insertRow);
overrideFunction(window.HTMLTableRowElement.prototype, 'insertCell', this.overriddenMethods.insertCell);
overrideFunction(window.HTMLFormElement.prototype, 'submit', this.overriddenMethods.formSubmit);
overrideFunction(window.HTMLAnchorElement.prototype, 'toString', this.overriddenMethods.anchorToString);
overrideFunction(window.CharacterData.prototype, 'appendData', this.overriddenMethods.appendData);
if (window.Document.prototype.registerElement)
overrideFunction(window.Document.prototype, 'registerElement', this.overriddenMethods.registerElement);
overrideFunction(nativeMethods.insertAdjacentMethodsOwner, 'insertAdjacentHTML', this.overriddenMethods.insertAdjacentHTML);
overrideFunction(nativeMethods.insertAdjacentMethodsOwner, 'insertAdjacentElement', this.overriddenMethods.insertAdjacentElement);
overrideFunction(nativeMethods.insertAdjacentMethodsOwner, 'insertAdjacentText', this.overriddenMethods.insertAdjacentText);
this._setValidBrowsingContextOnElementClick(window);
// NOTE: Cookie can be set up for the page by using the request initiated by img.
// For example: img.src = '<url that responds with the Set-Cookie header>'
// If img has the 'load' event handler, we redirect the request through proxy.
// For details, see https://github.com/DevExpress/testcafe-hammerhead/issues/651
this._eventSandbox.listeners.on(this._eventSandbox.listeners.EVENT_LISTENER_ATTACHED_EVENT, function (e) {
if (e.eventType === 'load' && isImgElement(e.el))
ElementSandbox._setProxiedSrc(e.el);
});
overrideDescriptor(window.HTMLElement.prototype, 'onload', {
getter: null,
setter: function (handler) {
if (isImgElement(this) && isValidEventListener(handler))
ElementSandbox._setProxiedSrc(this);
nativeMethods.htmlElementOnloadSetter.call(this, handler);
},
});
};
ElementSandbox.prototype._ensureTargetContainsExistingBrowsingContext = function (el) {
if (settings.get().allowMultipleWindows)
return;
if (!nativeMethods.hasAttribute.call(el, 'target'))
return;
var attr = nativeMethods.getAttribute.call(el, 'target');
var storedAttr = nativeMethods.getAttribute.call(el, DomProcessor.getStoredAttrName('target'));
el.setAttribute('target', storedAttr || attr);
};
ElementSandbox.prototype._setValidBrowsingContextOnElementClick = function (window) {
var _this = this;
this._eventSandbox.listeners.initElementListening(window, ['click']);
this._eventSandbox.listeners.addInternalEventBeforeListener(window, ['click'], function (e) {
var el = nativeMethods.eventTargetGetter.call(e);
if (isInputElement(el) && el.form)
el = el.form;
var tagName = getTagName(el);
if (!DomProcessor.isTagWithTargetAttr(tagName))
return;
_this._ensureTargetContainsExistingBrowsingContext(el);
});
};
ElementSandbox.prototype._setProxiedSrcUrlOnError = function (img) {
img.addEventListener('error', function (e) {
var storedAttr = nativeMethods.getAttribute.call(img, DomProcessor.getStoredAttrName('src'));
var imgSrc = nativeMethods.imageSrcGetter.call(img);
if (storedAttr && !parseProxyUrl(imgSrc) &&
isSupportedProtocol(imgSrc) && !isSpecialPage(imgSrc)) {
nativeMethods.setAttribute.call(img, 'src', getProxyUrl(storedAttr));
stopPropagation(e);
}
}, false);
};
ElementSandbox.prototype.getCorrectedTarget = function (target) {
if (target === void 0) { target = ''; }
if (settings.get().allowMultipleWindows)
return target;
if (target && !isKeywordTarget(target) && !findByName(target) ||
/_blank/i.test(target))
return '_top';
return target;
};
ElementSandbox.prototype._handleImageLoadEventRaising = function (el) {
if (this.proxyless)
return;
this._eventSandbox.listeners.initElementListening(el, ['load']);
this._eventSandbox.listeners.addInternalEventBeforeListener(el, ['load'], function (_e, _dispatched, preventEvent, _cancelHandlers, stopEventPropagation) {
if (el[INTERNAL_PROPS.cachedImage])
el[INTERNAL_PROPS.cachedImage] = false;
if (!el[INTERNAL_PROPS.skipNextLoadEventForImage])
return;
el[INTERNAL_PROPS.skipNextLoadEventForImage] = false;
preventEvent();
stopEventPropagation();
});
if (!el[INTERNAL_PROPS.forceProxySrcForImage] && !settings.get().forceProxySrcForImage)
this._setProxiedSrcUrlOnError(el);
};
ElementSandbox.prototype._processBaseTag = function (el) {
if (!this._isFirstBaseTagOnPage(el))
return;
var storedUrlAttr = nativeMethods.getAttribute.call(el, DomProcessor.getStoredAttrName('href'));
if (storedUrlAttr !== null)
urlResolver.updateBase(storedUrlAttr, el.ownerDocument || this.document);
};
ElementSandbox.prototype._reProcessElementWithTargetAttr = function (el, tagName) {
var targetAttr = domProcessor.getTargetAttr(el);
if (DomProcessor.isIframeFlagTag(tagName) && nativeMethods.getAttribute.call(el, targetAttr) === '_parent')
domProcessor.processElement(el, convertToProxyUrl);
};
ElementSandbox.prototype.processElement = function (el) {
var tagName = getTagName(el);
switch (tagName) {
case 'a':
this._childWindowSandbox.handleClickOnLinkOrArea(el);
break;
case 'img':
this._handleImageLoadEventRaising(el);
break;
case 'iframe':
case 'frame':
this._iframeSandbox.processIframe(el);
break;
case 'base':
this._processBaseTag(el);
break;
case 'area':
this._childWindowSandbox.handleClickOnLinkOrArea(el);
break;
}
// NOTE: we need to reprocess a tag client-side if it wasn't processed on the server.
// See the usage of Parse5DomAdapter.needToProcessUrl
this._reProcessElementWithTargetAttr(el, tagName);
};
return ElementSandbox;
}(SandboxBase));
var DEFAULT_TITLE_VALUE = '';
// NOTE: Hammehead always add the <title> element for each test before test execution.
// It's necessary to TestCafe can find the browser tab by page title.
// This <title> element stores the sandboxed title value in the internal property.
var INTERNAL_TITLE_PROP_NAME = 'hammerhead|document-title-storage|internal-prop-name';
var DocumentTitleStorage = /** @class */ (function (_super) {
__extends(DocumentTitleStorage, _super);
function DocumentTitleStorage(document) {
var _this = _super.call(this) || this;
_this._document = document;
return _this;
}
DocumentTitleStorage.prototype._ensureFirstTitleElement = function () {
var firstTitle = this.getFirstTitleElement();
if (firstTitle)
return firstTitle;
firstTitle = nativeMethods.createElement.call(this._document, 'title');
nativeMethods.appendChild.call(this._document.head, firstTitle);
this.emit('titleElementAdded');
return firstTitle;
};
DocumentTitleStorage.prototype._getValueFromFirstTitleElement = function () {
var firstTitle = this.getFirstTitleElement();
if (!firstTitle)
return DEFAULT_TITLE_VALUE;
return this.getTitleElementPropertyValue(firstTitle);
};
DocumentTitleStorage.prototype._setValueForFirstTitleElement = function (value) {
var firstTitle = this._ensureFirstTitleElement();
this.setTitleElementPropertyValue(firstTitle, value);
};
DocumentTitleStorage.prototype._getTitleElement = function (index) {
return this._document &&
this._document.head &&
nativeMethods.elementQuerySelectorAll.call(this._document.head, 'title')[index];
};
DocumentTitleStorage.prototype.getFirstTitleElement = function () {
return this._getTitleElement(0);
};
DocumentTitleStorage.prototype.getSecondTitleElement = function () {
return this._getTitleElement(1);
};
DocumentTitleStorage.prototype.getTitle = function () {
return this._getValueFromFirstTitleElement();
};
DocumentTitleStorage.prototype.setTitle = function (value) {
value = String(value);
this._setValueForFirstTitleElement(value);
};
DocumentTitleStorage.prototype.getTitleElementPropertyValue = function (element) {
return element[INTERNAL_TITLE_PROP_NAME] || DEFAULT_TITLE_VALUE;
};
DocumentTitleStorage.prototype.setTitleElementPropertyValue = function (element, value) {
value = String(value);
if (this.isElementProcessed(element))
element[INTERNAL_TITLE_PROP_NAME] = value;
else {
nativeMethods.objectDefineProperty(element, INTERNAL_TITLE_PROP_NAME, {
value: value,
writable: true,
});
}
};
DocumentTitleStorage.prototype.getDocument = function () {
return this._document;
};
DocumentTitleStorage.prototype.isElementProcessed = function (titleElement) {
return INTERNAL_TITLE_PROP_NAME in titleElement;
};
Object.defineProperty(DocumentTitleStorage, "DEFAULT_TITLE_VALUE", {
get: function () {
return DEFAULT_TITLE_VALUE;
},
enumerable: false,
configurable: true
});
return DocumentTitleStorage;
}(EventEmitter));
var DocumentTitleStorageInitializer = /** @class */ (function () {
function DocumentTitleStorageInitializer(storage) {
var _this = this;
this.storage = storage;
this.storage.on('titleElementAdded', function () { return _this._processFirstTitleElement(); });
}
DocumentTitleStorageInitializer.prototype._setProxiedTitleValue = function () {
var _a = settings.get(), sessionId = _a.sessionId, windowId = _a.windowId;
var value = "".concat(sessionId, "*").concat(windowId);
nativeMethods.documentTitleSetter.call(this.storage.getDocument(), value);
};
DocumentTitleStorageInitializer.prototype._processFirstTitleElement = function () {
var firstTitle = this.storage.getFirstTitleElement();
if (!firstTitle)
return false;
if (this.storage.isElementProcessed(firstTitle))
return false;
var value = nativeMethods.titleElementTextGetter.call(firstTitle);
this.storage.setTitleElementPropertyValue(firstTitle, value);
this._setProxiedTitleValue();
return true;
};
DocumentTitleStorageInitializer.prototype.onAttach = function () {
this._processFirstTitleElement();
};
DocumentTitleStorageInitializer.prototype.onPageTitleLoaded = function () {
if (this._processFirstTitleElement())
return;
var firstTitle = this.storage.getFirstTitleElement();
var secondTitle = this.storage.getSecondTitleElement();
if (!secondTitle)
return;
// NOTE: IE11 returns an empty string for the second <title> tag in the elements hierarchy.
var pageOriginValue = nativeMethods.titleElementTextGetter.call(secondTitle) ||
nativeMethods.htmlElementInnerTextGetter.call(secondTitle);
var serviceValue = nativeMethods.titleElementTextGetter.call(firstTitle);
nativeMethods.titleElementTextSetter.call(secondTitle, serviceValue);
removeElement(firstTitle);
this.storage.setTitleElementPropertyValue(secondTitle, pageOriginValue);
};
return DocumentTitleStorageInitializer;
}());
var ATTRIBUTE_SELECTOR_REG_EX = /\[([\w-]+)(\^?=.+?)]/g;
var ATTRIBUTE_OPERATOR_WITH_HASH_VALUE = /^\W+\s*#/;
var PSEUDO_CLASS_FOCUS_REG_EX = /\s*:focus\b/gi;
var PSEUDO_CLASS_HOVER_REG_EX = /:hover\b/gi;
// NOTE: for IE11 only
var DOCUMENT_FRAGMENT_NODE_TYPE = Node.DOCUMENT_FRAGMENT_NODE;
var NodeSandbox = /** @class */ (function (_super) {
__extends(NodeSandbox, _super);
function NodeSandbox(mutation, iframeSandbox, _eventSandbox, _uploadSandbox, shadowUI, _cookieSandbox, _childWindowSandbox) {
var _this = _super.call(this) || this;
_this.mutation = mutation;
_this.iframeSandbox = iframeSandbox;
_this._eventSandbox = _eventSandbox;
_this._uploadSandbox = _uploadSandbox;
_this.shadowUI = shadowUI;
_this._cookieSandbox = _cookieSandbox;
_this._childWindowSandbox = _childWindowSandbox;
_this.raiseBodyCreatedEvent = _this._onBodyCreated;
// NOTE: We need to define the property with the 'writable' descriptor for testing purposes
nativeMethods.objectDefineProperty(document, INTERNAL_PROPS.documentCharset, {
value: parseDocumentCharset(),
writable: true,
});
_this._documentTitleStorageInitializer = NodeSandbox._createDocumentTitleStorageInitializer();
_this.doc = new DocumentSandbox(_this, _this.shadowUI, _this._cookieSandbox, _this.iframeSandbox, _this._documentTitleStorageInitializer);
_this.win = new WindowSandbox(_this, _this._eventSandbox, _this._uploadSandbox, _this.mutation, _this._childWindowSandbox, _this._documentTitleStorageInitializer);
_this.element = new ElementSandbox(_this, _this._uploadSandbox, _this.iframeSandbox, _this.shadowUI, _this._eventSandbox, _this._childWindowSandbox);
return _this;
}
NodeSandbox._createDocumentTitleStorageInitializer = function () {
if (isIframeWindow(window))
return null;
var documentTitleStorage = new DocumentTitleStorage(document);
return new DocumentTitleStorageInitializer(documentTitleStorage);
};
NodeSandbox.prototype._onBodyCreated = function () {
this._eventSandbox.listeners.initDocumentBodyListening(this.document);
this.mutation.onBodyCreated(this.document.body);
};
NodeSandbox.prototype._processElement = function (el) {
var processedContext = el[INTERNAL_PROPS.processedContext];
var isBaseUrlChanged = !!el[INTERNAL_PROPS.currentBaseUrl] &&
el[INTERNAL_PROPS.currentBaseUrl] !== urlResolver.getBaseUrl(this.document);
if (!isBaseUrlChanged && (isShadowUIElement(el) || processedContext === this.window))
return;
var urlAttrName = null;
if (processedContext) {
urlAttrName = domProcessor.getUrlAttr(el);
urlAttrName = urlAttrName && el.hasAttribute(urlAttrName) ? urlAttrName : null;
}
var canAddNewProp = nativeMethods.objectIsExtensible(el);
var canUpdateExistingProp = processedContext && !nativeMethods.objectIsFrozen(el);
if (canAddNewProp || canUpdateExistingProp) {
nativeMethods.objectDefineProperty(el, INTERNAL_PROPS.processedContext, {
value: this.window,
writable: true,
});
}
// NOTE: We need to reprocess url attribute of element, if it's moved to different window (GH-564)
// or a base element is added dynamically (GH-1965)
if (urlAttrName)
el.setAttribute(urlAttrName, el.getAttribute(urlAttrName));
if (isBaseUrlChanged)
delete el[INTERNAL_PROPS.currentBaseUrl];
this.element.processElement(el);
};
NodeSandbox.prototype.onOriginFirstTitleElementInHeadLoaded = function () {
if (this._documentTitleStorageInitializer)
this._documentTitleStorageInitializer.onPageTitleLoaded();
};
NodeSandbox.prototype.processNodes = function (el, doc) {
if (!el) {
doc = doc || this.document;
if (doc.documentElement)
this.processNodes(doc.documentElement);
}
else if (el.querySelectorAll) {
if (el.nodeType !== DOCUMENT_FRAGMENT_NODE_TYPE)
this._processElement(el);
var children = getNativeQuerySelectorAll(el).call(el, '*');
var length_1 = nativeMethods.nodeListLengthGetter.call(children);
for (var i = 0; i < length_1; i++)
this._processElement(children[i]);
}
};
// NOTE: DOM sandbox hides evidence of the content proxying from a page native script. Proxy replaces URLs for
// resources. Our goal is to make the native script think that all resources are fetched from the destination
// resource, not from proxy, and also provide proxying for dynamically created elements.
NodeSandbox.prototype.attach = function (window) {
var _this = this;
var document = window.document;
var domContentLoadedEventRaised = false;
_super.prototype.attach.call(this, window, document);
if (this._documentTitleStorageInitializer)
this._documentTitleStorageInitializer.onAttach();
this.iframeSandbox.on(this.iframeSandbox.IFRAME_DOCUMENT_CREATED_EVENT, function (_a) {
var iframe = _a.iframe;
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
// NOTE: Before overriding the iframe, we must restore native document methods.
// Therefore, we save them before they are overridden.
// @ts-ignore
var iframeNativeMethods = new _this.nativeMethods.constructor(contentDocument, contentWindow);
contentWindow[INTERNAL_PROPS.iframeNativeMethods] = iframeNativeMethods;
// NOTE: Override only the document (in fact, we only need the 'write' and 'writeln' methods).
_this.doc.attach(contentWindow, contentDocument, true);
});
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
nativeMethods.objectDefineProperty(window, INTERNAL_PROPS.processDomMethodName, {
value: function (el, doc) {
// NOTE: TestCafe creates a shadow-ui root before the DOMContentLoaded event (once document.body is
// available). Sometimes for a very heavy DOM or a very slow loading the body doesn't contain all
// elements at that moment and as a result after a full page loading our root element becomes not
// the last child of the body. So we need to make the root last body child manually on every script
// loading until the DOMContentLoaded event is raised.
if (!domContentLoadedEventRaised)
_this.shadowUI.onBodyElementMutation();
_this.processNodes(el, doc);
},
configurable: true,
});
// NOTE: In some browsers (for example Firefox), the 'window.document' object is different when iframe is
// created and when the documents ready event is raised. Therefore, we need to update the 'document' object
// to override its methods (Q527555).
document.addEventListener('DOMContentLoaded', function () {
domContentLoadedEventRaised = true;
_this.processNodes(null, document);
}, false);
this.doc.attach(window, document);
this.win.attach(window);
this.element.attach(window);
};
NodeSandbox._processAttributeSelector = function (selector) {
if (!ATTRIBUTE_SELECTOR_REG_EX.test(selector))
return selector;
return selector + ',' + selector.replace(ATTRIBUTE_SELECTOR_REG_EX, function (str, name, operatorWithValue) {
if (URL_ATTRS.indexOf(name) !== -1 &&
!ATTRIBUTE_OPERATOR_WITH_HASH_VALUE.test(operatorWithValue)) {
name = DomProcessor.getStoredAttrName(name);
return '[' + name + operatorWithValue + ']';
}
return str;
});
};
NodeSandbox._processPseudoClassSelectors = function (selector) {
// NOTE: When a selector that contains the ':focus' pseudo-class is used in the querySelector and
// querySelectorAll functions, these functions return an empty result if the browser is not focused.
// This replaces ':focus' with a custom CSS class to return the current active element in that case.
// IE returns a valid element, so there is no need to replace the selector for it.
if (!isIE)
selector = selector.replace(PSEUDO_CLASS_FOCUS_REG_EX, '[' + INTERNAL_ATTRIBUTES.focusPseudoClass + ']');
selector = selector.replace(PSEUDO_CLASS_HOVER_REG_EX, '[' + INTERNAL_ATTRIBUTES.hoverPseudoClass + ']');
return selector;
};
NodeSandbox.processSelector = function (selector) {
if (selector) {
selector = NodeSandbox._processPseudoClassSelectors(selector);
selector = NodeSandbox._processAttributeSelector(selector);
}
return selector;
};
return NodeSandbox;
}(SandboxBase));
var NodeSandbox$1 = NodeSandbox;
function getAreaElementRectangle(el, mapContainer) {
var shape = nativeMethods.getAttribute.call(el, 'shape');
var coords = nativeMethods.getAttribute.call(el, 'coords');
var i = 0;
if (shape === 'default')
return getElementRectangle(mapContainer);
if (!shape || !coords)
return null;
coords = coords.split(',');
if (!coords.length)
return null;
for (i = 0; i < coords.length; i++) {
coords[i] = parseInt(coords[i], 10);
if (typeof coords[i] !== 'number')
return null;
}
var rectangle = null;
switch (shape) {
case 'rect':
if (coords.length === 4) {
rectangle = {
height: coords[3] - coords[1],
left: coords[0],
top: coords[1],
width: coords[2] - coords[0],
};
}
break;
case 'circle':
if (coords.length === 3) {
rectangle = {
height: coords[2] * 2,
left: coords[0] - coords[2],
top: coords[1] - coords[2],
width: coords[2] * 2,
};
}
break;
case 'poly':
if (coords.length >= 6 && coords.length % 2 === 0) {
rectangle = {};
rectangle.left = rectangle.right = coords[0];
rectangle.top = rectangle.bottom = coords[1];
for (i = 2; i < coords.length; i += 2) {
rectangle.left = coords[i] < rectangle.left ? coords[i] : rectangle.left;
rectangle.right = coords[i] > rectangle.right ? coords[i] : rectangle.right;
}
for (i = 3; i < coords.length; i += 2) {
rectangle.top = coords[i] < rectangle.top ? coords[i] : rectangle.top;
rectangle.bottom = coords[i] > rectangle.bottom ? coords[i] : rectangle.bottom;
}
rectangle.height = rectangle.bottom - rectangle.top;
rectangle.width = rectangle.right - rectangle.left;
}
break;
}
if (rectangle) {
var containerOffset = getOffsetPosition(mapContainer);
rectangle.left += containerOffset.left;
rectangle.top += containerOffset.top;
}
return rectangle;
}
function getMapElementRectangle(el) {
var mapContainer = getMapContainer(el);
if (mapContainer) {
if (/^map$/i.test(el.tagName))
return getElementRectangle(mapContainer);
else if (/^area$/i.test(el.tagName)) {
var areaElementRectangle = getAreaElementRectangle(el, mapContainer);
if (areaElementRectangle)
return areaElementRectangle;
}
}
return {
height: 0,
left: 0,
top: 0,
width: 0,
};
}
function getSelectChildRectangle(el) {
var select = getSelectParent(el);
if (select) {
var selectRectangle = getElementRectangle(select);
var selectBorders = getBordersWidth(select);
var selectRightScrollbar = getInnerWidth(select) ===
select.clientWidth ? 0 : getScrollbarSize();
var optionHeight = getOptionHeight(select);
var optionRealIndex = getChildVisibleIndex(select, el);
var optionVisibleIndex = Math.max(optionRealIndex - getScrollTop(select) / optionHeight, 0);
return {
height: optionHeight,
left: selectRectangle.left + selectBorders.left,
top: selectRectangle.top + selectBorders.top + getElementPadding(select).top +
optionVisibleIndex * optionHeight,
width: selectRectangle.width - (selectBorders.left + selectBorders.right) - selectRightScrollbar,
};
}
return getElementRectangle(el);
}
function getSvgElementRelativeRectangle(el) {
var isSvgTextElement = matches(el, 'tspan') || matches(el, 'tref') ||
getTagName(el) === 'textpath';
var boundingClientRect = el.getBoundingClientRect();
var elementRect = {
height: !isSvgTextElement ? boundingClientRect.height : el.offsetHeight,
left: boundingClientRect.left + (document.body.scrollLeft || document.documentElement.scrollLeft),
top: boundingClientRect.top + (document.body.scrollTop || document.documentElement.scrollTop),
width: !isSvgTextElement ? boundingClientRect.width : el.offsetWidth,
};
if (isSvgTextElement) {
var offsetParent = getOffsetParent(el);
var elOffset = getOffset(el);
var offsetParentOffset = getOffset(offsetParent);
var offsetParentIsBody = matches(offsetParent, 'body');
return {
height: elementRect.height || boundingClientRect.height,
left: offsetParentIsBody ? el.offsetLeft || elOffset.left : offsetParentOffset.left + el.offsetLeft,
top: offsetParentIsBody ? el.offsetTop || elOffset.top : offsetParentOffset.top + el.offsetTop,
width: elementRect.width || boundingClientRect.width,
};
}
if (isFirefox || isIE)
return elementRect;
var strokeWidth = nativeMethods.getAttribute.call(el, 'stroke-width') || get$1(el, 'stroke-width');
// NOTE: We assume that the 'stroke-width' attribute can only be set in pixels.
strokeWidth = strokeWidth ? +strokeWidth.replace(/px|em|ex|pt|pc|cm|mm|in/, '') : 1;
if (strokeWidth && +strokeWidth % 2 !== 0)
strokeWidth = +strokeWidth + 1;
if ((matches(el, 'line') || matches(el, 'polyline') || matches(el, 'polygon') ||
matches(el, 'path')) &&
(!elementRect.width || !elementRect.height)) {
if (!elementRect.width && elementRect.height) {
elementRect.left -= strokeWidth / 2;
elementRect.width = strokeWidth;
}
else if (elementRect.width && !elementRect.height) {
elementRect.height = strokeWidth;
elementRect.top -= strokeWidth / 2;
}
}
else {
if (matches(el, 'polygon')) {
elementRect.height += 2 * strokeWidth;
elementRect.left -= strokeWidth;
elementRect.top -= strokeWidth;
elementRect.width += 2 * strokeWidth;
}
elementRect.height += strokeWidth;
elementRect.left -= strokeWidth / 2;
elementRect.top -= strokeWidth / 2;
elementRect.width += strokeWidth;
}
return elementRect;
}
function getElementRectangle(el) {
var rectangle = {};
if (isMapElement(el))
rectangle = getMapElementRectangle(el);
else if (isVisibleChild(el))
rectangle = getSelectChildRectangle(el);
else {
var elementOffset = getOffsetPosition(el);
var relativeRectangle = isSVGElementOrChild(el) ? getSvgElementRelativeRectangle(el) : el.getBoundingClientRect();
rectangle = {
height: relativeRectangle.height,
left: elementOffset.left,
top: elementOffset.top,
width: relativeRectangle.width,
};
}
rectangle.height = Math.round(rectangle.height);
rectangle.left = Math.round(rectangle.left);
rectangle.top = Math.round(rectangle.top);
rectangle.width = Math.round(rectangle.width);
return rectangle;
}
function shouldIgnoreEventInsideIframe(el, x, y) {
if (getTagName(el) !== 'iframe')
return false;
var rect = getElementRectangle(el);
var borders = getBordersWidth(el);
var padding = getElementPadding(el);
// NOTE: we detect element's 'content' position: left, right, top and bottom
// which does not consider borders and paddings, so we need to
// subtract it for right and bottom, and add for left and top
var left = rect.left + borders.left + padding.left;
var top = rect.top + borders.top + padding.top;
var right = rect.left + rect.width - borders.right - padding.right;
var bottom = rect.top + rect.height - borders.bottom - padding.bottom;
return x >= left && x <= right && y >= top && y <= bottom;
}
function calcOffsetPosition(el, borders, offsetPosition) {
var isSvg = isSVGElementOrChild(el);
var relativeRectangle = isSvg ? getSvgElementRelativeRectangle(el) : null;
return {
left: isSvg ? relativeRectangle.left + borders.left : offsetPosition.left + borders.left,
top: isSvg ? relativeRectangle.top + borders.top : offsetPosition.top + borders.top,
};
}
function calcOffsetPositionInIframe(el, borders, offsetPosition, doc, currentIframe) {
var iframeBorders = getBordersWidth(currentIframe);
borders.left += iframeBorders.left;
borders.top += iframeBorders.top;
var iframeOffset = getOffsetPosition(currentIframe);
var iframePadding = getElementPadding(currentIframe);
var clientPosition = null;
if (isSVGElementOrChild(el)) {
var relativeRectangle = getSvgElementRelativeRectangle(el);
clientPosition = {
x: relativeRectangle.left - (document.body.scrollLeft || document.documentElement.scrollLeft) +
borders.left,
y: relativeRectangle.top - (document.body.scrollTop || document.documentElement.scrollTop) + borders.top,
};
}
else {
clientPosition = offsetToClientCoords({
x: offsetPosition.left + borders.left,
y: offsetPosition.top + borders.top,
}, doc);
}
return {
left: iframeOffset.left + clientPosition.x + iframePadding.left,
top: iframeOffset.top + clientPosition.y + iframePadding.top,
};
}
function getOffsetPosition(el, roundFn) {
if (roundFn === void 0) { roundFn = Math.round; }
if (isMapElement(el)) {
var rectangle = getMapElementRectangle(el);
return {
left: rectangle.left,
top: rectangle.top,
};
}
var doc = findDocument(el);
var isInIframe = isElementInIframe(el, doc);
var currentIframe = isInIframe ? getIframeByElement(doc) : null;
var offsetPosition = doc === el ? getOffset(doc.documentElement) : getOffset(el);
// NOTE: The jquery .offset() function doesn't take the body's border into account (except IE7)
// http://bugs.jquery.com/ticket/7948.
// NOTE: Sometimes, in IE, the getElementFromPoint method returns a cross-domain iframe's documentElement,
// but theres no way to access its body.
var borders = doc.body ? getBordersWidth(doc.body) : {
left: 0,
top: 0,
};
var calcOffsetPositionFn = !isInIframe || !currentIframe ? calcOffsetPosition : calcOffsetPositionInIframe;
var _a = calcOffsetPositionFn(el, borders, offsetPosition, doc, currentIframe), left = _a.left, top = _a.top;
if (isFunction(roundFn)) {
left = roundFn(left);
top = roundFn(top);
}
return { left: left, top: top };
}
function offsetToClientCoords(coords, currentDocument) {
var doc = currentDocument || document;
var documentScrollLeft = getScrollLeft(doc);
var documentScrollTop = getScrollTop(doc);
var bodyScrollLeft = getScrollLeft(doc.body);
var bodyScrollTop = getScrollTop(doc.body);
var scrollLeft = documentScrollLeft === 0 && bodyScrollLeft !== 0 ? bodyScrollLeft : documentScrollLeft;
var scrollTop = documentScrollTop === 0 && bodyScrollTop !== 0 ? bodyScrollTop : documentScrollTop;
return {
x: coords.x - scrollLeft,
y: coords.y - scrollTop,
};
}
var positionUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
getElementRectangle: getElementRectangle,
shouldIgnoreEventInsideIframe: shouldIgnoreEventInsideIframe,
getOffsetPosition: getOffsetPosition,
offsetToClientCoords: offsetToClientCoords
});
// NOTE: Tags from https://www.w3schools.com/tags/att_name.asp
var ELEMENTS_WITH_NAME_ATTRIBUTE = ['button', 'fieldset', 'form', 'iframe',
'input', 'map', 'meta', 'object', 'output', 'param', 'select', 'textarea'];
var COLLECTION_PROTO_GETTERS_RESERVE = 10;
var collectionProtoGettersCount = 0;
var HTMLCollectionInheritor = /** @class */ (function () {
function HTMLCollectionInheritor() {
}
return HTMLCollectionInheritor;
}());
HTMLCollectionInheritor.prototype = HTMLCollection.prototype;
var HTMLCollectionWrapper = /** @class */ (function (_super) {
__extends(HTMLCollectionWrapper, _super);
function HTMLCollectionWrapper(collection, tagName) {
var _this = _super.call(this) || this;
tagName = tagName.toLowerCase();
nativeMethods.objectDefineProperties(_this, {
_collection: { value: collection },
_filteredCollection: { value: [] },
_tagName: { value: tagName },
_version: { value: -Infinity, writable: true },
_namedProps: { value: ELEMENTS_WITH_NAME_ATTRIBUTE.indexOf(tagName) !== -1 ? [] : null },
_lastNativeLength: { value: 0, writable: true },
});
_this._refreshCollection();
return _this;
}
HTMLCollectionWrapper.prototype.item = function (index) {
this._refreshCollection();
return this._filteredCollection[index];
};
Object.defineProperty(HTMLCollectionWrapper.prototype, "length", {
get: function () {
this._refreshCollection();
return this._filteredCollection.length;
},
enumerable: false,
configurable: true
});
HTMLCollectionWrapper.prototype._refreshCollection = function () {
var storedNativeCollectionLength = this._lastNativeLength;
var nativeCollectionLength = nativeMethods.htmlCollectionLengthGetter.call(this._collection);
this._lastNativeLength = nativeCollectionLength;
if (!domMutationTracker.isOutdated(this._tagName, this._version) &&
(domMutationTracker.isDomContentLoaded() || storedNativeCollectionLength === nativeCollectionLength))
return;
var storedFilteredCollectionLength = this._filteredCollection.length;
var currentNamedProps = filterCollection(this, nativeCollectionLength);
this._version = domMutationTracker.getVersion(this._tagName);
updateCollectionIndexGetters(this, storedFilteredCollectionLength, this._filteredCollection.length);
updateNamedProps(this, this._namedProps, currentNamedProps);
};
return HTMLCollectionWrapper;
}(HTMLCollectionInheritor));
var additionalProtoMethods = {
constructor: {
value: HTMLCollectionWrapper.constructor,
configurable: true,
enumerable: false,
writable: true,
},
_refreshCollection: {
value: HTMLCollectionWrapper.prototype._refreshCollection,
enumerable: false,
},
};
if (HTMLCollection.prototype.namedItem) {
additionalProtoMethods.namedItem = {
value: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this._refreshCollection();
var namedItem = this._collection.namedItem.apply(this._collection, args);
return namedItem && isShadowUIElement(namedItem) ? null : namedItem;
},
enumerable: true,
configurable: true,
writable: true,
};
}
nativeMethods.objectDefineProperties(HTMLCollectionWrapper.prototype, additionalProtoMethods);
addShadowGetters(COLLECTION_PROTO_GETTERS_RESERVE);
function addShadowGetters(count) {
var _loop_1 = function (i) {
var idx = collectionProtoGettersCount++;
nativeMethods.objectDefineProperty(HTMLCollectionWrapper.prototype, idx, {
get: function () {
this.item(idx);
},
});
};
for (var i = 0; i < count; i++) {
_loop_1();
}
}
function updateCollectionIndexGetters(wrapper, oldLength, currentLength) {
if (oldLength === currentLength)
return;
var _loop_2 = function () {
var idx = oldLength++;
nativeMethods.objectDefineProperty(wrapper, idx, {
enumerable: true,
configurable: true,
get: function () { return wrapper.item(idx); },
});
};
while (oldLength < currentLength) {
_loop_2();
}
while (oldLength > currentLength)
delete wrapper[--oldLength];
var maxCollectionLength = collectionProtoGettersCount - COLLECTION_PROTO_GETTERS_RESERVE;
if (currentLength > maxCollectionLength)
addShadowGetters(currentLength - maxCollectionLength);
}
function updateNamedProps(wrapper, oldNamedProps, currentNamedProps) {
if (!currentNamedProps)
return;
for (var _i = 0, oldNamedProps_1 = oldNamedProps; _i < oldNamedProps_1.length; _i++) {
var oldProp = oldNamedProps_1[_i];
if (currentNamedProps.indexOf(oldProp) === -1)
delete wrapper[oldProp];
}
var _loop_3 = function (prop) {
if (!wrapper._collection[prop])
return "continue";
nativeMethods.objectDefineProperty(wrapper, prop, {
configurable: true,
get: function () {
this._refreshCollection();
return wrapper._collection[prop];
},
});
};
for (var _a = 0, currentNamedProps_1 = currentNamedProps; _a < currentNamedProps_1.length; _a++) {
var prop = currentNamedProps_1[_a];
_loop_3(prop);
}
}
function filterCollection(wrapper, nativeCollectionLength) {
var nativeCollection = wrapper._collection;
var currentNamedProps = wrapper._namedProps ? [] : null;
var filteredCollection = wrapper._filteredCollection;
filteredCollection.length = 0;
for (var i = 0; i < nativeCollectionLength; i++) {
var el = nativeCollection[i];
if (isShadowUIElement(el))
continue;
filteredCollection.push(el);
if (!currentNamedProps)
continue;
var nameAttr = nativeMethods.getAttribute.call(el, 'name');
if (nameAttr !== null)
currentNamedProps.push(nameAttr);
}
return currentNamedProps;
}
var IS_NON_STATIC_POSITION_RE = /fixed|relative|absolute/;
var CLASSNAME_RE = /\.((?:\\.|[-\w]|[^\x00-\xa0])+)/g; // eslint-disable-line no-control-regex
var IS_SHADOW_CONTAINER_FLAG = 'hammerhead|shadow-ui|container-flag';
var IS_SHADOW_CONTAINER_COLLECTION_FLAG = 'hammerhead|shadow-ui|container-collection-flag';
var HTML_COLLECTION_WRAPPER = 'hammerhead|shadow-ui|html-collection-wrapper';
var ShadowUI = /** @class */ (function (_super) {
__extends(ShadowUI, _super);
function ShadowUI(_nodeMutation, _messageSandbox, _iframeSandbox, _ieDebugSandbox) {
var _this = _super.call(this) || this;
_this._nodeMutation = _nodeMutation;
_this._messageSandbox = _messageSandbox;
_this._iframeSandbox = _iframeSandbox;
_this._ieDebugSandbox = _ieDebugSandbox;
_this.BODY_CONTENT_CHANGED_COMMAND = 'hammerhead|command|body-content-changed';
_this.ROOT_CLASS = 'root';
_this.ROOT_ID = 'root';
_this.HIDDEN_CLASS = 'hidden';
_this.BLIND_CLASS = 'blind';
_this.root = null;
_this.lastActiveElement = null;
_this.uiStyleSheetsHtmlBackup = null;
_this.wrapperCreators = _this._createWrapperCreators();
_this._initEventCallbacks();
return _this;
}
ShadowUI.prototype._initEventCallbacks = function () {
var _this = this;
this.runTaskScriptEventCallback = function (iframe) {
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
var iframeHead = contentDocument.head;
var iframeBody = contentDocument.body;
_this._restoreUIStyleSheets(iframeHead, _this._getUIStyleSheetsHtml());
_this.markShadowUIContainers(iframeHead, iframeBody);
};
this.beforeDocumentCleanedEventCallback = function () {
_this.uiStyleSheetsHtmlBackup = _this._getUIStyleSheetsHtml();
};
this.documentCleanedEventCallback = function (e) {
_this._restoreUIStyleSheets(e.document.head, _this.uiStyleSheetsHtmlBackup);
_this.uiStyleSheetsHtmlBackup = null;
_this.markShadowUIContainers(_this.document.head, _this.document.body);
};
this.documentClosedEventCallback = function (document) {
_this._restoreUIStyleSheets(document.head, _this.uiStyleSheetsHtmlBackup);
_this.uiStyleSheetsHtmlBackup = null;
_this.markShadowUIContainers(document.head, document.body);
};
this.bodyContentChangedEventCallback = function (body) {
var elContextWindow = body[INTERNAL_PROPS.processedContext];
if (elContextWindow !== window) {
_this._messageSandbox.sendServiceMsg({
cmd: _this.BODY_CONTENT_CHANGED_COMMAND,
}, elContextWindow);
}
else
_this.onBodyElementMutation();
};
this.serviceMsgReceivedEventCallback = function (e) {
if (e.message.cmd === _this.BODY_CONTENT_CHANGED_COMMAND)
_this.onBodyElementMutation();
};
this.bodyCreatedEventCallback = function (body) { return _this.markShadowUIContainers(_this.document.head, body); };
};
ShadowUI._filterElement = function (el) {
return el && isShadowUIElement(el) ? null : el;
};
ShadowUI.prototype._filterList = function (list, listLength, predicate) {
var filteredList = [];
for (var i = 0; i < listLength; i++) {
var el = predicate(list[i]);
if (el)
filteredList.push(list[i]);
}
//HACK: Sometimes client scripts want to get StyleSheet by one's property 'id' and by index. Real StyleSheetList can provide this possibility.
//We can't create a new StyleSheetList or change current yet, so we need to create a fake StyleSheetList.
if (isIE && list instanceof StyleSheetList) {
var _loop_1 = function (item) {
if (item.id)
nativeMethods.objectDefineProperty(filteredList, item.id, { get: function () { return item; } });
};
for (var _i = 0, filteredList_1 = filteredList; _i < filteredList_1.length; _i++) {
var item = filteredList_1[_i];
_loop_1(item);
}
}
nativeMethods.objectDefineProperty(filteredList, 'item', {
value: function (index) { return index >= filteredList.length ? null : filteredList[index]; },
});
if (list.namedItem) {
nativeMethods.objectDefineProperty(filteredList, 'namedItem', {
value: function (name) { return list.namedItem(name); },
});
}
return filteredList.length === listLength ? list : filteredList;
};
ShadowUI.prototype._filterNodeList = function (nodeList, originLength) {
return this._filterList(nodeList, originLength, function (item) { return ShadowUI._filterElement(item); });
};
ShadowUI.prototype._filterStyleSheetList = function (styleSheetList, originLength) {
return this._filterList(styleSheetList, originLength, function (item) { return ShadowUI._filterElement(item.ownerNode); });
};
ShadowUI._getFirstNonShadowElement = function (nodeList) {
var length = nativeMethods.nodeListLengthGetter.call(nodeList);
for (var i = 0; i < length; i++) {
if (ShadowUI._filterElement(nodeList[i]))
return nodeList[i];
}
return null;
};
ShadowUI.prototype._createWrapperCreators = function () {
var sandbox = this;
return {
getElementsByClassName: function (nativeGetElementsByClassNameFnName) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var elements = nativeMethods[nativeGetElementsByClassNameFnName].apply(this, args);
var length = nativeMethods.htmlCollectionLengthGetter.call(elements);
return sandbox._filterNodeList(elements, length);
};
},
getElementsByTagName: function (nativeGetElementsByTagNameFnName) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var nativeCollection = nativeMethods[nativeGetElementsByTagNameFnName].apply(this, args);
var tagName = args[0];
if (typeof tagName !== 'string' || !isHeadOrBodyOrHtmlElement(this) && !isFormElement(this) &&
tagName.toLowerCase() !== 'input' && nativeGetElementsByTagNameFnName !== 'getElementsByTagName')
return nativeCollection;
if (!nativeCollection[HTML_COLLECTION_WRAPPER])
// NOTE: This changes how the native method behaves. The returned collection will have this wrapper attached
// if the method was called with the same tagName parameter.
// This allows skipping the search if the DOM tree has not changed since the last call.
nativeCollection[HTML_COLLECTION_WRAPPER] = new HTMLCollectionWrapper(nativeCollection, tagName);
else
nativeCollection[HTML_COLLECTION_WRAPPER]._refreshCollection();
return nativeCollection[HTML_COLLECTION_WRAPPER];
};
},
querySelector: function (nativeQuerySelectorFnName, nativeQuerySelectorAllFnName) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (typeof args[0] === 'string')
args[0] = NodeSandbox$1.processSelector(args[0]);
var element = nativeMethods[nativeQuerySelectorFnName].apply(this, args);
var filteredElement = ShadowUI._filterElement(element);
if (!element || filteredElement)
return filteredElement;
return ShadowUI._getFirstNonShadowElement(nativeMethods[nativeQuerySelectorAllFnName].apply(this, args));
};
},
querySelectorAll: function (nativeQuerySelectorAllFnName) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (typeof args[0] === 'string')
args[0] = NodeSandbox$1.processSelector(args[0]);
var list = nativeMethods[nativeQuerySelectorAllFnName].apply(this, args);
var length = nativeMethods.nodeListLengthGetter.call(list);
return sandbox._filterNodeList(list, length);
};
},
};
};
ShadowUI.prototype._markShadowUIContainerAndCollections = function (containerEl) {
var children = nativeMethods.elementChildrenGetter.call(containerEl);
ShadowUI._markAsShadowContainer(containerEl);
ShadowUI.markAsShadowContainerCollection(children);
ShadowUI.markAsShadowContainerCollection(nativeMethods.nodeChildNodesGetter.call(containerEl));
};
ShadowUI.prototype.markShadowUIContainers = function (head, body) {
if (head)
this._markShadowUIContainerAndCollections(head);
if (body)
this._markShadowUIContainerAndCollections(body);
};
ShadowUI.prototype._bringRootToWindowTopLeft = function () {
var rootHasParentWithNonStaticPosition = false;
var parent = nativeMethods.nodeParentNodeGetter.call(this.root);
while (parent) {
var elementPosition = get$1(parent, 'position');
if (IS_NON_STATIC_POSITION_RE.test(elementPosition))
rootHasParentWithNonStaticPosition = true;
parent = nativeMethods.nodeParentNodeGetter.call(parent);
}
if (rootHasParentWithNonStaticPosition) {
var rootOffset = getOffsetPosition(this.root);
if (rootOffset.left !== 0 || rootOffset.top !== 0) {
var currentRootLeft = parseFloat(get$1(this.root, 'left')) || 0;
var currentRootTop = parseFloat(get$1(this.root, 'top')) || 0;
var newRootLeft = currentRootLeft - rootOffset.left + 'px';
var newRootTop = currentRootTop - rootOffset.top + 'px';
set(this.root, 'left', newRootLeft);
set(this.root, 'top', newRootTop);
}
}
};
ShadowUI.prototype._overrideDocumentMethods = function (window, document) {
var shadowUI = this;
var docProto = window.Document.prototype;
overrideFunction(docProto, 'elementFromPoint', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
// NOTE: T212974
shadowUI.addClass(shadowUI.getRoot(), shadowUI.HIDDEN_CLASS);
var res = ShadowUI._filterElement(nativeMethods.elementFromPoint.apply(this, args));
shadowUI.removeClass(shadowUI.getRoot(), shadowUI.HIDDEN_CLASS);
return res;
});
if (document.caretRangeFromPoint) {
overrideFunction(docProto, 'caretRangeFromPoint', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
shadowUI.addClass(shadowUI.getRoot(), shadowUI.HIDDEN_CLASS);
var res = nativeMethods.caretRangeFromPoint.apply(this, args);
if (res && res.startContainer && !ShadowUI._filterElement(res.startContainer))
res = null;
shadowUI.removeClass(shadowUI.getRoot(), shadowUI.HIDDEN_CLASS);
return res;
});
}
if (document.caretPositionFromPoint) {
overrideFunction(docProto, 'caretPositionFromPoint', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
shadowUI.addClass(shadowUI.getRoot(), shadowUI.HIDDEN_CLASS);
var res = nativeMethods.caretPositionFromPoint.apply(this, args);
if (res && res.offsetNode && !ShadowUI._filterElement(res.offsetNode))
res = null;
shadowUI.removeClass(shadowUI.getRoot(), shadowUI.HIDDEN_CLASS);
return res;
});
}
overrideFunction(docProto, 'getElementById', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return ShadowUI._filterElement(nativeMethods.getElementById.apply(this, args));
});
overrideFunction(docProto, 'getElementsByName', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var elements = nativeMethods.getElementsByName.apply(this, args);
var length = getElementsByNameReturnsHTMLCollection
? nativeMethods.htmlCollectionLengthGetter.call(elements)
: nativeMethods.nodeListLengthGetter.call(elements);
return shadowUI._filterNodeList(elements, length);
});
overrideFunction(docProto, 'getElementsByClassName', this.wrapperCreators.getElementsByClassName('getElementsByClassName'));
overrideFunction(docProto, 'getElementsByTagName', this.wrapperCreators.getElementsByTagName('getElementsByTagName'));
overrideFunction(docProto, 'querySelector', this.wrapperCreators.querySelector('querySelector', 'querySelectorAll'));
overrideFunction(docProto, 'querySelectorAll', this.wrapperCreators.querySelectorAll('querySelectorAll'));
};
ShadowUI.prototype._overrideElementMethods = function (window) {
var elementProto = window.Element.prototype;
var bodyProto = window.HTMLBodyElement.prototype;
var headProto = window.HTMLHeadElement.prototype;
overrideFunction(elementProto, 'getElementsByTagName', this.wrapperCreators.getElementsByTagName('elementGetElementsByTagName'));
overrideFunction(bodyProto, 'getElementsByClassName', this.wrapperCreators.getElementsByClassName('elementGetElementsByClassName'));
overrideFunction(bodyProto, 'querySelector', this.wrapperCreators.querySelector('elementQuerySelector', 'elementQuerySelectorAll'));
overrideFunction(bodyProto, 'querySelectorAll', this.wrapperCreators.querySelectorAll('elementQuerySelectorAll'));
overrideFunction(headProto, 'getElementsByClassName', bodyProto.getElementsByClassName);
overrideFunction(headProto, 'querySelector', bodyProto.querySelector);
overrideFunction(headProto, 'querySelectorAll', bodyProto.querySelectorAll);
};
ShadowUI.prototype._getUIStyleSheetsHtml = function () {
var stylesSelector = 'link.' + SHADOW_UI_CLASS_NAME.uiStylesheet;
var stylesheets = this.nativeMethods.querySelectorAll.call(this.document, stylesSelector);
var length = this.nativeMethods.nodeListLengthGetter.call(stylesheets);
var result = '';
for (var i = 0; i < length; i++)
result += nativeMethods.elementOuterHTMLGetter.call(stylesheets[i]);
return result;
};
ShadowUI.prototype._restoreUIStyleSheets = function (head, uiStyleSheetsHtml) {
if (!head || !uiStyleSheetsHtml)
return;
var parser = this.nativeMethods.createElement.call(this.document, 'div');
nativeMethods.elementInnerHTMLSetter.call(parser, uiStyleSheetsHtml);
var children = nativeMethods.elementChildrenGetter.call(parser);
var length = nativeMethods.htmlCollectionLengthGetter.call(children);
for (var i = 0; i < length; i++) {
var child = children[0];
ShadowUI.markElementAsShadow(child);
this.nativeMethods.removeChild.call(parser, child);
this.nativeMethods.appendChild.call(head, child);
}
};
ShadowUI.prototype._markElementsAsShadowInHead = function (head) {
var children = nativeMethods.elementChildrenGetter.call(head);
var length = nativeMethods.htmlCollectionLengthGetter.call(children);
for (var i = 0; i < length; i++) {
var child = children[i];
if (ShadowUI.containsShadowUIClassPostfix(child))
ShadowUI.markElementAsShadow(child);
}
};
ShadowUI.prototype.getRoot = function () {
var _this = this;
// GH-2418
if (isChrome && !ShadowUI.isShadowContainer(this.document.body))
this._markShadowUIContainerAndCollections(this.document.body);
if (!this.root || /* NOTE: T225944 */ !this.document.body.contains(this.root)) {
if (!this.root) {
// NOTE: B254893
this.root = nativeMethods.createElement.call(this.document, 'div');
nativeMethods.setAttribute.call(this.root, 'id', ShadowUI.patchId(this.ROOT_ID));
nativeMethods.setAttribute.call(this.root, 'contenteditable', 'false');
this.addClass(this.root, this.ROOT_CLASS);
ShadowUI.markElementAsShadow(this.root);
nativeMethods.appendChild.call(this.document.body, this.root);
var nativeDocumentAddEventListener = nativeMethods.documentAddEventListener || nativeMethods.addEventListener;
for (var _i = 0, _a = domProcessor.EVENTS; _i < _a.length; _i++) {
var event_1 = _a[_i];
nativeMethods.addEventListener.call(this.root, event_1, stopPropagation);
}
this._bringRootToWindowTopLeft();
nativeDocumentAddEventListener.call(this.document, 'DOMContentLoaded', function () {
_this.onBodyElementMutation();
_this._bringRootToWindowTopLeft();
});
}
else
nativeMethods.appendChild.call(this.document.body, this.root);
}
return this.root;
};
ShadowUI.prototype.attach = function (window) {
_super.prototype.attach.call(this, window, window.document);
this.markShadowUIContainers(this.document.head, this.document.body);
this._overrideDocumentMethods(window, window.document);
this._overrideElementMethods(window);
// NOTE: document.head equals null after call 'document.open' function
if (window.document.head)
this._markElementsAsShadowInHead(window.document.head);
this._initEvents();
};
ShadowUI.prototype._initEvents = function () {
this._iframeSandbox.on(this._iframeSandbox.RUN_TASK_SCRIPT_EVENT, this.runTaskScriptEventCallback);
this._nodeMutation.on(this._nodeMutation.BEFORE_DOCUMENT_CLEANED_EVENT, this.beforeDocumentCleanedEventCallback);
this._nodeMutation.on(this._nodeMutation.DOCUMENT_CLEANED_EVENT, this.documentCleanedEventCallback);
this._nodeMutation.on(this._nodeMutation.DOCUMENT_CLOSED_EVENT, this.documentClosedEventCallback);
this._nodeMutation.on(this._nodeMutation.BODY_CONTENT_CHANGED_EVENT, this.bodyContentChangedEventCallback);
this._messageSandbox.on(this._messageSandbox.SERVICE_MSG_RECEIVED_EVENT, this.serviceMsgReceivedEventCallback);
this._nodeMutation.on(this._nodeMutation.BODY_CREATED_EVENT, this.bodyCreatedEventCallback);
};
ShadowUI.prototype.onBodyElementMutation = function () {
if (!this.root || !this.document.body)
return;
var isRootInDom = closest(this.root, 'html');
var isRootLastChild = !this.nativeMethods.elementNextElementSiblingGetter.call(this.root);
// NOTE: Fix for B239138 - The 'Cannot read property 'document' of null' error
// is thrown on recording on the unroll.me site. There was an issue when
// document.body was replaced, so we need to reattach a UI to a new body manually.
var isRootInBody = nativeMethods.nodeParentNodeGetter.call(this.root) === this.document.body;
if (!(isRootInDom && isRootLastChild && isRootInBody))
this.nativeMethods.appendChild.call(this.document.body, this.root);
this.markShadowUIContainers(this.document.head, this.document.body);
};
// Accessors
ShadowUI.prototype.getFirstChild = function (el) {
var childNodes = nativeMethods.nodeChildNodesGetter.call(el);
var length = nativeMethods.nodeListLengthGetter.call(childNodes);
var filteredNodes = this._filterNodeList(childNodes, length);
return filteredNodes[0] || null;
};
ShadowUI.prototype.getFirstElementChild = function (el) {
var children = nativeMethods.elementChildrenGetter.call(el);
var length = nativeMethods.htmlCollectionLengthGetter.call(children);
return this._filterNodeList(children, length)[0] || null;
};
ShadowUI.prototype.getLastChild = function (el) {
var childNodes = nativeMethods.nodeChildNodesGetter.call(el);
var length = nativeMethods.nodeListLengthGetter.call(childNodes);
var filteredNodes = this._filterNodeList(childNodes, length);
var index = childNodes === filteredNodes ? length - 1 : filteredNodes.length - 1;
return index >= 0 ? filteredNodes[index] : null;
};
ShadowUI.prototype.getLastElementChild = function (el) {
var children = nativeMethods.elementChildrenGetter.call(el);
var length = nativeMethods.htmlCollectionLengthGetter.call(children);
var filteredNodes = this._filterNodeList(children, length);
var index = children === filteredNodes ? length - 1 : filteredNodes.length - 1;
return index >= 0 ? filteredNodes[index] : null;
};
ShadowUI.prototype.getNextSibling = function (el) {
if (!el)
return el;
do
el = nativeMethods.nodeNextSiblingGetter.call(el);
while (el && isShadowUIElement(el));
return el;
};
ShadowUI.prototype.getPrevSibling = function (el) {
if (!el)
return el;
do
el = nativeMethods.nodePrevSiblingGetter.call(el);
while (el && isShadowUIElement(el));
return el;
};
ShadowUI.prototype.getMutationRecordNextSibling = function (el) {
if (!el)
return el;
while (el && isShadowUIElement(el))
el = nativeMethods.nodeNextSiblingGetter.call(el);
return el;
};
ShadowUI.prototype.getMutationRecordPrevSibling = function (el) {
if (!el)
return el;
while (el && isShadowUIElement(el))
el = nativeMethods.nodePrevSiblingGetter.call(el);
return el;
};
ShadowUI.prototype.getNextElementSibling = function (el) {
do
el = nativeMethods.elementNextElementSiblingGetter.call(el);
while (el && isShadowUIElement(el));
return el;
};
ShadowUI.prototype.getPrevElementSibling = function (el) {
do
el = nativeMethods.elementPrevElementSiblingGetter.call(el);
while (el && isShadowUIElement(el));
return el;
};
// Utils
ShadowUI._checkElementsPosition = function (collection, length) {
if (!length)
return;
var shadowUIElements = [];
for (var i = 0; i < length; i++) {
var item = collection[i];
if (isShadowUIElement(item))
shadowUIElements.push(item);
}
var collectionOwner = shadowUIElements.length && nativeMethods.nodeParentNodeGetter.call(shadowUIElements[0]);
for (var _i = 0, shadowUIElements_1 = shadowUIElements; _i < shadowUIElements_1.length; _i++) {
var shadowUIElement = shadowUIElements_1[_i];
nativeMethods.appendChild.call(collectionOwner, shadowUIElement);
}
};
ShadowUI._hasFlag = function (obj, flag) {
try {
return !!obj[flag];
}
catch (e) {
return false;
}
};
// IE11 and Edge have a strange behavior: shadow container collection flag may be lost (GH-1763 and GH-2034)
ShadowUI._hasCollectionFlagForIE = function (obj, flag) {
try {
if (flag in obj)
return obj[flag];
var parent_1 = nativeMethods.nodeParentNodeGetter.call(obj[0]);
var result = isHeadOrBodyElement(parent_1) || isFormElement(parent_1);
nativeMethods.objectDefineProperty(obj, IS_SHADOW_CONTAINER_COLLECTION_FLAG, { value: result, configurable: true });
return result;
}
catch (e) {
return false;
}
};
ShadowUI.isShadowContainer = function (el) {
return ShadowUI._hasFlag(el, IS_SHADOW_CONTAINER_FLAG);
};
ShadowUI.isShadowContainerCollection = function (collection, length) {
return isIE && length
? ShadowUI._hasCollectionFlagForIE(collection, IS_SHADOW_CONTAINER_COLLECTION_FLAG)
: ShadowUI._hasFlag(collection, IS_SHADOW_CONTAINER_COLLECTION_FLAG);
};
ShadowUI._isShadowUIChildListMutation = function (mutation) {
if (isShadowUIElement(mutation.target))
return true;
var removedNodesLength = nativeMethods.nodeListLengthGetter.call(mutation.removedNodes);
for (var i = 0; i < removedNodesLength; i++) {
if (isShadowUIElement(mutation.removedNodes[i]))
return true;
}
var addedNodesLength = nativeMethods.nodeListLengthGetter.call(mutation.addedNodes);
for (var i = 0; i < addedNodesLength; i++) {
if (isShadowUIElement(mutation.addedNodes[i]))
return true;
}
return false;
};
ShadowUI._isShadowUIAttributeMutation = function (mutation) {
return isShadowUIElement(mutation.target) || isHammerheadAttr(mutation.attributeName);
};
ShadowUI._isShadowUICharacterDataMutation = function (mutation) {
return isShadowUIElement(mutation.target);
};
ShadowUI.isShadowUIMutation = function (mutation) {
switch (mutation.type) {
case 'childList':
return ShadowUI._isShadowUIChildListMutation(mutation);
case 'attributes':
return ShadowUI._isShadowUIAttributeMutation(mutation);
case 'characterData':
return ShadowUI._isShadowUICharacterDataMutation(mutation);
default:
return false;
}
};
ShadowUI.removeSelfRemovingScripts = function (document) {
var selfRemovingScripts = nativeMethods.querySelectorAll.call(document, '.' + SHADOW_UI_CLASS_NAME.selfRemovingScript);
var length = nativeMethods.nodeListLengthGetter.call(selfRemovingScripts);
for (var i = 0; i < length; i++)
removeElement(selfRemovingScripts[i]);
};
// API
ShadowUI.prototype.getShadowUICollectionLength = function (collection, length) {
var shadowUIElementCount = 0;
for (var i = 0; i < length; i++) {
if (isShadowUIElement(collection[i]))
shadowUIElementCount++;
}
if (shadowUIElementCount && !this._ieDebugSandbox.isDebuggerInitiator())
ShadowUI._checkElementsPosition(collection, length);
return length - shadowUIElementCount;
};
// NOTE: this method cannot be static because it is a part of the public API
ShadowUI.prototype.addClass = function (el, value) {
var patchedClass = ShadowUI.patchClassNames(value);
addClass(el, patchedClass);
};
// NOTE: this method cannot be static because it is a part of the public API
ShadowUI.prototype.removeClass = function (elem, value) {
var patchedClass = ShadowUI.patchClassNames(value);
removeClass(elem, patchedClass);
};
ShadowUI.hasClass = function (el, value) {
var patchedClass = ShadowUI.patchClassNames(value);
return hasClass(el, patchedClass);
};
ShadowUI.patchId = function (value) {
return value + SHADOW_UI_CLASS_NAME.postfix;
};
ShadowUI.patchClassNames = function (value) {
var names = value.split(/\s+/);
for (var i = 0; i < names.length; i++)
names[i] += SHADOW_UI_CLASS_NAME.postfix;
return names.join(' ');
};
ShadowUI.prototype.select = function (selector, context) {
var patchedSelector = selector.replace(CLASSNAME_RE, function (className) { return className + SHADOW_UI_CLASS_NAME.postfix; });
return context
? nativeMethods.elementQuerySelectorAll.call(context, patchedSelector)
: nativeMethods.querySelectorAll.call(this.document, patchedSelector);
};
ShadowUI.prototype.setBlind = function (value) {
if (value)
this.addClass(this.getRoot(), this.BLIND_CLASS);
else
this.removeClass(this.getRoot(), this.BLIND_CLASS);
};
ShadowUI.prototype.getLastActiveElement = function () {
return this.lastActiveElement;
};
ShadowUI.prototype.setLastActiveElement = function (el) {
this.lastActiveElement = el;
};
ShadowUI.prototype.insertBeforeRoot = function (newNodes) {
var rootEl = this.getRoot();
var rootParent = this.nativeMethods.nodeParentNodeGetter.call(rootEl);
var lastParentChild = this.nativeMethods.nodeLastChildGetter.call(rootParent);
// GH-2418
if (lastParentChild !== rootEl)
nativeMethods.appendChild.call(rootParent, rootEl);
if (newNodes.length > 1 || typeof newNodes[0] !== 'object') {
var fragment = document.createDocumentFragment.call(this.document);
for (var _i = 0, newNodes_1 = newNodes; _i < newNodes_1.length; _i++) {
var node = newNodes_1[_i];
if (typeof node === 'string')
node = nativeMethods.createTextNode.call(this.document, node);
nativeMethods.appendChild.call(fragment, node);
}
return nativeMethods.insertBefore.call(rootParent, fragment, rootEl);
}
return nativeMethods.insertBefore.call(rootParent, newNodes[0], rootEl);
};
ShadowUI.markElementAsShadow = function (el) {
el[INTERNAL_PROPS.shadowUIElement] = true;
};
// GH-2009
ShadowUI.markFormAsShadow = function (form) {
var formChildren = nativeMethods.elementChildrenGetter.call(form);
ShadowUI._markAsShadowContainer(form);
ShadowUI.markAsShadowContainerCollection(form.elements);
ShadowUI.markAsShadowContainerCollection(formChildren);
var childNodes = nativeMethods.nodeChildNodesGetter.call(form);
ShadowUI.markAsShadowContainerCollection(childNodes);
};
ShadowUI.markElementAndChildrenAsShadow = function (el) {
ShadowUI.markElementAsShadow(el);
// NOTE: For Text, Comment and ProcessingInstruction nodes
if (!el.querySelectorAll)
return;
var childElements = getNativeQuerySelectorAll(el).call(el, '*');
var length = nativeMethods.nodeListLengthGetter.call(childElements);
for (var i = 0; i < length; i++)
ShadowUI.markElementAsShadow(childElements[i]);
};
ShadowUI._markAsShadowContainer = function (container) {
nativeMethods.objectDefineProperty(container, IS_SHADOW_CONTAINER_FLAG, { value: true });
};
ShadowUI.markAsShadowContainerCollection = function (collection) {
nativeMethods.objectDefineProperty(collection, IS_SHADOW_CONTAINER_COLLECTION_FLAG, { value: true, configurable: true });
};
ShadowUI.containsShadowUIClassPostfix = function (element) {
return typeof element.className === 'string' &&
element.className.indexOf(SHADOW_UI_CLASS_NAME.postfix) !== -1;
};
return ShadowUI;
}(SandboxBase));
var ShadowUISandbox = ShadowUI;
function constructorIsCalledWithoutNewKeyword (callingContext, constructor) {
return callingContext instanceof constructor === false;
}
// https://mimesniff.spec.whatwg.org/
var IMAGE_TYPE_PATTERNS = [
{
mime: 'image/x-icon',
pattern: [0x00, 0x00, 0x01, 0x00],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'image/x-icon',
pattern: [0x00, 0x00, 0x02, 0x00],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'image/bmp',
pattern: [0x42, 0x4D],
mask: [0xFF, 0xFF],
},
{
mime: 'image/gif',
pattern: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'image/gif',
pattern: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'image/webp',
pattern: [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'image/png',
pattern: [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'image/jpeg',
pattern: [0xFF, 0xD8, 0xFF],
mask: [0xFF, 0xFF, 0xFF],
},
];
var AUDIO_VIDEO_TYPE_PATTERNS = [
{
mime: 'audio/basic',
pattern: [0x2E, 0x73, 0x6E, 0x64],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'audio/aiff',
pattern: [0x46, 0x4F, 0x52, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x41, 0x49, 0x46, 0x46],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'audio/mpeg',
pattern: [0x49, 0x44, 0x33],
mask: [0xFF, 0xFF, 0xFF],
},
{
mime: 'application/ogg',
pattern: [0x4F, 0x67, 0x67, 0x53, 0x00],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'audio/midi',
pattern: [0x4D, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'video/avi',
pattern: [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x41, 0x56, 0x49, 0x20],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'audio/wave',
pattern: [0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF],
},
];
var FONT_TYPE_PATTERNS = [
{
mime: 'application/vnd.ms-fontobject',
pattern: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x50],
mask: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF],
},
{
mime: 'application/octet-stream',
pattern: [0x00, 0x01, 0x00, 0x00],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'application/octet-stream',
pattern: [0x4F, 0x54, 0x54, 0x4F],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'application/octet-stream',
pattern: [0x74, 0x74, 0x63, 0x66],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'application/font-woff',
pattern: [0x77, 0x4F, 0x46, 0x46],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
];
var ARCHIVE_TYPE_PATTERNS = [
{
mime: 'application/x-gzip',
pattern: [0x1F, 0x8B, 0x08],
mask: [0xFF, 0xFF, 0xFF],
},
{
mime: 'application/zip',
pattern: [0x50, 0x4B, 0x03, 0x04],
mask: [0xFF, 0xFF, 0xFF, 0xFF],
},
{
mime: 'application/x-rar-compressed',
pattern: [0x52, 0x61, 0x72, 0x20, 0x1A, 0x07, 0x00],
mask: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
},
];
function matchPattern(pattern, data) {
if (data.length < pattern.pattern.length)
return false;
var p = 0;
var s = 0;
var maskedData = null;
while (p < pattern.pattern.length) {
maskedData = data[s] & pattern.mask[p];
if (maskedData !== pattern.pattern[p])
return false;
s++;
p++;
}
return true;
}
function matchMime(patternGroup, data) {
// Now, we don't support the cases when the data is is divided into several parts and its parts have different types
if (isArrayBuffer(data[0]))
data = data[0];
else if (isArrayBufferView(data[0]))
data = isDataView(data[0]) ? data[0].buffer : data[0];
var byteArray = new nativeMethods.Uint8Array(data);
for (var _i = 0, patternGroup_1 = patternGroup; _i < patternGroup_1.length; _i++) {
var pattern = patternGroup_1[_i];
if (matchPattern(pattern, byteArray))
return pattern.mime;
}
byteArray = null;
return '';
}
function getMimeType (data) {
return matchMime(IMAGE_TYPE_PATTERNS, data) ||
matchMime(AUDIO_VIDEO_TYPE_PATTERNS, data) ||
matchMime(FONT_TYPE_PATTERNS, data) ||
matchMime(ARCHIVE_TYPE_PATTERNS, data);
}
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
var ServiceCommands = {
getUploadedFiles: 'hammerhead|command|get-uploaded-files',
setCookie: 'hammerhead|command|set-cookie',
uploadFiles: 'hammerhead|command|upload-files',
};
var FileListWrapper = /** @class */ (function () {
function FileListWrapper(fileList) {
var _this = this;
nativeMethods.objectDefineProperty(this, 'length', {
get: function () { return fileList.length; },
});
for (var i = 0; i < fileList.length; i++)
this[i] = FileListWrapper._createFileWrapper(fileList[i]);
this.item = function (index) { return _this[index]; };
}
FileListWrapper._base64ToBlob = function (base64Data, fileInfo, sliceSize) {
var mimeType = fileInfo.info.type || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(base64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++)
byteNumbers[i] = slice.charCodeAt(i);
byteArrays.push(new Uint8Array(byteNumbers));
}
// NOTE: window.File in IE11 is not constructable.
return nativeMethods.File
? new nativeMethods.File(byteArrays, fileInfo.info.name, { type: mimeType, lastModified: fileInfo.info.lastModified })
: new nativeMethods.Blob(byteArrays, { type: mimeType });
};
FileListWrapper._createFileWrapper = function (fileInfo) {
var wrapper = null;
if (!window.Blob) {
wrapper = {
size: fileInfo.info.size,
type: fileInfo.info.type,
};
}
else if (fileInfo.blob) {
// NOTE: window.File in IE11 is not constructable.
wrapper = nativeMethods.File
? new nativeMethods.File([fileInfo.blob], fileInfo.info.name, { type: fileInfo.info.type, lastModified: fileInfo.info.lastModified })
: new nativeMethods.Blob([fileInfo.blob], { type: fileInfo.info.type });
}
else
wrapper = FileListWrapper._base64ToBlob(fileInfo.data, fileInfo);
wrapper.name = fileInfo.info.name;
if (fileInfo.info.lastModifiedDate)
wrapper.lastModifiedDate = fileInfo.info.lastModifiedDate;
wrapper.base64 = fileInfo.data;
return wrapper;
};
return FileListWrapper;
}());
//@ts-ignore
if (window.FileList)
FileListWrapper.prototype = FileList.prototype;
// NOTE: https://html.spec.whatwg.org/multipage/forms.html#fakepath-srsly.
var FAKE_PATH_STRING = 'C:\\fakepath\\';
var UploadInfoManager = /** @class */ (function () {
function UploadInfoManager(_transport) {
this._transport = _transport;
this.uploadInfo = [];
}
UploadInfoManager._getFileListData = function (fileList) {
var data = [];
for (var _i = 0, fileList_1 = fileList; _i < fileList_1.length; _i++) {
var file = fileList_1[_i];
data.push(file.base64);
}
return data;
};
UploadInfoManager.formatValue = function (fileNames) {
var value = '';
fileNames = typeof fileNames === 'string' ? [fileNames] : fileNames;
if (fileNames && fileNames.length) {
if (isWebKit)
value = FAKE_PATH_STRING + fileNames[0].split('/').pop();
else
return fileNames[0].split('/').pop();
}
return value;
};
UploadInfoManager.getFileNames = function (fileList, value) {
var result = [];
if (fileList) {
for (var _i = 0, fileList_2 = fileList; _i < fileList_2.length; _i++) {
var file = fileList_2[_i];
result.push(file.name);
}
}
else if (value.lastIndexOf('\\') !== -1)
result.push(value.substr(value.lastIndexOf('\\') + 1));
return result;
};
UploadInfoManager.prototype.loadFilesInfoFromServer = function (filePaths) {
return this._transport.asyncServiceMsg({
cmd: ServiceCommands.getUploadedFiles,
filePaths: typeof filePaths === 'string' ? [filePaths] : filePaths,
});
};
UploadInfoManager.prepareFileListWrapper = function (filesInfo) {
var errs = [];
var validFilesInfo = [];
for (var _i = 0, filesInfo_1 = filesInfo; _i < filesInfo_1.length; _i++) {
var fileInfo = filesInfo_1[_i];
if (fileInfo.err)
errs.push(fileInfo);
else
validFilesInfo.push(fileInfo);
}
return {
errs: errs,
fileList: new FileListWrapper(validFilesInfo),
};
};
UploadInfoManager.prototype.sendFilesInfoToServer = function (fileList, fileNames) {
return this._transport.asyncServiceMsg({
cmd: ServiceCommands.uploadFiles,
data: UploadInfoManager._getFileListData(fileList),
fileNames: fileNames,
});
};
UploadInfoManager.prototype.clearUploadInfo = function (input) {
var inputInfo = this.getUploadInfo(input);
if (inputInfo) {
/*eslint-disable no-restricted-properties*/
inputInfo.files = new FileListWrapper([]);
inputInfo.value = '';
/*eslint-enable no-restricted-properties*/
return removeInputInfo(input);
}
return null;
};
UploadInfoManager.prototype.getFiles = function (input) {
var inputInfo = this.getUploadInfo(input);
// eslint-disable-next-line no-restricted-properties
return inputInfo ? inputInfo.files : new FileListWrapper([]);
};
UploadInfoManager.prototype.getUploadInfo = function (input) {
for (var _i = 0, _a = this.uploadInfo; _i < _a.length; _i++) {
var uploadInfoItem = _a[_i];
if (uploadInfoItem.input === input)
return uploadInfoItem;
}
return null;
};
UploadInfoManager.prototype.getValue = function (input) {
var inputInfo = this.getUploadInfo(input);
// eslint-disable-next-line no-restricted-properties
return inputInfo ? inputInfo.value : '';
};
UploadInfoManager.prototype.loadFileListData = function (_input, fileList) {
if (!fileList.length)
return pinkie.resolve(new FileListWrapper([]));
return new pinkie(function (resolve) {
var fileReader = new FileReader();
var readedFiles = [];
var index = 0;
var file = fileList[index];
fileReader.addEventListener('load', function (e) {
var info = {
type: file.type,
name: file.name,
};
if (isNumber(file.lastModified))
info.lastModified = file.lastModified;
if (file.lastModifiedDate)
info.lastModifiedDate = file.lastModifiedDate;
var dataUrl = nativeMethods.eventTargetGetter.call(e).result;
readedFiles.push({
data: dataUrl.substr(dataUrl.indexOf(',') + 1),
blob: file.slice(0, file.size),
info: info,
});
if (fileList[++index]) {
file = fileList[index];
fileReader.readAsDataURL(file);
}
else
resolve(new FileListWrapper(readedFiles));
});
fileReader.readAsDataURL(file);
});
};
UploadInfoManager.prototype.setUploadInfo = function (input, fileList, value) {
var inputInfo = this.getUploadInfo(input);
if (!inputInfo) {
inputInfo = { input: input };
this.uploadInfo.push(inputInfo);
}
/*eslint-disable no-restricted-properties*/
inputInfo.files = fileList;
inputInfo.value = value;
/*eslint-enable no-restricted-properties*/
addInputInfo(input, fileList, value);
};
return UploadInfoManager;
}());
var SANDBOX_BACKUP = 'hammerhead|sandbox-backup';
function findRecord(storage, iframe) {
for (var i = storage.length - 1; i >= 0; i--) {
try {
if (storage[i].iframe === iframe)
return storage[i];
}
catch (e) {
storage.splice(i, 1);
}
}
return void 0;
}
function create(window, sandbox) {
var topSameDomainWindow = getTopSameDomainWindow(window);
var iframe = window !== topSameDomainWindow ? getFrameElement(window) : null;
var storage = topSameDomainWindow[SANDBOX_BACKUP];
if (!storage) {
storage = [];
nativeMethods.objectDefineProperty(topSameDomainWindow, SANDBOX_BACKUP, { value: storage });
}
var record = findRecord(storage, iframe);
if (record)
record.sandbox = sandbox;
else
storage.push({ iframe: iframe, sandbox: sandbox });
}
function get(window) {
var topSameDomainWindow = getTopSameDomainWindow(window);
var storage = topSameDomainWindow[SANDBOX_BACKUP];
var iframe = window !== topSameDomainWindow ? window.frameElement : null;
if (storage) {
var record = findRecord(storage, iframe);
return record ? record.sandbox : null;
}
return null;
}
var sandboxBackupUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
create: create,
get: get
});
var UploadSandbox = /** @class */ (function (_super) {
__extends(UploadSandbox, _super);
function UploadSandbox(_listeners, _eventSimulator, transport) {
var _this = _super.call(this) || this;
_this._listeners = _listeners;
_this._eventSimulator = _eventSimulator;
_this.START_FILE_UPLOADING_EVENT = 'hammerhead|event|start-file-uploading';
_this.END_FILE_UPLOADING_EVENT = 'hammerhead|event|end-file-uploading';
_this.infoManager = new UploadInfoManager(transport);
return _this;
}
UploadSandbox.prototype._riseChangeEvent = function (input) {
this._eventSimulator.change(input);
};
UploadSandbox._getCurrentInfoManager = function (input) {
var contextWindow = input[INTERNAL_PROPS.processedContext];
return get(contextWindow).upload.infoManager;
};
/*eslint-disable max-nested-callbacks */
UploadSandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
this._listeners.addInternalEventBeforeListener(window, ['change'], function (e, dispatched) {
var input = nativeMethods.eventTargetGetter.call(e);
var currentInfoManager = UploadSandbox._getCurrentInfoManager(input);
if (!dispatched && isFileInput(input)) {
stopPropagation(e);
preventDefault(e);
var value_1 = nativeMethods.inputValueGetter.call(input);
if (!!value_1 || !!currentInfoManager.getValue(input)) {
var files = nativeMethods.inputFilesGetter.call(input);
var fileNames_1 = UploadInfoManager.getFileNames(files, value_1);
_this.emit(_this.START_FILE_UPLOADING_EVENT, fileNames_1, input);
currentInfoManager.loadFileListData(input, files)
.then(function (fileList) {
currentInfoManager.setUploadInfo(input, fileList, value_1);
return _this.infoManager.sendFilesInfoToServer(fileList, fileNames_1);
})
.then(function (uploadInfo) {
_this._riseChangeEvent(input);
_this.emit(_this.END_FILE_UPLOADING_EVENT, uploadInfo);
});
}
}
});
if (!settings.get().isRecordMode && (isIE || isFirefox)) {
// NOTE: Google Chrome and Safari don't open the native browser dialog when TestCafe clicks on the input.
// 'Click' is a complex emulated action that uses 'dispatchEvent' method internally.
// Another browsers open the native browser dialog in this case.
// This is why, we are forced to prevent the browser's open file dialog.
this._listeners.addInternalEventBeforeListener(window, ['click'], function (e, dispatched) {
if (dispatched && isFileInput(nativeMethods.eventTargetGetter.call(e)))
preventDefault(e, true);
});
}
};
/*eslint-enable max-nested-callbacks */
UploadSandbox.getFiles = function (input) {
var files = nativeMethods.inputFilesGetter.call(input);
return files !== void 0 ? UploadSandbox._getCurrentInfoManager(input).getFiles(input) : void 0;
};
UploadSandbox.getUploadElementValue = function (input) {
return UploadSandbox._getCurrentInfoManager(input).getValue(input);
};
UploadSandbox.prototype.setUploadElementValue = function (input, value) {
if (value === '' && UploadSandbox._getCurrentInfoManager(input).clearUploadInfo(input) && isIE11)
this._riseChangeEvent(input);
};
// GH-1844, GH-2007
UploadSandbox._shouldRaiseChangeEvent = function (filesToUpload, currentUploadInfo) {
if (!currentUploadInfo)
return true;
// eslint-disable-next-line no-restricted-properties
var currentFiles = currentUploadInfo.files;
if (filesToUpload.length !== currentFiles.length ||
isFirefox || (isMacPlatform && isChrome || isSafari))
return true;
for (var _i = 0, filesToUpload_1 = filesToUpload; _i < filesToUpload_1.length; _i++) {
var file = filesToUpload_1[_i];
var found = false;
for (var _a = 0, currentFiles_1 = currentFiles; _a < currentFiles_1.length; _a++) {
var currentFile = currentFiles_1[_a];
if (file.name === currentFile.name) {
found = true;
break;
}
}
if (found === false)
return true;
}
return false;
};
UploadSandbox.prototype.doUpload = function (input, filePaths) {
var _this = this;
var currentInfoManager = UploadSandbox._getCurrentInfoManager(input);
filePaths = filePaths || [];
return this.infoManager.loadFilesInfoFromServer(filePaths)
.then(function (filesInfo) { return UploadInfoManager.prepareFileListWrapper(filesInfo); })
.then(function (data) {
if (!data.errs.length) {
var value = UploadInfoManager.formatValue(filePaths);
var inputInfo = currentInfoManager.getUploadInfo(input);
var shouldRaiseChangeEvent = UploadSandbox._shouldRaiseChangeEvent(data.fileList, inputInfo);
currentInfoManager.setUploadInfo(input, data.fileList, value);
if (shouldRaiseChangeEvent)
_this._riseChangeEvent(input);
}
return data.errs;
});
};
return UploadSandbox;
}(SandboxBase));
var anchor = nativeMethods.createElement.call(document, 'a');
var emptyAnchor = nativeMethods.createElement.call(document, 'a');
function getAnchorProperty(el, nativePropGetter) {
var href = nativeMethods.anchorHrefGetter.call(el);
if (!anchor)
reattach();
if (href) {
nativeMethods.anchorHrefSetter.call(anchor, getDestinationUrl(href));
return nativePropGetter.call(anchor);
}
return nativePropGetter.call(emptyAnchor);
}
function setAnchorProperty(el, nativePropSetter, value) {
var href = nativeMethods.anchorHrefGetter.call(el);
if (!anchor)
reattach();
if (href) {
nativeMethods.anchorHrefSetter.call(anchor, getDestinationUrl(href));
nativePropSetter.call(anchor, value);
el.setAttribute('href', nativeMethods.anchorHrefGetter.call(anchor));
}
return value;
}
function reattach() {
anchor = nativeMethods.createElement.call(document, 'a');
emptyAnchor = nativeMethods.createElement.call(document, 'a');
}
function dispose() {
anchor = null;
emptyAnchor = null;
}
// NOTE: For internal usage of Listeners.
var ELEMENT_LISTENING_EVENTS_STORAGE_PROP = 'hammerhead|element-listening-events-storage-prop';
function getElementCtx(el) {
return el[ELEMENT_LISTENING_EVENTS_STORAGE_PROP];
}
function getEventCtx(el, event) {
event = isIE && version > 10 && /MSPointer/.test(event) ? event.replace('MS', '').toLowerCase() : event;
var elementCtx = getElementCtx(el);
return elementCtx && elementCtx[event];
}
function isElementListening(el) {
return !!el[ELEMENT_LISTENING_EVENTS_STORAGE_PROP];
}
function addListeningElement(el, events) {
var elementCtx = getElementCtx(el) || {};
for (var i = 0; i < events.length; i++) {
if (!elementCtx[events[i]]) {
elementCtx[events[i]] = {
internalBeforeHandlers: [],
internalAfterHandlers: [],
outerHandlers: [],
outerHandlersWrapper: null,
wrappers: [],
cancelOuterHandlers: false,
};
}
}
if (!isElementListening(el)) {
nativeMethods.objectDefineProperty(el, ELEMENT_LISTENING_EVENTS_STORAGE_PROP, {
value: elementCtx,
writable: true,
});
}
}
function removeListeningElement(el) {
delete el[ELEMENT_LISTENING_EVENTS_STORAGE_PROP];
}
function addInternalAfterHandler(el, events, handler) {
var elementCtx = getElementCtx(el);
for (var _i = 0, events_1 = events; _i < events_1.length; _i++) {
var event_1 = events_1[_i];
elementCtx[event_1].internalAfterHandlers.unshift(handler);
nativeMethods.addEventListener.call(el, event_1, handler);
}
}
function addFirstInternalBeforeHandler(el, events, handler) {
var elementCtx = getElementCtx(el);
for (var _i = 0, events_2 = events; _i < events_2.length; _i++) {
var event_2 = events_2[_i];
elementCtx[event_2].internalBeforeHandlers.unshift(handler);
}
}
function addInternalBeforeHandler(el, events, handler) {
var elementCtx = getElementCtx(el);
for (var _i = 0, events_3 = events; _i < events_3.length; _i++) {
var event_3 = events_3[_i];
elementCtx[event_3].internalBeforeHandlers.push(handler);
}
}
function removeInternalBeforeHandler(el, events, handler) {
var elementCtx = getElementCtx(el);
for (var _i = 0, events_4 = events; _i < events_4.length; _i++) {
var event_4 = events_4[_i];
var internalBeforeHandlers = elementCtx[event_4].internalBeforeHandlers;
var handlerIndex = internalBeforeHandlers.indexOf(handler);
if (handlerIndex > -1)
internalBeforeHandlers.splice(handlerIndex, 1);
}
}
function wrapEventListener(eventCtx, listener, wrapper, useCapture) {
eventCtx.outerHandlers.push({
fn: listener,
useCapture: useCapture || false,
});
eventCtx.wrappers.push(wrapper);
}
function getWrapper(eventCtx, listener, useCapture) {
var originListeners = eventCtx.outerHandlers;
var wrappers = eventCtx.wrappers;
var wrapper = null;
for (var i = 0; i < originListeners.length; i++) {
var curListener = originListeners[i];
if (curListener.fn === listener && (curListener.useCapture || false) === (useCapture || false)) {
wrapper = wrappers[i];
wrappers.splice(i, 1);
originListeners.splice(i, 1);
return wrapper;
}
}
return null;
}
function updateInternalAfterHandlers(el, eventType) {
var elementCtx = getElementCtx(el);
for (var _i = 0, _a = elementCtx[eventType].internalAfterHandlers; _i < _a.length; _i++) {
var handler = _a[_i];
nativeMethods.removeEventListener.call(el, eventType, handler);
nativeMethods.addEventListener.call(el, eventType, handler);
}
}
var listeningContextUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
getElementCtx: getElementCtx,
getEventCtx: getEventCtx,
isElementListening: isElementListening,
addListeningElement: addListeningElement,
removeListeningElement: removeListeningElement,
addInternalAfterHandler: addInternalAfterHandler,
addFirstInternalBeforeHandler: addFirstInternalBeforeHandler,
addInternalBeforeHandler: addInternalBeforeHandler,
removeInternalBeforeHandler: removeInternalBeforeHandler,
wrapEventListener: wrapEventListener,
getWrapper: getWrapper,
updateInternalAfterHandlers: updateInternalAfterHandlers
});
var LISTENED_EVENTS = [
'click', 'mousedown', 'mouseup', 'dblclick', 'contextmenu', 'mousemove', 'mouseover', 'mouseout',
'pointerdown', 'pointermove', 'pointerover', 'pointerout', 'pointerup',
'MSPointerDown', 'MSPointerMove', 'MSPointerOver', 'MSPointerOut', 'MSPointerUp',
'touchstart', 'touchmove', 'touchend',
'keydown', 'keypress', 'keyup',
'change', 'focus', 'blur', 'focusin', 'focusout',
];
var EVENT_SANDBOX_DISPATCH_EVENT_FLAG = 'hammerhead|event-sandbox-dispatch-event-flag';
var Listeners = /** @class */ (function (_super) {
__extends(Listeners, _super);
function Listeners() {
var _this = _super.call(this) || this;
_this.EVENT_LISTENER_ATTACHED_EVENT = 'hammerhead|event|event-listener-attached';
_this.EVENT_LISTENER_DETACHED_EVENT = 'hammerhead|event|event-listener-detached';
_this.listeningCtx = listeningContextUtils;
_this.addInternalEventBeforeListener = _this.listeningCtx.addInternalBeforeHandler;
_this.addFirstInternalEventBeforeListener = _this.listeningCtx.addFirstInternalBeforeHandler;
_this.addInternalEventAfterListener = _this.listeningCtx.addInternalAfterHandler;
_this.removeInternalEventBeforeListener = _this.listeningCtx.removeInternalBeforeHandler;
return _this;
}
Listeners.getNativeAddEventListener = function (el) {
if (isIE11) {
if (isWindow(el))
return nativeMethods.windowAddEventListener;
return el.body !== void 0 ? nativeMethods.documentAddEventListener : nativeMethods.addEventListener;
}
return nativeMethods.addEventListener;
};
Listeners.getNativeRemoveEventListener = function (el) {
if (isIE11) {
if (isWindow(el))
return nativeMethods.windowRemoveEventListener;
return el.body !== void 0 ? nativeMethods.documentRemoveEventListener : nativeMethods.removeEventListener;
}
return nativeMethods.removeEventListener;
};
Listeners._isIEServiceHandler = function (listener) {
return listener.toString() === '[object FunctionWrapper]';
};
Listeners._getEventListenerWrapper = function (eventCtx, listener) {
return function (e) {
// NOTE: Ignore IE11's and Edge's service handlers (GH-379)
if (Listeners._isIEServiceHandler(listener) || eventCtx.cancelOuterHandlers)
return null;
if (isFunction(eventCtx.outerHandlersWrapper))
return eventCtx.outerHandlersWrapper.call(this, e, listener);
return callEventListener(this, listener, e);
};
};
Listeners._isDifferentHandler = function (outerHandlers, listener, useCapture) {
for (var _i = 0, outerHandlers_1 = outerHandlers; _i < outerHandlers_1.length; _i++) {
var outerHandler = outerHandlers_1[_i];
if (outerHandler.fn === listener && outerHandler.useCapture === useCapture)
return false;
}
return true;
};
Listeners._getUseCaptureParam = function (optionalParam) {
if (optionalParam && typeof optionalParam === 'boolean')
return optionalParam;
else if (optionalParam && typeof optionalParam === 'object')
return !!optionalParam.capture;
return false;
};
Listeners.prototype._createEventHandler = function () {
var listeners = this;
return function (e) {
var el = this;
var elWindow = el[INTERNAL_PROPS.processedContext] || window;
var eventPrevented = false;
var handlersCancelled = false;
var stopPropagationCalled = false;
var eventCtx = listeners.listeningCtx.getEventCtx(el, e.type);
if (!eventCtx)
return;
var internalHandlers = eventCtx.internalBeforeHandlers;
eventCtx.cancelOuterHandlers = false;
var preventEvent = function (allowBubbling) {
eventPrevented = true;
preventDefault(e, allowBubbling);
};
var cancelHandlers = function () {
if (!handlersCancelled)
eventCtx.cancelOuterHandlers = true;
handlersCancelled = true;
};
var stopEventPropagation = function () {
stopPropagationCalled = true;
stopPropagation(e);
};
// NOTE: Some listeners can remove itself when executed, so we need to copy the list of listeners here
var currentInternalHandlers = nativeMethods.arraySlice.call(internalHandlers);
for (var _i = 0, currentInternalHandlers_1 = currentInternalHandlers; _i < currentInternalHandlers_1.length; _i++) {
var internalHandler = currentInternalHandlers_1[_i];
internalHandler.call(el, e, elWindow[EVENT_SANDBOX_DISPATCH_EVENT_FLAG], preventEvent, cancelHandlers, stopEventPropagation);
if (eventPrevented || stopPropagationCalled)
break;
}
};
};
Listeners.prototype.createOverriddenMethods = function () {
var listeners = this;
return {
addEventListener: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var eventType = args[0], listener = args[1];
var el = this;
var useCapture = Listeners._getUseCaptureParam(args[2]);
var eventCtx = getEventCtx(el, eventType);
var nativeAddEventListener = Listeners.getNativeAddEventListener(el);
if (!eventCtx || !isValidEventListener(listener))
return nativeAddEventListener.apply(el, args);
// NOTE: T233158
var isDifferentHandler = Listeners._isDifferentHandler(eventCtx.outerHandlers, listener, useCapture);
if (!isDifferentHandler)
return null;
var wrapper = Listeners._getEventListenerWrapper(eventCtx, listener);
args[1] = wrapper;
wrapEventListener(eventCtx, listener, wrapper, useCapture);
var res = nativeAddEventListener.apply(el, args);
updateInternalAfterHandlers(el, eventType);
listeners.emit(listeners.EVENT_LISTENER_ATTACHED_EVENT, { el: el, eventType: eventType, listener: listener });
return res;
},
removeEventListener: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var eventType = args[0], listener = args[1];
var el = this;
var useCapture = Listeners._getUseCaptureParam(args[2]);
var nativeRemoveEventListener = Listeners.getNativeRemoveEventListener(el);
var eventCtx = getEventCtx(el, eventType);
if (!eventCtx || !isValidEventListener(listener))
return nativeRemoveEventListener.apply(el, args);
var wrapper = getWrapper(eventCtx, listener, useCapture);
args[1] = wrapper;
var res = nativeRemoveEventListener.apply(el, args);
listeners.emit(listeners.EVENT_LISTENER_DETACHED_EVENT, { el: el, listener: listener, eventType: eventType });
return res;
},
};
};
Listeners.prototype.initElementListening = function (el, events) {
if (events === void 0) { events = LISTENED_EVENTS; }
var nativeAddEventListener = Listeners.getNativeAddEventListener(el);
for (var _i = 0, events_1 = events; _i < events_1.length; _i++) {
var event_1 = events_1[_i];
if (!this.listeningCtx.getEventCtx(el, event_1))
nativeAddEventListener.call(el, event_1, this._createEventHandler(), true);
}
this.listeningCtx.addListeningElement(el, events);
if (isIE11) {
var overriddenMethods = this.createOverriddenMethods();
if (!el.addEventListener) {
// NOTE: we cannot use 'overrideFunction' here since the functions may not exist
el.addEventListener = overriddenMethods.addEventListener;
el.removeEventListener = overriddenMethods.removeEventListener;
overrideStringRepresentation(el.addEventListener, nativeMethods.addEventListener);
overrideStringRepresentation(el.removeEventListener, nativeMethods.removeEventListener);
}
else if (isNativeFunction(el.addEventListener)) {
overrideFunction(el, 'addEventListener', overriddenMethods.addEventListener);
overrideFunction(el, 'removeEventListener', overriddenMethods.removeEventListener);
}
}
};
Listeners.prototype.initDocumentBodyListening = function (doc) {
addListeningElement(doc.body, DOM_EVENTS);
if (isIE11) {
var overriddenMethods = this.createOverriddenMethods();
overrideFunction(doc.body, 'addEventListener', overriddenMethods.addEventListener);
overrideFunction(doc.body, 'removeEventListener', overriddenMethods.removeEventListener);
}
};
Listeners.prototype.restartElementListening = function (el) {
var nativeAddEventListener = Listeners.getNativeAddEventListener(el);
var elementCtx = this.listeningCtx.getElementCtx(el);
if (elementCtx) {
var eventNames = nativeMethods.objectKeys(elementCtx);
for (var _i = 0, eventNames_1 = eventNames; _i < eventNames_1.length; _i++) {
var eventName = eventNames_1[_i];
nativeAddEventListener.call(el, eventName, this._createEventHandler(), true);
}
}
};
Listeners.prototype.cancelElementListening = function (el) {
this.listeningCtx.removeListeningElement(el);
if (el.body)
this.listeningCtx.removeListeningElement(el.body);
};
Listeners.beforeDispatchEvent = function (el) {
var elWindow = el[INTERNAL_PROPS.processedContext] || window;
elWindow[EVENT_SANDBOX_DISPATCH_EVENT_FLAG] = (elWindow[EVENT_SANDBOX_DISPATCH_EVENT_FLAG] || 0) + 1;
};
Listeners.afterDispatchEvent = function (el) {
var elWindow = el[INTERNAL_PROPS.processedContext] || window;
elWindow[EVENT_SANDBOX_DISPATCH_EVENT_FLAG]--;
if (!elWindow[EVENT_SANDBOX_DISPATCH_EVENT_FLAG])
delete elWindow[EVENT_SANDBOX_DISPATCH_EVENT_FLAG];
};
Listeners.prototype.setEventListenerWrapper = function (el, events, wrapper) {
if (!this.listeningCtx.isElementListening(el))
this.initElementListening(el, events);
for (var _i = 0, events_2 = events; _i < events_2.length; _i++) {
var event_2 = events_2[_i];
var eventCtx = this.listeningCtx.getEventCtx(el, event_2);
eventCtx.outerHandlersWrapper = wrapper;
}
};
Listeners.prototype.getEventListeners = function (el, event) {
var eventCtx = this.listeningCtx.getEventCtx(el, event);
if (!eventCtx)
return null;
return nativeMethods.arrayMap.call(eventCtx.outerHandlers, function (handler) { return handler.fn; });
};
return Listeners;
}(EventEmitter));
var DefaultTarget;
(function (DefaultTarget) {
DefaultTarget["form"] = "_self";
DefaultTarget["linkOrArea"] = "_self";
DefaultTarget["windowOpen"] = "_blank";
})(DefaultTarget || (DefaultTarget = {}));
var defaultTarget = DefaultTarget;
var SET_SERVICE_WORKER_SETTINGS = 'hammerhead|set-service-worker-settings';
var INSTRUCTION_VALUES = (function () {
var values = [];
var keys = nativeMethods.objectKeys(SCRIPT_PROCESSING_INSTRUCTIONS);
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
values.push(SCRIPT_PROCESSING_INSTRUCTIONS[key]);
}
return values;
})();
var HTTP_PROTOCOL_RE = /^http/i;
var ALLOWED_SERVICE_WORKER_PROTOCOLS = ['https:', 'wss:', 'file:'];
var ALLOWED_SERVICE_WORKER_HOST_NAMES = ['localhost', '127.0.0.1'];
var JAVASCRIPT_MIME_TYPES = ['text/javascript', 'application/javascript', 'application/x-javascript'];
// NOTE: SVGAnimatedString prototype does not have a way to access the appropriate svg element.
// This is why we use this property to store svg element for which animVal and baseVal properties were set.
// It allows us to change the href-hammerhead-stored-value when it needs.
var CONTEXT_SVG_IMAGE_ELEMENT = 'hammerhead|context-svg-image-element';
var SANDBOX_DOM_TOKEN_LIST = 'hammerhead|sandbox-dom-token-list';
var SANDBOX_DOM_TOKEN_LIST_OWNER = 'hammerhead|sandbox-dom-token-list-owner';
var SANDBOX_DOM_TOKEN_LIST_UPDATE_FN = 'hammerhead|sandbox-dom-token-list-update';
var IS_PROXY_OBJECT_INTERNAL_PROP_NAME = 'hammerhead|is-proxy-object|internal-prop-name';
var IS_PROXY_OBJECT_INTERNAL_PROP_VALUE = 'hammerhead|is-proxy-object|internal-prop-value';
var PROXY_HANDLER_FLAG = 'hammerhead|proxy-handler-flag';
var NO_STACK_TRACE_AVAILABLE_MESSAGE = 'No stack trace available';
var DEFAULT_UNHANDLED_REJECTION_REASON_NAME = 'Error';
var TRACKED_EVENTS = ['error', 'unhandledrejection', 'hashchange'];
var WindowSandbox = /** @class */ (function (_super) {
__extends(WindowSandbox, _super);
function WindowSandbox(nodeSandbox, eventSandbox, uploadSandbox, nodeMutation, _childWindowSandbox, _documentTitleStorageInitializer) {
var _this = _super.call(this) || this;
_this._childWindowSandbox = _childWindowSandbox;
_this._documentTitleStorageInitializer = _documentTitleStorageInitializer;
_this.UNCAUGHT_JS_ERROR_EVENT = 'hammerhead|event|uncaught-js-error';
_this.UNHANDLED_REJECTION_EVENT = 'hammerhead|event|unhandled-rejection';
_this.HASH_CHANGE_EVENT = 'hammerhead|event|hashchange-event';
_this.nodeSandbox = nodeSandbox;
_this.messageSandbox = eventSandbox.message;
_this.listenersSandbox = eventSandbox.listeners;
_this.elementEditingWatcher = eventSandbox.elementEditingWatcher;
_this.eventSimulator = eventSandbox.eventSimulator;
_this.uploadSandbox = uploadSandbox;
_this.shadowUI = nodeSandbox.shadowUI;
_this.nodeMutation = nodeMutation;
_this.SANDBOX_DOM_TOKEN_LIST_UPDATE_FN = SANDBOX_DOM_TOKEN_LIST_UPDATE_FN;
return _this;
}
WindowSandbox._prepareStack = function (msg, stack) {
// NOTE: Firefox does not include an error message in a stack trace (unlike other browsers)
// It is possible to get a stack trace for unhandled Promise rejections only if Promise is rejected with the 'Error' instance value.
// This is why we should convert the stack to a common format.
if (!stack || stack.indexOf(msg) === -1) {
stack = stack || " ".concat(NO_STACK_TRACE_AVAILABLE_MESSAGE);
return "".concat(msg, "\n").concat(stack);
}
return stack;
};
WindowSandbox._getBlobProcessingSettings = function () {
return {
sessionId: settings.get().sessionId,
windowId: settings.get().windowId,
origin: getOriginHeader(),
};
};
WindowSandbox._isProcessableBlobParts = function (parts) {
var hasStringItem = false;
for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) {
var item = parts_1[_i];
if (!hasStringItem && typeof item === 'string') {
hasStringItem = true;
continue;
}
if (typeof item !== 'string' && typeof item !== 'number' && typeof item !== 'boolean')
return false;
}
return hasStringItem;
};
WindowSandbox._isProcessableBlob = function (array, opts) {
var type = opts && opts.type && opts.type.toString().toLowerCase() || getMimeType(array);
// NOTE: If we cannot identify the content type of data, we're trying to process it as a script
// (in the case of the "Array<string | number | boolean>" blob parts array: GH-2115).
// Unfortunately, we do not have the ability to exactly identify a script. That's why we make such
// an assumption. We cannot solve this problem at the Worker level either, because the operation of
// creating a new Blob instance is asynchronous. (GH-231)
return (!type || JAVASCRIPT_MIME_TYPES.indexOf(type) !== -1) && WindowSandbox._isProcessableBlobParts(array);
};
WindowSandbox.prototype._getWindowOpenTarget = function (originTarget) {
if (originTarget)
return this.nodeSandbox.element.getCorrectedTarget(String(originTarget));
return settings.get().allowMultipleWindows ? defaultTarget.windowOpen : '_self';
};
WindowSandbox.prototype._raiseUncaughtJsErrorEvent = function (type, event, window) {
if (isCrossDomainWindows(window, window.top))
return;
var sendToTopWindow = isIframeWindow(window);
var pageUrl = get$2();
var msg = null;
var stack = null;
if (type === this.UNHANDLED_REJECTION_EVENT) {
msg = WindowSandbox._formatUnhandledRejectionReason(event.reason);
stack = event.reason && event.reason.stack;
}
else if (type === this.UNCAUGHT_JS_ERROR_EVENT) {
msg = event.error ? event.error.message : event.message;
stack = event.error && event.error.stack;
}
stack = WindowSandbox._prepareStack(msg, stack);
stack = replaceProxiedUrlsInStack(stack);
if (sendToTopWindow) {
this.emit(type, { msg: msg, pageUrl: pageUrl, stack: stack, inIframe: true });
this.messageSandbox.sendServiceMsg({ msg: msg, pageUrl: pageUrl, stack: stack, cmd: type }, window.top);
}
else
this.emit(type, { msg: msg, pageUrl: pageUrl, stack: stack });
};
WindowSandbox.prototype._reattachHandler = function (window, eventName) {
var nativeAddEventListener = Listeners.getNativeAddEventListener(window);
var nativeRemoveEventListener = Listeners.getNativeRemoveEventListener(window);
nativeRemoveEventListener.call(window, eventName, this);
nativeAddEventListener.call(window, eventName, this);
};
WindowSandbox._formatUnhandledRejectionReason = function (reason) {
if (!isPrimitiveType(reason)) {
if (reason instanceof nativeMethods.Error) {
var name_1 = reason.name || DEFAULT_UNHANDLED_REJECTION_REASON_NAME;
return "".concat(name_1, ": ").concat(reason.message);
}
return nativeMethods.objectToString.call(reason);
}
return String(reason);
};
WindowSandbox._getUrlAttr = function (el, attr) {
var attrValue = nativeMethods.getAttribute.call(el, attr);
var currentDocument = el.ownerDocument || document;
if (attrValue === '' || attrValue === null && attr === 'action' && emptyActionAttrFallbacksToTheLocation)
return urlResolver.resolve('', currentDocument);
else if (attrValue === null)
return '';
else if (HASH_RE$1.test(attrValue))
return urlResolver.resolve(attrValue, currentDocument);
else if (!isValidUrl(attrValue))
return urlResolver.resolve(attrValue, currentDocument);
return resolveUrlAsDest(attrValue, attr === 'srcset');
};
WindowSandbox._removeProcessingInstructions = function (text) {
if (text) {
text = remove$1(text);
return styleProcessor.cleanUp(text, parseProxyUrl);
}
return text;
};
WindowSandbox._processTextPropValue = function (el, text) {
var processedText = text !== null && text !== void 0 ? String(text) : text;
if (processedText) {
if (isScriptElement(el))
return processScript(processedText, true, false, convertToProxyUrl, void 0, settings.get().proxyless);
else if (isStyleElement(el))
return styleProcessor.process(processedText, getProxyUrl, true);
}
return processedText;
};
WindowSandbox.prototype._overrideUrlAttrDescriptors = function (attr, elementConstructors) {
var windowSandbox = this;
for (var _i = 0, elementConstructors_1 = elementConstructors; _i < elementConstructors_1.length; _i++) {
var constructor = elementConstructors_1[_i];
overrideDescriptor(constructor.prototype, attr, {
getter: function () {
return WindowSandbox._getUrlAttr(this, attr);
},
setter: function (value) {
windowSandbox.nodeSandbox.element.setAttributeCore(this, [attr, value]);
},
});
}
};
WindowSandbox.prototype._overrideAttrDescriptors = function (attr, elementConstructors) {
var windowSandbox = this;
for (var _i = 0, elementConstructors_2 = elementConstructors; _i < elementConstructors_2.length; _i++) {
var constructor = elementConstructors_2[_i];
overrideDescriptor(constructor.prototype, attr, {
getter: function () {
return windowSandbox.nodeSandbox.element.getAttributeCore(this, [attr]) || '';
},
setter: function (value) {
windowSandbox.nodeSandbox.element.setAttributeCore(this, [attr, value]);
},
});
}
};
WindowSandbox.prototype._overrideUrlPropDescriptor = function (prop, nativePropGetter, nativePropSetter) {
// @ts-ignore
overrideDescriptor(window.HTMLAnchorElement.prototype, prop, {
getter: function () {
return getAnchorProperty(this, nativePropGetter);
},
setter: function (value) {
setAnchorProperty(this, nativePropSetter, value);
},
});
};
WindowSandbox.prototype._overrideEventPropDescriptor = function (window, eventName, nativePropSetter) {
var _this = this;
// @ts-ignore
var eventPropsOwner = nativeMethods.isEventPropsLocatedInProto ? window.Window.prototype : window;
overrideDescriptor(eventPropsOwner, 'on' + eventName, {
getter: null,
setter: function (handler) {
nativePropSetter.call(window, handler);
_this.listenersSandbox.emit(_this.listenersSandbox.EVENT_LISTENER_ATTACHED_EVENT, {
el: window,
listener: handler,
eventType: eventName,
});
},
});
};
WindowSandbox.prototype._createOverriddenDOMTokenListMethod = function (nativeMethod) {
var windowSandbox = this;
return function () {
var executionResult = nativeMethod.apply(this, arguments);
var tokenListOwner = this[SANDBOX_DOM_TOKEN_LIST_OWNER];
if (tokenListOwner)
// eslint-disable-next-line no-restricted-properties
windowSandbox.nodeSandbox.element.setAttributeCore(tokenListOwner, ['sandbox', this.toString()]);
return executionResult;
};
};
WindowSandbox._patchFunctionPrototype = function (fn, ctx) {
if (!ctx || isFunction(ctx))
return;
var inheritorProto = nativeMethods.objectGetPrototypeOf(ctx);
if (!inheritorProto)
return;
var fnProto = nativeMethods.objectGetPrototypeOf(inheritorProto);
while (fnProto && fnProto !== nativeMethods.Function.prototype)
fnProto = nativeMethods.objectGetPrototypeOf(fnProto);
if (!fnProto)
return;
// NOTE: Warning: Changing the [[Prototype]] of an object is currently a very slow operation in every browser
// and JavaScript engine. In addition, the effects of altering inheritance are subtle and far-flung, and are not
// limited to the time spent in the Object.setPrototypeOf(...) statement, but may extend to any code that has
// access to any object whose [[Prototype]] has been altered.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf
nativeMethods.objectSetPrototypeOf(fn, inheritorProto);
};
WindowSandbox._isSecureOrigin = function (url) {
// NOTE: https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features
var parsedUrl = parseUrl(resolveUrlAsDest(url));
/*eslint-disable no-restricted-properties*/
return ALLOWED_SERVICE_WORKER_PROTOCOLS.indexOf(parsedUrl.protocol) === -1 &&
ALLOWED_SERVICE_WORKER_HOST_NAMES.indexOf(parsedUrl.hostname) === -1;
/*eslint-enable no-restricted-properties*/
};
WindowSandbox.prototype._setSandboxedTextForTitleElements = function (el) {
if (isIframeWindow(window))
return;
var titleElements = getNativeQuerySelectorAll(el).call(el, 'title');
for (var _i = 0, titleElements_1 = titleElements; _i < titleElements_1.length; _i++) {
var titleElement = titleElements_1[_i];
// NOTE: SVGTitleElement can be here (GH-2364)
if (!isTitleElement(titleElement))
continue;
var nativeText = nativeMethods.titleElementTextGetter.call(titleElement);
this._documentTitleStorageInitializer.storage.setTitleElementPropertyValue(titleElement, nativeText);
}
};
WindowSandbox.prototype._overrideAllUrlAttrDescriptors = function () {
this._overrideUrlAttrDescriptors('data', [window.HTMLObjectElement]);
if (!this.proxyless) {
this._overrideUrlAttrDescriptors('src', [
window.HTMLImageElement,
window.HTMLScriptElement,
window.HTMLEmbedElement,
window.HTMLSourceElement,
window.HTMLMediaElement,
window.HTMLInputElement,
window.HTMLFrameElement,
window.HTMLIFrameElement,
]);
}
this._overrideUrlAttrDescriptors('action', [window.HTMLFormElement]);
this._overrideUrlAttrDescriptors('formAction', [
window.HTMLInputElement,
window.HTMLButtonElement,
]);
if (!this.proxyless) {
this._overrideUrlAttrDescriptors('href', [
window.HTMLAnchorElement,
window.HTMLLinkElement,
window.HTMLAreaElement,
window.HTMLBaseElement,
]);
}
if (nativeMethods.htmlManifestGetter)
this._overrideUrlAttrDescriptors('manifest', [window.HTMLHtmlElement]);
};
WindowSandbox.isProxyObject = function (obj) {
try {
return obj[IS_PROXY_OBJECT_INTERNAL_PROP_NAME] === IS_PROXY_OBJECT_INTERNAL_PROP_VALUE;
}
catch (e) {
return false;
}
};
WindowSandbox.prototype.handleEvent = function (event) {
if (event.defaultPrevented)
return;
if (event.type === 'unhandledrejection')
this._raiseUncaughtJsErrorEvent(this.UNHANDLED_REJECTION_EVENT, event, this.window);
else if (event.type === 'error') {
if (event.message.indexOf('NS_ERROR_NOT_INITIALIZED') !== -1)
event.preventDefault();
else
this._raiseUncaughtJsErrorEvent(this.UNCAUGHT_JS_ERROR_EVENT, event, window);
}
else if (event.type === 'hashchange')
this.emit(this.HASH_CHANGE_EVENT);
};
WindowSandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
var messageSandbox = this.messageSandbox;
var nodeSandbox = this.nodeSandbox;
var windowSandbox = this;
nativeMethods.arrayForEach.call(TRACKED_EVENTS, function (event) {
_this._reattachHandler(window, event);
});
this.listenersSandbox.initElementListening(window, TRACKED_EVENTS);
this.listenersSandbox.on(this.listenersSandbox.EVENT_LISTENER_ATTACHED_EVENT, function (e) {
if (e.el !== window)
return;
if (TRACKED_EVENTS.indexOf(e.eventType) !== -1)
_this._reattachHandler(window, e.eventType);
});
this._overrideEventPropDescriptor(window, 'error', nativeMethods.winOnErrorSetter);
this._overrideEventPropDescriptor(window, 'hashchange', nativeMethods.winOnHashChangeSetter);
if (nativeMethods.winOnUnhandledRejectionSetter)
this._overrideEventPropDescriptor(window, 'unhandledrejection', nativeMethods.winOnUnhandledRejectionSetter);
messageSandbox.on(messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (e) {
var _a = e.message, msg = _a.msg, pageUrl = _a.pageUrl, stack = _a.stack, cmd = _a.cmd;
if (cmd === _this.UNCAUGHT_JS_ERROR_EVENT || cmd === _this.UNHANDLED_REJECTION_EVENT)
windowSandbox.emit(cmd, { msg: msg, pageUrl: pageUrl, stack: stack });
});
overrideFunction(window.CanvasRenderingContext2D.prototype, 'drawImage', function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var image = args[0];
if (isImgElement(image) && !image[INTERNAL_PROPS.forceProxySrcForImage]) {
var src = nativeMethods.imageSrcGetter.call(image);
if (sameOriginCheck(location.toString(), src)) {
image = nativeMethods.createElement.call(window.document, 'img');
nativeMethods.imageSrcSetter.call(image, getProxyUrl(src));
args[0] = image;
if (!image.complete) {
nativeMethods.addEventListener.call(image, 'load', function () { return nativeMethods.canvasContextDrawImage.apply(_this, args); });
}
}
}
return nativeMethods.canvasContextDrawImage.apply(this, args);
});
if (nativeMethods.objectAssign) {
overrideFunction(window.Object, 'assign', function (target) {
var sources = [];
for (var _i = 1; _i < arguments.length; _i++) {
sources[_i - 1] = arguments[_i];
}
var args = [target];
var targetType = typeof target;
if (target && (targetType === 'object' || targetType === 'function') && sources.length) {
for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) {
var source = sources_1[_a];
var sourceType = typeof source;
if (!source || sourceType !== 'object' && sourceType !== 'function') {
nativeMethods.objectAssign.call(this, target, source);
continue;
}
var sourceSymbols = nativeMethods.objectGetOwnPropertySymbols.call(window.Object, source);
var sourceKeys = nativeMethods.arrayConcat.call(nativeMethods.objectKeys.call(window.Object, source), sourceSymbols);
for (var _b = 0, sourceKeys_1 = sourceKeys; _b < sourceKeys_1.length; _b++) {
var key = sourceKeys_1[_b];
window[SCRIPT_PROCESSING_INSTRUCTIONS.setProperty](target, key, source[key]);
}
}
}
else
args = nativeMethods.arrayConcat.call(args, sources);
return nativeMethods.objectAssign.apply(this, args);
});
}
overrideFunction(window, 'open', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
args[0] = getProxyUrl(args[0]);
args[1] = windowSandbox._getWindowOpenTarget(args[1]);
return windowSandbox._childWindowSandbox.handleWindowOpen(window, args);
});
if (window.FontFace && !this.proxyless) {
overrideConstructor(window, 'FontFace', function (family, source, descriptors) {
source = styleProcessor.process(source, convertToProxyUrl);
return new nativeMethods.FontFace(family, source, descriptors);
});
}
if (window.Worker && !this.proxyless) {
overrideConstructor(window, 'Worker', function WorkerWrapper() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var isCalledWithoutNewKeyword = constructorIsCalledWithoutNewKeyword(this, WorkerWrapper);
if (arguments.length === 0)
// @ts-ignore
return isCalledWithoutNewKeyword ? nativeMethods.Worker() : new nativeMethods.Worker();
if (isCalledWithoutNewKeyword)
return nativeMethods.Worker.apply(this, args);
var scriptURL = args[0];
if (typeof scriptURL !== 'string')
scriptURL = String(scriptURL);
scriptURL = getProxyUrl(scriptURL, { resourceType: stringifyResourceType({ isScript: true }) });
var worker = arguments.length === 1
? new nativeMethods.Worker(scriptURL)
: new nativeMethods.Worker(scriptURL, args[1]);
return worker;
}, true);
}
if (window.Blob) {
overrideConstructor(window, 'Blob', function (array, opts) {
if (arguments.length === 0)
return new nativeMethods.Blob();
if (WindowSandbox._isProcessableBlob(array, opts))
array = [processScript(array.join(''), true, false, convertToProxyUrl, void 0, settings.get().proxyless, WindowSandbox._getBlobProcessingSettings())];
// NOTE: IE11 throws an error when the second parameter of the Blob function is undefined (GH-44)
// If the overridden function is called with one parameter, we need to call the original function
// with one parameter as well.
return arguments.length === 1 ? new nativeMethods.Blob(array) : new nativeMethods.Blob(array, opts);
});
}
// NOTE: non-IE11 case. window.File in IE11 is not constructable.
if (nativeMethods.File) {
overrideConstructor(window, 'File', function (array, fileName, opts) {
if (arguments.length === 0)
return new nativeMethods.File();
if (WindowSandbox._isProcessableBlob(array, opts))
array = [processScript(array.join(''), true, false, convertToProxyUrl, void 0, settings.get().proxyless, WindowSandbox._getBlobProcessingSettings())];
return new nativeMethods.File(array, fileName, opts);
});
}
if (window.EventSource && !this.proxyless) {
overrideConstructor(window, 'EventSource', function (url, opts) {
if (arguments.length) {
var proxyUrl = getProxyUrl(url, { resourceType: stringifyResourceType({ isEventSource: true }) });
if (arguments.length === 1)
return new nativeMethods.EventSource(proxyUrl);
return new nativeMethods.EventSource(proxyUrl, opts);
}
return new nativeMethods.EventSource();
});
window.EventSource.CONNECTING = nativeMethods.EventSource.CONNECTING;
window.EventSource.OPEN = nativeMethods.EventSource.OPEN;
window.EventSource.CLOSED = nativeMethods.EventSource.CLOSED;
}
if (window.MutationObserver) {
overrideConstructor(window, 'MutationObserver', function (callback) {
var wrapper = function (mutations) {
var result = [];
for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) {
var mutation = mutations_1[_i];
if (!ShadowUISandbox.isShadowUIMutation(mutation))
result.push(mutation);
}
if (result.length)
callback.call(this, result, this);
};
return new nativeMethods.MutationObserver(wrapper);
});
if (window.WebKitMutationObserver)
window.WebKitMutationObserver = window.MutationObserver;
}
if (window.Proxy) {
overrideConstructor(window, 'Proxy', function (target, handler) {
if (handler.get && !handler.get[PROXY_HANDLER_FLAG]) {
var storedGet_1 = handler.get;
handler.get = function (getterTarget, name, receiver) {
if (name === IS_PROXY_OBJECT_INTERNAL_PROP_NAME)
return IS_PROXY_OBJECT_INTERNAL_PROP_VALUE;
else if (INSTRUCTION_VALUES.indexOf(name) > -1)
return window[name];
var result = storedGet_1.call(this, getterTarget, name, receiver);
if (name === 'eval' && result[CodeInstrumentation.WRAPPED_EVAL_FN])
return result[CodeInstrumentation.WRAPPED_EVAL_FN];
return result;
};
nativeMethods.objectDefineProperty(handler.get, PROXY_HANDLER_FLAG, { value: true, enumerable: false });
}
return new nativeMethods.Proxy(target, handler);
});
window.Proxy.revocable = nativeMethods.Proxy.revocable;
}
if (nativeMethods.registerServiceWorker && !this.proxyless) {
overrideFunction(window.navigator.serviceWorker, 'register', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var url = args[0], opts = args[1];
if (typeof url === 'string') {
if (WindowSandbox._isSecureOrigin(url)) {
// NOTE: We cannot create an instance of the DOMException in the Android 6.0 and in the Edge 17 browsers.
// The 'TypeError: Illegal constructor' error is raised if we try to call the constructor.
return pinkie.reject(isAndroid || isMSEdge && version >= 17
? new Error('Only secure origins are allowed.')
: new DOMException('Only secure origins are allowed.', 'SecurityError'));
}
args[0] = getProxyUrl(url, { resourceType: stringifyResourceType({ isServiceWorker: true }) });
}
args[1] = { scope: '/' };
return nativeMethods.registerServiceWorker.apply(window.navigator.serviceWorker, args)
.then(function (reg) { return new pinkie(function (resolve, reject) {
var parsedProxyUrl = parseProxyUrl(args[0]);
var serviceWorker = reg.installing;
if (!serviceWorker) {
resolve(reg);
return;
}
var channel = new nativeMethods.MessageChannel();
serviceWorker.postMessage({
cmd: SET_SERVICE_WORKER_SETTINGS,
currentScope: getScope(url),
optsScope: getScope(opts && opts.scope),
protocol: parsedProxyUrl.destResourceInfo.protocol,
host: parsedProxyUrl.destResourceInfo.host, // eslint-disable-line no-restricted-properties
}, [channel.port1]);
channel.port2.onmessage = function (e) {
var data = nativeMethods.messageEventDataGetter.call(e);
if (data.error)
reject(new Error(data.error));
else
resolve(reg);
};
}); });
});
}
if (nativeMethods.getRegistrationServiceWorker && !this.proxyless) {
overrideFunction(window.navigator.serviceWorker, 'getRegistration', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (typeof args[0] === 'string')
args[0] = '/';
return nativeMethods.getRegistrationServiceWorker.apply(window.navigator.serviceWorker, args);
});
}
if (window.Range.prototype.createContextualFragment) {
overrideFunction(window.Range.prototype, 'createContextualFragment', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var tagString = args[0];
if (typeof tagString === 'string') {
args[0] = processHtml(tagString, {
processedContext: this.startContainer && this.startContainer[INTERNAL_PROPS.processedContext],
});
}
var fragment = nativeMethods.createContextualFragment.apply(this, args);
nodeSandbox.processNodes(fragment);
return fragment;
});
}
if (window.EventTarget) {
var overriddenMethods = this.listenersSandbox.createOverriddenMethods();
overrideFunction(window.EventTarget.prototype, 'addEventListener', overriddenMethods.addEventListener);
overrideFunction(window.EventTarget.prototype, 'removeEventListener', overriddenMethods.removeEventListener);
}
if (!this.proxyless) {
overrideConstructor(window, 'Image', function () {
var image = null;
if (!arguments.length)
image = new nativeMethods.Image();
else if (arguments.length === 1)
image = new nativeMethods.Image(arguments[0]);
else
image = new nativeMethods.Image(arguments[0], arguments[1]);
image[INTERNAL_PROPS.forceProxySrcForImage] = true;
nodeSandbox.processNodes(image);
return image;
});
}
overrideConstructor(window, 'Function', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var functionBodyArgIndex = args.length - 1;
if (typeof args[functionBodyArgIndex] === 'string')
args[functionBodyArgIndex] = processScript(args[functionBodyArgIndex], false, false, convertToProxyUrl);
var fn = nativeMethods.Function.apply(this, args);
WindowSandbox._patchFunctionPrototype(fn, this);
return fn;
}, true);
overrideFunction(nativeMethods.Function.prototype, 'toString', function () {
if (nativeMethods.objectHasOwnProperty.call(this, INTERNAL_PROPS.nativeStrRepresentation))
return this[INTERNAL_PROPS.nativeStrRepresentation];
return nativeMethods.functionToString.call(this);
});
if (isFunction(window.history.pushState)
&& isFunction(window.history.replaceState)
&& !this.proxyless) {
var createWrapperForHistoryStateManipulationFn = function (nativeFn) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var url = args[2];
if (args.length > 2 && (url !== null && (isIE || url !== void 0)))
args[2] = getProxyUrl(url);
return nativeFn.apply(this, args);
};
};
overrideFunction(window.history, 'pushState', createWrapperForHistoryStateManipulationFn(nativeMethods.historyPushState));
overrideFunction(window.history, 'replaceState', createWrapperForHistoryStateManipulationFn(nativeMethods.historyReplaceState));
}
if (nativeMethods.sendBeacon && !this.proxyless) {
overrideFunction(window.Navigator.prototype, 'sendBeacon', function () {
if (typeof arguments[0] === 'string')
arguments[0] = getProxyUrl(arguments[0]);
return nativeMethods.sendBeacon.apply(this, arguments);
});
}
if (window.navigator.registerProtocolHandler && !this.proxyless) {
overrideFunction(window.navigator, 'registerProtocolHandler', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var urlIndex = 1;
if (typeof args[urlIndex] === 'string') {
// eslint-disable-next-line no-restricted-properties
var destHostname = getParsed().hostname;
var isDestUrl = false;
if (isFirefox) {
var parsedUrl = parseUrl(args[urlIndex]);
// eslint-disable-next-line no-restricted-properties
isDestUrl = parsedUrl.hostname && destHostname === parsedUrl.hostname;
}
else
isDestUrl = sameOriginCheck(get$2(), args[urlIndex]);
if (isDestUrl)
args[urlIndex] = getProxyUrl(args[urlIndex]);
}
return nativeMethods.registerProtocolHandler.apply(navigator, args);
});
}
if (window.FormData) {
overrideFunction(window.FormData.prototype, 'append', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var name = args[0], value = args[1];
// NOTE: We should not send our hidden input's value along with the file info,
// because our input may have incorrect value if the input with the file has been removed from DOM.
if (name === INTERNAL_ATTRIBUTES.uploadInfoHiddenInputName)
return;
// NOTE: If we append our file wrapper to FormData, we will lose the file name.
// This happens because the file wrapper is an instance of Blob
// and a browser thinks that Blob does not contain the "name" property.
if (args.length === 2 && isBlob(value) && 'name' in value)
args[2] = value['name'];
nativeMethods.formDataAppend.apply(this, args);
});
}
if (window.WebSocket && !this.proxyless) {
overrideConstructor(window, 'WebSocket', function (url, protocols) {
if (arguments.length === 0)
return new nativeMethods.WebSocket();
var proxyUrl = getProxyUrl(url, { resourceType: stringifyResourceType({ isWebSocket: true }) });
if (arguments.length === 1)
return new nativeMethods.WebSocket(proxyUrl);
else if (arguments.length === 2)
return new nativeMethods.WebSocket(proxyUrl, protocols);
return new nativeMethods.WebSocket(proxyUrl, protocols, arguments[2]);
});
window.WebSocket.CONNECTING = nativeMethods.WebSocket.CONNECTING;
window.WebSocket.OPEN = nativeMethods.WebSocket.OPEN;
window.WebSocket.CLOSING = nativeMethods.WebSocket.CLOSING;
window.WebSocket.CLOSED = nativeMethods.WebSocket.CLOSED;
if (nativeMethods.webSocketUrlGetter) {
overrideDescriptor(window.WebSocket.prototype, 'url', {
getter: function () {
var url = nativeMethods.webSocketUrlGetter.call(this);
var parsedUrl = parseProxyUrl(url);
if (parsedUrl && parsedUrl.destUrl)
return parsedUrl.destUrl.replace(HTTP_PROTOCOL_RE, 'ws');
return url;
},
});
}
}
if (!this.proxyless) {
overrideDescriptor(window.MessageEvent.prototype, 'origin', {
getter: function () {
var target = nativeMethods.eventTargetGetter.call(this);
var origin = nativeMethods.messageEventOriginGetter.call(this);
if (isWebSocket(target)) {
var parsedUrl = parseUrl(target.url);
if (parsedUrl)
// eslint-disable-next-line no-restricted-properties
return parsedUrl.protocol + '//' + parsedUrl.host;
}
else if (isWindow(target)) {
var data = nativeMethods.messageEventDataGetter.call(this);
if (data)
return data.originUrl;
}
return origin;
},
});
}
overrideDescriptor(window.HTMLCollection.prototype, 'length', {
getter: function () {
var length = nativeMethods.htmlCollectionLengthGetter.call(this);
if (ShadowUISandbox.isShadowContainerCollection(this, length))
return windowSandbox.shadowUI.getShadowUICollectionLength(this, length);
return length;
},
});
overrideDescriptor(window.NodeList.prototype, 'length', {
getter: function () {
var length = nativeMethods.nodeListLengthGetter.call(this);
if (ShadowUISandbox.isShadowContainerCollection(this))
return windowSandbox.shadowUI.getShadowUICollectionLength(this, length);
return length;
},
});
overrideDescriptor(window.Element.prototype, 'childElementCount', {
getter: function () {
if (ShadowUISandbox.isShadowContainer(this)) {
var children = nativeMethods.elementChildrenGetter.call(this);
var length_1 = nativeMethods.htmlCollectionLengthGetter.call(children);
return windowSandbox.shadowUI.getShadowUICollectionLength(children, length_1);
}
return nativeMethods.elementChildElementCountGetter.call(this);
},
});
if (nativeMethods.performanceEntryNameGetter && !this.proxyless) {
overrideDescriptor(window.PerformanceEntry.prototype, 'name', {
getter: function () {
var name = nativeMethods.performanceEntryNameGetter.call(this);
if (isPerformanceNavigationTiming(this)) {
var parsedProxyUrl = parseProxyUrl(name);
if (parsedProxyUrl)
return parsedProxyUrl.destUrl;
}
return name;
},
});
}
overrideDescriptor(window.HTMLInputElement.prototype, 'files', {
getter: function () {
if (this.type.toLowerCase() === 'file')
return UploadSandbox.getFiles(this);
return nativeMethods.inputFilesGetter.call(this);
},
});
overrideDescriptor(window.HTMLInputElement.prototype, 'value', {
getter: function () {
if (this.type.toLowerCase() === 'file')
return UploadSandbox.getUploadElementValue(this);
return nativeMethods.inputValueGetter.call(this);
},
setter: function (value) {
if (this.type.toLowerCase() === 'file')
return windowSandbox.uploadSandbox.setUploadElementValue(this, value);
nativeMethods.inputValueSetter.call(this, value);
var valueChanged = value !== nativeMethods.inputValueGetter.call(this);
if (valueChanged && !isShadowUIElement(this) && isTextEditableElementAndEditingAllowed(this))
windowSandbox.elementEditingWatcher.restartWatchingElementEditing(this);
},
});
// NOTE: HTMLInputElement raises the `change` event on `disabled` only in Chrome
if (isChrome) {
overrideDescriptor(window.HTMLInputElement.prototype, 'disabled', {
getter: null,
setter: function (value) {
if (nativeMethods.documentActiveElementGetter.call(document) === this) {
var savedValue = windowSandbox.elementEditingWatcher.getElementSavedValue(this);
var currentValue = nativeMethods.inputValueGetter.call(this);
if (windowSandbox.elementEditingWatcher.isEditingObserved(this) && currentValue !== savedValue)
windowSandbox.eventSimulator.change(this);
windowSandbox.elementEditingWatcher.stopWatching(this);
}
nativeMethods.inputDisabledSetter.call(this, value);
},
});
}
overrideDescriptor(window.HTMLInputElement.prototype, 'required', {
getter: function () {
return windowSandbox.nodeSandbox.element.getAttributeCore(this, ['required']) !== null;
},
setter: function (value) {
if (this.type.toLowerCase() !== 'file')
nativeMethods.inputRequiredSetter.call(this, value);
else if (value)
windowSandbox.nodeSandbox.element.setAttributeCore(this, ['required', '']);
else
windowSandbox.nodeSandbox.element.removeAttributeCore(this, ['required']);
},
});
overrideDescriptor(window.HTMLTextAreaElement.prototype, 'value', {
getter: null,
setter: function (value) {
nativeMethods.textAreaValueSetter.call(this, value);
if (!isShadowUIElement(this) && isTextEditableElementAndEditingAllowed(this))
windowSandbox.elementEditingWatcher.restartWatchingElementEditing(this);
},
});
if (!this.proxyless)
this._overrideAllUrlAttrDescriptors();
this._overrideAttrDescriptors('target', [
window.HTMLAnchorElement,
window.HTMLFormElement,
window.HTMLAreaElement,
window.HTMLBaseElement,
]);
this._overrideAttrDescriptors('formTarget', [
window.HTMLInputElement,
window.HTMLButtonElement,
]);
this._overrideAttrDescriptors('autocomplete', [window.HTMLInputElement]);
this._overrideAttrDescriptors('httpEquiv', [window.HTMLMetaElement]);
// NOTE: Some browsers (for example, Edge, Internet Explorer 11, Safari) don't support the 'integrity' property.
if (nativeMethods.scriptIntegrityGetter && nativeMethods.linkIntegrityGetter) {
this._overrideAttrDescriptors('integrity', [window.HTMLScriptElement]);
this._overrideAttrDescriptors('integrity', [window.HTMLLinkElement]);
}
this._overrideAttrDescriptors('rel', [window.HTMLLinkElement]);
if (nativeMethods.linkAsSetter)
this._overrideAttrDescriptors('as', [window.HTMLLinkElement]);
overrideDescriptor(window.HTMLInputElement.prototype, 'type', {
getter: null,
setter: function (value) {
windowSandbox.nodeSandbox.element.setAttributeCore(this, ['type', value]);
},
});
overrideDescriptor(window.HTMLIFrameElement.prototype, 'sandbox', {
getter: function () {
var domTokenList = this[SANDBOX_DOM_TOKEN_LIST];
if (!domTokenList) {
var span_1 = nativeMethods.createElement.call(document, 'span');
domTokenList = nativeMethods.elementClassListGetter.call(span_1);
span_1.className = windowSandbox.nodeSandbox.element.getAttributeCore(this, ['sandbox']) || '';
nativeMethods.objectDefineProperty(domTokenList, SANDBOX_DOM_TOKEN_LIST_OWNER, { value: this });
nativeMethods.objectDefineProperty(this, SANDBOX_DOM_TOKEN_LIST, { value: domTokenList });
nativeMethods.objectDefineProperty(this, SANDBOX_DOM_TOKEN_LIST_UPDATE_FN, {
value: function (value) {
span_1.className = value;
},
});
}
return domTokenList;
},
setter: function (value) {
windowSandbox.nodeSandbox.element.setAttributeCore(this, ['sandbox', value]);
if (this[SANDBOX_DOM_TOKEN_LIST_UPDATE_FN])
this[SANDBOX_DOM_TOKEN_LIST_UPDATE_FN](windowSandbox.nodeSandbox.element.getAttributeCore(this, ['sandbox']) || '');
},
});
if (nativeMethods.iframeSrcdocGetter) {
overrideDescriptor(window.HTMLIFrameElement.prototype, 'srcdoc', {
getter: function () {
return windowSandbox.nodeSandbox.element.getAttributeCore(this, ['srcdoc']) || '';
},
setter: function (value) {
windowSandbox.nodeSandbox.element.setAttributeCore(this, ['srcdoc', value]);
},
});
}
if (!this.proxyless) {
this._overrideUrlPropDescriptor('port', nativeMethods.anchorPortGetter, nativeMethods.anchorPortSetter);
this._overrideUrlPropDescriptor('host', nativeMethods.anchorHostGetter, nativeMethods.anchorHostSetter);
this._overrideUrlPropDescriptor('hostname', nativeMethods.anchorHostnameGetter, nativeMethods.anchorHostnameSetter);
this._overrideUrlPropDescriptor('pathname', nativeMethods.anchorPathnameGetter, nativeMethods.anchorPathnameSetter);
this._overrideUrlPropDescriptor('protocol', nativeMethods.anchorProtocolGetter, nativeMethods.anchorProtocolSetter);
this._overrideUrlPropDescriptor('search', nativeMethods.anchorSearchGetter, nativeMethods.anchorSearchSetter);
}
if (!this.proxyless) {
overrideDescriptor(window.SVGImageElement.prototype, 'href', {
getter: function () {
var imageHref = nativeMethods.svgImageHrefGetter.call(this);
if (!imageHref[CONTEXT_SVG_IMAGE_ELEMENT]) {
nativeMethods.objectDefineProperty(imageHref, CONTEXT_SVG_IMAGE_ELEMENT, {
value: this,
configurable: true,
});
}
return imageHref;
},
});
overrideDescriptor(window.SVGAnimatedString.prototype, 'baseVal', {
getter: function () {
var baseVal = nativeMethods.svgAnimStrBaseValGetter.call(this);
if (this[CONTEXT_SVG_IMAGE_ELEMENT])
baseVal = getDestinationUrl(baseVal);
return baseVal;
},
setter: function (value) {
var contextSVGImageElement = this[CONTEXT_SVG_IMAGE_ELEMENT];
if (contextSVGImageElement) {
var hasXlinkHrefAttr = nativeMethods.hasAttributeNS.call(contextSVGImageElement, XLINK_NAMESPACE, 'href');
windowSandbox.nodeSandbox.element.setAttributeCore(contextSVGImageElement, [hasXlinkHrefAttr ? 'xlink:href' : 'href', value]);
value = getProxyUrl(value);
}
nativeMethods.svgAnimStrBaseValSetter.call(this, value);
},
});
overrideDescriptor(window.SVGAnimatedString.prototype, 'animVal', {
getter: function () {
var animVal = nativeMethods.svgAnimStrAnimValGetter.call(this);
if (this[CONTEXT_SVG_IMAGE_ELEMENT])
return getDestinationUrl(animVal);
return animVal;
},
});
}
if (nativeMethods.anchorOriginGetter && !this.proxyless) {
overrideDescriptor(window.HTMLAnchorElement.prototype, 'origin', {
getter: function () {
return getAnchorProperty(this, nativeMethods.anchorOriginGetter);
},
});
}
if (!this.proxyless) {
overrideDescriptor(window.StyleSheet.prototype, 'href', {
getter: function () {
return getDestinationUrl(nativeMethods.styleSheetHrefGetter.call(this));
},
});
}
if (nativeMethods.cssStyleSheetHrefGetter) {
overrideDescriptor(window.CSSStyleSheet.prototype, 'href', {
getter: function () {
return getDestinationUrl(nativeMethods.cssStyleSheetHrefGetter.call(this));
},
});
}
if (nativeMethods.nodeBaseURIGetter) {
overrideDescriptor(window.Node.prototype, 'baseURI', {
getter: function () {
return getDestinationUrl(nativeMethods.nodeBaseURIGetter.call(this));
},
});
}
if (window.DOMParser) {
overrideFunction(window.DOMParser.prototype, 'parseFromString', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var str = args[0];
var type = args[1];
var processedHtml;
if (args.length > 1 && typeof str === 'string' && type === 'text/html') {
processedHtml = processHtml(str);
args[0] = processedHtml;
}
var document = nativeMethods.DOMParserParseFromString.apply(this, args);
if (processedHtml)
ShadowUISandbox.removeSelfRemovingScripts(document);
return document;
});
}
overrideDescriptor(window.Node.prototype, 'firstChild', {
getter: function () {
if (ShadowUISandbox.isShadowContainer(this))
return windowSandbox.shadowUI.getFirstChild(this);
return nativeMethods.nodeFirstChildGetter.call(this);
},
});
overrideDescriptor(window.Element.prototype, 'firstElementChild', {
getter: function () {
if (ShadowUISandbox.isShadowContainer(this))
return windowSandbox.shadowUI.getFirstElementChild(this);
return nativeMethods.elementFirstElementChildGetter.call(this);
},
});
overrideDescriptor(window.Node.prototype, 'lastChild', {
getter: function () {
if (ShadowUISandbox.isShadowContainer(this))
return windowSandbox.shadowUI.getLastChild(this);
return nativeMethods.nodeLastChildGetter.call(this);
},
});
overrideDescriptor(window.Element.prototype, 'lastElementChild', {
getter: function () {
if (ShadowUISandbox.isShadowContainer(this))
return windowSandbox.shadowUI.getLastElementChild(this);
return nativeMethods.elementLastElementChildGetter.call(this);
},
});
overrideDescriptor(window.Node.prototype, 'nextSibling', {
getter: function () {
return windowSandbox.shadowUI.getNextSibling(this);
},
});
overrideDescriptor(window.Node.prototype, 'previousSibling', {
getter: function () {
return windowSandbox.shadowUI.getPrevSibling(this);
},
});
overrideDescriptor(window.Element.prototype, 'nextElementSibling', {
getter: function () {
return windowSandbox.shadowUI.getNextElementSibling(this);
},
});
overrideDescriptor(window.Element.prototype, 'previousElementSibling', {
getter: function () {
return windowSandbox.shadowUI.getPrevElementSibling(this);
},
});
overrideDescriptor(window[nativeMethods.elementHTMLPropOwnerName].prototype, 'innerHTML', {
getter: function () {
if (windowSandbox._documentTitleStorageInitializer && isTitleElement(this))
return windowSandbox._documentTitleStorageInitializer.storage.getTitleElementPropertyValue(this);
var innerHTML = nativeMethods.elementInnerHTMLGetter.call(this);
if (isScriptElement(this))
return remove$1(innerHTML);
else if (isStyleElement(this))
return styleProcessor.cleanUp(innerHTML, parseProxyUrl);
return cleanUpHtml(innerHTML);
},
setter: function (value) {
if (windowSandbox._documentTitleStorageInitializer && isTitleElement(this)) {
windowSandbox._documentTitleStorageInitializer.storage.setTitleElementPropertyValue(this, value);
return;
}
var el = this;
var isStyleEl = isStyleElement(el);
var isScriptEl = isScriptElement(el);
var processedValue = value !== null && value !== void 0 ? String(value) : value;
if (processedValue) {
if (isStyleEl)
processedValue = styleProcessor.process(processedValue, getProxyUrl, true);
else if (isScriptEl)
processedValue = processScript(processedValue, true, false, convertToProxyUrl, void 0, settings.get().proxyless);
else {
processedValue = processHtml(processedValue, {
parentTag: el.tagName,
processedContext: el[INTERNAL_PROPS.processedContext],
});
}
}
if (!isStyleEl && !isScriptEl)
domMutationTracker.onChildrenChanged(el);
nativeMethods.elementInnerHTMLSetter.call(el, processedValue);
windowSandbox._setSandboxedTextForTitleElements(el);
if (isStyleEl || isScriptEl)
return;
domMutationTracker.onChildrenChanged(el);
if (windowSandbox.document.body === el) {
var shadowUIRoot = windowSandbox.shadowUI.getRoot();
windowSandbox.shadowUI.markShadowUIContainers(windowSandbox.document.head, el);
ShadowUISandbox.markElementAndChildrenAsShadow(shadowUIRoot);
}
else if (isShadowUIElement(el))
ShadowUISandbox.markElementAndChildrenAsShadow(el);
var parentDocument = findDocument(el);
var parentWindow = parentDocument ? parentDocument.defaultView : null;
// NOTE: For the iframe with an empty src.
if (parentWindow && parentWindow !== window &&
parentWindow[INTERNAL_PROPS.processDomMethodName])
parentWindow[INTERNAL_PROPS.processDomMethodName](el, parentDocument);
else if (window[INTERNAL_PROPS.processDomMethodName])
window[INTERNAL_PROPS.processDomMethodName](el);
// NOTE: Fix for B239138 - unroll.me 'Cannot read property 'document' of null' error raised
// during recording. There was an issue when the document.body was replaced, so we need to
// reattach UI to a new body manually.
// NOTE: This check is required because jQuery calls the set innerHTML method for an element
// in an unavailable window.
if (window.self) {
// NOTE: Use timeout, so that changes take effect.
if (isHtmlElement(el) || isBodyElement(el))
nativeMethods.setTimeout.call(window, function () { return windowSandbox.nodeMutation.onBodyContentChanged(el); }, 0);
}
},
});
overrideDescriptor(window[nativeMethods.elementHTMLPropOwnerName].prototype, 'outerHTML', {
getter: function () {
var outerHTML = nativeMethods.elementOuterHTMLGetter.call(this);
return cleanUpHtml(outerHTML);
},
setter: function (value) {
var el = this;
var parentEl = nativeMethods.nodeParentNodeGetter.call(el);
domMutationTracker.onElementChanged(el);
if (parentEl && value !== null && value !== void 0) {
var parentDocument = findDocument(parentEl);
var parentWindow = parentDocument ? parentDocument.defaultView : null;
nativeMethods.elementOuterHTMLSetter.call(el, processHtml(String(value), {
parentTag: parentEl && parentEl['tagName'],
processedContext: el[INTERNAL_PROPS.processedContext],
}));
windowSandbox._setSandboxedTextForTitleElements(parentEl);
domMutationTracker.onChildrenChanged(parentEl);
// NOTE: For the iframe with an empty src.
if (parentWindow && parentWindow !== window &&
parentWindow[INTERNAL_PROPS.processDomMethodName])
parentWindow[INTERNAL_PROPS.processDomMethodName](parentEl, parentDocument);
else if (window[INTERNAL_PROPS.processDomMethodName])
window[INTERNAL_PROPS.processDomMethodName](parentEl);
// NOTE: This check is required for an element in an unavailable window.
// NOTE: Use timeout, so that changes take effect.
if (window.self && isBodyElement(el))
nativeMethods.setTimeout.call(window, function () { return windowSandbox.shadowUI.onBodyElementMutation(); }, 0);
}
else
nativeMethods.elementOuterHTMLSetter.call(el, value);
},
});
overrideDescriptor(window.HTMLElement.prototype, 'innerText', {
getter: function () {
if (windowSandbox._documentTitleStorageInitializer && isTitleElement(this))
return windowSandbox._documentTitleStorageInitializer.storage.getTitleElementPropertyValue(this);
var textContent = nativeMethods.htmlElementInnerTextGetter.call(this);
return WindowSandbox._removeProcessingInstructions(textContent);
},
setter: function (value) {
if (windowSandbox._documentTitleStorageInitializer && isTitleElement(this)) {
windowSandbox._documentTitleStorageInitializer.storage.setTitleElementPropertyValue(this, value);
return;
}
var processedValue = WindowSandbox._processTextPropValue(this, value);
domMutationTracker.onChildrenChanged(this);
nativeMethods.htmlElementInnerTextSetter.call(this, processedValue);
},
});
overrideDescriptor(window.HTMLScriptElement.prototype, 'text', {
getter: function () {
var text = nativeMethods.scriptTextGetter.call(this);
return remove$1(text);
},
setter: function (value) {
var processedValue = value ? processScript(String(value), true, false, convertToProxyUrl, void 0, settings.get().proxyless) : value;
nativeMethods.scriptTextSetter.call(this, processedValue);
},
});
overrideDescriptor(window.HTMLAnchorElement.prototype, 'text', {
getter: function () {
var textContent = nativeMethods.anchorTextGetter.call(this);
return WindowSandbox._removeProcessingInstructions(textContent);
},
setter: function (value) {
var processedValue = WindowSandbox._processTextPropValue(this, value);
domMutationTracker.onChildrenChanged(this);
nativeMethods.anchorTextSetter.call(this, processedValue);
},
});
overrideDescriptor(window.Node.prototype, 'textContent', {
getter: function () {
if (windowSandbox._documentTitleStorageInitializer && isTitleElement(this))
return windowSandbox._documentTitleStorageInitializer.storage.getTitleElementPropertyValue(this);
var textContent = nativeMethods.nodeTextContentGetter.call(this);
return WindowSandbox._removeProcessingInstructions(textContent);
},
setter: function (value) {
if (windowSandbox._documentTitleStorageInitializer && isTitleElement(this)) {
windowSandbox._documentTitleStorageInitializer.storage.setTitleElementPropertyValue(this, value);
return;
}
var processedValue = WindowSandbox._processTextPropValue(this, value);
domMutationTracker.onChildrenChanged(this);
nativeMethods.nodeTextContentSetter.call(this, processedValue);
},
});
overrideDescriptor(window[nativeMethods.elementAttributesPropOwnerName].prototype, 'attributes', {
getter: function () {
return getAttributes(this);
},
});
overrideFunction(window.DOMTokenList.prototype, 'add', this._createOverriddenDOMTokenListMethod(nativeMethods.tokenListAdd));
overrideFunction(window.DOMTokenList.prototype, 'remove', this._createOverriddenDOMTokenListMethod(nativeMethods.tokenListRemove));
overrideFunction(window.DOMTokenList.prototype, 'toggle', this._createOverriddenDOMTokenListMethod(nativeMethods.tokenListToggle));
if (nativeMethods.tokenListReplace)
overrideFunction(window.DOMTokenList.prototype, 'replace', this._createOverriddenDOMTokenListMethod(nativeMethods.tokenListReplace));
if (nativeMethods.tokenListSupports) {
overrideFunction(window.DOMTokenList.prototype, 'supports', function () {
if (this[SANDBOX_DOM_TOKEN_LIST_OWNER]) {
var nativeTokenList = nativeMethods.iframeSandboxGetter.call(this[SANDBOX_DOM_TOKEN_LIST_OWNER]);
return nativeMethods.tokenListSupports.apply(nativeTokenList, arguments);
}
return nativeMethods.tokenListSupports.apply(this, arguments);
});
}
if (nativeMethods.tokenListValueSetter) {
overrideDescriptor(window.DOMTokenList.prototype, 'value', {
getter: null,
setter: function (value) {
var tokenListOwner = this[SANDBOX_DOM_TOKEN_LIST_OWNER];
nativeMethods.tokenListValueSetter.call(this, value);
if (tokenListOwner)
// eslint-disable-next-line no-restricted-properties
windowSandbox.nodeSandbox.element.setAttributeCore(tokenListOwner, ['sandbox', this.value]);
},
});
}
overrideFunction(window.DOMImplementation.prototype, 'createHTMLDocument', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var doc = nativeMethods.createHTMLDocument.apply(this, args);
urlResolver.init(doc);
return doc;
});
overrideDescriptor(window.MutationRecord.prototype, 'nextSibling', {
getter: function () {
var originNextSibling = nativeMethods.mutationRecordNextSiblingGetter.call(this);
return windowSandbox.shadowUI.getMutationRecordNextSibling(originNextSibling);
},
});
overrideDescriptor(window.MutationRecord.prototype, 'previousSibling', {
getter: function () {
var originPrevSibling = nativeMethods.mutationRecordPrevSiblingGetter.call(this);
return windowSandbox.shadowUI.getMutationRecordPrevSibling(originPrevSibling);
},
});
if (nativeMethods.windowOriginGetter) {
overrideDescriptor(window, 'origin', {
getter: function () {
var proxyOrigin = nativeMethods.windowOriginGetter.call(this);
if (!proxyOrigin || proxyOrigin === 'null')
return proxyOrigin;
var frame = getFrameElement(windowSandbox.window);
if (frame) {
var sandbox = windowSandbox.nodeSandbox.element.getAttributeCore(frame, ['sandbox']);
if (typeof sandbox === 'string' && sandbox.indexOf('allow-same-origin') === -1)
return 'null';
}
var parsedDestLocation = getParsed();
// eslint-disable-next-line no-restricted-properties
if (parsedDestLocation && parsedDestLocation.protocol === 'file:')
return 'null';
return getOriginHeader();
},
setter: function (value) {
return nativeMethods.windowOriginSetter.call(this, value);
},
});
}
if (this._documentTitleStorageInitializer) {
overrideDescriptor(window.HTMLTitleElement.prototype, 'text', {
getter: function () {
return windowSandbox._documentTitleStorageInitializer.storage.getTitleElementPropertyValue(this);
},
setter: function (value) {
windowSandbox._documentTitleStorageInitializer.storage.setTitleElementPropertyValue(this, value);
},
});
}
};
return WindowSandbox;
}(SandboxBase));
function noop () {
// NOTE: empty function
}
var PropertyAccessorsInstrumentation = /** @class */ (function (_super) {
__extends(PropertyAccessorsInstrumentation, _super);
function PropertyAccessorsInstrumentation() {
return _super !== null && _super.apply(this, arguments) || this;
}
// NOTE: Isolate throw statements into a separate function because the
// JS engine doesn't optimize such functions.
PropertyAccessorsInstrumentation._error = function (msg) {
throw new Error(msg);
};
PropertyAccessorsInstrumentation._setCrossDomainLocation = function (location, value) {
var proxyUrl = '';
if (typeof value !== 'string')
value = String(value);
if (!DomProcessor.isJsProtocol(value)) {
var resourceType = stringifyResourceType({ isIframe: true });
value = prepareUrl(value);
proxyUrl = location !== window.top.location
? getProxyUrl(value, { resourceType: resourceType })
: getProxyUrl(value, { proxyPort: settings.get().crossDomainProxyPort });
}
else
proxyUrl = DomProcessor.processJsAttrValue(value, { isJsProtocol: true, isEventAttr: false });
location.href = proxyUrl; // eslint-disable-line no-restricted-properties
return value;
};
PropertyAccessorsInstrumentation._getLocation = function (owner) {
var locationWrapper = LocationAccessorsInstrumentation.getLocationWrapper(owner);
if (locationWrapper)
return locationWrapper;
else if (!owner.location)
return owner.location;
var wnd = isWindow(owner) ? owner : owner.defaultView;
return new LocationWrapper(wnd, null, noop);
};
PropertyAccessorsInstrumentation._setLocation = function (owner, location) {
//@ts-ignore
var ownerWindow = isWindow(owner) ? owner : owner.defaultView;
var locationWrapper = LocationAccessorsInstrumentation.getLocationWrapper(ownerWindow);
if (!locationWrapper || locationWrapper === owner.location ||
isIE && isCrossDomainWindows(window, ownerWindow))
PropertyAccessorsInstrumentation._setCrossDomainLocation(owner.location, location);
else if (locationWrapper)
locationWrapper.href = location; // eslint-disable-line no-restricted-properties
return location;
};
PropertyAccessorsInstrumentation._propertyGetter = function (owner, propName, optional) {
if (optional === void 0) { optional = false; }
if (isNullOrUndefined(owner) && !optional)
PropertyAccessorsInstrumentation._error("Cannot read property '".concat(propName, "' of ").concat(inaccessibleTypeToStr(owner)));
if (typeof propName === 'string' && shouldInstrumentProperty(propName)) {
if (optional && isNullOrUndefined(owner))
return void 0;
else if (!WindowSandbox.isProxyObject(owner) && PropertyAccessorsInstrumentation._ACCESSORS[propName].condition(owner))
return PropertyAccessorsInstrumentation._ACCESSORS[propName].get(owner);
}
if (optional && isNullOrUndefined(owner))
return void 0;
return owner[propName];
};
PropertyAccessorsInstrumentation._propertySetter = function (owner, propName, value) {
if (isNullOrUndefined(owner))
PropertyAccessorsInstrumentation._error("Cannot set property '".concat(propName, "' of ").concat(inaccessibleTypeToStr(owner)));
if (typeof propName === 'string' && shouldInstrumentProperty(propName)) {
if (!WindowSandbox.isProxyObject(owner) && PropertyAccessorsInstrumentation._ACCESSORS[propName].condition(owner))
return PropertyAccessorsInstrumentation._ACCESSORS[propName].set(owner, value);
}
return owner[propName] = value; // eslint-disable-line no-return-assign
};
PropertyAccessorsInstrumentation.prototype.attach = function (window) {
var _a;
_super.prototype.attach.call(this, window);
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
nativeMethods.objectDefineProperties(window, (_a = {},
_a[SCRIPT_PROCESSING_INSTRUCTIONS.getProperty] = {
value: PropertyAccessorsInstrumentation._propertyGetter,
configurable: true,
},
_a[SCRIPT_PROCESSING_INSTRUCTIONS.setProperty] = {
value: PropertyAccessorsInstrumentation._propertySetter,
configurable: true,
},
_a));
};
PropertyAccessorsInstrumentation._ACCESSORS = {
href: {
condition: isLocation,
// eslint-disable-next-line no-restricted-properties
get: function (crossDomainLocation) { return crossDomainLocation.href; },
set: PropertyAccessorsInstrumentation._setCrossDomainLocation,
},
location: {
condition: function (owner) { return isDocument(owner) || isWindow(owner); },
get: PropertyAccessorsInstrumentation._getLocation,
set: PropertyAccessorsInstrumentation._setLocation,
},
};
return PropertyAccessorsInstrumentation;
}(SandboxBase));
// OPTIMIZATION: http://jsperf.com/call-apply-optimization
function fastApply(owner, methName, args) {
var meth = owner[methName];
switch (args.length) {
case 1:
return meth.call(owner, args[0]);
case 2:
return meth.call(owner, args[0], args[1]);
case 3:
return meth.call(owner, args[0], args[1], args[2]);
case 4:
return meth.call(owner, args[0], args[1], args[2], args[3]);
case 5:
return meth.call(owner, args[0], args[1], args[2], args[3], args[4]);
default:
return meth.apply(owner, args);
}
}
var MethodCallInstrumentation = /** @class */ (function (_super) {
__extends(MethodCallInstrumentation, _super);
function MethodCallInstrumentation(_messageSandbox) {
var _this = _super.call(this) || this;
_this._messageSandbox = _messageSandbox;
_this._buildMethodWrappers();
return _this;
}
MethodCallInstrumentation.prototype._buildMethodWrappers = function () {
var _this = this;
this.methodWrappers = {
postMessage: {
condition: isWindow,
method: function (contentWindow, args) { return _this._messageSandbox.postMessage(contentWindow, args); },
},
};
if (this.proxyless)
return;
// NOTE: We cannot get the location wrapper for a cross-domain window. Therefore, we need to
// intercept calls to the native 'replace' and 'assign' methods.
this.methodWrappers.replace = {
condition: isLocation,
method: function (location, args) { return location.replace(getProxyUrl(args[0], {
resourceType: MethodCallInstrumentation._getLocationResourceType(location),
})); },
};
this.methodWrappers.assign = {
condition: isLocation,
method: function (location, args) { return location.assign(getProxyUrl(args[0], {
resourceType: MethodCallInstrumentation._getLocationResourceType(location),
})); },
};
};
// NOTE: Isolate throw statement into a separate function because JS engine doesn't optimize such functions.
MethodCallInstrumentation._error = function (msg) {
throw new Error(msg);
};
MethodCallInstrumentation._getLocationResourceType = function (location) {
return window.top.location === location ? null : stringifyResourceType({ isIframe: true });
};
MethodCallInstrumentation._isPostMessageFn = function (win, fn) {
// NOTE: in iOS Safari 9.3 win.postMessage === win.postMessage equals false
if (win.postMessage === win.postMessage)
return win.postMessage === fn;
return fn && isFunction(fn.toString) && fn.toString() === win.postMessage.toString();
};
MethodCallInstrumentation.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.callMethod, {
value: function (owner, methName, args, optional) {
if (optional === void 0) { optional = false; }
if (isNullOrUndefined(owner) && !optional)
MethodCallInstrumentation._error("Cannot call method '".concat(methName, "' of ").concat(inaccessibleTypeToStr(owner)));
if (!isFunction(owner[methName]) && !optional)
MethodCallInstrumentation._error("'".concat(methName, "' is not a function"));
// OPTIMIZATION: previously we've performed the
// `this.methodWrappers.hasOwnProperty(methName)`
// check which is quite slow. Now we use the
// fast RegExp check instead.
if (typeof methName === 'string' && shouldInstrumentMethod(methName)) {
if (optional && !isFunction(owner[methName]))
return void 0;
else if (_this.methodWrappers[methName].condition(owner))
return _this.methodWrappers[methName].method(owner, args);
}
if (optional && !isFunction(owner[methName]))
return void 0;
return fastApply(owner, methName, args);
},
configurable: true,
});
var methodCallInstrumentation = this;
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.getPostMessage, {
value: function (win, postMessageFn) {
if (arguments.length === 1 && !isWindow(win)) {
// @ts-ignore
return win.postMessage;
}
if (arguments.length === 2 && !MethodCallInstrumentation._isPostMessageFn(this, postMessageFn))
return postMessageFn;
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
//@ts-ignore
return methodCallInstrumentation._messageSandbox.postMessage(this, args);
};
},
configurable: true,
});
};
return MethodCallInstrumentation;
}(SandboxBase));
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
var lodash = createCommonjsModule(function (module, exports) {
(function() {
/** Used as a safe reference for `undefined` in pre-ES5 environments. */
var undefined$1;
/** Used as the semantic version number. */
var VERSION = '4.17.21';
/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;
/** Error message constants. */
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
FUNC_ERROR_TEXT = 'Expected a function',
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';
/** Used as the maximum memoize cache size. */
var MAX_MEMOIZE_SIZE = 500;
/** Used as the internal argument placeholder. */
var PLACEHOLDER = '__lodash_placeholder__';
/** Used to compose bitmasks for cloning. */
var CLONE_DEEP_FLAG = 1,
CLONE_FLAT_FLAG = 2,
CLONE_SYMBOLS_FLAG = 4;
/** Used to compose bitmasks for value comparisons. */
var COMPARE_PARTIAL_FLAG = 1,
COMPARE_UNORDERED_FLAG = 2;
/** Used to compose bitmasks for function metadata. */
var WRAP_BIND_FLAG = 1,
WRAP_BIND_KEY_FLAG = 2,
WRAP_CURRY_BOUND_FLAG = 4,
WRAP_CURRY_FLAG = 8,
WRAP_CURRY_RIGHT_FLAG = 16,
WRAP_PARTIAL_FLAG = 32,
WRAP_PARTIAL_RIGHT_FLAG = 64,
WRAP_ARY_FLAG = 128,
WRAP_REARG_FLAG = 256,
WRAP_FLIP_FLAG = 512;
/** Used as default options for `_.truncate`. */
var DEFAULT_TRUNC_LENGTH = 30,
DEFAULT_TRUNC_OMISSION = '...';
/** Used to detect hot functions by number of calls within a span of milliseconds. */
var HOT_COUNT = 800,
HOT_SPAN = 16;
/** Used to indicate the type of lazy iteratees. */
var LAZY_FILTER_FLAG = 1,
LAZY_MAP_FLAG = 2,
LAZY_WHILE_FLAG = 3;
/** Used as references for various `Number` constants. */
var INFINITY = 1 / 0,
MAX_SAFE_INTEGER = 9007199254740991,
MAX_INTEGER = 1.7976931348623157e+308,
NAN = 0 / 0;
/** Used as references for the maximum length and index of an array. */
var MAX_ARRAY_LENGTH = 4294967295,
MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
/** Used to associate wrap methods with their bit flags. */
var wrapFlags = [
['ary', WRAP_ARY_FLAG],
['bind', WRAP_BIND_FLAG],
['bindKey', WRAP_BIND_KEY_FLAG],
['curry', WRAP_CURRY_FLAG],
['curryRight', WRAP_CURRY_RIGHT_FLAG],
['flip', WRAP_FLIP_FLAG],
['partial', WRAP_PARTIAL_FLAG],
['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
['rearg', WRAP_REARG_FLAG]
];
/** `Object#toString` result references. */
var argsTag = '[object Arguments]',
arrayTag = '[object Array]',
asyncTag = '[object AsyncFunction]',
boolTag = '[object Boolean]',
dateTag = '[object Date]',
domExcTag = '[object DOMException]',
errorTag = '[object Error]',
funcTag = '[object Function]',
genTag = '[object GeneratorFunction]',
mapTag = '[object Map]',
numberTag = '[object Number]',
nullTag = '[object Null]',
objectTag = '[object Object]',
promiseTag = '[object Promise]',
proxyTag = '[object Proxy]',
regexpTag = '[object RegExp]',
setTag = '[object Set]',
stringTag = '[object String]',
symbolTag = '[object Symbol]',
undefinedTag = '[object Undefined]',
weakMapTag = '[object WeakMap]',
weakSetTag = '[object WeakSet]';
var arrayBufferTag = '[object ArrayBuffer]',
dataViewTag = '[object DataView]',
float32Tag = '[object Float32Array]',
float64Tag = '[object Float64Array]',
int8Tag = '[object Int8Array]',
int16Tag = '[object Int16Array]',
int32Tag = '[object Int32Array]',
uint8Tag = '[object Uint8Array]',
uint8ClampedTag = '[object Uint8ClampedArray]',
uint16Tag = '[object Uint16Array]',
uint32Tag = '[object Uint32Array]';
/** Used to match empty string literals in compiled template source. */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/** Used to match HTML entities and HTML characters. */
var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
reUnescapedHtml = /[&<>"']/g,
reHasEscapedHtml = RegExp(reEscapedHtml.source),
reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
/** Used to match template delimiters. */
var reEscape = /<%-([\s\S]+?)%>/g,
reEvaluate = /<%([\s\S]+?)%>/g,
reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to match property names within property paths. */
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
reIsPlainProp = /^\w*$/,
rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
/**
* Used to match `RegExp`
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
*/
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);
/** Used to match leading whitespace. */
var reTrimStart = /^\s+/;
/** Used to match a single whitespace character. */
var reWhitespace = /\s/;
/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
reSplitDetails = /,? & /;
/** Used to match words composed of alphanumeric characters. */
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
/**
* Used to validate the `validate` option in `_.template` variable.
*
* Forbids characters which could potentially change the meaning of the function argument definition:
* - "()," (modification of function parameters)
* - "=" (default value)
* - "[]{}" (destructuring of function parameters)
* - "/" (beginning of a comment)
* - whitespace
*/
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;
/**
* Used to match
* [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match `RegExp` flags from their coerced string values. */
var reFlags = /\w*$/;
/** Used to detect bad signed hexadecimal string values. */
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
/** Used to detect binary string values. */
var reIsBinary = /^0b[01]+$/i;
/** Used to detect host constructors (Safari). */
var reIsHostCtor = /^\[object .+?Constructor\]$/;
/** Used to detect octal string values. */
var reIsOctal = /^0o[0-7]+$/i;
/** Used to detect unsigned integer values. */
var reIsUint = /^(?:0|[1-9]\d*)$/;
/** Used to match Latin Unicode letters (excluding mathematical operators). */
var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
/** Used to ensure capturing order of template delimiters. */
var reNoMatch = /($^)/;
/** Used to match unescaped characters in compiled string literals. */
var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
/** Used to compose unicode character classes. */
var rsAstralRange = '\\ud800-\\udfff',
rsComboMarksRange = '\\u0300-\\u036f',
reComboHalfMarksRange = '\\ufe20-\\ufe2f',
rsComboSymbolsRange = '\\u20d0-\\u20ff',
rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
rsDingbatRange = '\\u2700-\\u27bf',
rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
rsPunctuationRange = '\\u2000-\\u206f',
rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
rsVarRange = '\\ufe0e\\ufe0f',
rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
/** Used to compose unicode capture groups. */
var rsApos = "['\u2019]",
rsAstral = '[' + rsAstralRange + ']',
rsBreak = '[' + rsBreakRange + ']',
rsCombo = '[' + rsComboRange + ']',
rsDigits = '\\d+',
rsDingbat = '[' + rsDingbatRange + ']',
rsLower = '[' + rsLowerRange + ']',
rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
rsFitz = '\\ud83c[\\udffb-\\udfff]',
rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
rsNonAstral = '[^' + rsAstralRange + ']',
rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
rsUpper = '[' + rsUpperRange + ']',
rsZWJ = '\\u200d';
/** Used to compose unicode regexes. */
var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
reOptMod = rsModifier + '?',
rsOptVar = '[' + rsVarRange + ']?',
rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
rsSeq = rsOptVar + reOptMod + rsOptJoin,
rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
/** Used to match apostrophes. */
var reApos = RegExp(rsApos, 'g');
/**
* Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
* [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
*/
var reComboMark = RegExp(rsCombo, 'g');
/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
/** Used to match complex or compound words. */
var reUnicodeWord = RegExp([
rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
rsUpper + '+' + rsOptContrUpper,
rsOrdUpper,
rsOrdLower,
rsDigits,
rsEmoji
].join('|'), 'g');
/** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
/** Used to detect strings that need a more robust regexp to match words. */
var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
/** Used to assign default `context` object properties. */
var contextProps = [
'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
'_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
];
/** Used to make template sourceURLs easier to identify. */
var templateCounter = -1;
/** Used to identify `toStringTag` values of typed arrays. */
var typedArrayTags = {};
typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
typedArrayTags[uint32Tag] = true;
typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
typedArrayTags[errorTag] = typedArrayTags[funcTag] =
typedArrayTags[mapTag] = typedArrayTags[numberTag] =
typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
typedArrayTags[setTag] = typedArrayTags[stringTag] =
typedArrayTags[weakMapTag] = false;
/** Used to identify `toStringTag` values supported by `_.clone`. */
var cloneableTags = {};
cloneableTags[argsTag] = cloneableTags[arrayTag] =
cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
cloneableTags[boolTag] = cloneableTags[dateTag] =
cloneableTags[float32Tag] = cloneableTags[float64Tag] =
cloneableTags[int8Tag] = cloneableTags[int16Tag] =
cloneableTags[int32Tag] = cloneableTags[mapTag] =
cloneableTags[numberTag] = cloneableTags[objectTag] =
cloneableTags[regexpTag] = cloneableTags[setTag] =
cloneableTags[stringTag] = cloneableTags[symbolTag] =
cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
cloneableTags[errorTag] = cloneableTags[funcTag] =
cloneableTags[weakMapTag] = false;
/** Used to map Latin Unicode letters to basic Latin letters. */
var deburredLetters = {
// Latin-1 Supplement block.
'\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
'\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
'\xc7': 'C', '\xe7': 'c',
'\xd0': 'D', '\xf0': 'd',
'\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
'\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
'\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
'\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
'\xd1': 'N', '\xf1': 'n',
'\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
'\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
'\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
'\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
'\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
'\xc6': 'Ae', '\xe6': 'ae',
'\xde': 'Th', '\xfe': 'th',
'\xdf': 'ss',
// Latin Extended-A block.
'\u0100': 'A', '\u0102': 'A', '\u0104': 'A',
'\u0101': 'a', '\u0103': 'a', '\u0105': 'a',
'\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
'\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
'\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
'\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
'\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
'\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
'\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
'\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
'\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
'\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
'\u0134': 'J', '\u0135': 'j',
'\u0136': 'K', '\u0137': 'k', '\u0138': 'k',
'\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
'\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
'\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
'\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
'\u014c': 'O', '\u014e': 'O', '\u0150': 'O',
'\u014d': 'o', '\u014f': 'o', '\u0151': 'o',
'\u0154': 'R', '\u0156': 'R', '\u0158': 'R',
'\u0155': 'r', '\u0157': 'r', '\u0159': 'r',
'\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
'\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's',
'\u0162': 'T', '\u0164': 'T', '\u0166': 'T',
'\u0163': 't', '\u0165': 't', '\u0167': 't',
'\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
'\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
'\u0174': 'W', '\u0175': 'w',
'\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y',
'\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z',
'\u017a': 'z', '\u017c': 'z', '\u017e': 'z',
'\u0132': 'IJ', '\u0133': 'ij',
'\u0152': 'Oe', '\u0153': 'oe',
'\u0149': "'n", '\u017f': 's'
};
/** Used to map characters to HTML entities. */
var htmlEscapes = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;'
};
/** Used to map HTML entities to characters. */
var htmlUnescapes = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#39;': "'"
};
/** Used to escape characters for inclusion in compiled string literals. */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/** Built-in method references without a dependency on `root`. */
var freeParseFloat = parseFloat,
freeParseInt = parseInt;
/** Detect free variable `global` from Node.js. */
var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
/** Detect free variable `self`. */
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
/** Used as a reference to the global object. */
var root = freeGlobal || freeSelf || Function('return this')();
/** Detect free variable `exports`. */
var freeExports = exports && !exports.nodeType && exports;
/** Detect free variable `module`. */
var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
/** Detect the popular CommonJS extension `module.exports`. */
var moduleExports = freeModule && freeModule.exports === freeExports;
/** Detect free variable `process` from Node.js. */
var freeProcess = moduleExports && freeGlobal.process;
/** Used to access faster Node.js helpers. */
var nodeUtil = (function() {
try {
// Use `util.types` for Node.js 10+.
var types = freeModule && freeModule.require && freeModule.require('util').types;
if (types) {
return types;
}
// Legacy `process.binding('util')` for Node.js < 10.
return freeProcess && freeProcess.binding && freeProcess.binding('util');
} catch (e) {}
}());
/* Node.js helper references. */
var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
nodeIsDate = nodeUtil && nodeUtil.isDate,
nodeIsMap = nodeUtil && nodeUtil.isMap,
nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
nodeIsSet = nodeUtil && nodeUtil.isSet,
nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
/*--------------------------------------------------------------------------*/
/**
* A faster alternative to `Function#apply`, this function invokes `func`
* with the `this` binding of `thisArg` and the arguments of `args`.
*
* @private
* @param {Function} func The function to invoke.
* @param {*} thisArg The `this` binding of `func`.
* @param {Array} args The arguments to invoke `func` with.
* @returns {*} Returns the result of `func`.
*/
function apply(func, thisArg, args) {
switch (args.length) {
case 0: return func.call(thisArg);
case 1: return func.call(thisArg, args[0]);
case 2: return func.call(thisArg, args[0], args[1]);
case 3: return func.call(thisArg, args[0], args[1], args[2]);
}
return func.apply(thisArg, args);
}
/**
* A specialized version of `baseAggregator` for arrays.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} setter The function to set `accumulator` values.
* @param {Function} iteratee The iteratee to transform keys.
* @param {Object} accumulator The initial aggregated object.
* @returns {Function} Returns `accumulator`.
*/
function arrayAggregator(array, setter, iteratee, accumulator) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
var value = array[index];
setter(accumulator, value, iteratee(value), array);
}
return accumulator;
}
/**
* A specialized version of `_.forEach` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/
function arrayEach(array, iteratee) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
if (iteratee(array[index], index, array) === false) {
break;
}
}
return array;
}
/**
* A specialized version of `_.forEachRight` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns `array`.
*/
function arrayEachRight(array, iteratee) {
var length = array == null ? 0 : array.length;
while (length--) {
if (iteratee(array[length], length, array) === false) {
break;
}
}
return array;
}
/**
* A specialized version of `_.every` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {boolean} Returns `true` if all elements pass the predicate check,
* else `false`.
*/
function arrayEvery(array, predicate) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
if (!predicate(array[index], index, array)) {
return false;
}
}
return true;
}
/**
* A specialized version of `_.filter` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {Array} Returns the new filtered array.
*/
function arrayFilter(array, predicate) {
var index = -1,
length = array == null ? 0 : array.length,
resIndex = 0,
result = [];
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) {
result[resIndex++] = value;
}
}
return result;
}
/**
* A specialized version of `_.includes` for arrays without support for
* specifying an index to search from.
*
* @private
* @param {Array} [array] The array to inspect.
* @param {*} target The value to search for.
* @returns {boolean} Returns `true` if `target` is found, else `false`.
*/
function arrayIncludes(array, value) {
var length = array == null ? 0 : array.length;
return !!length && baseIndexOf(array, value, 0) > -1;
}
/**
* This function is like `arrayIncludes` except that it accepts a comparator.
*
* @private
* @param {Array} [array] The array to inspect.
* @param {*} target The value to search for.
* @param {Function} comparator The comparator invoked per element.
* @returns {boolean} Returns `true` if `target` is found, else `false`.
*/
function arrayIncludesWith(array, value, comparator) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
if (comparator(value, array[index])) {
return true;
}
}
return false;
}
/**
* A specialized version of `_.map` for arrays without support for iteratee
* shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns the new mapped array.
*/
function arrayMap(array, iteratee) {
var index = -1,
length = array == null ? 0 : array.length,
result = Array(length);
while (++index < length) {
result[index] = iteratee(array[index], index, array);
}
return result;
}
/**
* Appends the elements of `values` to `array`.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to append.
* @returns {Array} Returns `array`.
*/
function arrayPush(array, values) {
var index = -1,
length = values.length,
offset = array.length;
while (++index < length) {
array[offset + index] = values[index];
}
return array;
}
/**
* A specialized version of `_.reduce` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @param {boolean} [initAccum] Specify using the first element of `array` as
* the initial value.
* @returns {*} Returns the accumulated value.
*/
function arrayReduce(array, iteratee, accumulator, initAccum) {
var index = -1,
length = array == null ? 0 : array.length;
if (initAccum && length) {
accumulator = array[++index];
}
while (++index < length) {
accumulator = iteratee(accumulator, array[index], index, array);
}
return accumulator;
}
/**
* A specialized version of `_.reduceRight` for arrays without support for
* iteratee shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @param {boolean} [initAccum] Specify using the last element of `array` as
* the initial value.
* @returns {*} Returns the accumulated value.
*/
function arrayReduceRight(array, iteratee, accumulator, initAccum) {
var length = array == null ? 0 : array.length;
if (initAccum && length) {
accumulator = array[--length];
}
while (length--) {
accumulator = iteratee(accumulator, array[length], length, array);
}
return accumulator;
}
/**
* A specialized version of `_.some` for arrays without support for iteratee
* shorthands.
*
* @private
* @param {Array} [array] The array to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {boolean} Returns `true` if any element passes the predicate check,
* else `false`.
*/
function arraySome(array, predicate) {
var index = -1,
length = array == null ? 0 : array.length;
while (++index < length) {
if (predicate(array[index], index, array)) {
return true;
}
}
return false;
}
/**
* Gets the size of an ASCII `string`.
*
* @private
* @param {string} string The string inspect.
* @returns {number} Returns the string size.
*/
var asciiSize = baseProperty('length');
/**
* Converts an ASCII `string` to an array.
*
* @private
* @param {string} string The string to convert.
* @returns {Array} Returns the converted array.
*/
function asciiToArray(string) {
return string.split('');
}
/**
* Splits an ASCII `string` into an array of its words.
*
* @private
* @param {string} The string to inspect.
* @returns {Array} Returns the words of `string`.
*/
function asciiWords(string) {
return string.match(reAsciiWord) || [];
}
/**
* The base implementation of methods like `_.findKey` and `_.findLastKey`,
* without support for iteratee shorthands, which iterates over `collection`
* using `eachFunc`.
*
* @private
* @param {Array|Object} collection The collection to inspect.
* @param {Function} predicate The function invoked per iteration.
* @param {Function} eachFunc The function to iterate over `collection`.
* @returns {*} Returns the found element or its key, else `undefined`.
*/
function baseFindKey(collection, predicate, eachFunc) {
var result;
eachFunc(collection, function(value, key, collection) {
if (predicate(value, key, collection)) {
result = key;
return false;
}
});
return result;
}
/**
* The base implementation of `_.findIndex` and `_.findLastIndex` without
* support for iteratee shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} predicate The function invoked per iteration.
* @param {number} fromIndex The index to search from.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function baseFindIndex(array, predicate, fromIndex, fromRight) {
var length = array.length,
index = fromIndex + (fromRight ? 1 : -1);
while ((fromRight ? index-- : ++index < length)) {
if (predicate(array[index], index, array)) {
return index;
}
}
return -1;
}
/**
* The base implementation of `_.indexOf` without `fromIndex` bounds checks.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
return value === value
? strictIndexOf(array, value, fromIndex)
: baseFindIndex(array, baseIsNaN, fromIndex);
}
/**
* This function is like `baseIndexOf` except that it accepts a comparator.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @param {Function} comparator The comparator invoked per element.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function baseIndexOfWith(array, value, fromIndex, comparator) {
var index = fromIndex - 1,
length = array.length;
while (++index < length) {
if (comparator(array[index], value)) {
return index;
}
}
return -1;
}
/**
* The base implementation of `_.isNaN` without support for number objects.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
*/
function baseIsNaN(value) {
return value !== value;
}
/**
* The base implementation of `_.mean` and `_.meanBy` without support for
* iteratee shorthands.
*
* @private
* @param {Array} array The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {number} Returns the mean.
*/
function baseMean(array, iteratee) {
var length = array == null ? 0 : array.length;
return length ? (baseSum(array, iteratee) / length) : NAN;
}
/**
* The base implementation of `_.property` without support for deep paths.
*
* @private
* @param {string} key The key of the property to get.
* @returns {Function} Returns the new accessor function.
*/
function baseProperty(key) {
return function(object) {
return object == null ? undefined$1 : object[key];
};
}
/**
* The base implementation of `_.propertyOf` without support for deep paths.
*
* @private
* @param {Object} object The object to query.
* @returns {Function} Returns the new accessor function.
*/
function basePropertyOf(object) {
return function(key) {
return object == null ? undefined$1 : object[key];
};
}
/**
* The base implementation of `_.reduce` and `_.reduceRight`, without support
* for iteratee shorthands, which iterates over `collection` using `eachFunc`.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {*} accumulator The initial value.
* @param {boolean} initAccum Specify using the first or last element of
* `collection` as the initial value.
* @param {Function} eachFunc The function to iterate over `collection`.
* @returns {*} Returns the accumulated value.
*/
function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
eachFunc(collection, function(value, index, collection) {
accumulator = initAccum
? (initAccum = false, value)
: iteratee(accumulator, value, index, collection);
});
return accumulator;
}
/**
* The base implementation of `_.sortBy` which uses `comparer` to define the
* sort order of `array` and replaces criteria objects with their corresponding
* values.
*
* @private
* @param {Array} array The array to sort.
* @param {Function} comparer The function to define sort order.
* @returns {Array} Returns `array`.
*/
function baseSortBy(array, comparer) {
var length = array.length;
array.sort(comparer);
while (length--) {
array[length] = array[length].value;
}
return array;
}
/**
* The base implementation of `_.sum` and `_.sumBy` without support for
* iteratee shorthands.
*
* @private
* @param {Array} array The array to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {number} Returns the sum.
*/
function baseSum(array, iteratee) {
var result,
index = -1,
length = array.length;
while (++index < length) {
var current = iteratee(array[index]);
if (current !== undefined$1) {
result = result === undefined$1 ? current : (result + current);
}
}
return result;
}
/**
* The base implementation of `_.times` without support for iteratee shorthands
* or max array length checks.
*
* @private
* @param {number} n The number of times to invoke `iteratee`.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns the array of results.
*/
function baseTimes(n, iteratee) {
var index = -1,
result = Array(n);
while (++index < n) {
result[index] = iteratee(index);
}
return result;
}
/**
* The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
* of key-value pairs for `object` corresponding to the property names of `props`.
*
* @private
* @param {Object} object The object to query.
* @param {Array} props The property names to get values for.
* @returns {Object} Returns the key-value pairs.
*/
function baseToPairs(object, props) {
return arrayMap(props, function(key) {
return [key, object[key]];
});
}
/**
* The base implementation of `_.trim`.
*
* @private
* @param {string} string The string to trim.
* @returns {string} Returns the trimmed string.
*/
function baseTrim(string) {
return string
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
: string;
}
/**
* The base implementation of `_.unary` without support for storing metadata.
*
* @private
* @param {Function} func The function to cap arguments for.
* @returns {Function} Returns the new capped function.
*/
function baseUnary(func) {
return function(value) {
return func(value);
};
}
/**
* The base implementation of `_.values` and `_.valuesIn` which creates an
* array of `object` property values corresponding to the property names
* of `props`.
*
* @private
* @param {Object} object The object to query.
* @param {Array} props The property names to get values for.
* @returns {Object} Returns the array of property values.
*/
function baseValues(object, props) {
return arrayMap(props, function(key) {
return object[key];
});
}
/**
* Checks if a `cache` value for `key` exists.
*
* @private
* @param {Object} cache The cache to query.
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function cacheHas(cache, key) {
return cache.has(key);
}
/**
* Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
* that is not found in the character symbols.
*
* @private
* @param {Array} strSymbols The string symbols to inspect.
* @param {Array} chrSymbols The character symbols to find.
* @returns {number} Returns the index of the first unmatched string symbol.
*/
function charsStartIndex(strSymbols, chrSymbols) {
var index = -1,
length = strSymbols.length;
while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
return index;
}
/**
* Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
* that is not found in the character symbols.
*
* @private
* @param {Array} strSymbols The string symbols to inspect.
* @param {Array} chrSymbols The character symbols to find.
* @returns {number} Returns the index of the last unmatched string symbol.
*/
function charsEndIndex(strSymbols, chrSymbols) {
var index = strSymbols.length;
while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
return index;
}
/**
* Gets the number of `placeholder` occurrences in `array`.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} placeholder The placeholder to search for.
* @returns {number} Returns the placeholder count.
*/
function countHolders(array, placeholder) {
var length = array.length,
result = 0;
while (length--) {
if (array[length] === placeholder) {
++result;
}
}
return result;
}
/**
* Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
* letters to basic Latin letters.
*
* @private
* @param {string} letter The matched letter to deburr.
* @returns {string} Returns the deburred letter.
*/
var deburrLetter = basePropertyOf(deburredLetters);
/**
* Used by `_.escape` to convert characters to HTML entities.
*
* @private
* @param {string} chr The matched character to escape.
* @returns {string} Returns the escaped character.
*/
var escapeHtmlChar = basePropertyOf(htmlEscapes);
/**
* Used by `_.template` to escape characters for inclusion in compiled string literals.
*
* @private
* @param {string} chr The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeStringChar(chr) {
return '\\' + stringEscapes[chr];
}
/**
* Gets the value at `key` of `object`.
*
* @private
* @param {Object} [object] The object to query.
* @param {string} key The key of the property to get.
* @returns {*} Returns the property value.
*/
function getValue(object, key) {
return object == null ? undefined$1 : object[key];
}
/**
* Checks if `string` contains Unicode symbols.
*
* @private
* @param {string} string The string to inspect.
* @returns {boolean} Returns `true` if a symbol is found, else `false`.
*/
function hasUnicode(string) {
return reHasUnicode.test(string);
}
/**
* Checks if `string` contains a word composed of Unicode symbols.
*
* @private
* @param {string} string The string to inspect.
* @returns {boolean} Returns `true` if a word is found, else `false`.
*/
function hasUnicodeWord(string) {
return reHasUnicodeWord.test(string);
}
/**
* Converts `iterator` to an array.
*
* @private
* @param {Object} iterator The iterator to convert.
* @returns {Array} Returns the converted array.
*/
function iteratorToArray(iterator) {
var data,
result = [];
while (!(data = iterator.next()).done) {
result.push(data.value);
}
return result;
}
/**
* Converts `map` to its key-value pairs.
*
* @private
* @param {Object} map The map to convert.
* @returns {Array} Returns the key-value pairs.
*/
function mapToArray(map) {
var index = -1,
result = Array(map.size);
map.forEach(function(value, key) {
result[++index] = [key, value];
});
return result;
}
/**
* Creates a unary function that invokes `func` with its argument transformed.
*
* @private
* @param {Function} func The function to wrap.
* @param {Function} transform The argument transform.
* @returns {Function} Returns the new function.
*/
function overArg(func, transform) {
return function(arg) {
return func(transform(arg));
};
}
/**
* Replaces all `placeholder` elements in `array` with an internal placeholder
* and returns an array of their indexes.
*
* @private
* @param {Array} array The array to modify.
* @param {*} placeholder The placeholder to replace.
* @returns {Array} Returns the new array of placeholder indexes.
*/
function replaceHolders(array, placeholder) {
var index = -1,
length = array.length,
resIndex = 0,
result = [];
while (++index < length) {
var value = array[index];
if (value === placeholder || value === PLACEHOLDER) {
array[index] = PLACEHOLDER;
result[resIndex++] = index;
}
}
return result;
}
/**
* Converts `set` to an array of its values.
*
* @private
* @param {Object} set The set to convert.
* @returns {Array} Returns the values.
*/
function setToArray(set) {
var index = -1,
result = Array(set.size);
set.forEach(function(value) {
result[++index] = value;
});
return result;
}
/**
* Converts `set` to its value-value pairs.
*
* @private
* @param {Object} set The set to convert.
* @returns {Array} Returns the value-value pairs.
*/
function setToPairs(set) {
var index = -1,
result = Array(set.size);
set.forEach(function(value) {
result[++index] = [value, value];
});
return result;
}
/**
* A specialized version of `_.indexOf` which performs strict equality
* comparisons of values, i.e. `===`.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function strictIndexOf(array, value, fromIndex) {
var index = fromIndex - 1,
length = array.length;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* A specialized version of `_.lastIndexOf` which performs strict equality
* comparisons of values, i.e. `===`.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} fromIndex The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function strictLastIndexOf(array, value, fromIndex) {
var index = fromIndex + 1;
while (index--) {
if (array[index] === value) {
return index;
}
}
return index;
}
/**
* Gets the number of symbols in `string`.
*
* @private
* @param {string} string The string to inspect.
* @returns {number} Returns the string size.
*/
function stringSize(string) {
return hasUnicode(string)
? unicodeSize(string)
: asciiSize(string);
}
/**
* Converts `string` to an array.
*
* @private
* @param {string} string The string to convert.
* @returns {Array} Returns the converted array.
*/
function stringToArray(string) {
return hasUnicode(string)
? unicodeToArray(string)
: asciiToArray(string);
}
/**
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
* character of `string`.
*
* @private
* @param {string} string The string to inspect.
* @returns {number} Returns the index of the last non-whitespace character.
*/
function trimmedEndIndex(string) {
var index = string.length;
while (index-- && reWhitespace.test(string.charAt(index))) {}
return index;
}
/**
* Used by `_.unescape` to convert HTML entities to characters.
*
* @private
* @param {string} chr The matched character to unescape.
* @returns {string} Returns the unescaped character.
*/
var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
/**
* Gets the size of a Unicode `string`.
*
* @private
* @param {string} string The string inspect.
* @returns {number} Returns the string size.
*/
function unicodeSize(string) {
var result = reUnicode.lastIndex = 0;
while (reUnicode.test(string)) {
++result;
}
return result;
}
/**
* Converts a Unicode `string` to an array.
*
* @private
* @param {string} string The string to convert.
* @returns {Array} Returns the converted array.
*/
function unicodeToArray(string) {
return string.match(reUnicode) || [];
}
/**
* Splits a Unicode `string` into an array of its words.
*
* @private
* @param {string} The string to inspect.
* @returns {Array} Returns the words of `string`.
*/
function unicodeWords(string) {
return string.match(reUnicodeWord) || [];
}
/*--------------------------------------------------------------------------*/
/**
* Create a new pristine `lodash` function using the `context` object.
*
* @static
* @memberOf _
* @since 1.1.0
* @category Util
* @param {Object} [context=root] The context object.
* @returns {Function} Returns a new `lodash` function.
* @example
*
* _.mixin({ 'foo': _.constant('foo') });
*
* var lodash = _.runInContext();
* lodash.mixin({ 'bar': lodash.constant('bar') });
*
* _.isFunction(_.foo);
* // => true
* _.isFunction(_.bar);
* // => false
*
* lodash.isFunction(lodash.foo);
* // => false
* lodash.isFunction(lodash.bar);
* // => true
*
* // Create a suped-up `defer` in Node.js.
* var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
*/
var runInContext = (function runInContext(context) {
context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
/** Built-in constructor references. */
var Array = context.Array,
Date = context.Date,
Error = context.Error,
Function = context.Function,
Math = context.Math,
Object = context.Object,
RegExp = context.RegExp,
String = context.String,
TypeError = context.TypeError;
/** Used for built-in method references. */
var arrayProto = Array.prototype,
funcProto = Function.prototype,
objectProto = Object.prototype;
/** Used to detect overreaching core-js shims. */
var coreJsData = context['__core-js_shared__'];
/** Used to resolve the decompiled source of functions. */
var funcToString = funcProto.toString;
/** Used to check objects for own properties. */
var hasOwnProperty = objectProto.hasOwnProperty;
/** Used to generate unique IDs. */
var idCounter = 0;
/** Used to detect methods masquerading as native. */
var maskSrcKey = (function() {
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
return uid ? ('Symbol(src)_1.' + uid) : '';
}());
/**
* Used to resolve the
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
* of values.
*/
var nativeObjectToString = objectProto.toString;
/** Used to infer the `Object` constructor. */
var objectCtorString = funcToString.call(Object);
/** Used to restore the original `_` reference in `_.noConflict`. */
var oldDash = root._;
/** Used to detect if a method is native. */
var reIsNative = RegExp('^' +
funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
/** Built-in value references. */
var Buffer = moduleExports ? context.Buffer : undefined$1,
Symbol = context.Symbol,
Uint8Array = context.Uint8Array,
allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined$1,
getPrototype = overArg(Object.getPrototypeOf, Object),
objectCreate = Object.create,
propertyIsEnumerable = objectProto.propertyIsEnumerable,
splice = arrayProto.splice,
spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined$1,
symIterator = Symbol ? Symbol.iterator : undefined$1,
symToStringTag = Symbol ? Symbol.toStringTag : undefined$1;
var defineProperty = (function() {
try {
var func = getNative(Object, 'defineProperty');
func({}, '', {});
return func;
} catch (e) {}
}());
/** Mocked built-ins. */
var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
ctxNow = Date && Date.now !== root.Date.now && Date.now,
ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
/* Built-in method references for those with the same name as other `lodash` methods. */
var nativeCeil = Math.ceil,
nativeFloor = Math.floor,
nativeGetSymbols = Object.getOwnPropertySymbols,
nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined$1,
nativeIsFinite = context.isFinite,
nativeJoin = arrayProto.join,
nativeKeys = overArg(Object.keys, Object),
nativeMax = Math.max,
nativeMin = Math.min,
nativeNow = Date.now,
nativeParseInt = context.parseInt,
nativeRandom = Math.random,
nativeReverse = arrayProto.reverse;
/* Built-in method references that are verified to be native. */
var DataView = getNative(context, 'DataView'),
Map = getNative(context, 'Map'),
Promise = getNative(context, 'Promise'),
Set = getNative(context, 'Set'),
WeakMap = getNative(context, 'WeakMap'),
nativeCreate = getNative(Object, 'create');
/** Used to store function metadata. */
var metaMap = WeakMap && new WeakMap;
/** Used to lookup unminified function names. */
var realNames = {};
/** Used to detect maps, sets, and weakmaps. */
var dataViewCtorString = toSource(DataView),
mapCtorString = toSource(Map),
promiseCtorString = toSource(Promise),
setCtorString = toSource(Set),
weakMapCtorString = toSource(WeakMap);
/** Used to convert symbols to primitives and strings. */
var symbolProto = Symbol ? Symbol.prototype : undefined$1,
symbolValueOf = symbolProto ? symbolProto.valueOf : undefined$1,
symbolToString = symbolProto ? symbolProto.toString : undefined$1;
/*------------------------------------------------------------------------*/
/**
* Creates a `lodash` object which wraps `value` to enable implicit method
* chain sequences. Methods that operate on and return arrays, collections,
* and functions can be chained together. Methods that retrieve a single value
* or may return a primitive value will automatically end the chain sequence
* and return the unwrapped value. Otherwise, the value must be unwrapped
* with `_#value`.
*
* Explicit chain sequences, which must be unwrapped with `_#value`, may be
* enabled using `_.chain`.
*
* The execution of chained methods is lazy, that is, it's deferred until
* `_#value` is implicitly or explicitly called.
*
* Lazy evaluation allows several methods to support shortcut fusion.
* Shortcut fusion is an optimization to merge iteratee calls; this avoids
* the creation of intermediate arrays and can greatly reduce the number of
* iteratee executions. Sections of a chain sequence qualify for shortcut
* fusion if the section is applied to an array and iteratees accept only
* one argument. The heuristic for whether a section qualifies for shortcut
* fusion is subject to change.
*
* Chaining is supported in custom builds as long as the `_#value` method is
* directly or indirectly included in the build.
*
* In addition to lodash methods, wrappers have `Array` and `String` methods.
*
* The wrapper `Array` methods are:
* `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
*
* The wrapper `String` methods are:
* `replace` and `split`
*
* The wrapper methods that support shortcut fusion are:
* `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
* `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
* `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
*
* The chainable wrapper methods are:
* `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
* `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
* `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
* `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
* `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
* `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
* `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
* `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
* `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
* `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
* `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
* `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
* `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
* `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
* `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
* `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
* `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
* `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
* `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
* `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
* `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
* `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
* `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
* `zipObject`, `zipObjectDeep`, and `zipWith`
*
* The wrapper methods that are **not** chainable by default are:
* `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
* `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
* `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
* `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
* `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
* `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
* `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
* `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
* `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
* `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
* `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
* `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
* `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
* `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
* `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
* `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
* `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
* `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
* `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
* `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
* `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
* `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
* `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
* `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
* `upperFirst`, `value`, and `words`
*
* @name _
* @constructor
* @category Seq
* @param {*} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* function square(n) {
* return n * n;
* }
*
* var wrapped = _([1, 2, 3]);
*
* // Returns an unwrapped value.
* wrapped.reduce(_.add);
* // => 6
*
* // Returns a wrapped value.
* var squares = wrapped.map(square);
*
* _.isArray(squares);
* // => false
*
* _.isArray(squares.value());
* // => true
*/
function lodash(value) {
if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
if (value instanceof LodashWrapper) {
return value;
}
if (hasOwnProperty.call(value, '__wrapped__')) {
return wrapperClone(value);
}
}
return new LodashWrapper(value);
}
/**
* The base implementation of `_.create` without support for assigning
* properties to the created object.
*
* @private
* @param {Object} proto The object to inherit from.
* @returns {Object} Returns the new object.
*/
var baseCreate = (function() {
function object() {}
return function(proto) {
if (!isObject(proto)) {
return {};
}
if (objectCreate) {
return objectCreate(proto);
}
object.prototype = proto;
var result = new object;
object.prototype = undefined$1;
return result;
};
}());
/**
* The function whose prototype chain sequence wrappers inherit from.
*
* @private
*/
function baseLodash() {
// No operation performed.
}
/**
* The base constructor for creating `lodash` wrapper objects.
*
* @private
* @param {*} value The value to wrap.
* @param {boolean} [chainAll] Enable explicit method chain sequences.
*/
function LodashWrapper(value, chainAll) {
this.__wrapped__ = value;
this.__actions__ = [];
this.__chain__ = !!chainAll;
this.__index__ = 0;
this.__values__ = undefined$1;
}
/**
* By default, the template delimiters used by lodash are like those in
* embedded Ruby (ERB) as well as ES2015 template strings. Change the
* following template settings to use alternative delimiters.
*
* @static
* @memberOf _
* @type {Object}
*/
lodash.templateSettings = {
/**
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
* @type {RegExp}
*/
'escape': reEscape,
/**
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
* @type {RegExp}
*/
'evaluate': reEvaluate,
/**
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
* @type {RegExp}
*/
'interpolate': reInterpolate,
/**
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
* @type {string}
*/
'variable': '',
/**
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
* @type {Object}
*/
'imports': {
/**
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
* @type {Function}
*/
'_': lodash
}
};
// Ensure wrappers are instances of `baseLodash`.
lodash.prototype = baseLodash.prototype;
lodash.prototype.constructor = lodash;
LodashWrapper.prototype = baseCreate(baseLodash.prototype);
LodashWrapper.prototype.constructor = LodashWrapper;
/*------------------------------------------------------------------------*/
/**
* Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
*
* @private
* @constructor
* @param {*} value The value to wrap.
*/
function LazyWrapper(value) {
this.__wrapped__ = value;
this.__actions__ = [];
this.__dir__ = 1;
this.__filtered__ = false;
this.__iteratees__ = [];
this.__takeCount__ = MAX_ARRAY_LENGTH;
this.__views__ = [];
}
/**
* Creates a clone of the lazy wrapper object.
*
* @private
* @name clone
* @memberOf LazyWrapper
* @returns {Object} Returns the cloned `LazyWrapper` object.
*/
function lazyClone() {
var result = new LazyWrapper(this.__wrapped__);
result.__actions__ = copyArray(this.__actions__);
result.__dir__ = this.__dir__;
result.__filtered__ = this.__filtered__;
result.__iteratees__ = copyArray(this.__iteratees__);
result.__takeCount__ = this.__takeCount__;
result.__views__ = copyArray(this.__views__);
return result;
}
/**
* Reverses the direction of lazy iteration.
*
* @private
* @name reverse
* @memberOf LazyWrapper
* @returns {Object} Returns the new reversed `LazyWrapper` object.
*/
function lazyReverse() {
if (this.__filtered__) {
var result = new LazyWrapper(this);
result.__dir__ = -1;
result.__filtered__ = true;
} else {
result = this.clone();
result.__dir__ *= -1;
}
return result;
}
/**
* Extracts the unwrapped value from its lazy wrapper.
*
* @private
* @name value
* @memberOf LazyWrapper
* @returns {*} Returns the unwrapped value.
*/
function lazyValue() {
var array = this.__wrapped__.value(),
dir = this.__dir__,
isArr = isArray(array),
isRight = dir < 0,
arrLength = isArr ? array.length : 0,
view = getView(0, arrLength, this.__views__),
start = view.start,
end = view.end,
length = end - start,
index = isRight ? end : (start - 1),
iteratees = this.__iteratees__,
iterLength = iteratees.length,
resIndex = 0,
takeCount = nativeMin(length, this.__takeCount__);
if (!isArr || (!isRight && arrLength == length && takeCount == length)) {
return baseWrapperValue(array, this.__actions__);
}
var result = [];
outer:
while (length-- && resIndex < takeCount) {
index += dir;
var iterIndex = -1,
value = array[index];
while (++iterIndex < iterLength) {
var data = iteratees[iterIndex],
iteratee = data.iteratee,
type = data.type,
computed = iteratee(value);
if (type == LAZY_MAP_FLAG) {
value = computed;
} else if (!computed) {
if (type == LAZY_FILTER_FLAG) {
continue outer;
} else {
break outer;
}
}
}
result[resIndex++] = value;
}
return result;
}
// Ensure `LazyWrapper` is an instance of `baseLodash`.
LazyWrapper.prototype = baseCreate(baseLodash.prototype);
LazyWrapper.prototype.constructor = LazyWrapper;
/*------------------------------------------------------------------------*/
/**
* Creates a hash object.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function Hash(entries) {
var index = -1,
length = entries == null ? 0 : entries.length;
this.clear();
while (++index < length) {
var entry = entries[index];
this.set(entry[0], entry[1]);
}
}
/**
* Removes all key-value entries from the hash.
*
* @private
* @name clear
* @memberOf Hash
*/
function hashClear() {
this.__data__ = nativeCreate ? nativeCreate(null) : {};
this.size = 0;
}
/**
* Removes `key` and its value from the hash.
*
* @private
* @name delete
* @memberOf Hash
* @param {Object} hash The hash to modify.
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
function hashDelete(key) {
var result = this.has(key) && delete this.__data__[key];
this.size -= result ? 1 : 0;
return result;
}
/**
* Gets the hash value for `key`.
*
* @private
* @name get
* @memberOf Hash
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
function hashGet(key) {
var data = this.__data__;
if (nativeCreate) {
var result = data[key];
return result === HASH_UNDEFINED ? undefined$1 : result;
}
return hasOwnProperty.call(data, key) ? data[key] : undefined$1;
}
/**
* Checks if a hash value for `key` exists.
*
* @private
* @name has
* @memberOf Hash
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function hashHas(key) {
var data = this.__data__;
return nativeCreate ? (data[key] !== undefined$1) : hasOwnProperty.call(data, key);
}
/**
* Sets the hash `key` to `value`.
*
* @private
* @name set
* @memberOf Hash
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
* @returns {Object} Returns the hash instance.
*/
function hashSet(key, value) {
var data = this.__data__;
this.size += this.has(key) ? 0 : 1;
data[key] = (nativeCreate && value === undefined$1) ? HASH_UNDEFINED : value;
return this;
}
// Add methods to `Hash`.
Hash.prototype.clear = hashClear;
Hash.prototype['delete'] = hashDelete;
Hash.prototype.get = hashGet;
Hash.prototype.has = hashHas;
Hash.prototype.set = hashSet;
/*------------------------------------------------------------------------*/
/**
* Creates an list cache object.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function ListCache(entries) {
var index = -1,
length = entries == null ? 0 : entries.length;
this.clear();
while (++index < length) {
var entry = entries[index];
this.set(entry[0], entry[1]);
}
}
/**
* Removes all key-value entries from the list cache.
*
* @private
* @name clear
* @memberOf ListCache
*/
function listCacheClear() {
this.__data__ = [];
this.size = 0;
}
/**
* Removes `key` and its value from the list cache.
*
* @private
* @name delete
* @memberOf ListCache
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
function listCacheDelete(key) {
var data = this.__data__,
index = assocIndexOf(data, key);
if (index < 0) {
return false;
}
var lastIndex = data.length - 1;
if (index == lastIndex) {
data.pop();
} else {
splice.call(data, index, 1);
}
--this.size;
return true;
}
/**
* Gets the list cache value for `key`.
*
* @private
* @name get
* @memberOf ListCache
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
function listCacheGet(key) {
var data = this.__data__,
index = assocIndexOf(data, key);
return index < 0 ? undefined$1 : data[index][1];
}
/**
* Checks if a list cache value for `key` exists.
*
* @private
* @name has
* @memberOf ListCache
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function listCacheHas(key) {
return assocIndexOf(this.__data__, key) > -1;
}
/**
* Sets the list cache `key` to `value`.
*
* @private
* @name set
* @memberOf ListCache
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
* @returns {Object} Returns the list cache instance.
*/
function listCacheSet(key, value) {
var data = this.__data__,
index = assocIndexOf(data, key);
if (index < 0) {
++this.size;
data.push([key, value]);
} else {
data[index][1] = value;
}
return this;
}
// Add methods to `ListCache`.
ListCache.prototype.clear = listCacheClear;
ListCache.prototype['delete'] = listCacheDelete;
ListCache.prototype.get = listCacheGet;
ListCache.prototype.has = listCacheHas;
ListCache.prototype.set = listCacheSet;
/*------------------------------------------------------------------------*/
/**
* Creates a map cache object to store key-value pairs.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function MapCache(entries) {
var index = -1,
length = entries == null ? 0 : entries.length;
this.clear();
while (++index < length) {
var entry = entries[index];
this.set(entry[0], entry[1]);
}
}
/**
* Removes all key-value entries from the map.
*
* @private
* @name clear
* @memberOf MapCache
*/
function mapCacheClear() {
this.size = 0;
this.__data__ = {
'hash': new Hash,
'map': new (Map || ListCache),
'string': new Hash
};
}
/**
* Removes `key` and its value from the map.
*
* @private
* @name delete
* @memberOf MapCache
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
function mapCacheDelete(key) {
var result = getMapData(this, key)['delete'](key);
this.size -= result ? 1 : 0;
return result;
}
/**
* Gets the map value for `key`.
*
* @private
* @name get
* @memberOf MapCache
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
function mapCacheGet(key) {
return getMapData(this, key).get(key);
}
/**
* Checks if a map value for `key` exists.
*
* @private
* @name has
* @memberOf MapCache
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function mapCacheHas(key) {
return getMapData(this, key).has(key);
}
/**
* Sets the map `key` to `value`.
*
* @private
* @name set
* @memberOf MapCache
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
* @returns {Object} Returns the map cache instance.
*/
function mapCacheSet(key, value) {
var data = getMapData(this, key),
size = data.size;
data.set(key, value);
this.size += data.size == size ? 0 : 1;
return this;
}
// Add methods to `MapCache`.
MapCache.prototype.clear = mapCacheClear;
MapCache.prototype['delete'] = mapCacheDelete;
MapCache.prototype.get = mapCacheGet;
MapCache.prototype.has = mapCacheHas;
MapCache.prototype.set = mapCacheSet;
/*------------------------------------------------------------------------*/
/**
*
* Creates an array cache object to store unique values.
*
* @private
* @constructor
* @param {Array} [values] The values to cache.
*/
function SetCache(values) {
var index = -1,
length = values == null ? 0 : values.length;
this.__data__ = new MapCache;
while (++index < length) {
this.add(values[index]);
}
}
/**
* Adds `value` to the array cache.
*
* @private
* @name add
* @memberOf SetCache
* @alias push
* @param {*} value The value to cache.
* @returns {Object} Returns the cache instance.
*/
function setCacheAdd(value) {
this.__data__.set(value, HASH_UNDEFINED);
return this;
}
/**
* Checks if `value` is in the array cache.
*
* @private
* @name has
* @memberOf SetCache
* @param {*} value The value to search for.
* @returns {number} Returns `true` if `value` is found, else `false`.
*/
function setCacheHas(value) {
return this.__data__.has(value);
}
// Add methods to `SetCache`.
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
SetCache.prototype.has = setCacheHas;
/*------------------------------------------------------------------------*/
/**
* Creates a stack cache object to store key-value pairs.
*
* @private
* @constructor
* @param {Array} [entries] The key-value pairs to cache.
*/
function Stack(entries) {
var data = this.__data__ = new ListCache(entries);
this.size = data.size;
}
/**
* Removes all key-value entries from the stack.
*
* @private
* @name clear
* @memberOf Stack
*/
function stackClear() {
this.__data__ = new ListCache;
this.size = 0;
}
/**
* Removes `key` and its value from the stack.
*
* @private
* @name delete
* @memberOf Stack
* @param {string} key The key of the value to remove.
* @returns {boolean} Returns `true` if the entry was removed, else `false`.
*/
function stackDelete(key) {
var data = this.__data__,
result = data['delete'](key);
this.size = data.size;
return result;
}
/**
* Gets the stack value for `key`.
*
* @private
* @name get
* @memberOf Stack
* @param {string} key The key of the value to get.
* @returns {*} Returns the entry value.
*/
function stackGet(key) {
return this.__data__.get(key);
}
/**
* Checks if a stack value for `key` exists.
*
* @private
* @name has
* @memberOf Stack
* @param {string} key The key of the entry to check.
* @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
*/
function stackHas(key) {
return this.__data__.has(key);
}
/**
* Sets the stack `key` to `value`.
*
* @private
* @name set
* @memberOf Stack
* @param {string} key The key of the value to set.
* @param {*} value The value to set.
* @returns {Object} Returns the stack cache instance.
*/
function stackSet(key, value) {
var data = this.__data__;
if (data instanceof ListCache) {
var pairs = data.__data__;
if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
pairs.push([key, value]);
this.size = ++data.size;
return this;
}
data = this.__data__ = new MapCache(pairs);
}
data.set(key, value);
this.size = data.size;
return this;
}
// Add methods to `Stack`.
Stack.prototype.clear = stackClear;
Stack.prototype['delete'] = stackDelete;
Stack.prototype.get = stackGet;
Stack.prototype.has = stackHas;
Stack.prototype.set = stackSet;
/*------------------------------------------------------------------------*/
/**
* Creates an array of the enumerable property names of the array-like `value`.
*
* @private
* @param {*} value The value to query.
* @param {boolean} inherited Specify returning inherited property names.
* @returns {Array} Returns the array of property names.
*/
function arrayLikeKeys(value, inherited) {
var isArr = isArray(value),
isArg = !isArr && isArguments(value),
isBuff = !isArr && !isArg && isBuffer(value),
isType = !isArr && !isArg && !isBuff && isTypedArray(value),
skipIndexes = isArr || isArg || isBuff || isType,
result = skipIndexes ? baseTimes(value.length, String) : [],
length = result.length;
for (var key in value) {
if ((inherited || hasOwnProperty.call(value, key)) &&
!(skipIndexes && (
// Safari 9 has enumerable `arguments.length` in strict mode.
key == 'length' ||
// Node.js 0.10 has enumerable non-index properties on buffers.
(isBuff && (key == 'offset' || key == 'parent')) ||
// PhantomJS 2 has enumerable non-index properties on typed arrays.
(isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
// Skip index properties.
isIndex(key, length)
))) {
result.push(key);
}
}
return result;
}
/**
* A specialized version of `_.sample` for arrays.
*
* @private
* @param {Array} array The array to sample.
* @returns {*} Returns the random element.
*/
function arraySample(array) {
var length = array.length;
return length ? array[baseRandom(0, length - 1)] : undefined$1;
}
/**
* A specialized version of `_.sampleSize` for arrays.
*
* @private
* @param {Array} array The array to sample.
* @param {number} n The number of elements to sample.
* @returns {Array} Returns the random elements.
*/
function arraySampleSize(array, n) {
return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
}
/**
* A specialized version of `_.shuffle` for arrays.
*
* @private
* @param {Array} array The array to shuffle.
* @returns {Array} Returns the new shuffled array.
*/
function arrayShuffle(array) {
return shuffleSelf(copyArray(array));
}
/**
* This function is like `assignValue` except that it doesn't assign
* `undefined` values.
*
* @private
* @param {Object} object The object to modify.
* @param {string} key The key of the property to assign.
* @param {*} value The value to assign.
*/
function assignMergeValue(object, key, value) {
if ((value !== undefined$1 && !eq(object[key], value)) ||
(value === undefined$1 && !(key in object))) {
baseAssignValue(object, key, value);
}
}
/**
* Assigns `value` to `key` of `object` if the existing value is not equivalent
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons.
*
* @private
* @param {Object} object The object to modify.
* @param {string} key The key of the property to assign.
* @param {*} value The value to assign.
*/
function assignValue(object, key, value) {
var objValue = object[key];
if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
(value === undefined$1 && !(key in object))) {
baseAssignValue(object, key, value);
}
}
/**
* Gets the index at which the `key` is found in `array` of key-value pairs.
*
* @private
* @param {Array} array The array to inspect.
* @param {*} key The key to search for.
* @returns {number} Returns the index of the matched value, else `-1`.
*/
function assocIndexOf(array, key) {
var length = array.length;
while (length--) {
if (eq(array[length][0], key)) {
return length;
}
}
return -1;
}
/**
* Aggregates elements of `collection` on `accumulator` with keys transformed
* by `iteratee` and values set by `setter`.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} setter The function to set `accumulator` values.
* @param {Function} iteratee The iteratee to transform keys.
* @param {Object} accumulator The initial aggregated object.
* @returns {Function} Returns `accumulator`.
*/
function baseAggregator(collection, setter, iteratee, accumulator) {
baseEach(collection, function(value, key, collection) {
setter(accumulator, value, iteratee(value), collection);
});
return accumulator;
}
/**
* The base implementation of `_.assign` without support for multiple sources
* or `customizer` functions.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @returns {Object} Returns `object`.
*/
function baseAssign(object, source) {
return object && copyObject(source, keys(source), object);
}
/**
* The base implementation of `_.assignIn` without support for multiple sources
* or `customizer` functions.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @returns {Object} Returns `object`.
*/
function baseAssignIn(object, source) {
return object && copyObject(source, keysIn(source), object);
}
/**
* The base implementation of `assignValue` and `assignMergeValue` without
* value checks.
*
* @private
* @param {Object} object The object to modify.
* @param {string} key The key of the property to assign.
* @param {*} value The value to assign.
*/
function baseAssignValue(object, key, value) {
if (key == '__proto__' && defineProperty) {
defineProperty(object, key, {
'configurable': true,
'enumerable': true,
'value': value,
'writable': true
});
} else {
object[key] = value;
}
}
/**
* The base implementation of `_.at` without support for individual paths.
*
* @private
* @param {Object} object The object to iterate over.
* @param {string[]} paths The property paths to pick.
* @returns {Array} Returns the picked elements.
*/
function baseAt(object, paths) {
var index = -1,
length = paths.length,
result = Array(length),
skip = object == null;
while (++index < length) {
result[index] = skip ? undefined$1 : get(object, paths[index]);
}
return result;
}
/**
* The base implementation of `_.clamp` which doesn't coerce arguments.
*
* @private
* @param {number} number The number to clamp.
* @param {number} [lower] The lower bound.
* @param {number} upper The upper bound.
* @returns {number} Returns the clamped number.
*/
function baseClamp(number, lower, upper) {
if (number === number) {
if (upper !== undefined$1) {
number = number <= upper ? number : upper;
}
if (lower !== undefined$1) {
number = number >= lower ? number : lower;
}
}
return number;
}
/**
* The base implementation of `_.clone` and `_.cloneDeep` which tracks
* traversed objects.
*
* @private
* @param {*} value The value to clone.
* @param {boolean} bitmask The bitmask flags.
* 1 - Deep clone
* 2 - Flatten inherited properties
* 4 - Clone symbols
* @param {Function} [customizer] The function to customize cloning.
* @param {string} [key] The key of `value`.
* @param {Object} [object] The parent object of `value`.
* @param {Object} [stack] Tracks traversed objects and their clone counterparts.
* @returns {*} Returns the cloned value.
*/
function baseClone(value, bitmask, customizer, key, object, stack) {
var result,
isDeep = bitmask & CLONE_DEEP_FLAG,
isFlat = bitmask & CLONE_FLAT_FLAG,
isFull = bitmask & CLONE_SYMBOLS_FLAG;
if (customizer) {
result = object ? customizer(value, key, object, stack) : customizer(value);
}
if (result !== undefined$1) {
return result;
}
if (!isObject(value)) {
return value;
}
var isArr = isArray(value);
if (isArr) {
result = initCloneArray(value);
if (!isDeep) {
return copyArray(value, result);
}
} else {
var tag = getTag(value),
isFunc = tag == funcTag || tag == genTag;
if (isBuffer(value)) {
return cloneBuffer(value, isDeep);
}
if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
result = (isFlat || isFunc) ? {} : initCloneObject(value);
if (!isDeep) {
return isFlat
? copySymbolsIn(value, baseAssignIn(result, value))
: copySymbols(value, baseAssign(result, value));
}
} else {
if (!cloneableTags[tag]) {
return object ? value : {};
}
result = initCloneByTag(value, tag, isDeep);
}
}
// Check for circular references and return its corresponding clone.
stack || (stack = new Stack);
var stacked = stack.get(value);
if (stacked) {
return stacked;
}
stack.set(value, result);
if (isSet(value)) {
value.forEach(function(subValue) {
result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
});
} else if (isMap(value)) {
value.forEach(function(subValue, key) {
result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
});
}
var keysFunc = isFull
? (isFlat ? getAllKeysIn : getAllKeys)
: (isFlat ? keysIn : keys);
var props = isArr ? undefined$1 : keysFunc(value);
arrayEach(props || value, function(subValue, key) {
if (props) {
key = subValue;
subValue = value[key];
}
// Recursively populate clone (susceptible to call stack limits).
assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
});
return result;
}
/**
* The base implementation of `_.conforms` which doesn't clone `source`.
*
* @private
* @param {Object} source The object of property predicates to conform to.
* @returns {Function} Returns the new spec function.
*/
function baseConforms(source) {
var props = keys(source);
return function(object) {
return baseConformsTo(object, source, props);
};
}
/**
* The base implementation of `_.conformsTo` which accepts `props` to check.
*
* @private
* @param {Object} object The object to inspect.
* @param {Object} source The object of property predicates to conform to.
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
*/
function baseConformsTo(object, source, props) {
var length = props.length;
if (object == null) {
return !length;
}
object = Object(object);
while (length--) {
var key = props[length],
predicate = source[key],
value = object[key];
if ((value === undefined$1 && !(key in object)) || !predicate(value)) {
return false;
}
}
return true;
}
/**
* The base implementation of `_.delay` and `_.defer` which accepts `args`
* to provide to `func`.
*
* @private
* @param {Function} func The function to delay.
* @param {number} wait The number of milliseconds to delay invocation.
* @param {Array} args The arguments to provide to `func`.
* @returns {number|Object} Returns the timer id or timeout object.
*/
function baseDelay(func, wait, args) {
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
return setTimeout(function() { func.apply(undefined$1, args); }, wait);
}
/**
* The base implementation of methods like `_.difference` without support
* for excluding multiple arrays or iteratee shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Array} values The values to exclude.
* @param {Function} [iteratee] The iteratee invoked per element.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of filtered values.
*/
function baseDifference(array, values, iteratee, comparator) {
var index = -1,
includes = arrayIncludes,
isCommon = true,
length = array.length,
result = [],
valuesLength = values.length;
if (!length) {
return result;
}
if (iteratee) {
values = arrayMap(values, baseUnary(iteratee));
}
if (comparator) {
includes = arrayIncludesWith;
isCommon = false;
}
else if (values.length >= LARGE_ARRAY_SIZE) {
includes = cacheHas;
isCommon = false;
values = new SetCache(values);
}
outer:
while (++index < length) {
var value = array[index],
computed = iteratee == null ? value : iteratee(value);
value = (comparator || value !== 0) ? value : 0;
if (isCommon && computed === computed) {
var valuesIndex = valuesLength;
while (valuesIndex--) {
if (values[valuesIndex] === computed) {
continue outer;
}
}
result.push(value);
}
else if (!includes(values, computed, comparator)) {
result.push(value);
}
}
return result;
}
/**
* The base implementation of `_.forEach` without support for iteratee shorthands.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array|Object} Returns `collection`.
*/
var baseEach = createBaseEach(baseForOwn);
/**
* The base implementation of `_.forEachRight` without support for iteratee shorthands.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array|Object} Returns `collection`.
*/
var baseEachRight = createBaseEach(baseForOwnRight, true);
/**
* The base implementation of `_.every` without support for iteratee shorthands.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {boolean} Returns `true` if all elements pass the predicate check,
* else `false`
*/
function baseEvery(collection, predicate) {
var result = true;
baseEach(collection, function(value, index, collection) {
result = !!predicate(value, index, collection);
return result;
});
return result;
}
/**
* The base implementation of methods like `_.max` and `_.min` which accepts a
* `comparator` to determine the extremum value.
*
* @private
* @param {Array} array The array to iterate over.
* @param {Function} iteratee The iteratee invoked per iteration.
* @param {Function} comparator The comparator used to compare values.
* @returns {*} Returns the extremum value.
*/
function baseExtremum(array, iteratee, comparator) {
var index = -1,
length = array.length;
while (++index < length) {
var value = array[index],
current = iteratee(value);
if (current != null && (computed === undefined$1
? (current === current && !isSymbol(current))
: comparator(current, computed)
)) {
var computed = current,
result = value;
}
}
return result;
}
/**
* The base implementation of `_.fill` without an iteratee call guard.
*
* @private
* @param {Array} array The array to fill.
* @param {*} value The value to fill `array` with.
* @param {number} [start=0] The start position.
* @param {number} [end=array.length] The end position.
* @returns {Array} Returns `array`.
*/
function baseFill(array, value, start, end) {
var length = array.length;
start = toInteger(start);
if (start < 0) {
start = -start > length ? 0 : (length + start);
}
end = (end === undefined$1 || end > length) ? length : toInteger(end);
if (end < 0) {
end += length;
}
end = start > end ? 0 : toLength(end);
while (start < end) {
array[start++] = value;
}
return array;
}
/**
* The base implementation of `_.filter` without support for iteratee shorthands.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {Array} Returns the new filtered array.
*/
function baseFilter(collection, predicate) {
var result = [];
baseEach(collection, function(value, index, collection) {
if (predicate(value, index, collection)) {
result.push(value);
}
});
return result;
}
/**
* The base implementation of `_.flatten` with support for restricting flattening.
*
* @private
* @param {Array} array The array to flatten.
* @param {number} depth The maximum recursion depth.
* @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
* @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
* @param {Array} [result=[]] The initial result value.
* @returns {Array} Returns the new flattened array.
*/
function baseFlatten(array, depth, predicate, isStrict, result) {
var index = -1,
length = array.length;
predicate || (predicate = isFlattenable);
result || (result = []);
while (++index < length) {
var value = array[index];
if (depth > 0 && predicate(value)) {
if (depth > 1) {
// Recursively flatten arrays (susceptible to call stack limits).
baseFlatten(value, depth - 1, predicate, isStrict, result);
} else {
arrayPush(result, value);
}
} else if (!isStrict) {
result[result.length] = value;
}
}
return result;
}
/**
* The base implementation of `baseForOwn` which iterates over `object`
* properties returned by `keysFunc` and invokes `iteratee` for each property.
* Iteratee functions may exit iteration early by explicitly returning `false`.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {Function} keysFunc The function to get the keys of `object`.
* @returns {Object} Returns `object`.
*/
var baseFor = createBaseFor();
/**
* This function is like `baseFor` except that it iterates over properties
* in the opposite order.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @param {Function} keysFunc The function to get the keys of `object`.
* @returns {Object} Returns `object`.
*/
var baseForRight = createBaseFor(true);
/**
* The base implementation of `_.forOwn` without support for iteratee shorthands.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Object} Returns `object`.
*/
function baseForOwn(object, iteratee) {
return object && baseFor(object, iteratee, keys);
}
/**
* The base implementation of `_.forOwnRight` without support for iteratee shorthands.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Object} Returns `object`.
*/
function baseForOwnRight(object, iteratee) {
return object && baseForRight(object, iteratee, keys);
}
/**
* The base implementation of `_.functions` which creates an array of
* `object` function property names filtered from `props`.
*
* @private
* @param {Object} object The object to inspect.
* @param {Array} props The property names to filter.
* @returns {Array} Returns the function names.
*/
function baseFunctions(object, props) {
return arrayFilter(props, function(key) {
return isFunction(object[key]);
});
}
/**
* The base implementation of `_.get` without support for default values.
*
* @private
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to get.
* @returns {*} Returns the resolved value.
*/
function baseGet(object, path) {
path = castPath(path, object);
var index = 0,
length = path.length;
while (object != null && index < length) {
object = object[toKey(path[index++])];
}
return (index && index == length) ? object : undefined$1;
}
/**
* The base implementation of `getAllKeys` and `getAllKeysIn` which uses
* `keysFunc` and `symbolsFunc` to get the enumerable property names and
* symbols of `object`.
*
* @private
* @param {Object} object The object to query.
* @param {Function} keysFunc The function to get the keys of `object`.
* @param {Function} symbolsFunc The function to get the symbols of `object`.
* @returns {Array} Returns the array of property names and symbols.
*/
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
var result = keysFunc(object);
return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}
/**
* The base implementation of `getTag` without fallbacks for buggy environments.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
function baseGetTag(value) {
if (value == null) {
return value === undefined$1 ? undefinedTag : nullTag;
}
return (symToStringTag && symToStringTag in Object(value))
? getRawTag(value)
: objectToString(value);
}
/**
* The base implementation of `_.gt` which doesn't coerce arguments.
*
* @private
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if `value` is greater than `other`,
* else `false`.
*/
function baseGt(value, other) {
return value > other;
}
/**
* The base implementation of `_.has` without support for deep paths.
*
* @private
* @param {Object} [object] The object to query.
* @param {Array|string} key The key to check.
* @returns {boolean} Returns `true` if `key` exists, else `false`.
*/
function baseHas(object, key) {
return object != null && hasOwnProperty.call(object, key);
}
/**
* The base implementation of `_.hasIn` without support for deep paths.
*
* @private
* @param {Object} [object] The object to query.
* @param {Array|string} key The key to check.
* @returns {boolean} Returns `true` if `key` exists, else `false`.
*/
function baseHasIn(object, key) {
return object != null && key in Object(object);
}
/**
* The base implementation of `_.inRange` which doesn't coerce arguments.
*
* @private
* @param {number} number The number to check.
* @param {number} start The start of the range.
* @param {number} end The end of the range.
* @returns {boolean} Returns `true` if `number` is in the range, else `false`.
*/
function baseInRange(number, start, end) {
return number >= nativeMin(start, end) && number < nativeMax(start, end);
}
/**
* The base implementation of methods like `_.intersection`, without support
* for iteratee shorthands, that accepts an array of arrays to inspect.
*
* @private
* @param {Array} arrays The arrays to inspect.
* @param {Function} [iteratee] The iteratee invoked per element.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of shared values.
*/
function baseIntersection(arrays, iteratee, comparator) {
var includes = comparator ? arrayIncludesWith : arrayIncludes,
length = arrays[0].length,
othLength = arrays.length,
othIndex = othLength,
caches = Array(othLength),
maxLength = Infinity,
result = [];
while (othIndex--) {
var array = arrays[othIndex];
if (othIndex && iteratee) {
array = arrayMap(array, baseUnary(iteratee));
}
maxLength = nativeMin(array.length, maxLength);
caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
? new SetCache(othIndex && array)
: undefined$1;
}
array = arrays[0];
var index = -1,
seen = caches[0];
outer:
while (++index < length && result.length < maxLength) {
var value = array[index],
computed = iteratee ? iteratee(value) : value;
value = (comparator || value !== 0) ? value : 0;
if (!(seen
? cacheHas(seen, computed)
: includes(result, computed, comparator)
)) {
othIndex = othLength;
while (--othIndex) {
var cache = caches[othIndex];
if (!(cache
? cacheHas(cache, computed)
: includes(arrays[othIndex], computed, comparator))
) {
continue outer;
}
}
if (seen) {
seen.push(computed);
}
result.push(value);
}
}
return result;
}
/**
* The base implementation of `_.invert` and `_.invertBy` which inverts
* `object` with values transformed by `iteratee` and set by `setter`.
*
* @private
* @param {Object} object The object to iterate over.
* @param {Function} setter The function to set `accumulator` values.
* @param {Function} iteratee The iteratee to transform values.
* @param {Object} accumulator The initial inverted object.
* @returns {Function} Returns `accumulator`.
*/
function baseInverter(object, setter, iteratee, accumulator) {
baseForOwn(object, function(value, key, object) {
setter(accumulator, iteratee(value), key, object);
});
return accumulator;
}
/**
* The base implementation of `_.invoke` without support for individual
* method arguments.
*
* @private
* @param {Object} object The object to query.
* @param {Array|string} path The path of the method to invoke.
* @param {Array} args The arguments to invoke the method with.
* @returns {*} Returns the result of the invoked method.
*/
function baseInvoke(object, path, args) {
path = castPath(path, object);
object = parent(object, path);
var func = object == null ? object : object[toKey(last(path))];
return func == null ? undefined$1 : apply(func, object, args);
}
/**
* The base implementation of `_.isArguments`.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
*/
function baseIsArguments(value) {
return isObjectLike(value) && baseGetTag(value) == argsTag;
}
/**
* The base implementation of `_.isArrayBuffer` without Node.js optimizations.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
*/
function baseIsArrayBuffer(value) {
return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
}
/**
* The base implementation of `_.isDate` without Node.js optimizations.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a date object, else `false`.
*/
function baseIsDate(value) {
return isObjectLike(value) && baseGetTag(value) == dateTag;
}
/**
* The base implementation of `_.isEqual` which supports partial comparisons
* and tracks traversed objects.
*
* @private
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @param {boolean} bitmask The bitmask flags.
* 1 - Unordered comparison
* 2 - Partial comparison
* @param {Function} [customizer] The function to customize comparisons.
* @param {Object} [stack] Tracks traversed `value` and `other` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
function baseIsEqual(value, other, bitmask, customizer, stack) {
if (value === other) {
return true;
}
if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
return value !== value && other !== other;
}
return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
}
/**
* A specialized version of `baseIsEqual` for arrays and objects which performs
* deep comparisons and tracks traversed objects enabling objects with circular
* references to be compared.
*
* @private
* @param {Object} object The object to compare.
* @param {Object} other The other object to compare.
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
* @param {Function} customizer The function to customize comparisons.
* @param {Function} equalFunc The function to determine equivalents of values.
* @param {Object} [stack] Tracks traversed `object` and `other` objects.
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
*/
function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
var objIsArr = isArray(object),
othIsArr = isArray(other),
objTag = objIsArr ? arrayTag : getTag(object),
othTag = othIsArr ? arrayTag : getTag(other);
objTag = objTag == argsTag ? objectTag : objTag;
othTag = othTag == argsTag ? objectTag : othTag;
var objIsObj = objTag == objectTag,
othIsObj = othTag == objectTag,
isSameTag = objTag == othTag;
if (isSameTag && isBuffer(object)) {
if (!isBuffer(other)) {
return false;
}
objIsArr = true;
objIsObj = false;
}
if (isSameTag && !objIsObj) {
stack || (stack = new Stack);
return (objIsArr || isTypedArray(object))
? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
: equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
}
if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
if (objIsWrapped || othIsWrapped) {
var objUnwrapped = objIsWrapped ? object.value() : object,
othUnwrapped = othIsWrapped ? other.value() : other;
stack || (stack = new Stack);
return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
}
}
if (!isSameTag) {
return false;
}
stack || (stack = new Stack);
return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
}
/**
* The base implementation of `_.isMap` without Node.js optimizations.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a map, else `false`.
*/
function baseIsMap(value) {
return isObjectLike(value) && getTag(value) == mapTag;
}
/**
* The base implementation of `_.isMatch` without support for iteratee shorthands.
*
* @private
* @param {Object} object The object to inspect.
* @param {Object} source The object of property values to match.
* @param {Array} matchData The property names, values, and compare flags to match.
* @param {Function} [customizer] The function to customize comparisons.
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
*/
function baseIsMatch(object, source, matchData, customizer) {
var index = matchData.length,
length = index,
noCustomizer = !customizer;
if (object == null) {
return !length;
}
object = Object(object);
while (index--) {
var data = matchData[index];
if ((noCustomizer && data[2])
? data[1] !== object[data[0]]
: !(data[0] in object)
) {
return false;
}
}
while (++index < length) {
data = matchData[index];
var key = data[0],
objValue = object[key],
srcValue = data[1];
if (noCustomizer && data[2]) {
if (objValue === undefined$1 && !(key in object)) {
return false;
}
} else {
var stack = new Stack;
if (customizer) {
var result = customizer(objValue, srcValue, key, object, source, stack);
}
if (!(result === undefined$1
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
: result
)) {
return false;
}
}
}
return true;
}
/**
* The base implementation of `_.isNative` without bad shim checks.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a native function,
* else `false`.
*/
function baseIsNative(value) {
if (!isObject(value) || isMasked(value)) {
return false;
}
var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
return pattern.test(toSource(value));
}
/**
* The base implementation of `_.isRegExp` without Node.js optimizations.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
*/
function baseIsRegExp(value) {
return isObjectLike(value) && baseGetTag(value) == regexpTag;
}
/**
* The base implementation of `_.isSet` without Node.js optimizations.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a set, else `false`.
*/
function baseIsSet(value) {
return isObjectLike(value) && getTag(value) == setTag;
}
/**
* The base implementation of `_.isTypedArray` without Node.js optimizations.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
*/
function baseIsTypedArray(value) {
return isObjectLike(value) &&
isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
}
/**
* The base implementation of `_.iteratee`.
*
* @private
* @param {*} [value=_.identity] The value to convert to an iteratee.
* @returns {Function} Returns the iteratee.
*/
function baseIteratee(value) {
// Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
// See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
if (typeof value == 'function') {
return value;
}
if (value == null) {
return identity;
}
if (typeof value == 'object') {
return isArray(value)
? baseMatchesProperty(value[0], value[1])
: baseMatches(value);
}
return property(value);
}
/**
* The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
*/
function baseKeys(object) {
if (!isPrototype(object)) {
return nativeKeys(object);
}
var result = [];
for (var key in Object(object)) {
if (hasOwnProperty.call(object, key) && key != 'constructor') {
result.push(key);
}
}
return result;
}
/**
* The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
*/
function baseKeysIn(object) {
if (!isObject(object)) {
return nativeKeysIn(object);
}
var isProto = isPrototype(object),
result = [];
for (var key in object) {
if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
result.push(key);
}
}
return result;
}
/**
* The base implementation of `_.lt` which doesn't coerce arguments.
*
* @private
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if `value` is less than `other`,
* else `false`.
*/
function baseLt(value, other) {
return value < other;
}
/**
* The base implementation of `_.map` without support for iteratee shorthands.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} iteratee The function invoked per iteration.
* @returns {Array} Returns the new mapped array.
*/
function baseMap(collection, iteratee) {
var index = -1,
result = isArrayLike(collection) ? Array(collection.length) : [];
baseEach(collection, function(value, key, collection) {
result[++index] = iteratee(value, key, collection);
});
return result;
}
/**
* The base implementation of `_.matches` which doesn't clone `source`.
*
* @private
* @param {Object} source The object of property values to match.
* @returns {Function} Returns the new spec function.
*/
function baseMatches(source) {
var matchData = getMatchData(source);
if (matchData.length == 1 && matchData[0][2]) {
return matchesStrictComparable(matchData[0][0], matchData[0][1]);
}
return function(object) {
return object === source || baseIsMatch(object, source, matchData);
};
}
/**
* The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
*
* @private
* @param {string} path The path of the property to get.
* @param {*} srcValue The value to match.
* @returns {Function} Returns the new spec function.
*/
function baseMatchesProperty(path, srcValue) {
if (isKey(path) && isStrictComparable(srcValue)) {
return matchesStrictComparable(toKey(path), srcValue);
}
return function(object) {
var objValue = get(object, path);
return (objValue === undefined$1 && objValue === srcValue)
? hasIn(object, path)
: baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
};
}
/**
* The base implementation of `_.merge` without support for multiple sources.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @param {number} srcIndex The index of `source`.
* @param {Function} [customizer] The function to customize merged values.
* @param {Object} [stack] Tracks traversed source values and their merged
* counterparts.
*/
function baseMerge(object, source, srcIndex, customizer, stack) {
if (object === source) {
return;
}
baseFor(source, function(srcValue, key) {
stack || (stack = new Stack);
if (isObject(srcValue)) {
baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
}
else {
var newValue = customizer
? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack)
: undefined$1;
if (newValue === undefined$1) {
newValue = srcValue;
}
assignMergeValue(object, key, newValue);
}
}, keysIn);
}
/**
* A specialized version of `baseMerge` for arrays and objects which performs
* deep merges and tracks traversed objects enabling objects with circular
* references to be merged.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @param {string} key The key of the value to merge.
* @param {number} srcIndex The index of `source`.
* @param {Function} mergeFunc The function to merge values.
* @param {Function} [customizer] The function to customize assigned values.
* @param {Object} [stack] Tracks traversed source values and their merged
* counterparts.
*/
function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
var objValue = safeGet(object, key),
srcValue = safeGet(source, key),
stacked = stack.get(srcValue);
if (stacked) {
assignMergeValue(object, key, stacked);
return;
}
var newValue = customizer
? customizer(objValue, srcValue, (key + ''), object, source, stack)
: undefined$1;
var isCommon = newValue === undefined$1;
if (isCommon) {
var isArr = isArray(srcValue),
isBuff = !isArr && isBuffer(srcValue),
isTyped = !isArr && !isBuff && isTypedArray(srcValue);
newValue = srcValue;
if (isArr || isBuff || isTyped) {
if (isArray(objValue)) {
newValue = objValue;
}
else if (isArrayLikeObject(objValue)) {
newValue = copyArray(objValue);
}
else if (isBuff) {
isCommon = false;
newValue = cloneBuffer(srcValue, true);
}
else if (isTyped) {
isCommon = false;
newValue = cloneTypedArray(srcValue, true);
}
else {
newValue = [];
}
}
else if (isPlainObject(srcValue) || isArguments(srcValue)) {
newValue = objValue;
if (isArguments(objValue)) {
newValue = toPlainObject(objValue);
}
else if (!isObject(objValue) || isFunction(objValue)) {
newValue = initCloneObject(srcValue);
}
}
else {
isCommon = false;
}
}
if (isCommon) {
// Recursively merge objects and arrays (susceptible to call stack limits).
stack.set(srcValue, newValue);
mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
stack['delete'](srcValue);
}
assignMergeValue(object, key, newValue);
}
/**
* The base implementation of `_.nth` which doesn't coerce arguments.
*
* @private
* @param {Array} array The array to query.
* @param {number} n The index of the element to return.
* @returns {*} Returns the nth element of `array`.
*/
function baseNth(array, n) {
var length = array.length;
if (!length) {
return;
}
n += n < 0 ? length : 0;
return isIndex(n, length) ? array[n] : undefined$1;
}
/**
* The base implementation of `_.orderBy` without param guards.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
* @param {string[]} orders The sort orders of `iteratees`.
* @returns {Array} Returns the new sorted array.
*/
function baseOrderBy(collection, iteratees, orders) {
if (iteratees.length) {
iteratees = arrayMap(iteratees, function(iteratee) {
if (isArray(iteratee)) {
return function(value) {
return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
}
}
return iteratee;
});
} else {
iteratees = [identity];
}
var index = -1;
iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
var result = baseMap(collection, function(value, key, collection) {
var criteria = arrayMap(iteratees, function(iteratee) {
return iteratee(value);
});
return { 'criteria': criteria, 'index': ++index, 'value': value };
});
return baseSortBy(result, function(object, other) {
return compareMultiple(object, other, orders);
});
}
/**
* The base implementation of `_.pick` without support for individual
* property identifiers.
*
* @private
* @param {Object} object The source object.
* @param {string[]} paths The property paths to pick.
* @returns {Object} Returns the new object.
*/
function basePick(object, paths) {
return basePickBy(object, paths, function(value, path) {
return hasIn(object, path);
});
}
/**
* The base implementation of `_.pickBy` without support for iteratee shorthands.
*
* @private
* @param {Object} object The source object.
* @param {string[]} paths The property paths to pick.
* @param {Function} predicate The function invoked per property.
* @returns {Object} Returns the new object.
*/
function basePickBy(object, paths, predicate) {
var index = -1,
length = paths.length,
result = {};
while (++index < length) {
var path = paths[index],
value = baseGet(object, path);
if (predicate(value, path)) {
baseSet(result, castPath(path, object), value);
}
}
return result;
}
/**
* A specialized version of `baseProperty` which supports deep paths.
*
* @private
* @param {Array|string} path The path of the property to get.
* @returns {Function} Returns the new accessor function.
*/
function basePropertyDeep(path) {
return function(object) {
return baseGet(object, path);
};
}
/**
* The base implementation of `_.pullAllBy` without support for iteratee
* shorthands.
*
* @private
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @param {Function} [iteratee] The iteratee invoked per element.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns `array`.
*/
function basePullAll(array, values, iteratee, comparator) {
var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
index = -1,
length = values.length,
seen = array;
if (array === values) {
values = copyArray(values);
}
if (iteratee) {
seen = arrayMap(array, baseUnary(iteratee));
}
while (++index < length) {
var fromIndex = 0,
value = values[index],
computed = iteratee ? iteratee(value) : value;
while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
if (seen !== array) {
splice.call(seen, fromIndex, 1);
}
splice.call(array, fromIndex, 1);
}
}
return array;
}
/**
* The base implementation of `_.pullAt` without support for individual
* indexes or capturing the removed elements.
*
* @private
* @param {Array} array The array to modify.
* @param {number[]} indexes The indexes of elements to remove.
* @returns {Array} Returns `array`.
*/
function basePullAt(array, indexes) {
var length = array ? indexes.length : 0,
lastIndex = length - 1;
while (length--) {
var index = indexes[length];
if (length == lastIndex || index !== previous) {
var previous = index;
if (isIndex(index)) {
splice.call(array, index, 1);
} else {
baseUnset(array, index);
}
}
}
return array;
}
/**
* The base implementation of `_.random` without support for returning
* floating-point numbers.
*
* @private
* @param {number} lower The lower bound.
* @param {number} upper The upper bound.
* @returns {number} Returns the random number.
*/
function baseRandom(lower, upper) {
return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
}
/**
* The base implementation of `_.range` and `_.rangeRight` which doesn't
* coerce arguments.
*
* @private
* @param {number} start The start of the range.
* @param {number} end The end of the range.
* @param {number} step The value to increment or decrement by.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {Array} Returns the range of numbers.
*/
function baseRange(start, end, step, fromRight) {
var index = -1,
length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
result = Array(length);
while (length--) {
result[fromRight ? length : ++index] = start;
start += step;
}
return result;
}
/**
* The base implementation of `_.repeat` which doesn't coerce arguments.
*
* @private
* @param {string} string The string to repeat.
* @param {number} n The number of times to repeat the string.
* @returns {string} Returns the repeated string.
*/
function baseRepeat(string, n) {
var result = '';
if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
return result;
}
// Leverage the exponentiation by squaring algorithm for a faster repeat.
// See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
do {
if (n % 2) {
result += string;
}
n = nativeFloor(n / 2);
if (n) {
string += string;
}
} while (n);
return result;
}
/**
* The base implementation of `_.rest` which doesn't validate or coerce arguments.
*
* @private
* @param {Function} func The function to apply a rest parameter to.
* @param {number} [start=func.length-1] The start position of the rest parameter.
* @returns {Function} Returns the new function.
*/
function baseRest(func, start) {
return setToString(overRest(func, start, identity), func + '');
}
/**
* The base implementation of `_.sample`.
*
* @private
* @param {Array|Object} collection The collection to sample.
* @returns {*} Returns the random element.
*/
function baseSample(collection) {
return arraySample(values(collection));
}
/**
* The base implementation of `_.sampleSize` without param guards.
*
* @private
* @param {Array|Object} collection The collection to sample.
* @param {number} n The number of elements to sample.
* @returns {Array} Returns the random elements.
*/
function baseSampleSize(collection, n) {
var array = values(collection);
return shuffleSelf(array, baseClamp(n, 0, array.length));
}
/**
* The base implementation of `_.set`.
*
* @private
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to set.
* @param {*} value The value to set.
* @param {Function} [customizer] The function to customize path creation.
* @returns {Object} Returns `object`.
*/
function baseSet(object, path, value, customizer) {
if (!isObject(object)) {
return object;
}
path = castPath(path, object);
var index = -1,
length = path.length,
lastIndex = length - 1,
nested = object;
while (nested != null && ++index < length) {
var key = toKey(path[index]),
newValue = value;
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
return object;
}
if (index != lastIndex) {
var objValue = nested[key];
newValue = customizer ? customizer(objValue, key, nested) : undefined$1;
if (newValue === undefined$1) {
newValue = isObject(objValue)
? objValue
: (isIndex(path[index + 1]) ? [] : {});
}
}
assignValue(nested, key, newValue);
nested = nested[key];
}
return object;
}
/**
* The base implementation of `setData` without support for hot loop shorting.
*
* @private
* @param {Function} func The function to associate metadata with.
* @param {*} data The metadata.
* @returns {Function} Returns `func`.
*/
var baseSetData = !metaMap ? identity : function(func, data) {
metaMap.set(func, data);
return func;
};
/**
* The base implementation of `setToString` without support for hot loop shorting.
*
* @private
* @param {Function} func The function to modify.
* @param {Function} string The `toString` result.
* @returns {Function} Returns `func`.
*/
var baseSetToString = !defineProperty ? identity : function(func, string) {
return defineProperty(func, 'toString', {
'configurable': true,
'enumerable': false,
'value': constant(string),
'writable': true
});
};
/**
* The base implementation of `_.shuffle`.
*
* @private
* @param {Array|Object} collection The collection to shuffle.
* @returns {Array} Returns the new shuffled array.
*/
function baseShuffle(collection) {
return shuffleSelf(values(collection));
}
/**
* The base implementation of `_.slice` without an iteratee call guard.
*
* @private
* @param {Array} array The array to slice.
* @param {number} [start=0] The start position.
* @param {number} [end=array.length] The end position.
* @returns {Array} Returns the slice of `array`.
*/
function baseSlice(array, start, end) {
var index = -1,
length = array.length;
if (start < 0) {
start = -start > length ? 0 : (length + start);
}
end = end > length ? length : end;
if (end < 0) {
end += length;
}
length = start > end ? 0 : ((end - start) >>> 0);
start >>>= 0;
var result = Array(length);
while (++index < length) {
result[index] = array[index + start];
}
return result;
}
/**
* The base implementation of `_.some` without support for iteratee shorthands.
*
* @private
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} predicate The function invoked per iteration.
* @returns {boolean} Returns `true` if any element passes the predicate check,
* else `false`.
*/
function baseSome(collection, predicate) {
var result;
baseEach(collection, function(value, index, collection) {
result = predicate(value, index, collection);
return !result;
});
return !!result;
}
/**
* The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
* performs a binary search of `array` to determine the index at which `value`
* should be inserted into `array` in order to maintain its sort order.
*
* @private
* @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate.
* @param {boolean} [retHighest] Specify returning the highest qualified index.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
*/
function baseSortedIndex(array, value, retHighest) {
var low = 0,
high = array == null ? low : array.length;
if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
while (low < high) {
var mid = (low + high) >>> 1,
computed = array[mid];
if (computed !== null && !isSymbol(computed) &&
(retHighest ? (computed <= value) : (computed < value))) {
low = mid + 1;
} else {
high = mid;
}
}
return high;
}
return baseSortedIndexBy(array, value, identity, retHighest);
}
/**
* The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
* which invokes `iteratee` for `value` and each element of `array` to compute
* their sort ranking. The iteratee is invoked with one argument; (value).
*
* @private
* @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate.
* @param {Function} iteratee The iteratee invoked per element.
* @param {boolean} [retHighest] Specify returning the highest qualified index.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
*/
function baseSortedIndexBy(array, value, iteratee, retHighest) {
var low = 0,
high = array == null ? 0 : array.length;
if (high === 0) {
return 0;
}
value = iteratee(value);
var valIsNaN = value !== value,
valIsNull = value === null,
valIsSymbol = isSymbol(value),
valIsUndefined = value === undefined$1;
while (low < high) {
var mid = nativeFloor((low + high) / 2),
computed = iteratee(array[mid]),
othIsDefined = computed !== undefined$1,
othIsNull = computed === null,
othIsReflexive = computed === computed,
othIsSymbol = isSymbol(computed);
if (valIsNaN) {
var setLow = retHighest || othIsReflexive;
} else if (valIsUndefined) {
setLow = othIsReflexive && (retHighest || othIsDefined);
} else if (valIsNull) {
setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
} else if (valIsSymbol) {
setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
} else if (othIsNull || othIsSymbol) {
setLow = false;
} else {
setLow = retHighest ? (computed <= value) : (computed < value);
}
if (setLow) {
low = mid + 1;
} else {
high = mid;
}
}
return nativeMin(high, MAX_ARRAY_INDEX);
}
/**
* The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
* support for iteratee shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The iteratee invoked per element.
* @returns {Array} Returns the new duplicate free array.
*/
function baseSortedUniq(array, iteratee) {
var index = -1,
length = array.length,
resIndex = 0,
result = [];
while (++index < length) {
var value = array[index],
computed = iteratee ? iteratee(value) : value;
if (!index || !eq(computed, seen)) {
var seen = computed;
result[resIndex++] = value === 0 ? 0 : value;
}
}
return result;
}
/**
* The base implementation of `_.toNumber` which doesn't ensure correct
* conversions of binary, hexadecimal, or octal string values.
*
* @private
* @param {*} value The value to process.
* @returns {number} Returns the number.
*/
function baseToNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
return +value;
}
/**
* The base implementation of `_.toString` which doesn't convert nullish
* values to empty strings.
*
* @private
* @param {*} value The value to process.
* @returns {string} Returns the string.
*/
function baseToString(value) {
// Exit early for strings to avoid a performance hit in some environments.
if (typeof value == 'string') {
return value;
}
if (isArray(value)) {
// Recursively convert values (susceptible to call stack limits).
return arrayMap(value, baseToString) + '';
}
if (isSymbol(value)) {
return symbolToString ? symbolToString.call(value) : '';
}
var result = (value + '');
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}
/**
* The base implementation of `_.uniqBy` without support for iteratee shorthands.
*
* @private
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The iteratee invoked per element.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new duplicate free array.
*/
function baseUniq(array, iteratee, comparator) {
var index = -1,
includes = arrayIncludes,
length = array.length,
isCommon = true,
result = [],
seen = result;
if (comparator) {
isCommon = false;
includes = arrayIncludesWith;
}
else if (length >= LARGE_ARRAY_SIZE) {
var set = iteratee ? null : createSet(array);
if (set) {
return setToArray(set);
}
isCommon = false;
includes = cacheHas;
seen = new SetCache;
}
else {
seen = iteratee ? [] : result;
}
outer:
while (++index < length) {
var value = array[index],
computed = iteratee ? iteratee(value) : value;
value = (comparator || value !== 0) ? value : 0;
if (isCommon && computed === computed) {
var seenIndex = seen.length;
while (seenIndex--) {
if (seen[seenIndex] === computed) {
continue outer;
}
}
if (iteratee) {
seen.push(computed);
}
result.push(value);
}
else if (!includes(seen, computed, comparator)) {
if (seen !== result) {
seen.push(computed);
}
result.push(value);
}
}
return result;
}
/**
* The base implementation of `_.unset`.
*
* @private
* @param {Object} object The object to modify.
* @param {Array|string} path The property path to unset.
* @returns {boolean} Returns `true` if the property is deleted, else `false`.
*/
function baseUnset(object, path) {
path = castPath(path, object);
object = parent(object, path);
return object == null || delete object[toKey(last(path))];
}
/**
* The base implementation of `_.update`.
*
* @private
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to update.
* @param {Function} updater The function to produce the updated value.
* @param {Function} [customizer] The function to customize path creation.
* @returns {Object} Returns `object`.
*/
function baseUpdate(object, path, updater, customizer) {
return baseSet(object, path, updater(baseGet(object, path)), customizer);
}
/**
* The base implementation of methods like `_.dropWhile` and `_.takeWhile`
* without support for iteratee shorthands.
*
* @private
* @param {Array} array The array to query.
* @param {Function} predicate The function invoked per iteration.
* @param {boolean} [isDrop] Specify dropping elements instead of taking them.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {Array} Returns the slice of `array`.
*/
function baseWhile(array, predicate, isDrop, fromRight) {
var length = array.length,
index = fromRight ? length : -1;
while ((fromRight ? index-- : ++index < length) &&
predicate(array[index], index, array)) {}
return isDrop
? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
: baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
}
/**
* The base implementation of `wrapperValue` which returns the result of
* performing a sequence of actions on the unwrapped `value`, where each
* successive action is supplied the return value of the previous.
*
* @private
* @param {*} value The unwrapped value.
* @param {Array} actions Actions to perform to resolve the unwrapped value.
* @returns {*} Returns the resolved value.
*/
function baseWrapperValue(value, actions) {
var result = value;
if (result instanceof LazyWrapper) {
result = result.value();
}
return arrayReduce(actions, function(result, action) {
return action.func.apply(action.thisArg, arrayPush([result], action.args));
}, result);
}
/**
* The base implementation of methods like `_.xor`, without support for
* iteratee shorthands, that accepts an array of arrays to inspect.
*
* @private
* @param {Array} arrays The arrays to inspect.
* @param {Function} [iteratee] The iteratee invoked per element.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of values.
*/
function baseXor(arrays, iteratee, comparator) {
var length = arrays.length;
if (length < 2) {
return length ? baseUniq(arrays[0]) : [];
}
var index = -1,
result = Array(length);
while (++index < length) {
var array = arrays[index],
othIndex = -1;
while (++othIndex < length) {
if (othIndex != index) {
result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
}
}
}
return baseUniq(baseFlatten(result, 1), iteratee, comparator);
}
/**
* This base implementation of `_.zipObject` which assigns values using `assignFunc`.
*
* @private
* @param {Array} props The property identifiers.
* @param {Array} values The property values.
* @param {Function} assignFunc The function to assign values.
* @returns {Object} Returns the new object.
*/
function baseZipObject(props, values, assignFunc) {
var index = -1,
length = props.length,
valsLength = values.length,
result = {};
while (++index < length) {
var value = index < valsLength ? values[index] : undefined$1;
assignFunc(result, props[index], value);
}
return result;
}
/**
* Casts `value` to an empty array if it's not an array like object.
*
* @private
* @param {*} value The value to inspect.
* @returns {Array|Object} Returns the cast array-like object.
*/
function castArrayLikeObject(value) {
return isArrayLikeObject(value) ? value : [];
}
/**
* Casts `value` to `identity` if it's not a function.
*
* @private
* @param {*} value The value to inspect.
* @returns {Function} Returns cast function.
*/
function castFunction(value) {
return typeof value == 'function' ? value : identity;
}
/**
* Casts `value` to a path array if it's not one.
*
* @private
* @param {*} value The value to inspect.
* @param {Object} [object] The object to query keys on.
* @returns {Array} Returns the cast property path array.
*/
function castPath(value, object) {
if (isArray(value)) {
return value;
}
return isKey(value, object) ? [value] : stringToPath(toString(value));
}
/**
* A `baseRest` alias which can be replaced with `identity` by module
* replacement plugins.
*
* @private
* @type {Function}
* @param {Function} func The function to apply a rest parameter to.
* @returns {Function} Returns the new function.
*/
var castRest = baseRest;
/**
* Casts `array` to a slice if it's needed.
*
* @private
* @param {Array} array The array to inspect.
* @param {number} start The start position.
* @param {number} [end=array.length] The end position.
* @returns {Array} Returns the cast slice.
*/
function castSlice(array, start, end) {
var length = array.length;
end = end === undefined$1 ? length : end;
return (!start && end >= length) ? array : baseSlice(array, start, end);
}
/**
* A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
*
* @private
* @param {number|Object} id The timer id or timeout object of the timer to clear.
*/
var clearTimeout = ctxClearTimeout || function(id) {
return root.clearTimeout(id);
};
/**
* Creates a clone of `buffer`.
*
* @private
* @param {Buffer} buffer The buffer to clone.
* @param {boolean} [isDeep] Specify a deep clone.
* @returns {Buffer} Returns the cloned buffer.
*/
function cloneBuffer(buffer, isDeep) {
if (isDeep) {
return buffer.slice();
}
var length = buffer.length,
result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
buffer.copy(result);
return result;
}
/**
* Creates a clone of `arrayBuffer`.
*
* @private
* @param {ArrayBuffer} arrayBuffer The array buffer to clone.
* @returns {ArrayBuffer} Returns the cloned array buffer.
*/
function cloneArrayBuffer(arrayBuffer) {
var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
new Uint8Array(result).set(new Uint8Array(arrayBuffer));
return result;
}
/**
* Creates a clone of `dataView`.
*
* @private
* @param {Object} dataView The data view to clone.
* @param {boolean} [isDeep] Specify a deep clone.
* @returns {Object} Returns the cloned data view.
*/
function cloneDataView(dataView, isDeep) {
var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
}
/**
* Creates a clone of `regexp`.
*
* @private
* @param {Object} regexp The regexp to clone.
* @returns {Object} Returns the cloned regexp.
*/
function cloneRegExp(regexp) {
var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
result.lastIndex = regexp.lastIndex;
return result;
}
/**
* Creates a clone of the `symbol` object.
*
* @private
* @param {Object} symbol The symbol object to clone.
* @returns {Object} Returns the cloned symbol object.
*/
function cloneSymbol(symbol) {
return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
}
/**
* Creates a clone of `typedArray`.
*
* @private
* @param {Object} typedArray The typed array to clone.
* @param {boolean} [isDeep] Specify a deep clone.
* @returns {Object} Returns the cloned typed array.
*/
function cloneTypedArray(typedArray, isDeep) {
var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
}
/**
* Compares values to sort them in ascending order.
*
* @private
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {number} Returns the sort order indicator for `value`.
*/
function compareAscending(value, other) {
if (value !== other) {
var valIsDefined = value !== undefined$1,
valIsNull = value === null,
valIsReflexive = value === value,
valIsSymbol = isSymbol(value);
var othIsDefined = other !== undefined$1,
othIsNull = other === null,
othIsReflexive = other === other,
othIsSymbol = isSymbol(other);
if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
(valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
(valIsNull && othIsDefined && othIsReflexive) ||
(!valIsDefined && othIsReflexive) ||
!valIsReflexive) {
return 1;
}
if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
(othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
(othIsNull && valIsDefined && valIsReflexive) ||
(!othIsDefined && valIsReflexive) ||
!othIsReflexive) {
return -1;
}
}
return 0;
}
/**
* Used by `_.orderBy` to compare multiple properties of a value to another
* and stable sort them.
*
* If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
* specify an order of "desc" for descending or "asc" for ascending sort order
* of corresponding values.
*
* @private
* @param {Object} object The object to compare.
* @param {Object} other The other object to compare.
* @param {boolean[]|string[]} orders The order to sort by for each property.
* @returns {number} Returns the sort order indicator for `object`.
*/
function compareMultiple(object, other, orders) {
var index = -1,
objCriteria = object.criteria,
othCriteria = other.criteria,
length = objCriteria.length,
ordersLength = orders.length;
while (++index < length) {
var result = compareAscending(objCriteria[index], othCriteria[index]);
if (result) {
if (index >= ordersLength) {
return result;
}
var order = orders[index];
return result * (order == 'desc' ? -1 : 1);
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to provide the same value for
// `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
// for more details.
//
// This also ensures a stable sort in V8 and other engines.
// See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
return object.index - other.index;
}
/**
* Creates an array that is the composition of partially applied arguments,
* placeholders, and provided arguments into a single array of arguments.
*
* @private
* @param {Array} args The provided arguments.
* @param {Array} partials The arguments to prepend to those provided.
* @param {Array} holders The `partials` placeholder indexes.
* @params {boolean} [isCurried] Specify composing for a curried function.
* @returns {Array} Returns the new array of composed arguments.
*/
function composeArgs(args, partials, holders, isCurried) {
var argsIndex = -1,
argsLength = args.length,
holdersLength = holders.length,
leftIndex = -1,
leftLength = partials.length,
rangeLength = nativeMax(argsLength - holdersLength, 0),
result = Array(leftLength + rangeLength),
isUncurried = !isCurried;
while (++leftIndex < leftLength) {
result[leftIndex] = partials[leftIndex];
}
while (++argsIndex < holdersLength) {
if (isUncurried || argsIndex < argsLength) {
result[holders[argsIndex]] = args[argsIndex];
}
}
while (rangeLength--) {
result[leftIndex++] = args[argsIndex++];
}
return result;
}
/**
* This function is like `composeArgs` except that the arguments composition
* is tailored for `_.partialRight`.
*
* @private
* @param {Array} args The provided arguments.
* @param {Array} partials The arguments to append to those provided.
* @param {Array} holders The `partials` placeholder indexes.
* @params {boolean} [isCurried] Specify composing for a curried function.
* @returns {Array} Returns the new array of composed arguments.
*/
function composeArgsRight(args, partials, holders, isCurried) {
var argsIndex = -1,
argsLength = args.length,
holdersIndex = -1,
holdersLength = holders.length,
rightIndex = -1,
rightLength = partials.length,
rangeLength = nativeMax(argsLength - holdersLength, 0),
result = Array(rangeLength + rightLength),
isUncurried = !isCurried;
while (++argsIndex < rangeLength) {
result[argsIndex] = args[argsIndex];
}
var offset = argsIndex;
while (++rightIndex < rightLength) {
result[offset + rightIndex] = partials[rightIndex];
}
while (++holdersIndex < holdersLength) {
if (isUncurried || argsIndex < argsLength) {
result[offset + holders[holdersIndex]] = args[argsIndex++];
}
}
return result;
}
/**
* Copies the values of `source` to `array`.
*
* @private
* @param {Array} source The array to copy values from.
* @param {Array} [array=[]] The array to copy values to.
* @returns {Array} Returns `array`.
*/
function copyArray(source, array) {
var index = -1,
length = source.length;
array || (array = Array(length));
while (++index < length) {
array[index] = source[index];
}
return array;
}
/**
* Copies properties of `source` to `object`.
*
* @private
* @param {Object} source The object to copy properties from.
* @param {Array} props The property identifiers to copy.
* @param {Object} [object={}] The object to copy properties to.
* @param {Function} [customizer] The function to customize copied values.
* @returns {Object} Returns `object`.
*/
function copyObject(source, props, object, customizer) {
var isNew = !object;
object || (object = {});
var index = -1,
length = props.length;
while (++index < length) {
var key = props[index];
var newValue = customizer
? customizer(object[key], source[key], key, object, source)
: undefined$1;
if (newValue === undefined$1) {
newValue = source[key];
}
if (isNew) {
baseAssignValue(object, key, newValue);
} else {
assignValue(object, key, newValue);
}
}
return object;
}
/**
* Copies own symbols of `source` to `object`.
*
* @private
* @param {Object} source The object to copy symbols from.
* @param {Object} [object={}] The object to copy symbols to.
* @returns {Object} Returns `object`.
*/
function copySymbols(source, object) {
return copyObject(source, getSymbols(source), object);
}
/**
* Copies own and inherited symbols of `source` to `object`.
*
* @private
* @param {Object} source The object to copy symbols from.
* @param {Object} [object={}] The object to copy symbols to.
* @returns {Object} Returns `object`.
*/
function copySymbolsIn(source, object) {
return copyObject(source, getSymbolsIn(source), object);
}
/**
* Creates a function like `_.groupBy`.
*
* @private
* @param {Function} setter The function to set accumulator values.
* @param {Function} [initializer] The accumulator object initializer.
* @returns {Function} Returns the new aggregator function.
*/
function createAggregator(setter, initializer) {
return function(collection, iteratee) {
var func = isArray(collection) ? arrayAggregator : baseAggregator,
accumulator = initializer ? initializer() : {};
return func(collection, setter, getIteratee(iteratee, 2), accumulator);
};
}
/**
* Creates a function like `_.assign`.
*
* @private
* @param {Function} assigner The function to assign values.
* @returns {Function} Returns the new assigner function.
*/
function createAssigner(assigner) {
return baseRest(function(object, sources) {
var index = -1,
length = sources.length,
customizer = length > 1 ? sources[length - 1] : undefined$1,
guard = length > 2 ? sources[2] : undefined$1;
customizer = (assigner.length > 3 && typeof customizer == 'function')
? (length--, customizer)
: undefined$1;
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
customizer = length < 3 ? undefined$1 : customizer;
length = 1;
}
object = Object(object);
while (++index < length) {
var source = sources[index];
if (source) {
assigner(object, source, index, customizer);
}
}
return object;
});
}
/**
* Creates a `baseEach` or `baseEachRight` function.
*
* @private
* @param {Function} eachFunc The function to iterate over a collection.
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {Function} Returns the new base function.
*/
function createBaseEach(eachFunc, fromRight) {
return function(collection, iteratee) {
if (collection == null) {
return collection;
}
if (!isArrayLike(collection)) {
return eachFunc(collection, iteratee);
}
var length = collection.length,
index = fromRight ? length : -1,
iterable = Object(collection);
while ((fromRight ? index-- : ++index < length)) {
if (iteratee(iterable[index], index, iterable) === false) {
break;
}
}
return collection;
};
}
/**
* Creates a base function for methods like `_.forIn` and `_.forOwn`.
*
* @private
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {Function} Returns the new base function.
*/
function createBaseFor(fromRight) {
return function(object, iteratee, keysFunc) {
var index = -1,
iterable = Object(object),
props = keysFunc(object),
length = props.length;
while (length--) {
var key = props[fromRight ? length : ++index];
if (iteratee(iterable[key], key, iterable) === false) {
break;
}
}
return object;
};
}
/**
* Creates a function that wraps `func` to invoke it with the optional `this`
* binding of `thisArg`.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {*} [thisArg] The `this` binding of `func`.
* @returns {Function} Returns the new wrapped function.
*/
function createBind(func, bitmask, thisArg) {
var isBind = bitmask & WRAP_BIND_FLAG,
Ctor = createCtor(func);
function wrapper() {
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
return fn.apply(isBind ? thisArg : this, arguments);
}
return wrapper;
}
/**
* Creates a function like `_.lowerFirst`.
*
* @private
* @param {string} methodName The name of the `String` case method to use.
* @returns {Function} Returns the new case function.
*/
function createCaseFirst(methodName) {
return function(string) {
string = toString(string);
var strSymbols = hasUnicode(string)
? stringToArray(string)
: undefined$1;
var chr = strSymbols
? strSymbols[0]
: string.charAt(0);
var trailing = strSymbols
? castSlice(strSymbols, 1).join('')
: string.slice(1);
return chr[methodName]() + trailing;
};
}
/**
* Creates a function like `_.camelCase`.
*
* @private
* @param {Function} callback The function to combine each word.
* @returns {Function} Returns the new compounder function.
*/
function createCompounder(callback) {
return function(string) {
return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
};
}
/**
* Creates a function that produces an instance of `Ctor` regardless of
* whether it was invoked as part of a `new` expression or by `call` or `apply`.
*
* @private
* @param {Function} Ctor The constructor to wrap.
* @returns {Function} Returns the new wrapped function.
*/
function createCtor(Ctor) {
return function() {
// Use a `switch` statement to work with class constructors. See
// http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
// for more details.
var args = arguments;
switch (args.length) {
case 0: return new Ctor;
case 1: return new Ctor(args[0]);
case 2: return new Ctor(args[0], args[1]);
case 3: return new Ctor(args[0], args[1], args[2]);
case 4: return new Ctor(args[0], args[1], args[2], args[3]);
case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
}
var thisBinding = baseCreate(Ctor.prototype),
result = Ctor.apply(thisBinding, args);
// Mimic the constructor's `return` behavior.
// See https://es5.github.io/#x13.2.2 for more details.
return isObject(result) ? result : thisBinding;
};
}
/**
* Creates a function that wraps `func` to enable currying.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {number} arity The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/
function createCurry(func, bitmask, arity) {
var Ctor = createCtor(func);
function wrapper() {
var length = arguments.length,
args = Array(length),
index = length,
placeholder = getHolder(wrapper);
while (index--) {
args[index] = arguments[index];
}
var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
? []
: replaceHolders(args, placeholder);
length -= holders.length;
if (length < arity) {
return createRecurry(
func, bitmask, createHybrid, wrapper.placeholder, undefined$1,
args, holders, undefined$1, undefined$1, arity - length);
}
var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
return apply(fn, this, args);
}
return wrapper;
}
/**
* Creates a `_.find` or `_.findLast` function.
*
* @private
* @param {Function} findIndexFunc The function to find the collection index.
* @returns {Function} Returns the new find function.
*/
function createFind(findIndexFunc) {
return function(collection, predicate, fromIndex) {
var iterable = Object(collection);
if (!isArrayLike(collection)) {
var iteratee = getIteratee(predicate, 3);
collection = keys(collection);
predicate = function(key) { return iteratee(iterable[key], key, iterable); };
}
var index = findIndexFunc(collection, predicate, fromIndex);
return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined$1;
};
}
/**
* Creates a `_.flow` or `_.flowRight` function.
*
* @private
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {Function} Returns the new flow function.
*/
function createFlow(fromRight) {
return flatRest(function(funcs) {
var length = funcs.length,
index = length,
prereq = LodashWrapper.prototype.thru;
if (fromRight) {
funcs.reverse();
}
while (index--) {
var func = funcs[index];
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
var wrapper = new LodashWrapper([], true);
}
}
index = wrapper ? index : length;
while (++index < length) {
func = funcs[index];
var funcName = getFuncName(func),
data = funcName == 'wrapper' ? getData(func) : undefined$1;
if (data && isLaziable(data[0]) &&
data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
!data[4].length && data[9] == 1
) {
wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
} else {
wrapper = (func.length == 1 && isLaziable(func))
? wrapper[funcName]()
: wrapper.thru(func);
}
}
return function() {
var args = arguments,
value = args[0];
if (wrapper && args.length == 1 && isArray(value)) {
return wrapper.plant(value).value();
}
var index = 0,
result = length ? funcs[index].apply(this, args) : value;
while (++index < length) {
result = funcs[index].call(this, result);
}
return result;
};
});
}
/**
* Creates a function that wraps `func` to invoke it with optional `this`
* binding of `thisArg`, partial application, and currying.
*
* @private
* @param {Function|string} func The function or method name to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to prepend to those provided to
* the new function.
* @param {Array} [holders] The `partials` placeholder indexes.
* @param {Array} [partialsRight] The arguments to append to those provided
* to the new function.
* @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
* @param {Array} [argPos] The argument positions of the new function.
* @param {number} [ary] The arity cap of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/
function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
var isAry = bitmask & WRAP_ARY_FLAG,
isBind = bitmask & WRAP_BIND_FLAG,
isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
isFlip = bitmask & WRAP_FLIP_FLAG,
Ctor = isBindKey ? undefined$1 : createCtor(func);
function wrapper() {
var length = arguments.length,
args = Array(length),
index = length;
while (index--) {
args[index] = arguments[index];
}
if (isCurried) {
var placeholder = getHolder(wrapper),
holdersCount = countHolders(args, placeholder);
}
if (partials) {
args = composeArgs(args, partials, holders, isCurried);
}
if (partialsRight) {
args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
}
length -= holdersCount;
if (isCurried && length < arity) {
var newHolders = replaceHolders(args, placeholder);
return createRecurry(
func, bitmask, createHybrid, wrapper.placeholder, thisArg,
args, newHolders, argPos, ary, arity - length
);
}
var thisBinding = isBind ? thisArg : this,
fn = isBindKey ? thisBinding[func] : func;
length = args.length;
if (argPos) {
args = reorder(args, argPos);
} else if (isFlip && length > 1) {
args.reverse();
}
if (isAry && ary < length) {
args.length = ary;
}
if (this && this !== root && this instanceof wrapper) {
fn = Ctor || createCtor(fn);
}
return fn.apply(thisBinding, args);
}
return wrapper;
}
/**
* Creates a function like `_.invertBy`.
*
* @private
* @param {Function} setter The function to set accumulator values.
* @param {Function} toIteratee The function to resolve iteratees.
* @returns {Function} Returns the new inverter function.
*/
function createInverter(setter, toIteratee) {
return function(object, iteratee) {
return baseInverter(object, setter, toIteratee(iteratee), {});
};
}
/**
* Creates a function that performs a mathematical operation on two values.
*
* @private
* @param {Function} operator The function to perform the operation.
* @param {number} [defaultValue] The value used for `undefined` arguments.
* @returns {Function} Returns the new mathematical operation function.
*/
function createMathOperation(operator, defaultValue) {
return function(value, other) {
var result;
if (value === undefined$1 && other === undefined$1) {
return defaultValue;
}
if (value !== undefined$1) {
result = value;
}
if (other !== undefined$1) {
if (result === undefined$1) {
return other;
}
if (typeof value == 'string' || typeof other == 'string') {
value = baseToString(value);
other = baseToString(other);
} else {
value = baseToNumber(value);
other = baseToNumber(other);
}
result = operator(value, other);
}
return result;
};
}
/**
* Creates a function like `_.over`.
*
* @private
* @param {Function} arrayFunc The function to iterate over iteratees.
* @returns {Function} Returns the new over function.
*/
function createOver(arrayFunc) {
return flatRest(function(iteratees) {
iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
return baseRest(function(args) {
var thisArg = this;
return arrayFunc(iteratees, function(iteratee) {
return apply(iteratee, thisArg, args);
});
});
});
}
/**
* Creates the padding for `string` based on `length`. The `chars` string
* is truncated if the number of characters exceeds `length`.
*
* @private
* @param {number} length The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padding for `string`.
*/
function createPadding(length, chars) {
chars = chars === undefined$1 ? ' ' : baseToString(chars);
var charsLength = chars.length;
if (charsLength < 2) {
return charsLength ? baseRepeat(chars, length) : chars;
}
var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
return hasUnicode(chars)
? castSlice(stringToArray(result), 0, length).join('')
: result.slice(0, length);
}
/**
* Creates a function that wraps `func` to invoke it with the `this` binding
* of `thisArg` and `partials` prepended to the arguments it receives.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {*} thisArg The `this` binding of `func`.
* @param {Array} partials The arguments to prepend to those provided to
* the new function.
* @returns {Function} Returns the new wrapped function.
*/
function createPartial(func, bitmask, thisArg, partials) {
var isBind = bitmask & WRAP_BIND_FLAG,
Ctor = createCtor(func);
function wrapper() {
var argsIndex = -1,
argsLength = arguments.length,
leftIndex = -1,
leftLength = partials.length,
args = Array(leftLength + argsLength),
fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
while (++leftIndex < leftLength) {
args[leftIndex] = partials[leftIndex];
}
while (argsLength--) {
args[leftIndex++] = arguments[++argsIndex];
}
return apply(fn, isBind ? thisArg : this, args);
}
return wrapper;
}
/**
* Creates a `_.range` or `_.rangeRight` function.
*
* @private
* @param {boolean} [fromRight] Specify iterating from right to left.
* @returns {Function} Returns the new range function.
*/
function createRange(fromRight) {
return function(start, end, step) {
if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
end = step = undefined$1;
}
// Ensure the sign of `-0` is preserved.
start = toFinite(start);
if (end === undefined$1) {
end = start;
start = 0;
} else {
end = toFinite(end);
}
step = step === undefined$1 ? (start < end ? 1 : -1) : toFinite(step);
return baseRange(start, end, step, fromRight);
};
}
/**
* Creates a function that performs a relational operation on two values.
*
* @private
* @param {Function} operator The function to perform the operation.
* @returns {Function} Returns the new relational operation function.
*/
function createRelationalOperation(operator) {
return function(value, other) {
if (!(typeof value == 'string' && typeof other == 'string')) {
value = toNumber(value);
other = toNumber(other);
}
return operator(value, other);
};
}
/**
* Creates a function that wraps `func` to continue currying.
*
* @private
* @param {Function} func The function to wrap.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @param {Function} wrapFunc The function to create the `func` wrapper.
* @param {*} placeholder The placeholder value.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to prepend to those provided to
* the new function.
* @param {Array} [holders] The `partials` placeholder indexes.
* @param {Array} [argPos] The argument positions of the new function.
* @param {number} [ary] The arity cap of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/
function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
var isCurry = bitmask & WRAP_CURRY_FLAG,
newHolders = isCurry ? holders : undefined$1,
newHoldersRight = isCurry ? undefined$1 : holders,
newPartials = isCurry ? partials : undefined$1,
newPartialsRight = isCurry ? undefined$1 : partials;
bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
}
var newData = [
func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
newHoldersRight, argPos, ary, arity
];
var result = wrapFunc.apply(undefined$1, newData);
if (isLaziable(func)) {
setData(result, newData);
}
result.placeholder = placeholder;
return setWrapToString(result, func, bitmask);
}
/**
* Creates a function like `_.round`.
*
* @private
* @param {string} methodName The name of the `Math` method to use when rounding.
* @returns {Function} Returns the new round function.
*/
function createRound(methodName) {
var func = Math[methodName];
return function(number, precision) {
number = toNumber(number);
precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
if (precision && nativeIsFinite(number)) {
// Shift with exponential notation to avoid floating-point issues.
// See [MDN](https://mdn.io/round#Examples) for more details.
var pair = (toString(number) + 'e').split('e'),
value = func(pair[0] + 'e' + (+pair[1] + precision));
pair = (toString(value) + 'e').split('e');
return +(pair[0] + 'e' + (+pair[1] - precision));
}
return func(number);
};
}
/**
* Creates a set object of `values`.
*
* @private
* @param {Array} values The values to add to the set.
* @returns {Object} Returns the new set.
*/
var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
return new Set(values);
};
/**
* Creates a `_.toPairs` or `_.toPairsIn` function.
*
* @private
* @param {Function} keysFunc The function to get the keys of a given object.
* @returns {Function} Returns the new pairs function.
*/
function createToPairs(keysFunc) {
return function(object) {
var tag = getTag(object);
if (tag == mapTag) {
return mapToArray(object);
}
if (tag == setTag) {
return setToPairs(object);
}
return baseToPairs(object, keysFunc(object));
};
}
/**
* Creates a function that either curries or invokes `func` with optional
* `this` binding and partially applied arguments.
*
* @private
* @param {Function|string} func The function or method name to wrap.
* @param {number} bitmask The bitmask flags.
* 1 - `_.bind`
* 2 - `_.bindKey`
* 4 - `_.curry` or `_.curryRight` of a bound function
* 8 - `_.curry`
* 16 - `_.curryRight`
* 32 - `_.partial`
* 64 - `_.partialRight`
* 128 - `_.rearg`
* 256 - `_.ary`
* 512 - `_.flip`
* @param {*} [thisArg] The `this` binding of `func`.
* @param {Array} [partials] The arguments to be partially applied.
* @param {Array} [holders] The `partials` placeholder indexes.
* @param {Array} [argPos] The argument positions of the new function.
* @param {number} [ary] The arity cap of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new wrapped function.
*/
function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
if (!isBindKey && typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
var length = partials ? partials.length : 0;
if (!length) {
bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
partials = holders = undefined$1;
}
ary = ary === undefined$1 ? ary : nativeMax(toInteger(ary), 0);
arity = arity === undefined$1 ? arity : toInteger(arity);
length -= holders ? holders.length : 0;
if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
var partialsRight = partials,
holdersRight = holders;
partials = holders = undefined$1;
}
var data = isBindKey ? undefined$1 : getData(func);
var newData = [
func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
argPos, ary, arity
];
if (data) {
mergeData(newData, data);
}
func = newData[0];
bitmask = newData[1];
thisArg = newData[2];
partials = newData[3];
holders = newData[4];
arity = newData[9] = newData[9] === undefined$1
? (isBindKey ? 0 : func.length)
: nativeMax(newData[9] - length, 0);
if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
}
if (!bitmask || bitmask == WRAP_BIND_FLAG) {
var result = createBind(func, bitmask, thisArg);
} else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
result = createCurry(func, bitmask, arity);
} else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
result = createPartial(func, bitmask, thisArg, partials);
} else {
result = createHybrid.apply(undefined$1, newData);
}
var setter = data ? baseSetData : setData;
return setWrapToString(setter(result, newData), func, bitmask);
}
/**
* Used by `_.defaults` to customize its `_.assignIn` use to assign properties
* of source objects to the destination object for all destination properties
* that resolve to `undefined`.
*
* @private
* @param {*} objValue The destination value.
* @param {*} srcValue The source value.
* @param {string} key The key of the property to assign.
* @param {Object} object The parent object of `objValue`.
* @returns {*} Returns the value to assign.
*/
function customDefaultsAssignIn(objValue, srcValue, key, object) {
if (objValue === undefined$1 ||
(eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
return srcValue;
}
return objValue;
}
/**
* Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
* objects into destination objects that are passed thru.
*
* @private
* @param {*} objValue The destination value.
* @param {*} srcValue The source value.
* @param {string} key The key of the property to merge.
* @param {Object} object The parent object of `objValue`.
* @param {Object} source The parent object of `srcValue`.
* @param {Object} [stack] Tracks traversed source values and their merged
* counterparts.
* @returns {*} Returns the value to assign.
*/
function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
if (isObject(objValue) && isObject(srcValue)) {
// Recursively merge objects and arrays (susceptible to call stack limits).
stack.set(srcValue, objValue);
baseMerge(objValue, srcValue, undefined$1, customDefaultsMerge, stack);
stack['delete'](srcValue);
}
return objValue;
}
/**
* Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
* objects.
*
* @private
* @param {*} value The value to inspect.
* @param {string} key The key of the property to inspect.
* @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
*/
function customOmitClone(value) {
return isPlainObject(value) ? undefined$1 : value;
}
/**
* A specialized version of `baseIsEqualDeep` for arrays with support for
* partial deep comparisons.
*
* @private
* @param {Array} array The array to compare.
* @param {Array} other The other array to compare.
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
* @param {Function} customizer The function to customize comparisons.
* @param {Function} equalFunc The function to determine equivalents of values.
* @param {Object} stack Tracks traversed `array` and `other` objects.
* @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
*/
function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
arrLength = array.length,
othLength = other.length;
if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
return false;
}
// Check that cyclic values are equal.
var arrStacked = stack.get(array);
var othStacked = stack.get(other);
if (arrStacked && othStacked) {
return arrStacked == other && othStacked == array;
}
var index = -1,
result = true,
seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined$1;
stack.set(array, other);
stack.set(other, array);
// Ignore non-index properties.
while (++index < arrLength) {
var arrValue = array[index],
othValue = other[index];
if (customizer) {
var compared = isPartial
? customizer(othValue, arrValue, index, other, array, stack)
: customizer(arrValue, othValue, index, array, other, stack);
}
if (compared !== undefined$1) {
if (compared) {
continue;
}
result = false;
break;
}
// Recursively compare arrays (susceptible to call stack limits).
if (seen) {
if (!arraySome(other, function(othValue, othIndex) {
if (!cacheHas(seen, othIndex) &&
(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
return seen.push(othIndex);
}
})) {
result = false;
break;
}
} else if (!(
arrValue === othValue ||
equalFunc(arrValue, othValue, bitmask, customizer, stack)
)) {
result = false;
break;
}
}
stack['delete'](array);
stack['delete'](other);
return result;
}
/**
* A specialized version of `baseIsEqualDeep` for comparing objects of
* the same `toStringTag`.
*
* **Note:** This function only supports comparing values with tags of
* `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
*
* @private
* @param {Object} object The object to compare.
* @param {Object} other The other object to compare.
* @param {string} tag The `toStringTag` of the objects to compare.
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
* @param {Function} customizer The function to customize comparisons.
* @param {Function} equalFunc The function to determine equivalents of values.
* @param {Object} stack Tracks traversed `object` and `other` objects.
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
*/
function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
switch (tag) {
case dataViewTag:
if ((object.byteLength != other.byteLength) ||
(object.byteOffset != other.byteOffset)) {
return false;
}
object = object.buffer;
other = other.buffer;
case arrayBufferTag:
if ((object.byteLength != other.byteLength) ||
!equalFunc(new Uint8Array(object), new Uint8Array(other))) {
return false;
}
return true;
case boolTag:
case dateTag:
case numberTag:
// Coerce booleans to `1` or `0` and dates to milliseconds.
// Invalid dates are coerced to `NaN`.
return eq(+object, +other);
case errorTag:
return object.name == other.name && object.message == other.message;
case regexpTag:
case stringTag:
// Coerce regexes to strings and treat strings, primitives and objects,
// as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
// for more details.
return object == (other + '');
case mapTag:
var convert = mapToArray;
case setTag:
var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
convert || (convert = setToArray);
if (object.size != other.size && !isPartial) {
return false;
}
// Assume cyclic values are equal.
var stacked = stack.get(object);
if (stacked) {
return stacked == other;
}
bitmask |= COMPARE_UNORDERED_FLAG;
// Recursively compare objects (susceptible to call stack limits).
stack.set(object, other);
var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
stack['delete'](object);
return result;
case symbolTag:
if (symbolValueOf) {
return symbolValueOf.call(object) == symbolValueOf.call(other);
}
}
return false;
}
/**
* A specialized version of `baseIsEqualDeep` for objects with support for
* partial deep comparisons.
*
* @private
* @param {Object} object The object to compare.
* @param {Object} other The other object to compare.
* @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
* @param {Function} customizer The function to customize comparisons.
* @param {Function} equalFunc The function to determine equivalents of values.
* @param {Object} stack Tracks traversed `object` and `other` objects.
* @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
*/
function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
objProps = getAllKeys(object),
objLength = objProps.length,
othProps = getAllKeys(other),
othLength = othProps.length;
if (objLength != othLength && !isPartial) {
return false;
}
var index = objLength;
while (index--) {
var key = objProps[index];
if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
return false;
}
}
// Check that cyclic values are equal.
var objStacked = stack.get(object);
var othStacked = stack.get(other);
if (objStacked && othStacked) {
return objStacked == other && othStacked == object;
}
var result = true;
stack.set(object, other);
stack.set(other, object);
var skipCtor = isPartial;
while (++index < objLength) {
key = objProps[index];
var objValue = object[key],
othValue = other[key];
if (customizer) {
var compared = isPartial
? customizer(othValue, objValue, key, other, object, stack)
: customizer(objValue, othValue, key, object, other, stack);
}
// Recursively compare objects (susceptible to call stack limits).
if (!(compared === undefined$1
? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
: compared
)) {
result = false;
break;
}
skipCtor || (skipCtor = key == 'constructor');
}
if (result && !skipCtor) {
var objCtor = object.constructor,
othCtor = other.constructor;
// Non `Object` object instances with different constructors are not equal.
if (objCtor != othCtor &&
('constructor' in object && 'constructor' in other) &&
!(typeof objCtor == 'function' && objCtor instanceof objCtor &&
typeof othCtor == 'function' && othCtor instanceof othCtor)) {
result = false;
}
}
stack['delete'](object);
stack['delete'](other);
return result;
}
/**
* A specialized version of `baseRest` which flattens the rest array.
*
* @private
* @param {Function} func The function to apply a rest parameter to.
* @returns {Function} Returns the new function.
*/
function flatRest(func) {
return setToString(overRest(func, undefined$1, flatten), func + '');
}
/**
* Creates an array of own enumerable property names and symbols of `object`.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names and symbols.
*/
function getAllKeys(object) {
return baseGetAllKeys(object, keys, getSymbols);
}
/**
* Creates an array of own and inherited enumerable property names and
* symbols of `object`.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names and symbols.
*/
function getAllKeysIn(object) {
return baseGetAllKeys(object, keysIn, getSymbolsIn);
}
/**
* Gets metadata for `func`.
*
* @private
* @param {Function} func The function to query.
* @returns {*} Returns the metadata for `func`.
*/
var getData = !metaMap ? noop : function(func) {
return metaMap.get(func);
};
/**
* Gets the name of `func`.
*
* @private
* @param {Function} func The function to query.
* @returns {string} Returns the function name.
*/
function getFuncName(func) {
var result = (func.name + ''),
array = realNames[result],
length = hasOwnProperty.call(realNames, result) ? array.length : 0;
while (length--) {
var data = array[length],
otherFunc = data.func;
if (otherFunc == null || otherFunc == func) {
return data.name;
}
}
return result;
}
/**
* Gets the argument placeholder value for `func`.
*
* @private
* @param {Function} func The function to inspect.
* @returns {*} Returns the placeholder value.
*/
function getHolder(func) {
var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
return object.placeholder;
}
/**
* Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
* this function returns the custom method, otherwise it returns `baseIteratee`.
* If arguments are provided, the chosen function is invoked with them and
* its result is returned.
*
* @private
* @param {*} [value] The value to convert to an iteratee.
* @param {number} [arity] The arity of the created iteratee.
* @returns {Function} Returns the chosen function or its result.
*/
function getIteratee() {
var result = lodash.iteratee || iteratee;
result = result === iteratee ? baseIteratee : result;
return arguments.length ? result(arguments[0], arguments[1]) : result;
}
/**
* Gets the data for `map`.
*
* @private
* @param {Object} map The map to query.
* @param {string} key The reference key.
* @returns {*} Returns the map data.
*/
function getMapData(map, key) {
var data = map.__data__;
return isKeyable(key)
? data[typeof key == 'string' ? 'string' : 'hash']
: data.map;
}
/**
* Gets the property names, values, and compare flags of `object`.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the match data of `object`.
*/
function getMatchData(object) {
var result = keys(object),
length = result.length;
while (length--) {
var key = result[length],
value = object[key];
result[length] = [key, value, isStrictComparable(value)];
}
return result;
}
/**
* Gets the native function at `key` of `object`.
*
* @private
* @param {Object} object The object to query.
* @param {string} key The key of the method to get.
* @returns {*} Returns the function if it's native, else `undefined`.
*/
function getNative(object, key) {
var value = getValue(object, key);
return baseIsNative(value) ? value : undefined$1;
}
/**
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the raw `toStringTag`.
*/
function getRawTag(value) {
var isOwn = hasOwnProperty.call(value, symToStringTag),
tag = value[symToStringTag];
try {
value[symToStringTag] = undefined$1;
var unmasked = true;
} catch (e) {}
var result = nativeObjectToString.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag] = tag;
} else {
delete value[symToStringTag];
}
}
return result;
}
/**
* Creates an array of the own enumerable symbols of `object`.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of symbols.
*/
var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
if (object == null) {
return [];
}
object = Object(object);
return arrayFilter(nativeGetSymbols(object), function(symbol) {
return propertyIsEnumerable.call(object, symbol);
});
};
/**
* Creates an array of the own and inherited enumerable symbols of `object`.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of symbols.
*/
var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
var result = [];
while (object) {
arrayPush(result, getSymbols(object));
object = getPrototype(object);
}
return result;
};
/**
* Gets the `toStringTag` of `value`.
*
* @private
* @param {*} value The value to query.
* @returns {string} Returns the `toStringTag`.
*/
var getTag = baseGetTag;
// Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
(Map && getTag(new Map) != mapTag) ||
(Promise && getTag(Promise.resolve()) != promiseTag) ||
(Set && getTag(new Set) != setTag) ||
(WeakMap && getTag(new WeakMap) != weakMapTag)) {
getTag = function(value) {
var result = baseGetTag(value),
Ctor = result == objectTag ? value.constructor : undefined$1,
ctorString = Ctor ? toSource(Ctor) : '';
if (ctorString) {
switch (ctorString) {
case dataViewCtorString: return dataViewTag;
case mapCtorString: return mapTag;
case promiseCtorString: return promiseTag;
case setCtorString: return setTag;
case weakMapCtorString: return weakMapTag;
}
}
return result;
};
}
/**
* Gets the view, applying any `transforms` to the `start` and `end` positions.
*
* @private
* @param {number} start The start of the view.
* @param {number} end The end of the view.
* @param {Array} transforms The transformations to apply to the view.
* @returns {Object} Returns an object containing the `start` and `end`
* positions of the view.
*/
function getView(start, end, transforms) {
var index = -1,
length = transforms.length;
while (++index < length) {
var data = transforms[index],
size = data.size;
switch (data.type) {
case 'drop': start += size; break;
case 'dropRight': end -= size; break;
case 'take': end = nativeMin(end, start + size); break;
case 'takeRight': start = nativeMax(start, end - size); break;
}
}
return { 'start': start, 'end': end };
}
/**
* Extracts wrapper details from the `source` body comment.
*
* @private
* @param {string} source The source to inspect.
* @returns {Array} Returns the wrapper details.
*/
function getWrapDetails(source) {
var match = source.match(reWrapDetails);
return match ? match[1].split(reSplitDetails) : [];
}
/**
* Checks if `path` exists on `object`.
*
* @private
* @param {Object} object The object to query.
* @param {Array|string} path The path to check.
* @param {Function} hasFunc The function to check properties.
* @returns {boolean} Returns `true` if `path` exists, else `false`.
*/
function hasPath(object, path, hasFunc) {
path = castPath(path, object);
var index = -1,
length = path.length,
result = false;
while (++index < length) {
var key = toKey(path[index]);
if (!(result = object != null && hasFunc(object, key))) {
break;
}
object = object[key];
}
if (result || ++index != length) {
return result;
}
length = object == null ? 0 : object.length;
return !!length && isLength(length) && isIndex(key, length) &&
(isArray(object) || isArguments(object));
}
/**
* Initializes an array clone.
*
* @private
* @param {Array} array The array to clone.
* @returns {Array} Returns the initialized clone.
*/
function initCloneArray(array) {
var length = array.length,
result = new array.constructor(length);
// Add properties assigned by `RegExp#exec`.
if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
result.index = array.index;
result.input = array.input;
}
return result;
}
/**
* Initializes an object clone.
*
* @private
* @param {Object} object The object to clone.
* @returns {Object} Returns the initialized clone.
*/
function initCloneObject(object) {
return (typeof object.constructor == 'function' && !isPrototype(object))
? baseCreate(getPrototype(object))
: {};
}
/**
* Initializes an object clone based on its `toStringTag`.
*
* **Note:** This function only supports cloning values with tags of
* `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
*
* @private
* @param {Object} object The object to clone.
* @param {string} tag The `toStringTag` of the object to clone.
* @param {boolean} [isDeep] Specify a deep clone.
* @returns {Object} Returns the initialized clone.
*/
function initCloneByTag(object, tag, isDeep) {
var Ctor = object.constructor;
switch (tag) {
case arrayBufferTag:
return cloneArrayBuffer(object);
case boolTag:
case dateTag:
return new Ctor(+object);
case dataViewTag:
return cloneDataView(object, isDeep);
case float32Tag: case float64Tag:
case int8Tag: case int16Tag: case int32Tag:
case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
return cloneTypedArray(object, isDeep);
case mapTag:
return new Ctor;
case numberTag:
case stringTag:
return new Ctor(object);
case regexpTag:
return cloneRegExp(object);
case setTag:
return new Ctor;
case symbolTag:
return cloneSymbol(object);
}
}
/**
* Inserts wrapper `details` in a comment at the top of the `source` body.
*
* @private
* @param {string} source The source to modify.
* @returns {Array} details The details to insert.
* @returns {string} Returns the modified source.
*/
function insertWrapDetails(source, details) {
var length = details.length;
if (!length) {
return source;
}
var lastIndex = length - 1;
details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
details = details.join(length > 2 ? ', ' : ' ');
return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
}
/**
* Checks if `value` is a flattenable `arguments` object or array.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
*/
function isFlattenable(value) {
return isArray(value) || isArguments(value) ||
!!(spreadableSymbol && value && value[spreadableSymbol]);
}
/**
* Checks if `value` is a valid array-like index.
*
* @private
* @param {*} value The value to check.
* @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
*/
function isIndex(value, length) {
var type = typeof value;
length = length == null ? MAX_SAFE_INTEGER : length;
return !!length &&
(type == 'number' ||
(type != 'symbol' && reIsUint.test(value))) &&
(value > -1 && value % 1 == 0 && value < length);
}
/**
* Checks if the given arguments are from an iteratee call.
*
* @private
* @param {*} value The potential iteratee value argument.
* @param {*} index The potential iteratee index or key argument.
* @param {*} object The potential iteratee object argument.
* @returns {boolean} Returns `true` if the arguments are from an iteratee call,
* else `false`.
*/
function isIterateeCall(value, index, object) {
if (!isObject(object)) {
return false;
}
var type = typeof index;
if (type == 'number'
? (isArrayLike(object) && isIndex(index, object.length))
: (type == 'string' && index in object)
) {
return eq(object[index], value);
}
return false;
}
/**
* Checks if `value` is a property name and not a property path.
*
* @private
* @param {*} value The value to check.
* @param {Object} [object] The object to query keys on.
* @returns {boolean} Returns `true` if `value` is a property name, else `false`.
*/
function isKey(value, object) {
if (isArray(value)) {
return false;
}
var type = typeof value;
if (type == 'number' || type == 'symbol' || type == 'boolean' ||
value == null || isSymbol(value)) {
return true;
}
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
(object != null && value in Object(object));
}
/**
* Checks if `value` is suitable for use as unique object key.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is suitable, else `false`.
*/
function isKeyable(value) {
var type = typeof value;
return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
? (value !== '__proto__')
: (value === null);
}
/**
* Checks if `func` has a lazy counterpart.
*
* @private
* @param {Function} func The function to check.
* @returns {boolean} Returns `true` if `func` has a lazy counterpart,
* else `false`.
*/
function isLaziable(func) {
var funcName = getFuncName(func),
other = lodash[funcName];
if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
return false;
}
if (func === other) {
return true;
}
var data = getData(other);
return !!data && func === data[0];
}
/**
* Checks if `func` has its source masked.
*
* @private
* @param {Function} func The function to check.
* @returns {boolean} Returns `true` if `func` is masked, else `false`.
*/
function isMasked(func) {
return !!maskSrcKey && (maskSrcKey in func);
}
/**
* Checks if `func` is capable of being masked.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `func` is maskable, else `false`.
*/
var isMaskable = coreJsData ? isFunction : stubFalse;
/**
* Checks if `value` is likely a prototype object.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
*/
function isPrototype(value) {
var Ctor = value && value.constructor,
proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
return value === proto;
}
/**
* Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` if suitable for strict
* equality comparisons, else `false`.
*/
function isStrictComparable(value) {
return value === value && !isObject(value);
}
/**
* A specialized version of `matchesProperty` for source values suitable
* for strict equality comparisons, i.e. `===`.
*
* @private
* @param {string} key The key of the property to get.
* @param {*} srcValue The value to match.
* @returns {Function} Returns the new spec function.
*/
function matchesStrictComparable(key, srcValue) {
return function(object) {
if (object == null) {
return false;
}
return object[key] === srcValue &&
(srcValue !== undefined$1 || (key in Object(object)));
};
}
/**
* A specialized version of `_.memoize` which clears the memoized function's
* cache when it exceeds `MAX_MEMOIZE_SIZE`.
*
* @private
* @param {Function} func The function to have its output memoized.
* @returns {Function} Returns the new memoized function.
*/
function memoizeCapped(func) {
var result = memoize(func, function(key) {
if (cache.size === MAX_MEMOIZE_SIZE) {
cache.clear();
}
return key;
});
var cache = result.cache;
return result;
}
/**
* Merges the function metadata of `source` into `data`.
*
* Merging metadata reduces the number of wrappers used to invoke a function.
* This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
* may be applied regardless of execution order. Methods like `_.ary` and
* `_.rearg` modify function arguments, making the order in which they are
* executed important, preventing the merging of metadata. However, we make
* an exception for a safe combined case where curried functions have `_.ary`
* and or `_.rearg` applied.
*
* @private
* @param {Array} data The destination metadata.
* @param {Array} source The source metadata.
* @returns {Array} Returns `data`.
*/
function mergeData(data, source) {
var bitmask = data[1],
srcBitmask = source[1],
newBitmask = bitmask | srcBitmask,
isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
var isCombo =
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
// Exit early if metadata can't be merged.
if (!(isCommon || isCombo)) {
return data;
}
// Use source `thisArg` if available.
if (srcBitmask & WRAP_BIND_FLAG) {
data[2] = source[2];
// Set when currying a bound function.
newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
}
// Compose partial arguments.
var value = source[3];
if (value) {
var partials = data[3];
data[3] = partials ? composeArgs(partials, value, source[4]) : value;
data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
}
// Compose partial right arguments.
value = source[5];
if (value) {
partials = data[5];
data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
}
// Use source `argPos` if available.
value = source[7];
if (value) {
data[7] = value;
}
// Use source `ary` if it's smaller.
if (srcBitmask & WRAP_ARY_FLAG) {
data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
}
// Use source `arity` if one is not provided.
if (data[9] == null) {
data[9] = source[9];
}
// Use source `func` and merge bitmasks.
data[0] = source[0];
data[1] = newBitmask;
return data;
}
/**
* This function is like
* [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
* except that it includes inherited enumerable properties.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
*/
function nativeKeysIn(object) {
var result = [];
if (object != null) {
for (var key in Object(object)) {
result.push(key);
}
}
return result;
}
/**
* Converts `value` to a string using `Object.prototype.toString`.
*
* @private
* @param {*} value The value to convert.
* @returns {string} Returns the converted string.
*/
function objectToString(value) {
return nativeObjectToString.call(value);
}
/**
* A specialized version of `baseRest` which transforms the rest array.
*
* @private
* @param {Function} func The function to apply a rest parameter to.
* @param {number} [start=func.length-1] The start position of the rest parameter.
* @param {Function} transform The rest array transform.
* @returns {Function} Returns the new function.
*/
function overRest(func, start, transform) {
start = nativeMax(start === undefined$1 ? (func.length - 1) : start, 0);
return function() {
var args = arguments,
index = -1,
length = nativeMax(args.length - start, 0),
array = Array(length);
while (++index < length) {
array[index] = args[start + index];
}
index = -1;
var otherArgs = Array(start + 1);
while (++index < start) {
otherArgs[index] = args[index];
}
otherArgs[start] = transform(array);
return apply(func, this, otherArgs);
};
}
/**
* Gets the parent value at `path` of `object`.
*
* @private
* @param {Object} object The object to query.
* @param {Array} path The path to get the parent value of.
* @returns {*} Returns the parent value.
*/
function parent(object, path) {
return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
}
/**
* Reorder `array` according to the specified indexes where the element at
* the first index is assigned as the first element, the element at
* the second index is assigned as the second element, and so on.
*
* @private
* @param {Array} array The array to reorder.
* @param {Array} indexes The arranged array indexes.
* @returns {Array} Returns `array`.
*/
function reorder(array, indexes) {
var arrLength = array.length,
length = nativeMin(indexes.length, arrLength),
oldArray = copyArray(array);
while (length--) {
var index = indexes[length];
array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined$1;
}
return array;
}
/**
* Gets the value at `key`, unless `key` is "__proto__" or "constructor".
*
* @private
* @param {Object} object The object to query.
* @param {string} key The key of the property to get.
* @returns {*} Returns the property value.
*/
function safeGet(object, key) {
if (key === 'constructor' && typeof object[key] === 'function') {
return;
}
if (key == '__proto__') {
return;
}
return object[key];
}
/**
* Sets metadata for `func`.
*
* **Note:** If this function becomes hot, i.e. is invoked a lot in a short
* period of time, it will trip its breaker and transition to an identity
* function to avoid garbage collection pauses in V8. See
* [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
* for more details.
*
* @private
* @param {Function} func The function to associate metadata with.
* @param {*} data The metadata.
* @returns {Function} Returns `func`.
*/
var setData = shortOut(baseSetData);
/**
* A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
*
* @private
* @param {Function} func The function to delay.
* @param {number} wait The number of milliseconds to delay invocation.
* @returns {number|Object} Returns the timer id or timeout object.
*/
var setTimeout = ctxSetTimeout || function(func, wait) {
return root.setTimeout(func, wait);
};
/**
* Sets the `toString` method of `func` to return `string`.
*
* @private
* @param {Function} func The function to modify.
* @param {Function} string The `toString` result.
* @returns {Function} Returns `func`.
*/
var setToString = shortOut(baseSetToString);
/**
* Sets the `toString` method of `wrapper` to mimic the source of `reference`
* with wrapper details in a comment at the top of the source body.
*
* @private
* @param {Function} wrapper The function to modify.
* @param {Function} reference The reference function.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @returns {Function} Returns `wrapper`.
*/
function setWrapToString(wrapper, reference, bitmask) {
var source = (reference + '');
return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
}
/**
* Creates a function that'll short out and invoke `identity` instead
* of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
* milliseconds.
*
* @private
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new shortable function.
*/
function shortOut(func) {
var count = 0,
lastCalled = 0;
return function() {
var stamp = nativeNow(),
remaining = HOT_SPAN - (stamp - lastCalled);
lastCalled = stamp;
if (remaining > 0) {
if (++count >= HOT_COUNT) {
return arguments[0];
}
} else {
count = 0;
}
return func.apply(undefined$1, arguments);
};
}
/**
* A specialized version of `_.shuffle` which mutates and sets the size of `array`.
*
* @private
* @param {Array} array The array to shuffle.
* @param {number} [size=array.length] The size of `array`.
* @returns {Array} Returns `array`.
*/
function shuffleSelf(array, size) {
var index = -1,
length = array.length,
lastIndex = length - 1;
size = size === undefined$1 ? length : size;
while (++index < size) {
var rand = baseRandom(index, lastIndex),
value = array[rand];
array[rand] = array[index];
array[index] = value;
}
array.length = size;
return array;
}
/**
* Converts `string` to a property path array.
*
* @private
* @param {string} string The string to convert.
* @returns {Array} Returns the property path array.
*/
var stringToPath = memoizeCapped(function(string) {
var result = [];
if (string.charCodeAt(0) === 46 /* . */) {
result.push('');
}
string.replace(rePropName, function(match, number, quote, subString) {
result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match));
});
return result;
});
/**
* Converts `value` to a string key if it's not a string or symbol.
*
* @private
* @param {*} value The value to inspect.
* @returns {string|symbol} Returns the key.
*/
function toKey(value) {
if (typeof value == 'string' || isSymbol(value)) {
return value;
}
var result = (value + '');
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
}
/**
* Converts `func` to its source code.
*
* @private
* @param {Function} func The function to convert.
* @returns {string} Returns the source code.
*/
function toSource(func) {
if (func != null) {
try {
return funcToString.call(func);
} catch (e) {}
try {
return (func + '');
} catch (e) {}
}
return '';
}
/**
* Updates wrapper `details` based on `bitmask` flags.
*
* @private
* @returns {Array} details The details to modify.
* @param {number} bitmask The bitmask flags. See `createWrap` for more details.
* @returns {Array} Returns `details`.
*/
function updateWrapDetails(details, bitmask) {
arrayEach(wrapFlags, function(pair) {
var value = '_.' + pair[0];
if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
details.push(value);
}
});
return details.sort();
}
/**
* Creates a clone of `wrapper`.
*
* @private
* @param {Object} wrapper The wrapper to clone.
* @returns {Object} Returns the cloned wrapper.
*/
function wrapperClone(wrapper) {
if (wrapper instanceof LazyWrapper) {
return wrapper.clone();
}
var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
result.__actions__ = copyArray(wrapper.__actions__);
result.__index__ = wrapper.__index__;
result.__values__ = wrapper.__values__;
return result;
}
/*------------------------------------------------------------------------*/
/**
* Creates an array of elements split into groups the length of `size`.
* If `array` can't be split evenly, the final chunk will be the remaining
* elements.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to process.
* @param {number} [size=1] The length of each chunk
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the new array of chunks.
* @example
*
* _.chunk(['a', 'b', 'c', 'd'], 2);
* // => [['a', 'b'], ['c', 'd']]
*
* _.chunk(['a', 'b', 'c', 'd'], 3);
* // => [['a', 'b', 'c'], ['d']]
*/
function chunk(array, size, guard) {
if ((guard ? isIterateeCall(array, size, guard) : size === undefined$1)) {
size = 1;
} else {
size = nativeMax(toInteger(size), 0);
}
var length = array == null ? 0 : array.length;
if (!length || size < 1) {
return [];
}
var index = 0,
resIndex = 0,
result = Array(nativeCeil(length / size));
while (index < length) {
result[resIndex++] = baseSlice(array, index, (index += size));
}
return result;
}
/**
* Creates an array with all falsey values removed. The values `false`, `null`,
* `0`, `""`, `undefined`, and `NaN` are falsey.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to compact.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
* // => [1, 2, 3]
*/
function compact(array) {
var index = -1,
length = array == null ? 0 : array.length,
resIndex = 0,
result = [];
while (++index < length) {
var value = array[index];
if (value) {
result[resIndex++] = value;
}
}
return result;
}
/**
* Creates a new array concatenating `array` with any additional arrays
* and/or values.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to concatenate.
* @param {...*} [values] The values to concatenate.
* @returns {Array} Returns the new concatenated array.
* @example
*
* var array = [1];
* var other = _.concat(array, 2, [3], [[4]]);
*
* console.log(other);
* // => [1, 2, 3, [4]]
*
* console.log(array);
* // => [1]
*/
function concat() {
var length = arguments.length;
if (!length) {
return [];
}
var args = Array(length - 1),
array = arguments[0],
index = length;
while (index--) {
args[index - 1] = arguments[index];
}
return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
}
/**
* Creates an array of `array` values not included in the other given arrays
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons. The order and references of result values are
* determined by the first array.
*
* **Note:** Unlike `_.pullAll`, this method returns a new array.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to inspect.
* @param {...Array} [values] The values to exclude.
* @returns {Array} Returns the new array of filtered values.
* @see _.without, _.xor
* @example
*
* _.difference([2, 1], [2, 3]);
* // => [1]
*/
var difference = baseRest(function(array, values) {
return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
: [];
});
/**
* This method is like `_.difference` except that it accepts `iteratee` which
* is invoked for each element of `array` and `values` to generate the criterion
* by which they're compared. The order and references of result values are
* determined by the first array. The iteratee is invoked with one argument:
* (value).
*
* **Note:** Unlike `_.pullAllBy`, this method returns a new array.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {...Array} [values] The values to exclude.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
* // => [1.2]
*
* // The `_.property` iteratee shorthand.
* _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
var differenceBy = baseRest(function(array, values) {
var iteratee = last(values);
if (isArrayLikeObject(iteratee)) {
iteratee = undefined$1;
}
return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
: [];
});
/**
* This method is like `_.difference` except that it accepts `comparator`
* which is invoked to compare elements of `array` to `values`. The order and
* references of result values are determined by the first array. The comparator
* is invoked with two arguments: (arrVal, othVal).
*
* **Note:** Unlike `_.pullAllWith`, this method returns a new array.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {...Array} [values] The values to exclude.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
*
* _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
* // => [{ 'x': 2, 'y': 1 }]
*/
var differenceWith = baseRest(function(array, values) {
var comparator = last(values);
if (isArrayLikeObject(comparator)) {
comparator = undefined$1;
}
return isArrayLikeObject(array)
? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined$1, comparator)
: [];
});
/**
* Creates a slice of `array` with `n` elements dropped from the beginning.
*
* @static
* @memberOf _
* @since 0.5.0
* @category Array
* @param {Array} array The array to query.
* @param {number} [n=1] The number of elements to drop.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.drop([1, 2, 3]);
* // => [2, 3]
*
* _.drop([1, 2, 3], 2);
* // => [3]
*
* _.drop([1, 2, 3], 5);
* // => []
*
* _.drop([1, 2, 3], 0);
* // => [1, 2, 3]
*/
function drop(array, n, guard) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
n = (guard || n === undefined$1) ? 1 : toInteger(n);
return baseSlice(array, n < 0 ? 0 : n, length);
}
/**
* Creates a slice of `array` with `n` elements dropped from the end.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {number} [n=1] The number of elements to drop.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.dropRight([1, 2, 3]);
* // => [1, 2]
*
* _.dropRight([1, 2, 3], 2);
* // => [1]
*
* _.dropRight([1, 2, 3], 5);
* // => []
*
* _.dropRight([1, 2, 3], 0);
* // => [1, 2, 3]
*/
function dropRight(array, n, guard) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
n = (guard || n === undefined$1) ? 1 : toInteger(n);
n = length - n;
return baseSlice(array, 0, n < 0 ? 0 : n);
}
/**
* Creates a slice of `array` excluding elements dropped from the end.
* Elements are dropped until `predicate` returns falsey. The predicate is
* invoked with three arguments: (value, index, array).
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the slice of `array`.
* @example
*
* var users = [
* { 'user': 'barney', 'active': true },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': false }
* ];
*
* _.dropRightWhile(users, function(o) { return !o.active; });
* // => objects for ['barney']
*
* // The `_.matches` iteratee shorthand.
* _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
* // => objects for ['barney', 'fred']
*
* // The `_.matchesProperty` iteratee shorthand.
* _.dropRightWhile(users, ['active', false]);
* // => objects for ['barney']
*
* // The `_.property` iteratee shorthand.
* _.dropRightWhile(users, 'active');
* // => objects for ['barney', 'fred', 'pebbles']
*/
function dropRightWhile(array, predicate) {
return (array && array.length)
? baseWhile(array, getIteratee(predicate, 3), true, true)
: [];
}
/**
* Creates a slice of `array` excluding elements dropped from the beginning.
* Elements are dropped until `predicate` returns falsey. The predicate is
* invoked with three arguments: (value, index, array).
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the slice of `array`.
* @example
*
* var users = [
* { 'user': 'barney', 'active': false },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': true }
* ];
*
* _.dropWhile(users, function(o) { return !o.active; });
* // => objects for ['pebbles']
*
* // The `_.matches` iteratee shorthand.
* _.dropWhile(users, { 'user': 'barney', 'active': false });
* // => objects for ['fred', 'pebbles']
*
* // The `_.matchesProperty` iteratee shorthand.
* _.dropWhile(users, ['active', false]);
* // => objects for ['pebbles']
*
* // The `_.property` iteratee shorthand.
* _.dropWhile(users, 'active');
* // => objects for ['barney', 'fred', 'pebbles']
*/
function dropWhile(array, predicate) {
return (array && array.length)
? baseWhile(array, getIteratee(predicate, 3), true)
: [];
}
/**
* Fills elements of `array` with `value` from `start` up to, but not
* including, `end`.
*
* **Note:** This method mutates `array`.
*
* @static
* @memberOf _
* @since 3.2.0
* @category Array
* @param {Array} array The array to fill.
* @param {*} value The value to fill `array` with.
* @param {number} [start=0] The start position.
* @param {number} [end=array.length] The end position.
* @returns {Array} Returns `array`.
* @example
*
* var array = [1, 2, 3];
*
* _.fill(array, 'a');
* console.log(array);
* // => ['a', 'a', 'a']
*
* _.fill(Array(3), 2);
* // => [2, 2, 2]
*
* _.fill([4, 6, 8, 10], '*', 1, 3);
* // => [4, '*', '*', 10]
*/
function fill(array, value, start, end) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
start = 0;
end = length;
}
return baseFill(array, value, start, end);
}
/**
* This method is like `_.find` except that it returns the index of the first
* element `predicate` returns truthy for instead of the element itself.
*
* @static
* @memberOf _
* @since 1.1.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var users = [
* { 'user': 'barney', 'active': false },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': true }
* ];
*
* _.findIndex(users, function(o) { return o.user == 'barney'; });
* // => 0
*
* // The `_.matches` iteratee shorthand.
* _.findIndex(users, { 'user': 'fred', 'active': false });
* // => 1
*
* // The `_.matchesProperty` iteratee shorthand.
* _.findIndex(users, ['active', false]);
* // => 0
*
* // The `_.property` iteratee shorthand.
* _.findIndex(users, 'active');
* // => 2
*/
function findIndex(array, predicate, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (index < 0) {
index = nativeMax(length + index, 0);
}
return baseFindIndex(array, getIteratee(predicate, 3), index);
}
/**
* This method is like `_.findIndex` except that it iterates over elements
* of `collection` from right to left.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var users = [
* { 'user': 'barney', 'active': true },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': false }
* ];
*
* _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
* // => 2
*
* // The `_.matches` iteratee shorthand.
* _.findLastIndex(users, { 'user': 'barney', 'active': true });
* // => 0
*
* // The `_.matchesProperty` iteratee shorthand.
* _.findLastIndex(users, ['active', false]);
* // => 2
*
* // The `_.property` iteratee shorthand.
* _.findLastIndex(users, 'active');
* // => 0
*/
function findLastIndex(array, predicate, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = length - 1;
if (fromIndex !== undefined$1) {
index = toInteger(fromIndex);
index = fromIndex < 0
? nativeMax(length + index, 0)
: nativeMin(index, length - 1);
}
return baseFindIndex(array, getIteratee(predicate, 3), index, true);
}
/**
* Flattens `array` a single level deep.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to flatten.
* @returns {Array} Returns the new flattened array.
* @example
*
* _.flatten([1, [2, [3, [4]], 5]]);
* // => [1, 2, [3, [4]], 5]
*/
function flatten(array) {
var length = array == null ? 0 : array.length;
return length ? baseFlatten(array, 1) : [];
}
/**
* Recursively flattens `array`.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to flatten.
* @returns {Array} Returns the new flattened array.
* @example
*
* _.flattenDeep([1, [2, [3, [4]], 5]]);
* // => [1, 2, 3, 4, 5]
*/
function flattenDeep(array) {
var length = array == null ? 0 : array.length;
return length ? baseFlatten(array, INFINITY) : [];
}
/**
* Recursively flatten `array` up to `depth` times.
*
* @static
* @memberOf _
* @since 4.4.0
* @category Array
* @param {Array} array The array to flatten.
* @param {number} [depth=1] The maximum recursion depth.
* @returns {Array} Returns the new flattened array.
* @example
*
* var array = [1, [2, [3, [4]], 5]];
*
* _.flattenDepth(array, 1);
* // => [1, 2, [3, [4]], 5]
*
* _.flattenDepth(array, 2);
* // => [1, 2, 3, [4], 5]
*/
function flattenDepth(array, depth) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
depth = depth === undefined$1 ? 1 : toInteger(depth);
return baseFlatten(array, depth);
}
/**
* The inverse of `_.toPairs`; this method returns an object composed
* from key-value `pairs`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} pairs The key-value pairs.
* @returns {Object} Returns the new object.
* @example
*
* _.fromPairs([['a', 1], ['b', 2]]);
* // => { 'a': 1, 'b': 2 }
*/
function fromPairs(pairs) {
var index = -1,
length = pairs == null ? 0 : pairs.length,
result = {};
while (++index < length) {
var pair = pairs[index];
result[pair[0]] = pair[1];
}
return result;
}
/**
* Gets the first element of `array`.
*
* @static
* @memberOf _
* @since 0.1.0
* @alias first
* @category Array
* @param {Array} array The array to query.
* @returns {*} Returns the first element of `array`.
* @example
*
* _.head([1, 2, 3]);
* // => 1
*
* _.head([]);
* // => undefined
*/
function head(array) {
return (array && array.length) ? array[0] : undefined$1;
}
/**
* Gets the index at which the first occurrence of `value` is found in `array`
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons. If `fromIndex` is negative, it's used as the
* offset from the end of `array`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
* @example
*
* _.indexOf([1, 2, 1, 2], 2);
* // => 1
*
* // Search from the `fromIndex`.
* _.indexOf([1, 2, 1, 2], 2, 2);
* // => 3
*/
function indexOf(array, value, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = fromIndex == null ? 0 : toInteger(fromIndex);
if (index < 0) {
index = nativeMax(length + index, 0);
}
return baseIndexOf(array, value, index);
}
/**
* Gets all but the last element of `array`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to query.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.initial([1, 2, 3]);
* // => [1, 2]
*/
function initial(array) {
var length = array == null ? 0 : array.length;
return length ? baseSlice(array, 0, -1) : [];
}
/**
* Creates an array of unique values that are included in all given arrays
* using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons. The order and references of result values are
* determined by the first array.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @returns {Array} Returns the new array of intersecting values.
* @example
*
* _.intersection([2, 1], [2, 3]);
* // => [2]
*/
var intersection = baseRest(function(arrays) {
var mapped = arrayMap(arrays, castArrayLikeObject);
return (mapped.length && mapped[0] === arrays[0])
? baseIntersection(mapped)
: [];
});
/**
* This method is like `_.intersection` except that it accepts `iteratee`
* which is invoked for each element of each `arrays` to generate the criterion
* by which they're compared. The order and references of result values are
* determined by the first array. The iteratee is invoked with one argument:
* (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Array} Returns the new array of intersecting values.
* @example
*
* _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
* // => [2.1]
*
* // The `_.property` iteratee shorthand.
* _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }]
*/
var intersectionBy = baseRest(function(arrays) {
var iteratee = last(arrays),
mapped = arrayMap(arrays, castArrayLikeObject);
if (iteratee === last(mapped)) {
iteratee = undefined$1;
} else {
mapped.pop();
}
return (mapped.length && mapped[0] === arrays[0])
? baseIntersection(mapped, getIteratee(iteratee, 2))
: [];
});
/**
* This method is like `_.intersection` except that it accepts `comparator`
* which is invoked to compare elements of `arrays`. The order and references
* of result values are determined by the first array. The comparator is
* invoked with two arguments: (arrVal, othVal).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of intersecting values.
* @example
*
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
* var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
*
* _.intersectionWith(objects, others, _.isEqual);
* // => [{ 'x': 1, 'y': 2 }]
*/
var intersectionWith = baseRest(function(arrays) {
var comparator = last(arrays),
mapped = arrayMap(arrays, castArrayLikeObject);
comparator = typeof comparator == 'function' ? comparator : undefined$1;
if (comparator) {
mapped.pop();
}
return (mapped.length && mapped[0] === arrays[0])
? baseIntersection(mapped, undefined$1, comparator)
: [];
});
/**
* Converts all elements in `array` into a string separated by `separator`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to convert.
* @param {string} [separator=','] The element separator.
* @returns {string} Returns the joined string.
* @example
*
* _.join(['a', 'b', 'c'], '~');
* // => 'a~b~c'
*/
function join(array, separator) {
return array == null ? '' : nativeJoin.call(array, separator);
}
/**
* Gets the last element of `array`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to query.
* @returns {*} Returns the last element of `array`.
* @example
*
* _.last([1, 2, 3]);
* // => 3
*/
function last(array) {
var length = array == null ? 0 : array.length;
return length ? array[length - 1] : undefined$1;
}
/**
* This method is like `_.indexOf` except that it iterates over elements of
* `array` from right to left.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the matched value, else `-1`.
* @example
*
* _.lastIndexOf([1, 2, 1, 2], 2);
* // => 3
*
* // Search from the `fromIndex`.
* _.lastIndexOf([1, 2, 1, 2], 2, 2);
* // => 1
*/
function lastIndexOf(array, value, fromIndex) {
var length = array == null ? 0 : array.length;
if (!length) {
return -1;
}
var index = length;
if (fromIndex !== undefined$1) {
index = toInteger(fromIndex);
index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
}
return value === value
? strictLastIndexOf(array, value, index)
: baseFindIndex(array, baseIsNaN, index, true);
}
/**
* Gets the element at index `n` of `array`. If `n` is negative, the nth
* element from the end is returned.
*
* @static
* @memberOf _
* @since 4.11.0
* @category Array
* @param {Array} array The array to query.
* @param {number} [n=0] The index of the element to return.
* @returns {*} Returns the nth element of `array`.
* @example
*
* var array = ['a', 'b', 'c', 'd'];
*
* _.nth(array, 1);
* // => 'b'
*
* _.nth(array, -2);
* // => 'c';
*/
function nth(array, n) {
return (array && array.length) ? baseNth(array, toInteger(n)) : undefined$1;
}
/**
* Removes all given values from `array` using
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons.
*
* **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
* to remove elements from an array by predicate.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Array
* @param {Array} array The array to modify.
* @param {...*} [values] The values to remove.
* @returns {Array} Returns `array`.
* @example
*
* var array = ['a', 'b', 'c', 'a', 'b', 'c'];
*
* _.pull(array, 'a', 'c');
* console.log(array);
* // => ['b', 'b']
*/
var pull = baseRest(pullAll);
/**
* This method is like `_.pull` except that it accepts an array of values to remove.
*
* **Note:** Unlike `_.difference`, this method mutates `array`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @returns {Array} Returns `array`.
* @example
*
* var array = ['a', 'b', 'c', 'a', 'b', 'c'];
*
* _.pullAll(array, ['a', 'c']);
* console.log(array);
* // => ['b', 'b']
*/
function pullAll(array, values) {
return (array && array.length && values && values.length)
? basePullAll(array, values)
: array;
}
/**
* This method is like `_.pullAll` except that it accepts `iteratee` which is
* invoked for each element of `array` and `values` to generate the criterion
* by which they're compared. The iteratee is invoked with one argument: (value).
*
* **Note:** Unlike `_.differenceBy`, this method mutates `array`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Array} Returns `array`.
* @example
*
* var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
*
* _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
* console.log(array);
* // => [{ 'x': 2 }]
*/
function pullAllBy(array, values, iteratee) {
return (array && array.length && values && values.length)
? basePullAll(array, values, getIteratee(iteratee, 2))
: array;
}
/**
* This method is like `_.pullAll` except that it accepts `comparator` which
* is invoked to compare elements of `array` to `values`. The comparator is
* invoked with two arguments: (arrVal, othVal).
*
* **Note:** Unlike `_.differenceWith`, this method mutates `array`.
*
* @static
* @memberOf _
* @since 4.6.0
* @category Array
* @param {Array} array The array to modify.
* @param {Array} values The values to remove.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns `array`.
* @example
*
* var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
*
* _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
* console.log(array);
* // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
*/
function pullAllWith(array, values, comparator) {
return (array && array.length && values && values.length)
? basePullAll(array, values, undefined$1, comparator)
: array;
}
/**
* Removes elements from `array` corresponding to `indexes` and returns an
* array of removed elements.
*
* **Note:** Unlike `_.at`, this method mutates `array`.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to modify.
* @param {...(number|number[])} [indexes] The indexes of elements to remove.
* @returns {Array} Returns the new array of removed elements.
* @example
*
* var array = ['a', 'b', 'c', 'd'];
* var pulled = _.pullAt(array, [1, 3]);
*
* console.log(array);
* // => ['a', 'c']
*
* console.log(pulled);
* // => ['b', 'd']
*/
var pullAt = flatRest(function(array, indexes) {
var length = array == null ? 0 : array.length,
result = baseAt(array, indexes);
basePullAt(array, arrayMap(indexes, function(index) {
return isIndex(index, length) ? +index : index;
}).sort(compareAscending));
return result;
});
/**
* Removes all elements from `array` that `predicate` returns truthy for
* and returns an array of the removed elements. The predicate is invoked
* with three arguments: (value, index, array).
*
* **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
* to pull elements from an array by value.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Array
* @param {Array} array The array to modify.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new array of removed elements.
* @example
*
* var array = [1, 2, 3, 4];
* var evens = _.remove(array, function(n) {
* return n % 2 == 0;
* });
*
* console.log(array);
* // => [1, 3]
*
* console.log(evens);
* // => [2, 4]
*/
function remove(array, predicate) {
var result = [];
if (!(array && array.length)) {
return result;
}
var index = -1,
indexes = [],
length = array.length;
predicate = getIteratee(predicate, 3);
while (++index < length) {
var value = array[index];
if (predicate(value, index, array)) {
result.push(value);
indexes.push(index);
}
}
basePullAt(array, indexes);
return result;
}
/**
* Reverses `array` so that the first element becomes the last, the second
* element becomes the second to last, and so on.
*
* **Note:** This method mutates `array` and is based on
* [`Array#reverse`](https://mdn.io/Array/reverse).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to modify.
* @returns {Array} Returns `array`.
* @example
*
* var array = [1, 2, 3];
*
* _.reverse(array);
* // => [3, 2, 1]
*
* console.log(array);
* // => [3, 2, 1]
*/
function reverse(array) {
return array == null ? array : nativeReverse.call(array);
}
/**
* Creates a slice of `array` from `start` up to, but not including, `end`.
*
* **Note:** This method is used instead of
* [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
* returned.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to slice.
* @param {number} [start=0] The start position.
* @param {number} [end=array.length] The end position.
* @returns {Array} Returns the slice of `array`.
*/
function slice(array, start, end) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
start = 0;
end = length;
}
else {
start = start == null ? 0 : toInteger(start);
end = end === undefined$1 ? length : toInteger(end);
}
return baseSlice(array, start, end);
}
/**
* Uses a binary search to determine the lowest index at which `value`
* should be inserted into `array` in order to maintain its sort order.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* _.sortedIndex([30, 50], 40);
* // => 1
*/
function sortedIndex(array, value) {
return baseSortedIndex(array, value);
}
/**
* This method is like `_.sortedIndex` except that it accepts `iteratee`
* which is invoked for `value` and each element of `array` to compute their
* sort ranking. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* var objects = [{ 'x': 4 }, { 'x': 5 }];
*
* _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
* // => 0
*
* // The `_.property` iteratee shorthand.
* _.sortedIndexBy(objects, { 'x': 4 }, 'x');
* // => 0
*/
function sortedIndexBy(array, value, iteratee) {
return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
}
/**
* This method is like `_.indexOf` except that it performs a binary
* search on a sorted `array`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @returns {number} Returns the index of the matched value, else `-1`.
* @example
*
* _.sortedIndexOf([4, 5, 5, 5, 6], 5);
* // => 1
*/
function sortedIndexOf(array, value) {
var length = array == null ? 0 : array.length;
if (length) {
var index = baseSortedIndex(array, value);
if (index < length && eq(array[index], value)) {
return index;
}
}
return -1;
}
/**
* This method is like `_.sortedIndex` except that it returns the highest
* index at which `value` should be inserted into `array` in order to
* maintain its sort order.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* _.sortedLastIndex([4, 5, 5, 5, 6], 5);
* // => 4
*/
function sortedLastIndex(array, value) {
return baseSortedIndex(array, value, true);
}
/**
* This method is like `_.sortedLastIndex` except that it accepts `iteratee`
* which is invoked for `value` and each element of `array` to compute their
* sort ranking. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The sorted array to inspect.
* @param {*} value The value to evaluate.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* var objects = [{ 'x': 4 }, { 'x': 5 }];
*
* _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
* // => 1
*
* // The `_.property` iteratee shorthand.
* _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
* // => 1
*/
function sortedLastIndexBy(array, value, iteratee) {
return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
}
/**
* This method is like `_.lastIndexOf` except that it performs a binary
* search on a sorted `array`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {*} value The value to search for.
* @returns {number} Returns the index of the matched value, else `-1`.
* @example
*
* _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
* // => 3
*/
function sortedLastIndexOf(array, value) {
var length = array == null ? 0 : array.length;
if (length) {
var index = baseSortedIndex(array, value, true) - 1;
if (eq(array[index], value)) {
return index;
}
}
return -1;
}
/**
* This method is like `_.uniq` except that it's designed and optimized
* for sorted arrays.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.sortedUniq([1, 1, 2]);
* // => [1, 2]
*/
function sortedUniq(array) {
return (array && array.length)
? baseSortedUniq(array)
: [];
}
/**
* This method is like `_.uniqBy` except that it's designed and optimized
* for sorted arrays.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} [iteratee] The iteratee invoked per element.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
* // => [1.1, 2.3]
*/
function sortedUniqBy(array, iteratee) {
return (array && array.length)
? baseSortedUniq(array, getIteratee(iteratee, 2))
: [];
}
/**
* Gets all but the first element of `array`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to query.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.tail([1, 2, 3]);
* // => [2, 3]
*/
function tail(array) {
var length = array == null ? 0 : array.length;
return length ? baseSlice(array, 1, length) : [];
}
/**
* Creates a slice of `array` with `n` elements taken from the beginning.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to query.
* @param {number} [n=1] The number of elements to take.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.take([1, 2, 3]);
* // => [1]
*
* _.take([1, 2, 3], 2);
* // => [1, 2]
*
* _.take([1, 2, 3], 5);
* // => [1, 2, 3]
*
* _.take([1, 2, 3], 0);
* // => []
*/
function take(array, n, guard) {
if (!(array && array.length)) {
return [];
}
n = (guard || n === undefined$1) ? 1 : toInteger(n);
return baseSlice(array, 0, n < 0 ? 0 : n);
}
/**
* Creates a slice of `array` with `n` elements taken from the end.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {number} [n=1] The number of elements to take.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the slice of `array`.
* @example
*
* _.takeRight([1, 2, 3]);
* // => [3]
*
* _.takeRight([1, 2, 3], 2);
* // => [2, 3]
*
* _.takeRight([1, 2, 3], 5);
* // => [1, 2, 3]
*
* _.takeRight([1, 2, 3], 0);
* // => []
*/
function takeRight(array, n, guard) {
var length = array == null ? 0 : array.length;
if (!length) {
return [];
}
n = (guard || n === undefined$1) ? 1 : toInteger(n);
n = length - n;
return baseSlice(array, n < 0 ? 0 : n, length);
}
/**
* Creates a slice of `array` with elements taken from the end. Elements are
* taken until `predicate` returns falsey. The predicate is invoked with
* three arguments: (value, index, array).
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the slice of `array`.
* @example
*
* var users = [
* { 'user': 'barney', 'active': true },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': false }
* ];
*
* _.takeRightWhile(users, function(o) { return !o.active; });
* // => objects for ['fred', 'pebbles']
*
* // The `_.matches` iteratee shorthand.
* _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
* // => objects for ['pebbles']
*
* // The `_.matchesProperty` iteratee shorthand.
* _.takeRightWhile(users, ['active', false]);
* // => objects for ['fred', 'pebbles']
*
* // The `_.property` iteratee shorthand.
* _.takeRightWhile(users, 'active');
* // => []
*/
function takeRightWhile(array, predicate) {
return (array && array.length)
? baseWhile(array, getIteratee(predicate, 3), false, true)
: [];
}
/**
* Creates a slice of `array` with elements taken from the beginning. Elements
* are taken until `predicate` returns falsey. The predicate is invoked with
* three arguments: (value, index, array).
*
* @static
* @memberOf _
* @since 3.0.0
* @category Array
* @param {Array} array The array to query.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the slice of `array`.
* @example
*
* var users = [
* { 'user': 'barney', 'active': false },
* { 'user': 'fred', 'active': false },
* { 'user': 'pebbles', 'active': true }
* ];
*
* _.takeWhile(users, function(o) { return !o.active; });
* // => objects for ['barney', 'fred']
*
* // The `_.matches` iteratee shorthand.
* _.takeWhile(users, { 'user': 'barney', 'active': false });
* // => objects for ['barney']
*
* // The `_.matchesProperty` iteratee shorthand.
* _.takeWhile(users, ['active', false]);
* // => objects for ['barney', 'fred']
*
* // The `_.property` iteratee shorthand.
* _.takeWhile(users, 'active');
* // => []
*/
function takeWhile(array, predicate) {
return (array && array.length)
? baseWhile(array, getIteratee(predicate, 3))
: [];
}
/**
* Creates an array of unique values, in order, from all given arrays using
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @returns {Array} Returns the new array of combined values.
* @example
*
* _.union([2], [1, 2]);
* // => [2, 1]
*/
var union = baseRest(function(arrays) {
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
});
/**
* This method is like `_.union` except that it accepts `iteratee` which is
* invoked for each element of each `arrays` to generate the criterion by
* which uniqueness is computed. Result values are chosen from the first
* array in which the value occurs. The iteratee is invoked with one argument:
* (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Array} Returns the new array of combined values.
* @example
*
* _.unionBy([2.1], [1.2, 2.3], Math.floor);
* // => [2.1, 1.2]
*
* // The `_.property` iteratee shorthand.
* _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
var unionBy = baseRest(function(arrays) {
var iteratee = last(arrays);
if (isArrayLikeObject(iteratee)) {
iteratee = undefined$1;
}
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
});
/**
* This method is like `_.union` except that it accepts `comparator` which
* is invoked to compare elements of `arrays`. Result values are chosen from
* the first array in which the value occurs. The comparator is invoked
* with two arguments: (arrVal, othVal).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of combined values.
* @example
*
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
* var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
*
* _.unionWith(objects, others, _.isEqual);
* // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
*/
var unionWith = baseRest(function(arrays) {
var comparator = last(arrays);
comparator = typeof comparator == 'function' ? comparator : undefined$1;
return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined$1, comparator);
});
/**
* Creates a duplicate-free version of an array, using
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons, in which only the first occurrence of each element
* is kept. The order of result values is determined by the order they occur
* in the array.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to inspect.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.uniq([2, 1, 2]);
* // => [2, 1]
*/
function uniq(array) {
return (array && array.length) ? baseUniq(array) : [];
}
/**
* This method is like `_.uniq` except that it accepts `iteratee` which is
* invoked for each element in `array` to generate the criterion by which
* uniqueness is computed. The order of result values is determined by the
* order they occur in the array. The iteratee is invoked with one argument:
* (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.uniqBy([2.1, 1.2, 2.3], Math.floor);
* // => [2.1, 1.2]
*
* // The `_.property` iteratee shorthand.
* _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
function uniqBy(array, iteratee) {
return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
}
/**
* This method is like `_.uniq` except that it accepts `comparator` which
* is invoked to compare elements of `array`. The order of result values is
* determined by the order they occur in the array.The comparator is invoked
* with two arguments: (arrVal, othVal).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
*
* _.uniqWith(objects, _.isEqual);
* // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
*/
function uniqWith(array, comparator) {
comparator = typeof comparator == 'function' ? comparator : undefined$1;
return (array && array.length) ? baseUniq(array, undefined$1, comparator) : [];
}
/**
* This method is like `_.zip` except that it accepts an array of grouped
* elements and creates an array regrouping the elements to their pre-zip
* configuration.
*
* @static
* @memberOf _
* @since 1.2.0
* @category Array
* @param {Array} array The array of grouped elements to process.
* @returns {Array} Returns the new array of regrouped elements.
* @example
*
* var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
* // => [['a', 1, true], ['b', 2, false]]
*
* _.unzip(zipped);
* // => [['a', 'b'], [1, 2], [true, false]]
*/
function unzip(array) {
if (!(array && array.length)) {
return [];
}
var length = 0;
array = arrayFilter(array, function(group) {
if (isArrayLikeObject(group)) {
length = nativeMax(group.length, length);
return true;
}
});
return baseTimes(length, function(index) {
return arrayMap(array, baseProperty(index));
});
}
/**
* This method is like `_.unzip` except that it accepts `iteratee` to specify
* how regrouped values should be combined. The iteratee is invoked with the
* elements of each group: (...group).
*
* @static
* @memberOf _
* @since 3.8.0
* @category Array
* @param {Array} array The array of grouped elements to process.
* @param {Function} [iteratee=_.identity] The function to combine
* regrouped values.
* @returns {Array} Returns the new array of regrouped elements.
* @example
*
* var zipped = _.zip([1, 2], [10, 20], [100, 200]);
* // => [[1, 10, 100], [2, 20, 200]]
*
* _.unzipWith(zipped, _.add);
* // => [3, 30, 300]
*/
function unzipWith(array, iteratee) {
if (!(array && array.length)) {
return [];
}
var result = unzip(array);
if (iteratee == null) {
return result;
}
return arrayMap(result, function(group) {
return apply(iteratee, undefined$1, group);
});
}
/**
* Creates an array excluding all given values using
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* for equality comparisons.
*
* **Note:** Unlike `_.pull`, this method returns a new array.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {Array} array The array to inspect.
* @param {...*} [values] The values to exclude.
* @returns {Array} Returns the new array of filtered values.
* @see _.difference, _.xor
* @example
*
* _.without([2, 1, 2, 3], 1, 2);
* // => [3]
*/
var without = baseRest(function(array, values) {
return isArrayLikeObject(array)
? baseDifference(array, values)
: [];
});
/**
* Creates an array of unique values that is the
* [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
* of the given arrays. The order of result values is determined by the order
* they occur in the arrays.
*
* @static
* @memberOf _
* @since 2.4.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @returns {Array} Returns the new array of filtered values.
* @see _.difference, _.without
* @example
*
* _.xor([2, 1], [2, 3]);
* // => [1, 3]
*/
var xor = baseRest(function(arrays) {
return baseXor(arrayFilter(arrays, isArrayLikeObject));
});
/**
* This method is like `_.xor` except that it accepts `iteratee` which is
* invoked for each element of each `arrays` to generate the criterion by
* which by which they're compared. The order of result values is determined
* by the order they occur in the arrays. The iteratee is invoked with one
* argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
* // => [1.2, 3.4]
*
* // The `_.property` iteratee shorthand.
* _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 2 }]
*/
var xorBy = baseRest(function(arrays) {
var iteratee = last(arrays);
if (isArrayLikeObject(iteratee)) {
iteratee = undefined$1;
}
return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
});
/**
* This method is like `_.xor` except that it accepts `comparator` which is
* invoked to compare elements of `arrays`. The order of result values is
* determined by the order they occur in the arrays. The comparator is invoked
* with two arguments: (arrVal, othVal).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {...Array} [arrays] The arrays to inspect.
* @param {Function} [comparator] The comparator invoked per element.
* @returns {Array} Returns the new array of filtered values.
* @example
*
* var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
* var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
*
* _.xorWith(objects, others, _.isEqual);
* // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
*/
var xorWith = baseRest(function(arrays) {
var comparator = last(arrays);
comparator = typeof comparator == 'function' ? comparator : undefined$1;
return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined$1, comparator);
});
/**
* Creates an array of grouped elements, the first of which contains the
* first elements of the given arrays, the second of which contains the
* second elements of the given arrays, and so on.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Array
* @param {...Array} [arrays] The arrays to process.
* @returns {Array} Returns the new array of grouped elements.
* @example
*
* _.zip(['a', 'b'], [1, 2], [true, false]);
* // => [['a', 1, true], ['b', 2, false]]
*/
var zip = baseRest(unzip);
/**
* This method is like `_.fromPairs` except that it accepts two arrays,
* one of property identifiers and one of corresponding values.
*
* @static
* @memberOf _
* @since 0.4.0
* @category Array
* @param {Array} [props=[]] The property identifiers.
* @param {Array} [values=[]] The property values.
* @returns {Object} Returns the new object.
* @example
*
* _.zipObject(['a', 'b'], [1, 2]);
* // => { 'a': 1, 'b': 2 }
*/
function zipObject(props, values) {
return baseZipObject(props || [], values || [], assignValue);
}
/**
* This method is like `_.zipObject` except that it supports property paths.
*
* @static
* @memberOf _
* @since 4.1.0
* @category Array
* @param {Array} [props=[]] The property identifiers.
* @param {Array} [values=[]] The property values.
* @returns {Object} Returns the new object.
* @example
*
* _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
* // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
*/
function zipObjectDeep(props, values) {
return baseZipObject(props || [], values || [], baseSet);
}
/**
* This method is like `_.zip` except that it accepts `iteratee` to specify
* how grouped values should be combined. The iteratee is invoked with the
* elements of each group: (...group).
*
* @static
* @memberOf _
* @since 3.8.0
* @category Array
* @param {...Array} [arrays] The arrays to process.
* @param {Function} [iteratee=_.identity] The function to combine
* grouped values.
* @returns {Array} Returns the new array of grouped elements.
* @example
*
* _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
* return a + b + c;
* });
* // => [111, 222]
*/
var zipWith = baseRest(function(arrays) {
var length = arrays.length,
iteratee = length > 1 ? arrays[length - 1] : undefined$1;
iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined$1;
return unzipWith(arrays, iteratee);
});
/*------------------------------------------------------------------------*/
/**
* Creates a `lodash` wrapper instance that wraps `value` with explicit method
* chain sequences enabled. The result of such sequences must be unwrapped
* with `_#value`.
*
* @static
* @memberOf _
* @since 1.3.0
* @category Seq
* @param {*} value The value to wrap.
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36 },
* { 'user': 'fred', 'age': 40 },
* { 'user': 'pebbles', 'age': 1 }
* ];
*
* var youngest = _
* .chain(users)
* .sortBy('age')
* .map(function(o) {
* return o.user + ' is ' + o.age;
* })
* .head()
* .value();
* // => 'pebbles is 1'
*/
function chain(value) {
var result = lodash(value);
result.__chain__ = true;
return result;
}
/**
* This method invokes `interceptor` and returns `value`. The interceptor
* is invoked with one argument; (value). The purpose of this method is to
* "tap into" a method chain sequence in order to modify intermediate results.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Seq
* @param {*} value The value to provide to `interceptor`.
* @param {Function} interceptor The function to invoke.
* @returns {*} Returns `value`.
* @example
*
* _([1, 2, 3])
* .tap(function(array) {
* // Mutate input array.
* array.pop();
* })
* .reverse()
* .value();
* // => [2, 1]
*/
function tap(value, interceptor) {
interceptor(value);
return value;
}
/**
* This method is like `_.tap` except that it returns the result of `interceptor`.
* The purpose of this method is to "pass thru" values replacing intermediate
* results in a method chain sequence.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Seq
* @param {*} value The value to provide to `interceptor`.
* @param {Function} interceptor The function to invoke.
* @returns {*} Returns the result of `interceptor`.
* @example
*
* _(' abc ')
* .chain()
* .trim()
* .thru(function(value) {
* return [value];
* })
* .value();
* // => ['abc']
*/
function thru(value, interceptor) {
return interceptor(value);
}
/**
* This method is the wrapper version of `_.at`.
*
* @name at
* @memberOf _
* @since 1.0.0
* @category Seq
* @param {...(string|string[])} [paths] The property paths to pick.
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
*
* _(object).at(['a[0].b.c', 'a[1]']).value();
* // => [3, 4]
*/
var wrapperAt = flatRest(function(paths) {
var length = paths.length,
start = length ? paths[0] : 0,
value = this.__wrapped__,
interceptor = function(object) { return baseAt(object, paths); };
if (length > 1 || this.__actions__.length ||
!(value instanceof LazyWrapper) || !isIndex(start)) {
return this.thru(interceptor);
}
value = value.slice(start, +start + (length ? 1 : 0));
value.__actions__.push({
'func': thru,
'args': [interceptor],
'thisArg': undefined$1
});
return new LodashWrapper(value, this.__chain__).thru(function(array) {
if (length && !array.length) {
array.push(undefined$1);
}
return array;
});
});
/**
* Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
*
* @name chain
* @memberOf _
* @since 0.1.0
* @category Seq
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36 },
* { 'user': 'fred', 'age': 40 }
* ];
*
* // A sequence without explicit chaining.
* _(users).head();
* // => { 'user': 'barney', 'age': 36 }
*
* // A sequence with explicit chaining.
* _(users)
* .chain()
* .head()
* .pick('user')
* .value();
* // => { 'user': 'barney' }
*/
function wrapperChain() {
return chain(this);
}
/**
* Executes the chain sequence and returns the wrapped result.
*
* @name commit
* @memberOf _
* @since 3.2.0
* @category Seq
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* var array = [1, 2];
* var wrapped = _(array).push(3);
*
* console.log(array);
* // => [1, 2]
*
* wrapped = wrapped.commit();
* console.log(array);
* // => [1, 2, 3]
*
* wrapped.last();
* // => 3
*
* console.log(array);
* // => [1, 2, 3]
*/
function wrapperCommit() {
return new LodashWrapper(this.value(), this.__chain__);
}
/**
* Gets the next value on a wrapped object following the
* [iterator protocol](https://mdn.io/iteration_protocols#iterator).
*
* @name next
* @memberOf _
* @since 4.0.0
* @category Seq
* @returns {Object} Returns the next iterator value.
* @example
*
* var wrapped = _([1, 2]);
*
* wrapped.next();
* // => { 'done': false, 'value': 1 }
*
* wrapped.next();
* // => { 'done': false, 'value': 2 }
*
* wrapped.next();
* // => { 'done': true, 'value': undefined }
*/
function wrapperNext() {
if (this.__values__ === undefined$1) {
this.__values__ = toArray(this.value());
}
var done = this.__index__ >= this.__values__.length,
value = done ? undefined$1 : this.__values__[this.__index__++];
return { 'done': done, 'value': value };
}
/**
* Enables the wrapper to be iterable.
*
* @name Symbol.iterator
* @memberOf _
* @since 4.0.0
* @category Seq
* @returns {Object} Returns the wrapper object.
* @example
*
* var wrapped = _([1, 2]);
*
* wrapped[Symbol.iterator]() === wrapped;
* // => true
*
* Array.from(wrapped);
* // => [1, 2]
*/
function wrapperToIterator() {
return this;
}
/**
* Creates a clone of the chain sequence planting `value` as the wrapped value.
*
* @name plant
* @memberOf _
* @since 3.2.0
* @category Seq
* @param {*} value The value to plant.
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* function square(n) {
* return n * n;
* }
*
* var wrapped = _([1, 2]).map(square);
* var other = wrapped.plant([3, 4]);
*
* other.value();
* // => [9, 16]
*
* wrapped.value();
* // => [1, 4]
*/
function wrapperPlant(value) {
var result,
parent = this;
while (parent instanceof baseLodash) {
var clone = wrapperClone(parent);
clone.__index__ = 0;
clone.__values__ = undefined$1;
if (result) {
previous.__wrapped__ = clone;
} else {
result = clone;
}
var previous = clone;
parent = parent.__wrapped__;
}
previous.__wrapped__ = value;
return result;
}
/**
* This method is the wrapper version of `_.reverse`.
*
* **Note:** This method mutates the wrapped array.
*
* @name reverse
* @memberOf _
* @since 0.1.0
* @category Seq
* @returns {Object} Returns the new `lodash` wrapper instance.
* @example
*
* var array = [1, 2, 3];
*
* _(array).reverse().value()
* // => [3, 2, 1]
*
* console.log(array);
* // => [3, 2, 1]
*/
function wrapperReverse() {
var value = this.__wrapped__;
if (value instanceof LazyWrapper) {
var wrapped = value;
if (this.__actions__.length) {
wrapped = new LazyWrapper(this);
}
wrapped = wrapped.reverse();
wrapped.__actions__.push({
'func': thru,
'args': [reverse],
'thisArg': undefined$1
});
return new LodashWrapper(wrapped, this.__chain__);
}
return this.thru(reverse);
}
/**
* Executes the chain sequence to resolve the unwrapped value.
*
* @name value
* @memberOf _
* @since 0.1.0
* @alias toJSON, valueOf
* @category Seq
* @returns {*} Returns the resolved unwrapped value.
* @example
*
* _([1, 2, 3]).value();
* // => [1, 2, 3]
*/
function wrapperValue() {
return baseWrapperValue(this.__wrapped__, this.__actions__);
}
/*------------------------------------------------------------------------*/
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` thru `iteratee`. The corresponding value of
* each key is the number of times the key was returned by `iteratee`. The
* iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 0.5.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.countBy([6.1, 4.2, 6.3], Math.floor);
* // => { '4': 1, '6': 2 }
*
* // The `_.property` iteratee shorthand.
* _.countBy(['one', 'two', 'three'], 'length');
* // => { '3': 2, '5': 1 }
*/
var countBy = createAggregator(function(result, value, key) {
if (hasOwnProperty.call(result, key)) {
++result[key];
} else {
baseAssignValue(result, key, 1);
}
});
/**
* Checks if `predicate` returns truthy for **all** elements of `collection`.
* Iteration is stopped once `predicate` returns falsey. The predicate is
* invoked with three arguments: (value, index|key, collection).
*
* **Note:** This method returns `true` for
* [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
* [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
* elements of empty collections.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {boolean} Returns `true` if all elements pass the predicate check,
* else `false`.
* @example
*
* _.every([true, 1, null, 'yes'], Boolean);
* // => false
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': false },
* { 'user': 'fred', 'age': 40, 'active': false }
* ];
*
* // The `_.matches` iteratee shorthand.
* _.every(users, { 'user': 'barney', 'active': false });
* // => false
*
* // The `_.matchesProperty` iteratee shorthand.
* _.every(users, ['active', false]);
* // => true
*
* // The `_.property` iteratee shorthand.
* _.every(users, 'active');
* // => false
*/
function every(collection, predicate, guard) {
var func = isArray(collection) ? arrayEvery : baseEvery;
if (guard && isIterateeCall(collection, predicate, guard)) {
predicate = undefined$1;
}
return func(collection, getIteratee(predicate, 3));
}
/**
* Iterates over elements of `collection`, returning an array of all elements
* `predicate` returns truthy for. The predicate is invoked with three
* arguments: (value, index|key, collection).
*
* **Note:** Unlike `_.remove`, this method returns a new array.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new filtered array.
* @see _.reject
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': true },
* { 'user': 'fred', 'age': 40, 'active': false }
* ];
*
* _.filter(users, function(o) { return !o.active; });
* // => objects for ['fred']
*
* // The `_.matches` iteratee shorthand.
* _.filter(users, { 'age': 36, 'active': true });
* // => objects for ['barney']
*
* // The `_.matchesProperty` iteratee shorthand.
* _.filter(users, ['active', false]);
* // => objects for ['fred']
*
* // The `_.property` iteratee shorthand.
* _.filter(users, 'active');
* // => objects for ['barney']
*
* // Combining several predicates using `_.overEvery` or `_.overSome`.
* _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
* // => objects for ['fred', 'barney']
*/
function filter(collection, predicate) {
var func = isArray(collection) ? arrayFilter : baseFilter;
return func(collection, getIteratee(predicate, 3));
}
/**
* Iterates over elements of `collection`, returning the first element
* `predicate` returns truthy for. The predicate is invoked with three
* arguments: (value, index|key, collection).
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to inspect.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @param {number} [fromIndex=0] The index to search from.
* @returns {*} Returns the matched element, else `undefined`.
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': true },
* { 'user': 'fred', 'age': 40, 'active': false },
* { 'user': 'pebbles', 'age': 1, 'active': true }
* ];
*
* _.find(users, function(o) { return o.age < 40; });
* // => object for 'barney'
*
* // The `_.matches` iteratee shorthand.
* _.find(users, { 'age': 1, 'active': true });
* // => object for 'pebbles'
*
* // The `_.matchesProperty` iteratee shorthand.
* _.find(users, ['active', false]);
* // => object for 'fred'
*
* // The `_.property` iteratee shorthand.
* _.find(users, 'active');
* // => object for 'barney'
*/
var find = createFind(findIndex);
/**
* This method is like `_.find` except that it iterates over elements of
* `collection` from right to left.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Collection
* @param {Array|Object} collection The collection to inspect.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @param {number} [fromIndex=collection.length-1] The index to search from.
* @returns {*} Returns the matched element, else `undefined`.
* @example
*
* _.findLast([1, 2, 3, 4], function(n) {
* return n % 2 == 1;
* });
* // => 3
*/
var findLast = createFind(findLastIndex);
/**
* Creates a flattened array of values by running each element in `collection`
* thru `iteratee` and flattening the mapped results. The iteratee is invoked
* with three arguments: (value, index|key, collection).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new flattened array.
* @example
*
* function duplicate(n) {
* return [n, n];
* }
*
* _.flatMap([1, 2], duplicate);
* // => [1, 1, 2, 2]
*/
function flatMap(collection, iteratee) {
return baseFlatten(map(collection, iteratee), 1);
}
/**
* This method is like `_.flatMap` except that it recursively flattens the
* mapped results.
*
* @static
* @memberOf _
* @since 4.7.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new flattened array.
* @example
*
* function duplicate(n) {
* return [[[n, n]]];
* }
*
* _.flatMapDeep([1, 2], duplicate);
* // => [1, 1, 2, 2]
*/
function flatMapDeep(collection, iteratee) {
return baseFlatten(map(collection, iteratee), INFINITY);
}
/**
* This method is like `_.flatMap` except that it recursively flattens the
* mapped results up to `depth` times.
*
* @static
* @memberOf _
* @since 4.7.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {number} [depth=1] The maximum recursion depth.
* @returns {Array} Returns the new flattened array.
* @example
*
* function duplicate(n) {
* return [[[n, n]]];
* }
*
* _.flatMapDepth([1, 2], duplicate, 2);
* // => [[1, 1], [2, 2]]
*/
function flatMapDepth(collection, iteratee, depth) {
depth = depth === undefined$1 ? 1 : toInteger(depth);
return baseFlatten(map(collection, iteratee), depth);
}
/**
* Iterates over elements of `collection` and invokes `iteratee` for each element.
* The iteratee is invoked with three arguments: (value, index|key, collection).
* Iteratee functions may exit iteration early by explicitly returning `false`.
*
* **Note:** As with other "Collections" methods, objects with a "length"
* property are iterated like arrays. To avoid this behavior use `_.forIn`
* or `_.forOwn` for object iteration.
*
* @static
* @memberOf _
* @since 0.1.0
* @alias each
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array|Object} Returns `collection`.
* @see _.forEachRight
* @example
*
* _.forEach([1, 2], function(value) {
* console.log(value);
* });
* // => Logs `1` then `2`.
*
* _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
* console.log(key);
* });
* // => Logs 'a' then 'b' (iteration order is not guaranteed).
*/
function forEach(collection, iteratee) {
var func = isArray(collection) ? arrayEach : baseEach;
return func(collection, getIteratee(iteratee, 3));
}
/**
* This method is like `_.forEach` except that it iterates over elements of
* `collection` from right to left.
*
* @static
* @memberOf _
* @since 2.0.0
* @alias eachRight
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array|Object} Returns `collection`.
* @see _.forEach
* @example
*
* _.forEachRight([1, 2], function(value) {
* console.log(value);
* });
* // => Logs `2` then `1`.
*/
function forEachRight(collection, iteratee) {
var func = isArray(collection) ? arrayEachRight : baseEachRight;
return func(collection, getIteratee(iteratee, 3));
}
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` thru `iteratee`. The order of grouped values
* is determined by the order they occur in `collection`. The corresponding
* value of each key is an array of elements responsible for generating the
* key. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.groupBy([6.1, 4.2, 6.3], Math.floor);
* // => { '4': [4.2], '6': [6.1, 6.3] }
*
* // The `_.property` iteratee shorthand.
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
var groupBy = createAggregator(function(result, value, key) {
if (hasOwnProperty.call(result, key)) {
result[key].push(value);
} else {
baseAssignValue(result, key, [value]);
}
});
/**
* Checks if `value` is in `collection`. If `collection` is a string, it's
* checked for a substring of `value`, otherwise
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* is used for equality comparisons. If `fromIndex` is negative, it's used as
* the offset from the end of `collection`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object|string} collection The collection to inspect.
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
* @returns {boolean} Returns `true` if `value` is found, else `false`.
* @example
*
* _.includes([1, 2, 3], 1);
* // => true
*
* _.includes([1, 2, 3], 1, 2);
* // => false
*
* _.includes({ 'a': 1, 'b': 2 }, 1);
* // => true
*
* _.includes('abcd', 'bc');
* // => true
*/
function includes(collection, value, fromIndex, guard) {
collection = isArrayLike(collection) ? collection : values(collection);
fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
var length = collection.length;
if (fromIndex < 0) {
fromIndex = nativeMax(length + fromIndex, 0);
}
return isString(collection)
? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
: (!!length && baseIndexOf(collection, value, fromIndex) > -1);
}
/**
* Invokes the method at `path` of each element in `collection`, returning
* an array of the results of each invoked method. Any additional arguments
* are provided to each invoked method. If `path` is a function, it's invoked
* for, and `this` bound to, each element in `collection`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Array|Function|string} path The path of the method to invoke or
* the function invoked per iteration.
* @param {...*} [args] The arguments to invoke each method with.
* @returns {Array} Returns the array of results.
* @example
*
* _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
* // => [[1, 5, 7], [1, 2, 3]]
*
* _.invokeMap([123, 456], String.prototype.split, '');
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
var invokeMap = baseRest(function(collection, path, args) {
var index = -1,
isFunc = typeof path == 'function',
result = isArrayLike(collection) ? Array(collection.length) : [];
baseEach(collection, function(value) {
result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
});
return result;
});
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` thru `iteratee`. The corresponding value of
* each key is the last element responsible for generating the key. The
* iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee to transform keys.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* var array = [
* { 'dir': 'left', 'code': 97 },
* { 'dir': 'right', 'code': 100 }
* ];
*
* _.keyBy(array, function(o) {
* return String.fromCharCode(o.code);
* });
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*
* _.keyBy(array, 'dir');
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
*/
var keyBy = createAggregator(function(result, value, key) {
baseAssignValue(result, key, value);
});
/**
* Creates an array of values by running each element in `collection` thru
* `iteratee`. The iteratee is invoked with three arguments:
* (value, index|key, collection).
*
* Many lodash methods are guarded to work as iteratees for methods like
* `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
*
* The guarded methods are:
* `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
* `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
* `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
* `template`, `trim`, `trimEnd`, `trimStart`, and `words`
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new mapped array.
* @example
*
* function square(n) {
* return n * n;
* }
*
* _.map([4, 8], square);
* // => [16, 64]
*
* _.map({ 'a': 4, 'b': 8 }, square);
* // => [16, 64] (iteration order is not guaranteed)
*
* var users = [
* { 'user': 'barney' },
* { 'user': 'fred' }
* ];
*
* // The `_.property` iteratee shorthand.
* _.map(users, 'user');
* // => ['barney', 'fred']
*/
function map(collection, iteratee) {
var func = isArray(collection) ? arrayMap : baseMap;
return func(collection, getIteratee(iteratee, 3));
}
/**
* This method is like `_.sortBy` except that it allows specifying the sort
* orders of the iteratees to sort by. If `orders` is unspecified, all values
* are sorted in ascending order. Otherwise, specify an order of "desc" for
* descending or "asc" for ascending sort order of corresponding values.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
* The iteratees to sort by.
* @param {string[]} [orders] The sort orders of `iteratees`.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
* @returns {Array} Returns the new sorted array.
* @example
*
* var users = [
* { 'user': 'fred', 'age': 48 },
* { 'user': 'barney', 'age': 34 },
* { 'user': 'fred', 'age': 40 },
* { 'user': 'barney', 'age': 36 }
* ];
*
* // Sort by `user` in ascending order and by `age` in descending order.
* _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
*/
function orderBy(collection, iteratees, orders, guard) {
if (collection == null) {
return [];
}
if (!isArray(iteratees)) {
iteratees = iteratees == null ? [] : [iteratees];
}
orders = guard ? undefined$1 : orders;
if (!isArray(orders)) {
orders = orders == null ? [] : [orders];
}
return baseOrderBy(collection, iteratees, orders);
}
/**
* Creates an array of elements split into two groups, the first of which
* contains elements `predicate` returns truthy for, the second of which
* contains elements `predicate` returns falsey for. The predicate is
* invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 3.0.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the array of grouped elements.
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': false },
* { 'user': 'fred', 'age': 40, 'active': true },
* { 'user': 'pebbles', 'age': 1, 'active': false }
* ];
*
* _.partition(users, function(o) { return o.active; });
* // => objects for [['fred'], ['barney', 'pebbles']]
*
* // The `_.matches` iteratee shorthand.
* _.partition(users, { 'age': 1, 'active': false });
* // => objects for [['pebbles'], ['barney', 'fred']]
*
* // The `_.matchesProperty` iteratee shorthand.
* _.partition(users, ['active', false]);
* // => objects for [['barney', 'pebbles'], ['fred']]
*
* // The `_.property` iteratee shorthand.
* _.partition(users, 'active');
* // => objects for [['fred'], ['barney', 'pebbles']]
*/
var partition = createAggregator(function(result, value, key) {
result[key ? 0 : 1].push(value);
}, function() { return [[], []]; });
/**
* Reduces `collection` to a value which is the accumulated result of running
* each element in `collection` thru `iteratee`, where each successive
* invocation is supplied the return value of the previous. If `accumulator`
* is not given, the first element of `collection` is used as the initial
* value. The iteratee is invoked with four arguments:
* (accumulator, value, index|key, collection).
*
* Many lodash methods are guarded to work as iteratees for methods like
* `_.reduce`, `_.reduceRight`, and `_.transform`.
*
* The guarded methods are:
* `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
* and `sortBy`
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @returns {*} Returns the accumulated value.
* @see _.reduceRight
* @example
*
* _.reduce([1, 2], function(sum, n) {
* return sum + n;
* }, 0);
* // => 3
*
* _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
* (result[value] || (result[value] = [])).push(key);
* return result;
* }, {});
* // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
*/
function reduce(collection, iteratee, accumulator) {
var func = isArray(collection) ? arrayReduce : baseReduce,
initAccum = arguments.length < 3;
return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
}
/**
* This method is like `_.reduce` except that it iterates over elements of
* `collection` from right to left.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [accumulator] The initial value.
* @returns {*} Returns the accumulated value.
* @see _.reduce
* @example
*
* var array = [[0, 1], [2, 3], [4, 5]];
*
* _.reduceRight(array, function(flattened, other) {
* return flattened.concat(other);
* }, []);
* // => [4, 5, 2, 3, 0, 1]
*/
function reduceRight(collection, iteratee, accumulator) {
var func = isArray(collection) ? arrayReduceRight : baseReduce,
initAccum = arguments.length < 3;
return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
}
/**
* The opposite of `_.filter`; this method returns the elements of `collection`
* that `predicate` does **not** return truthy for.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {Array} Returns the new filtered array.
* @see _.filter
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': false },
* { 'user': 'fred', 'age': 40, 'active': true }
* ];
*
* _.reject(users, function(o) { return !o.active; });
* // => objects for ['fred']
*
* // The `_.matches` iteratee shorthand.
* _.reject(users, { 'age': 40, 'active': true });
* // => objects for ['barney']
*
* // The `_.matchesProperty` iteratee shorthand.
* _.reject(users, ['active', false]);
* // => objects for ['fred']
*
* // The `_.property` iteratee shorthand.
* _.reject(users, 'active');
* // => objects for ['barney']
*/
function reject(collection, predicate) {
var func = isArray(collection) ? arrayFilter : baseFilter;
return func(collection, negate(getIteratee(predicate, 3)));
}
/**
* Gets a random element from `collection`.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Collection
* @param {Array|Object} collection The collection to sample.
* @returns {*} Returns the random element.
* @example
*
* _.sample([1, 2, 3, 4]);
* // => 2
*/
function sample(collection) {
var func = isArray(collection) ? arraySample : baseSample;
return func(collection);
}
/**
* Gets `n` random elements at unique keys from `collection` up to the
* size of `collection`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Collection
* @param {Array|Object} collection The collection to sample.
* @param {number} [n=1] The number of elements to sample.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the random elements.
* @example
*
* _.sampleSize([1, 2, 3], 2);
* // => [3, 1]
*
* _.sampleSize([1, 2, 3], 4);
* // => [2, 3, 1]
*/
function sampleSize(collection, n, guard) {
if ((guard ? isIterateeCall(collection, n, guard) : n === undefined$1)) {
n = 1;
} else {
n = toInteger(n);
}
var func = isArray(collection) ? arraySampleSize : baseSampleSize;
return func(collection, n);
}
/**
* Creates an array of shuffled values, using a version of the
* [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to shuffle.
* @returns {Array} Returns the new shuffled array.
* @example
*
* _.shuffle([1, 2, 3, 4]);
* // => [4, 1, 3, 2]
*/
function shuffle(collection) {
var func = isArray(collection) ? arrayShuffle : baseShuffle;
return func(collection);
}
/**
* Gets the size of `collection` by returning its length for array-like
* values or the number of own enumerable string keyed properties for objects.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object|string} collection The collection to inspect.
* @returns {number} Returns the collection size.
* @example
*
* _.size([1, 2, 3]);
* // => 3
*
* _.size({ 'a': 1, 'b': 2 });
* // => 2
*
* _.size('pebbles');
* // => 7
*/
function size(collection) {
if (collection == null) {
return 0;
}
if (isArrayLike(collection)) {
return isString(collection) ? stringSize(collection) : collection.length;
}
var tag = getTag(collection);
if (tag == mapTag || tag == setTag) {
return collection.size;
}
return baseKeys(collection).length;
}
/**
* Checks if `predicate` returns truthy for **any** element of `collection`.
* Iteration is stopped once `predicate` returns truthy. The predicate is
* invoked with three arguments: (value, index|key, collection).
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {boolean} Returns `true` if any element passes the predicate check,
* else `false`.
* @example
*
* _.some([null, 0, 'yes', false], Boolean);
* // => true
*
* var users = [
* { 'user': 'barney', 'active': true },
* { 'user': 'fred', 'active': false }
* ];
*
* // The `_.matches` iteratee shorthand.
* _.some(users, { 'user': 'barney', 'active': false });
* // => false
*
* // The `_.matchesProperty` iteratee shorthand.
* _.some(users, ['active', false]);
* // => true
*
* // The `_.property` iteratee shorthand.
* _.some(users, 'active');
* // => true
*/
function some(collection, predicate, guard) {
var func = isArray(collection) ? arraySome : baseSome;
if (guard && isIterateeCall(collection, predicate, guard)) {
predicate = undefined$1;
}
return func(collection, getIteratee(predicate, 3));
}
/**
* Creates an array of elements, sorted in ascending order by the results of
* running each element in a collection thru each iteratee. This method
* performs a stable sort, that is, it preserves the original sort order of
* equal elements. The iteratees are invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 0.1.0
* @category Collection
* @param {Array|Object} collection The collection to iterate over.
* @param {...(Function|Function[])} [iteratees=[_.identity]]
* The iteratees to sort by.
* @returns {Array} Returns the new sorted array.
* @example
*
* var users = [
* { 'user': 'fred', 'age': 48 },
* { 'user': 'barney', 'age': 36 },
* { 'user': 'fred', 'age': 30 },
* { 'user': 'barney', 'age': 34 }
* ];
*
* _.sortBy(users, [function(o) { return o.user; }]);
* // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
*
* _.sortBy(users, ['user', 'age']);
* // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
*/
var sortBy = baseRest(function(collection, iteratees) {
if (collection == null) {
return [];
}
var length = iteratees.length;
if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
iteratees = [];
} else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
iteratees = [iteratees[0]];
}
return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
});
/*------------------------------------------------------------------------*/
/**
* Gets the timestamp of the number of milliseconds that have elapsed since
* the Unix epoch (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @since 2.4.0
* @category Date
* @returns {number} Returns the timestamp.
* @example
*
* _.defer(function(stamp) {
* console.log(_.now() - stamp);
* }, _.now());
* // => Logs the number of milliseconds it took for the deferred invocation.
*/
var now = ctxNow || function() {
return root.Date.now();
};
/*------------------------------------------------------------------------*/
/**
* The opposite of `_.before`; this method creates a function that invokes
* `func` once it's called `n` or more times.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {number} n The number of calls before `func` is invoked.
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var saves = ['profile', 'settings'];
*
* var done = _.after(saves.length, function() {
* console.log('done saving!');
* });
*
* _.forEach(saves, function(type) {
* asyncSave({ 'type': type, 'complete': done });
* });
* // => Logs 'done saving!' after the two async saves have completed.
*/
function after(n, func) {
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
n = toInteger(n);
return function() {
if (--n < 1) {
return func.apply(this, arguments);
}
};
}
/**
* Creates a function that invokes `func`, with up to `n` arguments,
* ignoring any additional arguments.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Function
* @param {Function} func The function to cap arguments for.
* @param {number} [n=func.length] The arity cap.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Function} Returns the new capped function.
* @example
*
* _.map(['6', '8', '10'], _.ary(parseInt, 1));
* // => [6, 8, 10]
*/
function ary(func, n, guard) {
n = guard ? undefined$1 : n;
n = (func && n == null) ? func.length : n;
return createWrap(func, WRAP_ARY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, n);
}
/**
* Creates a function that invokes `func`, with the `this` binding and arguments
* of the created function, while it's called less than `n` times. Subsequent
* calls to the created function return the result of the last `func` invocation.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Function
* @param {number} n The number of calls at which `func` is no longer invoked.
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* jQuery(element).on('click', _.before(5, addContactToList));
* // => Allows adding up to 4 contacts to the list.
*/
function before(n, func) {
var result;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
n = toInteger(n);
return function() {
if (--n > 0) {
result = func.apply(this, arguments);
}
if (n <= 1) {
func = undefined$1;
}
return result;
};
}
/**
* Creates a function that invokes `func` with the `this` binding of `thisArg`
* and `partials` prepended to the arguments it receives.
*
* The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
* may be used as a placeholder for partially applied arguments.
*
* **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
* property of bound functions.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to bind.
* @param {*} thisArg The `this` binding of `func`.
* @param {...*} [partials] The arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* function greet(greeting, punctuation) {
* return greeting + ' ' + this.user + punctuation;
* }
*
* var object = { 'user': 'fred' };
*
* var bound = _.bind(greet, object, 'hi');
* bound('!');
* // => 'hi fred!'
*
* // Bound with placeholders.
* var bound = _.bind(greet, object, _, '!');
* bound('hi');
* // => 'hi fred!'
*/
var bind = baseRest(function(func, thisArg, partials) {
var bitmask = WRAP_BIND_FLAG;
if (partials.length) {
var holders = replaceHolders(partials, getHolder(bind));
bitmask |= WRAP_PARTIAL_FLAG;
}
return createWrap(func, bitmask, thisArg, partials, holders);
});
/**
* Creates a function that invokes the method at `object[key]` with `partials`
* prepended to the arguments it receives.
*
* This method differs from `_.bind` by allowing bound functions to reference
* methods that may be redefined or don't yet exist. See
* [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
* for more details.
*
* The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
* builds, may be used as a placeholder for partially applied arguments.
*
* @static
* @memberOf _
* @since 0.10.0
* @category Function
* @param {Object} object The object to invoke the method on.
* @param {string} key The key of the method.
* @param {...*} [partials] The arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var object = {
* 'user': 'fred',
* 'greet': function(greeting, punctuation) {
* return greeting + ' ' + this.user + punctuation;
* }
* };
*
* var bound = _.bindKey(object, 'greet', 'hi');
* bound('!');
* // => 'hi fred!'
*
* object.greet = function(greeting, punctuation) {
* return greeting + 'ya ' + this.user + punctuation;
* };
*
* bound('!');
* // => 'hiya fred!'
*
* // Bound with placeholders.
* var bound = _.bindKey(object, 'greet', _, '!');
* bound('hi');
* // => 'hiya fred!'
*/
var bindKey = baseRest(function(object, key, partials) {
var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
if (partials.length) {
var holders = replaceHolders(partials, getHolder(bindKey));
bitmask |= WRAP_PARTIAL_FLAG;
}
return createWrap(key, bitmask, object, partials, holders);
});
/**
* Creates a function that accepts arguments of `func` and either invokes
* `func` returning its result, if at least `arity` number of arguments have
* been provided, or returns a function that accepts the remaining `func`
* arguments, and so on. The arity of `func` may be specified if `func.length`
* is not sufficient.
*
* The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
* may be used as a placeholder for provided arguments.
*
* **Note:** This method doesn't set the "length" property of curried functions.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Function
* @param {Function} func The function to curry.
* @param {number} [arity=func.length] The arity of `func`.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Function} Returns the new curried function.
* @example
*
* var abc = function(a, b, c) {
* return [a, b, c];
* };
*
* var curried = _.curry(abc);
*
* curried(1)(2)(3);
* // => [1, 2, 3]
*
* curried(1, 2)(3);
* // => [1, 2, 3]
*
* curried(1, 2, 3);
* // => [1, 2, 3]
*
* // Curried with placeholders.
* curried(1)(_, 3)(2);
* // => [1, 2, 3]
*/
function curry(func, arity, guard) {
arity = guard ? undefined$1 : arity;
var result = createWrap(func, WRAP_CURRY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
result.placeholder = curry.placeholder;
return result;
}
/**
* This method is like `_.curry` except that arguments are applied to `func`
* in the manner of `_.partialRight` instead of `_.partial`.
*
* The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
* builds, may be used as a placeholder for provided arguments.
*
* **Note:** This method doesn't set the "length" property of curried functions.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Function
* @param {Function} func The function to curry.
* @param {number} [arity=func.length] The arity of `func`.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Function} Returns the new curried function.
* @example
*
* var abc = function(a, b, c) {
* return [a, b, c];
* };
*
* var curried = _.curryRight(abc);
*
* curried(3)(2)(1);
* // => [1, 2, 3]
*
* curried(2, 3)(1);
* // => [1, 2, 3]
*
* curried(1, 2, 3);
* // => [1, 2, 3]
*
* // Curried with placeholders.
* curried(3)(1, _)(2);
* // => [1, 2, 3]
*/
function curryRight(func, arity, guard) {
arity = guard ? undefined$1 : arity;
var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
result.placeholder = curryRight.placeholder;
return result;
}
/**
* Creates a debounced function that delays invoking `func` until after `wait`
* milliseconds have elapsed since the last time the debounced function was
* invoked. The debounced function comes with a `cancel` method to cancel
* delayed `func` invocations and a `flush` method to immediately invoke them.
* Provide `options` to indicate whether `func` should be invoked on the
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
* with the last arguments provided to the debounced function. Subsequent
* calls to the debounced function return the result of the last `func`
* invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the debounced function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.debounce` and `_.throttle`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to debounce.
* @param {number} [wait=0] The number of milliseconds to delay.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=false]
* Specify invoking on the leading edge of the timeout.
* @param {number} [options.maxWait]
* The maximum time `func` is allowed to be delayed before it's invoked.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // Avoid costly calculations while the window size is in flux.
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
*
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
* jQuery(element).on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* }));
*
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
* var source = new EventSource('/stream');
* jQuery(source).on('message', debounced);
*
* // Cancel the trailing debounced invocation.
* jQuery(window).on('popstate', debounced.cancel);
*/
function debounce(func, wait, options) {
var lastArgs,
lastThis,
maxWait,
result,
timerId,
lastCallTime,
lastInvokeTime = 0,
leading = false,
maxing = false,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber(wait) || 0;
if (isObject(options)) {
leading = !!options.leading;
maxing = 'maxWait' in options;
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs,
thisArg = lastThis;
lastArgs = lastThis = undefined$1;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTime = time;
// Start the timer for the trailing edge.
timerId = setTimeout(timerExpired, wait);
// Invoke the leading edge.
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime,
timeWaiting = wait - timeSinceLastCall;
return maxing
? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
: timeWaiting;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime,
timeSinceLastInvoke = time - lastInvokeTime;
// Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return (lastCallTime === undefined$1 || (timeSinceLastCall >= wait) ||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
}
function timerExpired() {
var time = now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
// Restart the timer.
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = undefined$1;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = undefined$1;
return result;
}
function cancel() {
if (timerId !== undefined$1) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = undefined$1;
}
function flush() {
return timerId === undefined$1 ? result : trailingEdge(now());
}
function debounced() {
var time = now(),
isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === undefined$1) {
return leadingEdge(lastCallTime);
}
if (maxing) {
// Handle invocations in a tight loop.
clearTimeout(timerId);
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === undefined$1) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
/**
* Defers invoking the `func` until the current call stack has cleared. Any
* additional arguments are provided to `func` when it's invoked.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to defer.
* @param {...*} [args] The arguments to invoke `func` with.
* @returns {number} Returns the timer id.
* @example
*
* _.defer(function(text) {
* console.log(text);
* }, 'deferred');
* // => Logs 'deferred' after one millisecond.
*/
var defer = baseRest(function(func, args) {
return baseDelay(func, 1, args);
});
/**
* Invokes `func` after `wait` milliseconds. Any additional arguments are
* provided to `func` when it's invoked.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to delay.
* @param {number} wait The number of milliseconds to delay invocation.
* @param {...*} [args] The arguments to invoke `func` with.
* @returns {number} Returns the timer id.
* @example
*
* _.delay(function(text) {
* console.log(text);
* }, 1000, 'later');
* // => Logs 'later' after one second.
*/
var delay = baseRest(function(func, wait, args) {
return baseDelay(func, toNumber(wait) || 0, args);
});
/**
* Creates a function that invokes `func` with arguments reversed.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Function
* @param {Function} func The function to flip arguments for.
* @returns {Function} Returns the new flipped function.
* @example
*
* var flipped = _.flip(function() {
* return _.toArray(arguments);
* });
*
* flipped('a', 'b', 'c', 'd');
* // => ['d', 'c', 'b', 'a']
*/
function flip(func) {
return createWrap(func, WRAP_FLIP_FLAG);
}
/**
* Creates a function that memoizes the result of `func`. If `resolver` is
* provided, it determines the cache key for storing the result based on the
* arguments provided to the memoized function. By default, the first argument
* provided to the memoized function is used as the map cache key. The `func`
* is invoked with the `this` binding of the memoized function.
*
* **Note:** The cache is exposed as the `cache` property on the memoized
* function. Its creation may be customized by replacing the `_.memoize.Cache`
* constructor with one whose instances implement the
* [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
* method interface of `clear`, `delete`, `get`, `has`, and `set`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to have its output memoized.
* @param {Function} [resolver] The function to resolve the cache key.
* @returns {Function} Returns the new memoized function.
* @example
*
* var object = { 'a': 1, 'b': 2 };
* var other = { 'c': 3, 'd': 4 };
*
* var values = _.memoize(_.values);
* values(object);
* // => [1, 2]
*
* values(other);
* // => [3, 4]
*
* object.a = 2;
* values(object);
* // => [1, 2]
*
* // Modify the result cache.
* values.cache.set(object, ['a', 'b']);
* values(object);
* // => ['a', 'b']
*
* // Replace `_.memoize.Cache`.
* _.memoize.Cache = WeakMap;
*/
function memoize(func, resolver) {
if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
throw new TypeError(FUNC_ERROR_TEXT);
}
var memoized = function() {
var args = arguments,
key = resolver ? resolver.apply(this, args) : args[0],
cache = memoized.cache;
if (cache.has(key)) {
return cache.get(key);
}
var result = func.apply(this, args);
memoized.cache = cache.set(key, result) || cache;
return result;
};
memoized.cache = new (memoize.Cache || MapCache);
return memoized;
}
// Expose `MapCache`.
memoize.Cache = MapCache;
/**
* Creates a function that negates the result of the predicate `func`. The
* `func` predicate is invoked with the `this` binding and arguments of the
* created function.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Function
* @param {Function} predicate The predicate to negate.
* @returns {Function} Returns the new negated function.
* @example
*
* function isEven(n) {
* return n % 2 == 0;
* }
*
* _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
* // => [1, 3, 5]
*/
function negate(predicate) {
if (typeof predicate != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
return function() {
var args = arguments;
switch (args.length) {
case 0: return !predicate.call(this);
case 1: return !predicate.call(this, args[0]);
case 2: return !predicate.call(this, args[0], args[1]);
case 3: return !predicate.call(this, args[0], args[1], args[2]);
}
return !predicate.apply(this, args);
};
}
/**
* Creates a function that is restricted to invoking `func` once. Repeat calls
* to the function return the value of the first invocation. The `func` is
* invoked with the `this` binding and arguments of the created function.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var initialize = _.once(createApplication);
* initialize();
* initialize();
* // => `createApplication` is invoked once
*/
function once(func) {
return before(2, func);
}
/**
* Creates a function that invokes `func` with its arguments transformed.
*
* @static
* @since 4.0.0
* @memberOf _
* @category Function
* @param {Function} func The function to wrap.
* @param {...(Function|Function[])} [transforms=[_.identity]]
* The argument transforms.
* @returns {Function} Returns the new function.
* @example
*
* function doubled(n) {
* return n * 2;
* }
*
* function square(n) {
* return n * n;
* }
*
* var func = _.overArgs(function(x, y) {
* return [x, y];
* }, [square, doubled]);
*
* func(9, 3);
* // => [81, 6]
*
* func(10, 5);
* // => [100, 10]
*/
var overArgs = castRest(function(func, transforms) {
transforms = (transforms.length == 1 && isArray(transforms[0]))
? arrayMap(transforms[0], baseUnary(getIteratee()))
: arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
var funcsLength = transforms.length;
return baseRest(function(args) {
var index = -1,
length = nativeMin(args.length, funcsLength);
while (++index < length) {
args[index] = transforms[index].call(this, args[index]);
}
return apply(func, this, args);
});
});
/**
* Creates a function that invokes `func` with `partials` prepended to the
* arguments it receives. This method is like `_.bind` except it does **not**
* alter the `this` binding.
*
* The `_.partial.placeholder` value, which defaults to `_` in monolithic
* builds, may be used as a placeholder for partially applied arguments.
*
* **Note:** This method doesn't set the "length" property of partially
* applied functions.
*
* @static
* @memberOf _
* @since 0.2.0
* @category Function
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [partials] The arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* function greet(greeting, name) {
* return greeting + ' ' + name;
* }
*
* var sayHelloTo = _.partial(greet, 'hello');
* sayHelloTo('fred');
* // => 'hello fred'
*
* // Partially applied with placeholders.
* var greetFred = _.partial(greet, _, 'fred');
* greetFred('hi');
* // => 'hi fred'
*/
var partial = baseRest(function(func, partials) {
var holders = replaceHolders(partials, getHolder(partial));
return createWrap(func, WRAP_PARTIAL_FLAG, undefined$1, partials, holders);
});
/**
* This method is like `_.partial` except that partially applied arguments
* are appended to the arguments it receives.
*
* The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
* builds, may be used as a placeholder for partially applied arguments.
*
* **Note:** This method doesn't set the "length" property of partially
* applied functions.
*
* @static
* @memberOf _
* @since 1.0.0
* @category Function
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [partials] The arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* function greet(greeting, name) {
* return greeting + ' ' + name;
* }
*
* var greetFred = _.partialRight(greet, 'fred');
* greetFred('hi');
* // => 'hi fred'
*
* // Partially applied with placeholders.
* var sayHelloTo = _.partialRight(greet, 'hello', _);
* sayHelloTo('fred');
* // => 'hello fred'
*/
var partialRight = baseRest(function(func, partials) {
var holders = replaceHolders(partials, getHolder(partialRight));
return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined$1, partials, holders);
});
/**
* Creates a function that invokes `func` with arguments arranged according
* to the specified `indexes` where the argument value at the first index is
* provided as the first argument, the argument value at the second index is
* provided as the second argument, and so on.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Function
* @param {Function} func The function to rearrange arguments for.
* @param {...(number|number[])} indexes The arranged argument indexes.
* @returns {Function} Returns the new function.
* @example
*
* var rearged = _.rearg(function(a, b, c) {
* return [a, b, c];
* }, [2, 0, 1]);
*
* rearged('b', 'c', 'a')
* // => ['a', 'b', 'c']
*/
var rearg = flatRest(function(func, indexes) {
return createWrap(func, WRAP_REARG_FLAG, undefined$1, undefined$1, undefined$1, indexes);
});
/**
* Creates a function that invokes `func` with the `this` binding of the
* created function and arguments from `start` and beyond provided as
* an array.
*
* **Note:** This method is based on the
* [rest parameter](https://mdn.io/rest_parameters).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Function
* @param {Function} func The function to apply a rest parameter to.
* @param {number} [start=func.length-1] The start position of the rest parameter.
* @returns {Function} Returns the new function.
* @example
*
* var say = _.rest(function(what, names) {
* return what + ' ' + _.initial(names).join(', ') +
* (_.size(names) > 1 ? ', & ' : '') + _.last(names);
* });
*
* say('hello', 'fred', 'barney', 'pebbles');
* // => 'hello fred, barney, & pebbles'
*/
function rest(func, start) {
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
start = start === undefined$1 ? start : toInteger(start);
return baseRest(func, start);
}
/**
* Creates a function that invokes `func` with the `this` binding of the
* create function and an array of arguments much like
* [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
*
* **Note:** This method is based on the
* [spread operator](https://mdn.io/spread_operator).
*
* @static
* @memberOf _
* @since 3.2.0
* @category Function
* @param {Function} func The function to spread arguments over.
* @param {number} [start=0] The start position of the spread.
* @returns {Function} Returns the new function.
* @example
*
* var say = _.spread(function(who, what) {
* return who + ' says ' + what;
* });
*
* say(['fred', 'hello']);
* // => 'fred says hello'
*
* var numbers = Promise.all([
* Promise.resolve(40),
* Promise.resolve(36)
* ]);
*
* numbers.then(_.spread(function(x, y) {
* return x + y;
* }));
* // => a Promise of 76
*/
function spread(func, start) {
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
start = start == null ? 0 : nativeMax(toInteger(start), 0);
return baseRest(function(args) {
var array = args[start],
otherArgs = castSlice(args, 0, start);
if (array) {
arrayPush(otherArgs, array);
}
return apply(func, this, otherArgs);
});
}
/**
* Creates a throttled function that only invokes `func` at most once per
* every `wait` milliseconds. The throttled function comes with a `cancel`
* method to cancel delayed `func` invocations and a `flush` method to
* immediately invoke them. Provide `options` to indicate whether `func`
* should be invoked on the leading and/or trailing edge of the `wait`
* timeout. The `func` is invoked with the last arguments provided to the
* throttled function. Subsequent calls to the throttled function return the
* result of the last `func` invocation.
*
* **Note:** If `leading` and `trailing` options are `true`, `func` is
* invoked on the trailing edge of the timeout only if the throttled function
* is invoked more than once during the `wait` timeout.
*
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
*
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
* for details over the differences between `_.throttle` and `_.debounce`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {Function} func The function to throttle.
* @param {number} [wait=0] The number of milliseconds to throttle invocations to.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.leading=true]
* Specify invoking on the leading edge of the timeout.
* @param {boolean} [options.trailing=true]
* Specify invoking on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* // Avoid excessively updating the position while scrolling.
* jQuery(window).on('scroll', _.throttle(updatePosition, 100));
*
* // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
* var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
* jQuery(element).on('click', throttled);
*
* // Cancel the trailing throttled invocation.
* jQuery(window).on('popstate', throttled.cancel);
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (typeof func != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
if (isObject(options)) {
leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? !!options.trailing : trailing;
}
return debounce(func, wait, {
'leading': leading,
'maxWait': wait,
'trailing': trailing
});
}
/**
* Creates a function that accepts up to one argument, ignoring any
* additional arguments.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Function
* @param {Function} func The function to cap arguments for.
* @returns {Function} Returns the new capped function.
* @example
*
* _.map(['6', '8', '10'], _.unary(parseInt));
* // => [6, 8, 10]
*/
function unary(func) {
return ary(func, 1);
}
/**
* Creates a function that provides `value` to `wrapper` as its first
* argument. Any additional arguments provided to the function are appended
* to those provided to the `wrapper`. The wrapper is invoked with the `this`
* binding of the created function.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Function
* @param {*} value The value to wrap.
* @param {Function} [wrapper=identity] The wrapper function.
* @returns {Function} Returns the new function.
* @example
*
* var p = _.wrap(_.escape, function(func, text) {
* return '<p>' + func(text) + '</p>';
* });
*
* p('fred, barney, & pebbles');
* // => '<p>fred, barney, &amp; pebbles</p>'
*/
function wrap(value, wrapper) {
return partial(castFunction(wrapper), value);
}
/*------------------------------------------------------------------------*/
/**
* Casts `value` as an array if it's not one.
*
* @static
* @memberOf _
* @since 4.4.0
* @category Lang
* @param {*} value The value to inspect.
* @returns {Array} Returns the cast array.
* @example
*
* _.castArray(1);
* // => [1]
*
* _.castArray({ 'a': 1 });
* // => [{ 'a': 1 }]
*
* _.castArray('abc');
* // => ['abc']
*
* _.castArray(null);
* // => [null]
*
* _.castArray(undefined);
* // => [undefined]
*
* _.castArray();
* // => []
*
* var array = [1, 2, 3];
* console.log(_.castArray(array) === array);
* // => true
*/
function castArray() {
if (!arguments.length) {
return [];
}
var value = arguments[0];
return isArray(value) ? value : [value];
}
/**
* Creates a shallow clone of `value`.
*
* **Note:** This method is loosely based on the
* [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
* and supports cloning arrays, array buffers, booleans, date objects, maps,
* numbers, `Object` objects, regexes, sets, strings, symbols, and typed
* arrays. The own enumerable properties of `arguments` objects are cloned
* as plain objects. An empty object is returned for uncloneable values such
* as error objects, functions, DOM nodes, and WeakMaps.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to clone.
* @returns {*} Returns the cloned value.
* @see _.cloneDeep
* @example
*
* var objects = [{ 'a': 1 }, { 'b': 2 }];
*
* var shallow = _.clone(objects);
* console.log(shallow[0] === objects[0]);
* // => true
*/
function clone(value) {
return baseClone(value, CLONE_SYMBOLS_FLAG);
}
/**
* This method is like `_.clone` except that it accepts `customizer` which
* is invoked to produce the cloned value. If `customizer` returns `undefined`,
* cloning is handled by the method instead. The `customizer` is invoked with
* up to four arguments; (value [, index|key, object, stack]).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to clone.
* @param {Function} [customizer] The function to customize cloning.
* @returns {*} Returns the cloned value.
* @see _.cloneDeepWith
* @example
*
* function customizer(value) {
* if (_.isElement(value)) {
* return value.cloneNode(false);
* }
* }
*
* var el = _.cloneWith(document.body, customizer);
*
* console.log(el === document.body);
* // => false
* console.log(el.nodeName);
* // => 'BODY'
* console.log(el.childNodes.length);
* // => 0
*/
function cloneWith(value, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined$1;
return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
}
/**
* This method is like `_.clone` except that it recursively clones `value`.
*
* @static
* @memberOf _
* @since 1.0.0
* @category Lang
* @param {*} value The value to recursively clone.
* @returns {*} Returns the deep cloned value.
* @see _.clone
* @example
*
* var objects = [{ 'a': 1 }, { 'b': 2 }];
*
* var deep = _.cloneDeep(objects);
* console.log(deep[0] === objects[0]);
* // => false
*/
function cloneDeep(value) {
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
}
/**
* This method is like `_.cloneWith` except that it recursively clones `value`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to recursively clone.
* @param {Function} [customizer] The function to customize cloning.
* @returns {*} Returns the deep cloned value.
* @see _.cloneWith
* @example
*
* function customizer(value) {
* if (_.isElement(value)) {
* return value.cloneNode(true);
* }
* }
*
* var el = _.cloneDeepWith(document.body, customizer);
*
* console.log(el === document.body);
* // => false
* console.log(el.nodeName);
* // => 'BODY'
* console.log(el.childNodes.length);
* // => 20
*/
function cloneDeepWith(value, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined$1;
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
}
/**
* Checks if `object` conforms to `source` by invoking the predicate
* properties of `source` with the corresponding property values of `object`.
*
* **Note:** This method is equivalent to `_.conforms` when `source` is
* partially applied.
*
* @static
* @memberOf _
* @since 4.14.0
* @category Lang
* @param {Object} object The object to inspect.
* @param {Object} source The object of property predicates to conform to.
* @returns {boolean} Returns `true` if `object` conforms, else `false`.
* @example
*
* var object = { 'a': 1, 'b': 2 };
*
* _.conformsTo(object, { 'b': function(n) { return n > 1; } });
* // => true
*
* _.conformsTo(object, { 'b': function(n) { return n > 2; } });
* // => false
*/
function conformsTo(object, source) {
return source == null || baseConformsTo(object, source, keys(source));
}
/**
* Performs a
* [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
* comparison between two values to determine if they are equivalent.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'a': 1 };
* var other = { 'a': 1 };
*
* _.eq(object, object);
* // => true
*
* _.eq(object, other);
* // => false
*
* _.eq('a', 'a');
* // => true
*
* _.eq('a', Object('a'));
* // => false
*
* _.eq(NaN, NaN);
* // => true
*/
function eq(value, other) {
return value === other || (value !== value && other !== other);
}
/**
* Checks if `value` is greater than `other`.
*
* @static
* @memberOf _
* @since 3.9.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if `value` is greater than `other`,
* else `false`.
* @see _.lt
* @example
*
* _.gt(3, 1);
* // => true
*
* _.gt(3, 3);
* // => false
*
* _.gt(1, 3);
* // => false
*/
var gt = createRelationalOperation(baseGt);
/**
* Checks if `value` is greater than or equal to `other`.
*
* @static
* @memberOf _
* @since 3.9.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if `value` is greater than or equal to
* `other`, else `false`.
* @see _.lte
* @example
*
* _.gte(3, 1);
* // => true
*
* _.gte(3, 3);
* // => true
*
* _.gte(1, 3);
* // => false
*/
var gte = createRelationalOperation(function(value, other) {
return value >= other;
});
/**
* Checks if `value` is likely an `arguments` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an `arguments` object,
* else `false`.
* @example
*
* _.isArguments(function() { return arguments; }());
* // => true
*
* _.isArguments([1, 2, 3]);
* // => false
*/
var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
!propertyIsEnumerable.call(value, 'callee');
};
/**
* Checks if `value` is classified as an `Array` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array, else `false`.
* @example
*
* _.isArray([1, 2, 3]);
* // => true
*
* _.isArray(document.body.children);
* // => false
*
* _.isArray('abc');
* // => false
*
* _.isArray(_.noop);
* // => false
*/
var isArray = Array.isArray;
/**
* Checks if `value` is classified as an `ArrayBuffer` object.
*
* @static
* @memberOf _
* @since 4.3.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
* @example
*
* _.isArrayBuffer(new ArrayBuffer(2));
* // => true
*
* _.isArrayBuffer(new Array(2));
* // => false
*/
var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
/**
* Checks if `value` is array-like. A value is considered array-like if it's
* not a function and has a `value.length` that's an integer greater than or
* equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is array-like, else `false`.
* @example
*
* _.isArrayLike([1, 2, 3]);
* // => true
*
* _.isArrayLike(document.body.children);
* // => true
*
* _.isArrayLike('abc');
* // => true
*
* _.isArrayLike(_.noop);
* // => false
*/
function isArrayLike(value) {
return value != null && isLength(value.length) && !isFunction(value);
}
/**
* This method is like `_.isArrayLike` except that it also checks if `value`
* is an object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an array-like object,
* else `false`.
* @example
*
* _.isArrayLikeObject([1, 2, 3]);
* // => true
*
* _.isArrayLikeObject(document.body.children);
* // => true
*
* _.isArrayLikeObject('abc');
* // => false
*
* _.isArrayLikeObject(_.noop);
* // => false
*/
function isArrayLikeObject(value) {
return isObjectLike(value) && isArrayLike(value);
}
/**
* Checks if `value` is classified as a boolean primitive or object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
* @example
*
* _.isBoolean(false);
* // => true
*
* _.isBoolean(null);
* // => false
*/
function isBoolean(value) {
return value === true || value === false ||
(isObjectLike(value) && baseGetTag(value) == boolTag);
}
/**
* Checks if `value` is a buffer.
*
* @static
* @memberOf _
* @since 4.3.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
* @example
*
* _.isBuffer(new Buffer(2));
* // => true
*
* _.isBuffer(new Uint8Array(2));
* // => false
*/
var isBuffer = nativeIsBuffer || stubFalse;
/**
* Checks if `value` is classified as a `Date` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a date object, else `false`.
* @example
*
* _.isDate(new Date);
* // => true
*
* _.isDate('Mon April 23 2012');
* // => false
*/
var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
/**
* Checks if `value` is likely a DOM element.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
* @example
*
* _.isElement(document.body);
* // => true
*
* _.isElement('<body>');
* // => false
*/
function isElement(value) {
return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
}
/**
* Checks if `value` is an empty object, collection, map, or set.
*
* Objects are considered empty if they have no own enumerable string keyed
* properties.
*
* Array-like values such as `arguments` objects, arrays, buffers, strings, or
* jQuery-like collections are considered empty if they have a `length` of `0`.
* Similarly, maps and sets are considered empty if they have a `size` of `0`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is empty, else `false`.
* @example
*
* _.isEmpty(null);
* // => true
*
* _.isEmpty(true);
* // => true
*
* _.isEmpty(1);
* // => true
*
* _.isEmpty([1, 2, 3]);
* // => false
*
* _.isEmpty({ 'a': 1 });
* // => false
*/
function isEmpty(value) {
if (value == null) {
return true;
}
if (isArrayLike(value) &&
(isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
isBuffer(value) || isTypedArray(value) || isArguments(value))) {
return !value.length;
}
var tag = getTag(value);
if (tag == mapTag || tag == setTag) {
return !value.size;
}
if (isPrototype(value)) {
return !baseKeys(value).length;
}
for (var key in value) {
if (hasOwnProperty.call(value, key)) {
return false;
}
}
return true;
}
/**
* Performs a deep comparison between two values to determine if they are
* equivalent.
*
* **Note:** This method supports comparing arrays, array buffers, booleans,
* date objects, error objects, maps, numbers, `Object` objects, regexes,
* sets, strings, symbols, and typed arrays. `Object` objects are compared
* by their own, not inherited, enumerable properties. Functions and DOM
* nodes are compared by strict equality, i.e. `===`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'a': 1 };
* var other = { 'a': 1 };
*
* _.isEqual(object, other);
* // => true
*
* object === other;
* // => false
*/
function isEqual(value, other) {
return baseIsEqual(value, other);
}
/**
* This method is like `_.isEqual` except that it accepts `customizer` which
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
* are handled by the method instead. The `customizer` is invoked with up to
* six arguments: (objValue, othValue [, index|key, object, other, stack]).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @param {Function} [customizer] The function to customize comparisons.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* function isGreeting(value) {
* return /^h(?:i|ello)$/.test(value);
* }
*
* function customizer(objValue, othValue) {
* if (isGreeting(objValue) && isGreeting(othValue)) {
* return true;
* }
* }
*
* var array = ['hello', 'goodbye'];
* var other = ['hi', 'goodbye'];
*
* _.isEqualWith(array, other, customizer);
* // => true
*/
function isEqualWith(value, other, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined$1;
var result = customizer ? customizer(value, other) : undefined$1;
return result === undefined$1 ? baseIsEqual(value, other, undefined$1, customizer) : !!result;
}
/**
* Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
* `SyntaxError`, `TypeError`, or `URIError` object.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an error object, else `false`.
* @example
*
* _.isError(new Error);
* // => true
*
* _.isError(Error);
* // => false
*/
function isError(value) {
if (!isObjectLike(value)) {
return false;
}
var tag = baseGetTag(value);
return tag == errorTag || tag == domExcTag ||
(typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
}
/**
* Checks if `value` is a finite primitive number.
*
* **Note:** This method is based on
* [`Number.isFinite`](https://mdn.io/Number/isFinite).
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
* @example
*
* _.isFinite(3);
* // => true
*
* _.isFinite(Number.MIN_VALUE);
* // => true
*
* _.isFinite(Infinity);
* // => false
*
* _.isFinite('3');
* // => false
*/
function isFinite(value) {
return typeof value == 'number' && nativeIsFinite(value);
}
/**
* Checks if `value` is classified as a `Function` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
*
* _.isFunction(/abc/);
* // => false
*/
function isFunction(value) {
if (!isObject(value)) {
return false;
}
// The use of `Object#toString` avoids issues with the `typeof` operator
// in Safari 9 which returns 'object' for typed arrays and other constructors.
var tag = baseGetTag(value);
return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
}
/**
* Checks if `value` is an integer.
*
* **Note:** This method is based on
* [`Number.isInteger`](https://mdn.io/Number/isInteger).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an integer, else `false`.
* @example
*
* _.isInteger(3);
* // => true
*
* _.isInteger(Number.MIN_VALUE);
* // => false
*
* _.isInteger(Infinity);
* // => false
*
* _.isInteger('3');
* // => false
*/
function isInteger(value) {
return typeof value == 'number' && value == toInteger(value);
}
/**
* Checks if `value` is a valid array-like length.
*
* **Note:** This method is loosely based on
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
* @example
*
* _.isLength(3);
* // => true
*
* _.isLength(Number.MIN_VALUE);
* // => false
*
* _.isLength(Infinity);
* // => false
*
* _.isLength('3');
* // => false
*/
function isLength(value) {
return typeof value == 'number' &&
value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
}
/**
* Checks if `value` is the
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(_.noop);
* // => true
*
* _.isObject(null);
* // => false
*/
function isObject(value) {
var type = typeof value;
return value != null && (type == 'object' || type == 'function');
}
/**
* Checks if `value` is object-like. A value is object-like if it's not `null`
* and has a `typeof` result of "object".
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
* @example
*
* _.isObjectLike({});
* // => true
*
* _.isObjectLike([1, 2, 3]);
* // => true
*
* _.isObjectLike(_.noop);
* // => false
*
* _.isObjectLike(null);
* // => false
*/
function isObjectLike(value) {
return value != null && typeof value == 'object';
}
/**
* Checks if `value` is classified as a `Map` object.
*
* @static
* @memberOf _
* @since 4.3.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a map, else `false`.
* @example
*
* _.isMap(new Map);
* // => true
*
* _.isMap(new WeakMap);
* // => false
*/
var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
/**
* Performs a partial deep comparison between `object` and `source` to
* determine if `object` contains equivalent property values.
*
* **Note:** This method is equivalent to `_.matches` when `source` is
* partially applied.
*
* Partial comparisons will match empty array and empty object `source`
* values against any array or object value, respectively. See `_.isEqual`
* for a list of supported value comparisons.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Lang
* @param {Object} object The object to inspect.
* @param {Object} source The object of property values to match.
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
* @example
*
* var object = { 'a': 1, 'b': 2 };
*
* _.isMatch(object, { 'b': 2 });
* // => true
*
* _.isMatch(object, { 'b': 1 });
* // => false
*/
function isMatch(object, source) {
return object === source || baseIsMatch(object, source, getMatchData(source));
}
/**
* This method is like `_.isMatch` except that it accepts `customizer` which
* is invoked to compare values. If `customizer` returns `undefined`, comparisons
* are handled by the method instead. The `customizer` is invoked with five
* arguments: (objValue, srcValue, index|key, object, source).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {Object} object The object to inspect.
* @param {Object} source The object of property values to match.
* @param {Function} [customizer] The function to customize comparisons.
* @returns {boolean} Returns `true` if `object` is a match, else `false`.
* @example
*
* function isGreeting(value) {
* return /^h(?:i|ello)$/.test(value);
* }
*
* function customizer(objValue, srcValue) {
* if (isGreeting(objValue) && isGreeting(srcValue)) {
* return true;
* }
* }
*
* var object = { 'greeting': 'hello' };
* var source = { 'greeting': 'hi' };
*
* _.isMatchWith(object, source, customizer);
* // => true
*/
function isMatchWith(object, source, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined$1;
return baseIsMatch(object, source, getMatchData(source), customizer);
}
/**
* Checks if `value` is `NaN`.
*
* **Note:** This method is based on
* [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
* global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
* `undefined` and other non-number values.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
* // => true
*
* _.isNaN(new Number(NaN));
* // => true
*
* isNaN(undefined);
* // => true
*
* _.isNaN(undefined);
* // => false
*/
function isNaN(value) {
// An `NaN` primitive is the only value that is not equal to itself.
// Perform the `toStringTag` check first to avoid errors with some
// ActiveX objects in IE.
return isNumber(value) && value != +value;
}
/**
* Checks if `value` is a pristine native function.
*
* **Note:** This method can't reliably detect native functions in the presence
* of the core-js package because core-js circumvents this kind of detection.
* Despite multiple requests, the core-js maintainer has made it clear: any
* attempt to fix the detection will be obstructed. As a result, we're left
* with little choice but to throw an error. Unfortunately, this also affects
* packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
* which rely on core-js.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a native function,
* else `false`.
* @example
*
* _.isNative(Array.prototype.push);
* // => true
*
* _.isNative(_);
* // => false
*/
function isNative(value) {
if (isMaskable(value)) {
throw new Error(CORE_ERROR_TEXT);
}
return baseIsNative(value);
}
/**
* Checks if `value` is `null`.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
* // => true
*
* _.isNull(void 0);
* // => false
*/
function isNull(value) {
return value === null;
}
/**
* Checks if `value` is `null` or `undefined`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is nullish, else `false`.
* @example
*
* _.isNil(null);
* // => true
*
* _.isNil(void 0);
* // => true
*
* _.isNil(NaN);
* // => false
*/
function isNil(value) {
return value == null;
}
/**
* Checks if `value` is classified as a `Number` primitive or object.
*
* **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
* classified as numbers, use the `_.isFinite` method.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a number, else `false`.
* @example
*
* _.isNumber(3);
* // => true
*
* _.isNumber(Number.MIN_VALUE);
* // => true
*
* _.isNumber(Infinity);
* // => true
*
* _.isNumber('3');
* // => false
*/
function isNumber(value) {
return typeof value == 'number' ||
(isObjectLike(value) && baseGetTag(value) == numberTag);
}
/**
* Checks if `value` is a plain object, that is, an object created by the
* `Object` constructor or one with a `[[Prototype]]` of `null`.
*
* @static
* @memberOf _
* @since 0.8.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Foo() {
* this.a = 1;
* }
*
* _.isPlainObject(new Foo);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*
* _.isPlainObject(Object.create(null));
* // => true
*/
function isPlainObject(value) {
if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
return false;
}
var proto = getPrototype(value);
if (proto === null) {
return true;
}
var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
return typeof Ctor == 'function' && Ctor instanceof Ctor &&
funcToString.call(Ctor) == objectCtorString;
}
/**
* Checks if `value` is classified as a `RegExp` object.
*
* @static
* @memberOf _
* @since 0.1.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
* @example
*
* _.isRegExp(/abc/);
* // => true
*
* _.isRegExp('/abc/');
* // => false
*/
var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
/**
* Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
* double precision number which isn't the result of a rounded unsafe integer.
*
* **Note:** This method is based on
* [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
* @example
*
* _.isSafeInteger(3);
* // => true
*
* _.isSafeInteger(Number.MIN_VALUE);
* // => false
*
* _.isSafeInteger(Infinity);
* // => false
*
* _.isSafeInteger('3');
* // => false
*/
function isSafeInteger(value) {
return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
}
/**
* Checks if `value` is classified as a `Set` object.
*
* @static
* @memberOf _
* @since 4.3.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a set, else `false`.
* @example
*
* _.isSet(new Set);
* // => true
*
* _.isSet(new WeakSet);
* // => false
*/
var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
/**
* Checks if `value` is classified as a `String` primitive or object.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a string, else `false`.
* @example
*
* _.isString('abc');
* // => true
*
* _.isString(1);
* // => false
*/
function isString(value) {
return typeof value == 'string' ||
(!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
}
/**
* Checks if `value` is classified as a `Symbol` primitive or object.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
* @example
*
* _.isSymbol(Symbol.iterator);
* // => true
*
* _.isSymbol('abc');
* // => false
*/
function isSymbol(value) {
return typeof value == 'symbol' ||
(isObjectLike(value) && baseGetTag(value) == symbolTag);
}
/**
* Checks if `value` is classified as a typed array.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
* @example
*
* _.isTypedArray(new Uint8Array);
* // => true
*
* _.isTypedArray([]);
* // => false
*/
var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
/**
* Checks if `value` is `undefined`.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
* // => true
*
* _.isUndefined(null);
* // => false
*/
function isUndefined(value) {
return value === undefined$1;
}
/**
* Checks if `value` is classified as a `WeakMap` object.
*
* @static
* @memberOf _
* @since 4.3.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
* @example
*
* _.isWeakMap(new WeakMap);
* // => true
*
* _.isWeakMap(new Map);
* // => false
*/
function isWeakMap(value) {
return isObjectLike(value) && getTag(value) == weakMapTag;
}
/**
* Checks if `value` is classified as a `WeakSet` object.
*
* @static
* @memberOf _
* @since 4.3.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
* @example
*
* _.isWeakSet(new WeakSet);
* // => true
*
* _.isWeakSet(new Set);
* // => false
*/
function isWeakSet(value) {
return isObjectLike(value) && baseGetTag(value) == weakSetTag;
}
/**
* Checks if `value` is less than `other`.
*
* @static
* @memberOf _
* @since 3.9.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if `value` is less than `other`,
* else `false`.
* @see _.gt
* @example
*
* _.lt(1, 3);
* // => true
*
* _.lt(3, 3);
* // => false
*
* _.lt(3, 1);
* // => false
*/
var lt = createRelationalOperation(baseLt);
/**
* Checks if `value` is less than or equal to `other`.
*
* @static
* @memberOf _
* @since 3.9.0
* @category Lang
* @param {*} value The value to compare.
* @param {*} other The other value to compare.
* @returns {boolean} Returns `true` if `value` is less than or equal to
* `other`, else `false`.
* @see _.gte
* @example
*
* _.lte(1, 3);
* // => true
*
* _.lte(3, 3);
* // => true
*
* _.lte(3, 1);
* // => false
*/
var lte = createRelationalOperation(function(value, other) {
return value <= other;
});
/**
* Converts `value` to an array.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Lang
* @param {*} value The value to convert.
* @returns {Array} Returns the converted array.
* @example
*
* _.toArray({ 'a': 1, 'b': 2 });
* // => [1, 2]
*
* _.toArray('abc');
* // => ['a', 'b', 'c']
*
* _.toArray(1);
* // => []
*
* _.toArray(null);
* // => []
*/
function toArray(value) {
if (!value) {
return [];
}
if (isArrayLike(value)) {
return isString(value) ? stringToArray(value) : copyArray(value);
}
if (symIterator && value[symIterator]) {
return iteratorToArray(value[symIterator]());
}
var tag = getTag(value),
func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
return func(value);
}
/**
* Converts `value` to a finite number.
*
* @static
* @memberOf _
* @since 4.12.0
* @category Lang
* @param {*} value The value to convert.
* @returns {number} Returns the converted number.
* @example
*
* _.toFinite(3.2);
* // => 3.2
*
* _.toFinite(Number.MIN_VALUE);
* // => 5e-324
*
* _.toFinite(Infinity);
* // => 1.7976931348623157e+308
*
* _.toFinite('3.2');
* // => 3.2
*/
function toFinite(value) {
if (!value) {
return value === 0 ? value : 0;
}
value = toNumber(value);
if (value === INFINITY || value === -INFINITY) {
var sign = (value < 0 ? -1 : 1);
return sign * MAX_INTEGER;
}
return value === value ? value : 0;
}
/**
* Converts `value` to an integer.
*
* **Note:** This method is loosely based on
* [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to convert.
* @returns {number} Returns the converted integer.
* @example
*
* _.toInteger(3.2);
* // => 3
*
* _.toInteger(Number.MIN_VALUE);
* // => 0
*
* _.toInteger(Infinity);
* // => 1.7976931348623157e+308
*
* _.toInteger('3.2');
* // => 3
*/
function toInteger(value) {
var result = toFinite(value),
remainder = result % 1;
return result === result ? (remainder ? result - remainder : result) : 0;
}
/**
* Converts `value` to an integer suitable for use as the length of an
* array-like object.
*
* **Note:** This method is based on
* [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to convert.
* @returns {number} Returns the converted integer.
* @example
*
* _.toLength(3.2);
* // => 3
*
* _.toLength(Number.MIN_VALUE);
* // => 0
*
* _.toLength(Infinity);
* // => 4294967295
*
* _.toLength('3.2');
* // => 3
*/
function toLength(value) {
return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
}
/**
* Converts `value` to a number.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to process.
* @returns {number} Returns the number.
* @example
*
* _.toNumber(3.2);
* // => 3.2
*
* _.toNumber(Number.MIN_VALUE);
* // => 5e-324
*
* _.toNumber(Infinity);
* // => Infinity
*
* _.toNumber('3.2');
* // => 3.2
*/
function toNumber(value) {
if (typeof value == 'number') {
return value;
}
if (isSymbol(value)) {
return NAN;
}
if (isObject(value)) {
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
value = isObject(other) ? (other + '') : other;
}
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
: (reIsBadHex.test(value) ? NAN : +value);
}
/**
* Converts `value` to a plain object flattening inherited enumerable string
* keyed properties of `value` to own properties of the plain object.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Lang
* @param {*} value The value to convert.
* @returns {Object} Returns the converted plain object.
* @example
*
* function Foo() {
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.assign({ 'a': 1 }, new Foo);
* // => { 'a': 1, 'b': 2 }
*
* _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
* // => { 'a': 1, 'b': 2, 'c': 3 }
*/
function toPlainObject(value) {
return copyObject(value, keysIn(value));
}
/**
* Converts `value` to a safe integer. A safe integer can be compared and
* represented correctly.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to convert.
* @returns {number} Returns the converted integer.
* @example
*
* _.toSafeInteger(3.2);
* // => 3
*
* _.toSafeInteger(Number.MIN_VALUE);
* // => 0
*
* _.toSafeInteger(Infinity);
* // => 9007199254740991
*
* _.toSafeInteger('3.2');
* // => 3
*/
function toSafeInteger(value) {
return value
? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER)
: (value === 0 ? value : 0);
}
/**
* Converts `value` to a string. An empty string is returned for `null`
* and `undefined` values. The sign of `-0` is preserved.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to convert.
* @returns {string} Returns the converted string.
* @example
*
* _.toString(null);
* // => ''
*
* _.toString(-0);
* // => '-0'
*
* _.toString([1, 2, 3]);
* // => '1,2,3'
*/
function toString(value) {
return value == null ? '' : baseToString(value);
}
/*------------------------------------------------------------------------*/
/**
* Assigns own enumerable string keyed properties of source objects to the
* destination object. Source objects are applied from left to right.
* Subsequent sources overwrite property assignments of previous sources.
*
* **Note:** This method mutates `object` and is loosely based on
* [`Object.assign`](https://mdn.io/Object/assign).
*
* @static
* @memberOf _
* @since 0.10.0
* @category Object
* @param {Object} object The destination object.
* @param {...Object} [sources] The source objects.
* @returns {Object} Returns `object`.
* @see _.assignIn
* @example
*
* function Foo() {
* this.a = 1;
* }
*
* function Bar() {
* this.c = 3;
* }
*
* Foo.prototype.b = 2;
* Bar.prototype.d = 4;
*
* _.assign({ 'a': 0 }, new Foo, new Bar);
* // => { 'a': 1, 'c': 3 }
*/
var assign = createAssigner(function(object, source) {
if (isPrototype(source) || isArrayLike(source)) {
copyObject(source, keys(source), object);
return;
}
for (var key in source) {
if (hasOwnProperty.call(source, key)) {
assignValue(object, key, source[key]);
}
}
});
/**
* This method is like `_.assign` except that it iterates over own and
* inherited source properties.
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @alias extend
* @category Object
* @param {Object} object The destination object.
* @param {...Object} [sources] The source objects.
* @returns {Object} Returns `object`.
* @see _.assign
* @example
*
* function Foo() {
* this.a = 1;
* }
*
* function Bar() {
* this.c = 3;
* }
*
* Foo.prototype.b = 2;
* Bar.prototype.d = 4;
*
* _.assignIn({ 'a': 0 }, new Foo, new Bar);
* // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
*/
var assignIn = createAssigner(function(object, source) {
copyObject(source, keysIn(source), object);
});
/**
* This method is like `_.assignIn` except that it accepts `customizer`
* which is invoked to produce the assigned values. If `customizer` returns
* `undefined`, assignment is handled by the method instead. The `customizer`
* is invoked with five arguments: (objValue, srcValue, key, object, source).
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @alias extendWith
* @category Object
* @param {Object} object The destination object.
* @param {...Object} sources The source objects.
* @param {Function} [customizer] The function to customize assigned values.
* @returns {Object} Returns `object`.
* @see _.assignWith
* @example
*
* function customizer(objValue, srcValue) {
* return _.isUndefined(objValue) ? srcValue : objValue;
* }
*
* var defaults = _.partialRight(_.assignInWith, customizer);
*
* defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
* // => { 'a': 1, 'b': 2 }
*/
var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
copyObject(source, keysIn(source), object, customizer);
});
/**
* This method is like `_.assign` except that it accepts `customizer`
* which is invoked to produce the assigned values. If `customizer` returns
* `undefined`, assignment is handled by the method instead. The `customizer`
* is invoked with five arguments: (objValue, srcValue, key, object, source).
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The destination object.
* @param {...Object} sources The source objects.
* @param {Function} [customizer] The function to customize assigned values.
* @returns {Object} Returns `object`.
* @see _.assignInWith
* @example
*
* function customizer(objValue, srcValue) {
* return _.isUndefined(objValue) ? srcValue : objValue;
* }
*
* var defaults = _.partialRight(_.assignWith, customizer);
*
* defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
* // => { 'a': 1, 'b': 2 }
*/
var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
copyObject(source, keys(source), object, customizer);
});
/**
* Creates an array of values corresponding to `paths` of `object`.
*
* @static
* @memberOf _
* @since 1.0.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {...(string|string[])} [paths] The property paths to pick.
* @returns {Array} Returns the picked values.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
*
* _.at(object, ['a[0].b.c', 'a[1]']);
* // => [3, 4]
*/
var at = flatRest(baseAt);
/**
* Creates an object that inherits from the `prototype` object. If a
* `properties` object is given, its own enumerable string keyed properties
* are assigned to the created object.
*
* @static
* @memberOf _
* @since 2.3.0
* @category Object
* @param {Object} prototype The object to inherit from.
* @param {Object} [properties] The properties to assign to the object.
* @returns {Object} Returns the new object.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* function Circle() {
* Shape.call(this);
* }
*
* Circle.prototype = _.create(Shape.prototype, {
* 'constructor': Circle
* });
*
* var circle = new Circle;
* circle instanceof Circle;
* // => true
*
* circle instanceof Shape;
* // => true
*/
function create(prototype, properties) {
var result = baseCreate(prototype);
return properties == null ? result : baseAssign(result, properties);
}
/**
* Assigns own and inherited enumerable string keyed properties of source
* objects to the destination object for all destination properties that
* resolve to `undefined`. Source objects are applied from left to right.
* Once a property is set, additional values of the same property are ignored.
*
* **Note:** This method mutates `object`.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The destination object.
* @param {...Object} [sources] The source objects.
* @returns {Object} Returns `object`.
* @see _.defaultsDeep
* @example
*
* _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
* // => { 'a': 1, 'b': 2 }
*/
var defaults = baseRest(function(object, sources) {
object = Object(object);
var index = -1;
var length = sources.length;
var guard = length > 2 ? sources[2] : undefined$1;
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
length = 1;
}
while (++index < length) {
var source = sources[index];
var props = keysIn(source);
var propsIndex = -1;
var propsLength = props.length;
while (++propsIndex < propsLength) {
var key = props[propsIndex];
var value = object[key];
if (value === undefined$1 ||
(eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) {
object[key] = source[key];
}
}
}
return object;
});
/**
* This method is like `_.defaults` except that it recursively assigns
* default properties.
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 3.10.0
* @category Object
* @param {Object} object The destination object.
* @param {...Object} [sources] The source objects.
* @returns {Object} Returns `object`.
* @see _.defaults
* @example
*
* _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
* // => { 'a': { 'b': 2, 'c': 3 } }
*/
var defaultsDeep = baseRest(function(args) {
args.push(undefined$1, customDefaultsMerge);
return apply(mergeWith, undefined$1, args);
});
/**
* This method is like `_.find` except that it returns the key of the first
* element `predicate` returns truthy for instead of the element itself.
*
* @static
* @memberOf _
* @since 1.1.0
* @category Object
* @param {Object} object The object to inspect.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {string|undefined} Returns the key of the matched element,
* else `undefined`.
* @example
*
* var users = {
* 'barney': { 'age': 36, 'active': true },
* 'fred': { 'age': 40, 'active': false },
* 'pebbles': { 'age': 1, 'active': true }
* };
*
* _.findKey(users, function(o) { return o.age < 40; });
* // => 'barney' (iteration order is not guaranteed)
*
* // The `_.matches` iteratee shorthand.
* _.findKey(users, { 'age': 1, 'active': true });
* // => 'pebbles'
*
* // The `_.matchesProperty` iteratee shorthand.
* _.findKey(users, ['active', false]);
* // => 'fred'
*
* // The `_.property` iteratee shorthand.
* _.findKey(users, 'active');
* // => 'barney'
*/
function findKey(object, predicate) {
return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
}
/**
* This method is like `_.findKey` except that it iterates over elements of
* a collection in the opposite order.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Object
* @param {Object} object The object to inspect.
* @param {Function} [predicate=_.identity] The function invoked per iteration.
* @returns {string|undefined} Returns the key of the matched element,
* else `undefined`.
* @example
*
* var users = {
* 'barney': { 'age': 36, 'active': true },
* 'fred': { 'age': 40, 'active': false },
* 'pebbles': { 'age': 1, 'active': true }
* };
*
* _.findLastKey(users, function(o) { return o.age < 40; });
* // => returns 'pebbles' assuming `_.findKey` returns 'barney'
*
* // The `_.matches` iteratee shorthand.
* _.findLastKey(users, { 'age': 36, 'active': true });
* // => 'barney'
*
* // The `_.matchesProperty` iteratee shorthand.
* _.findLastKey(users, ['active', false]);
* // => 'fred'
*
* // The `_.property` iteratee shorthand.
* _.findLastKey(users, 'active');
* // => 'pebbles'
*/
function findLastKey(object, predicate) {
return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
}
/**
* Iterates over own and inherited enumerable string keyed properties of an
* object and invokes `iteratee` for each property. The iteratee is invoked
* with three arguments: (value, key, object). Iteratee functions may exit
* iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @since 0.3.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Object} Returns `object`.
* @see _.forInRight
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.forIn(new Foo, function(value, key) {
* console.log(key);
* });
* // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
*/
function forIn(object, iteratee) {
return object == null
? object
: baseFor(object, getIteratee(iteratee, 3), keysIn);
}
/**
* This method is like `_.forIn` except that it iterates over properties of
* `object` in the opposite order.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Object} Returns `object`.
* @see _.forIn
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.forInRight(new Foo, function(value, key) {
* console.log(key);
* });
* // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
*/
function forInRight(object, iteratee) {
return object == null
? object
: baseForRight(object, getIteratee(iteratee, 3), keysIn);
}
/**
* Iterates over own enumerable string keyed properties of an object and
* invokes `iteratee` for each property. The iteratee is invoked with three
* arguments: (value, key, object). Iteratee functions may exit iteration
* early by explicitly returning `false`.
*
* @static
* @memberOf _
* @since 0.3.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Object} Returns `object`.
* @see _.forOwnRight
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.forOwn(new Foo, function(value, key) {
* console.log(key);
* });
* // => Logs 'a' then 'b' (iteration order is not guaranteed).
*/
function forOwn(object, iteratee) {
return object && baseForOwn(object, getIteratee(iteratee, 3));
}
/**
* This method is like `_.forOwn` except that it iterates over properties of
* `object` in the opposite order.
*
* @static
* @memberOf _
* @since 2.0.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Object} Returns `object`.
* @see _.forOwn
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.forOwnRight(new Foo, function(value, key) {
* console.log(key);
* });
* // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
*/
function forOwnRight(object, iteratee) {
return object && baseForOwnRight(object, getIteratee(iteratee, 3));
}
/**
* Creates an array of function property names from own enumerable properties
* of `object`.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The object to inspect.
* @returns {Array} Returns the function names.
* @see _.functionsIn
* @example
*
* function Foo() {
* this.a = _.constant('a');
* this.b = _.constant('b');
* }
*
* Foo.prototype.c = _.constant('c');
*
* _.functions(new Foo);
* // => ['a', 'b']
*/
function functions(object) {
return object == null ? [] : baseFunctions(object, keys(object));
}
/**
* Creates an array of function property names from own and inherited
* enumerable properties of `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The object to inspect.
* @returns {Array} Returns the function names.
* @see _.functions
* @example
*
* function Foo() {
* this.a = _.constant('a');
* this.b = _.constant('b');
* }
*
* Foo.prototype.c = _.constant('c');
*
* _.functionsIn(new Foo);
* // => ['a', 'b', 'c']
*/
function functionsIn(object) {
return object == null ? [] : baseFunctions(object, keysIn(object));
}
/**
* Gets the value at `path` of `object`. If the resolved value is
* `undefined`, the `defaultValue` is returned in its place.
*
* @static
* @memberOf _
* @since 3.7.0
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to get.
* @param {*} [defaultValue] The value returned for `undefined` resolved values.
* @returns {*} Returns the resolved value.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
*
* _.get(object, 'a[0].b.c');
* // => 3
*
* _.get(object, ['a', '0', 'b', 'c']);
* // => 3
*
* _.get(object, 'a.b.c', 'default');
* // => 'default'
*/
function get(object, path, defaultValue) {
var result = object == null ? undefined$1 : baseGet(object, path);
return result === undefined$1 ? defaultValue : result;
}
/**
* Checks if `path` is a direct property of `object`.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path to check.
* @returns {boolean} Returns `true` if `path` exists, else `false`.
* @example
*
* var object = { 'a': { 'b': 2 } };
* var other = _.create({ 'a': _.create({ 'b': 2 }) });
*
* _.has(object, 'a');
* // => true
*
* _.has(object, 'a.b');
* // => true
*
* _.has(object, ['a', 'b']);
* // => true
*
* _.has(other, 'a');
* // => false
*/
function has(object, path) {
return object != null && hasPath(object, path, baseHas);
}
/**
* Checks if `path` is a direct or inherited property of `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path to check.
* @returns {boolean} Returns `true` if `path` exists, else `false`.
* @example
*
* var object = _.create({ 'a': _.create({ 'b': 2 }) });
*
* _.hasIn(object, 'a');
* // => true
*
* _.hasIn(object, 'a.b');
* // => true
*
* _.hasIn(object, ['a', 'b']);
* // => true
*
* _.hasIn(object, 'b');
* // => false
*/
function hasIn(object, path) {
return object != null && hasPath(object, path, baseHasIn);
}
/**
* Creates an object composed of the inverted keys and values of `object`.
* If `object` contains duplicate values, subsequent values overwrite
* property assignments of previous values.
*
* @static
* @memberOf _
* @since 0.7.0
* @category Object
* @param {Object} object The object to invert.
* @returns {Object} Returns the new inverted object.
* @example
*
* var object = { 'a': 1, 'b': 2, 'c': 1 };
*
* _.invert(object);
* // => { '1': 'c', '2': 'b' }
*/
var invert = createInverter(function(result, value, key) {
if (value != null &&
typeof value.toString != 'function') {
value = nativeObjectToString.call(value);
}
result[value] = key;
}, constant(identity));
/**
* This method is like `_.invert` except that the inverted object is generated
* from the results of running each element of `object` thru `iteratee`. The
* corresponding inverted value of each inverted key is an array of keys
* responsible for generating the inverted value. The iteratee is invoked
* with one argument: (value).
*
* @static
* @memberOf _
* @since 4.1.0
* @category Object
* @param {Object} object The object to invert.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {Object} Returns the new inverted object.
* @example
*
* var object = { 'a': 1, 'b': 2, 'c': 1 };
*
* _.invertBy(object);
* // => { '1': ['a', 'c'], '2': ['b'] }
*
* _.invertBy(object, function(value) {
* return 'group' + value;
* });
* // => { 'group1': ['a', 'c'], 'group2': ['b'] }
*/
var invertBy = createInverter(function(result, value, key) {
if (value != null &&
typeof value.toString != 'function') {
value = nativeObjectToString.call(value);
}
if (hasOwnProperty.call(result, value)) {
result[value].push(key);
} else {
result[value] = [key];
}
}, getIteratee);
/**
* Invokes the method at `path` of `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path of the method to invoke.
* @param {...*} [args] The arguments to invoke the method with.
* @returns {*} Returns the result of the invoked method.
* @example
*
* var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
*
* _.invoke(object, 'a[0].b.c.slice', 1, 3);
* // => [2, 3]
*/
var invoke = baseRest(baseInvoke);
/**
* Creates an array of the own enumerable property names of `object`.
*
* **Note:** Non-object values are coerced to objects. See the
* [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
* for more details.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.keys(new Foo);
* // => ['a', 'b'] (iteration order is not guaranteed)
*
* _.keys('hi');
* // => ['0', '1']
*/
function keys(object) {
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}
/**
* Creates an array of the own and inherited enumerable property names of `object`.
*
* **Note:** Non-object values are coerced to objects.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.keysIn(new Foo);
* // => ['a', 'b', 'c'] (iteration order is not guaranteed)
*/
function keysIn(object) {
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
}
/**
* The opposite of `_.mapValues`; this method creates an object with the
* same values as `object` and keys generated by running each own enumerable
* string keyed property of `object` thru `iteratee`. The iteratee is invoked
* with three arguments: (value, key, object).
*
* @static
* @memberOf _
* @since 3.8.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Object} Returns the new mapped object.
* @see _.mapValues
* @example
*
* _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
* return key + value;
* });
* // => { 'a1': 1, 'b2': 2 }
*/
function mapKeys(object, iteratee) {
var result = {};
iteratee = getIteratee(iteratee, 3);
baseForOwn(object, function(value, key, object) {
baseAssignValue(result, iteratee(value, key, object), value);
});
return result;
}
/**
* Creates an object with the same keys as `object` and values generated
* by running each own enumerable string keyed property of `object` thru
* `iteratee`. The iteratee is invoked with three arguments:
* (value, key, object).
*
* @static
* @memberOf _
* @since 2.4.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Object} Returns the new mapped object.
* @see _.mapKeys
* @example
*
* var users = {
* 'fred': { 'user': 'fred', 'age': 40 },
* 'pebbles': { 'user': 'pebbles', 'age': 1 }
* };
*
* _.mapValues(users, function(o) { return o.age; });
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
*
* // The `_.property` iteratee shorthand.
* _.mapValues(users, 'age');
* // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
*/
function mapValues(object, iteratee) {
var result = {};
iteratee = getIteratee(iteratee, 3);
baseForOwn(object, function(value, key, object) {
baseAssignValue(result, key, iteratee(value, key, object));
});
return result;
}
/**
* This method is like `_.assign` except that it recursively merges own and
* inherited enumerable string keyed properties of source objects into the
* destination object. Source properties that resolve to `undefined` are
* skipped if a destination value exists. Array and plain object properties
* are merged recursively. Other objects and value types are overridden by
* assignment. Source objects are applied from left to right. Subsequent
* sources overwrite property assignments of previous sources.
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 0.5.0
* @category Object
* @param {Object} object The destination object.
* @param {...Object} [sources] The source objects.
* @returns {Object} Returns `object`.
* @example
*
* var object = {
* 'a': [{ 'b': 2 }, { 'd': 4 }]
* };
*
* var other = {
* 'a': [{ 'c': 3 }, { 'e': 5 }]
* };
*
* _.merge(object, other);
* // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
*/
var merge = createAssigner(function(object, source, srcIndex) {
baseMerge(object, source, srcIndex);
});
/**
* This method is like `_.merge` except that it accepts `customizer` which
* is invoked to produce the merged values of the destination and source
* properties. If `customizer` returns `undefined`, merging is handled by the
* method instead. The `customizer` is invoked with six arguments:
* (objValue, srcValue, key, object, source, stack).
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The destination object.
* @param {...Object} sources The source objects.
* @param {Function} customizer The function to customize assigned values.
* @returns {Object} Returns `object`.
* @example
*
* function customizer(objValue, srcValue) {
* if (_.isArray(objValue)) {
* return objValue.concat(srcValue);
* }
* }
*
* var object = { 'a': [1], 'b': [2] };
* var other = { 'a': [3], 'b': [4] };
*
* _.mergeWith(object, other, customizer);
* // => { 'a': [1, 3], 'b': [2, 4] }
*/
var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
baseMerge(object, source, srcIndex, customizer);
});
/**
* The opposite of `_.pick`; this method creates an object composed of the
* own and inherited enumerable property paths of `object` that are not omitted.
*
* **Note:** This method is considerably slower than `_.pick`.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The source object.
* @param {...(string|string[])} [paths] The property paths to omit.
* @returns {Object} Returns the new object.
* @example
*
* var object = { 'a': 1, 'b': '2', 'c': 3 };
*
* _.omit(object, ['a', 'c']);
* // => { 'b': '2' }
*/
var omit = flatRest(function(object, paths) {
var result = {};
if (object == null) {
return result;
}
var isDeep = false;
paths = arrayMap(paths, function(path) {
path = castPath(path, object);
isDeep || (isDeep = path.length > 1);
return path;
});
copyObject(object, getAllKeysIn(object), result);
if (isDeep) {
result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
}
var length = paths.length;
while (length--) {
baseUnset(result, paths[length]);
}
return result;
});
/**
* The opposite of `_.pickBy`; this method creates an object composed of
* the own and inherited enumerable string keyed properties of `object` that
* `predicate` doesn't return truthy for. The predicate is invoked with two
* arguments: (value, key).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The source object.
* @param {Function} [predicate=_.identity] The function invoked per property.
* @returns {Object} Returns the new object.
* @example
*
* var object = { 'a': 1, 'b': '2', 'c': 3 };
*
* _.omitBy(object, _.isNumber);
* // => { 'b': '2' }
*/
function omitBy(object, predicate) {
return pickBy(object, negate(getIteratee(predicate)));
}
/**
* Creates an object composed of the picked `object` properties.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The source object.
* @param {...(string|string[])} [paths] The property paths to pick.
* @returns {Object} Returns the new object.
* @example
*
* var object = { 'a': 1, 'b': '2', 'c': 3 };
*
* _.pick(object, ['a', 'c']);
* // => { 'a': 1, 'c': 3 }
*/
var pick = flatRest(function(object, paths) {
return object == null ? {} : basePick(object, paths);
});
/**
* Creates an object composed of the `object` properties `predicate` returns
* truthy for. The predicate is invoked with two arguments: (value, key).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The source object.
* @param {Function} [predicate=_.identity] The function invoked per property.
* @returns {Object} Returns the new object.
* @example
*
* var object = { 'a': 1, 'b': '2', 'c': 3 };
*
* _.pickBy(object, _.isNumber);
* // => { 'a': 1, 'c': 3 }
*/
function pickBy(object, predicate) {
if (object == null) {
return {};
}
var props = arrayMap(getAllKeysIn(object), function(prop) {
return [prop];
});
predicate = getIteratee(predicate);
return basePickBy(object, props, function(value, path) {
return predicate(value, path[0]);
});
}
/**
* This method is like `_.get` except that if the resolved value is a
* function it's invoked with the `this` binding of its parent object and
* its result is returned.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The object to query.
* @param {Array|string} path The path of the property to resolve.
* @param {*} [defaultValue] The value returned for `undefined` resolved values.
* @returns {*} Returns the resolved value.
* @example
*
* var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
*
* _.result(object, 'a[0].b.c1');
* // => 3
*
* _.result(object, 'a[0].b.c2');
* // => 4
*
* _.result(object, 'a[0].b.c3', 'default');
* // => 'default'
*
* _.result(object, 'a[0].b.c3', _.constant('default'));
* // => 'default'
*/
function result(object, path, defaultValue) {
path = castPath(path, object);
var index = -1,
length = path.length;
// Ensure the loop is entered when path is empty.
if (!length) {
length = 1;
object = undefined$1;
}
while (++index < length) {
var value = object == null ? undefined$1 : object[toKey(path[index])];
if (value === undefined$1) {
index = length;
value = defaultValue;
}
object = isFunction(value) ? value.call(object) : value;
}
return object;
}
/**
* Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
* it's created. Arrays are created for missing index properties while objects
* are created for all other missing properties. Use `_.setWith` to customize
* `path` creation.
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 3.7.0
* @category Object
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to set.
* @param {*} value The value to set.
* @returns {Object} Returns `object`.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
*
* _.set(object, 'a[0].b.c', 4);
* console.log(object.a[0].b.c);
* // => 4
*
* _.set(object, ['x', '0', 'y', 'z'], 5);
* console.log(object.x[0].y.z);
* // => 5
*/
function set(object, path, value) {
return object == null ? object : baseSet(object, path, value);
}
/**
* This method is like `_.set` except that it accepts `customizer` which is
* invoked to produce the objects of `path`. If `customizer` returns `undefined`
* path creation is handled by the method instead. The `customizer` is invoked
* with three arguments: (nsValue, key, nsObject).
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to set.
* @param {*} value The value to set.
* @param {Function} [customizer] The function to customize assigned values.
* @returns {Object} Returns `object`.
* @example
*
* var object = {};
*
* _.setWith(object, '[0][1]', 'a', Object);
* // => { '0': { '1': 'a' } }
*/
function setWith(object, path, value, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined$1;
return object == null ? object : baseSet(object, path, value, customizer);
}
/**
* Creates an array of own enumerable string keyed-value pairs for `object`
* which can be consumed by `_.fromPairs`. If `object` is a map or set, its
* entries are returned.
*
* @static
* @memberOf _
* @since 4.0.0
* @alias entries
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the key-value pairs.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.toPairs(new Foo);
* // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
*/
var toPairs = createToPairs(keys);
/**
* Creates an array of own and inherited enumerable string keyed-value pairs
* for `object` which can be consumed by `_.fromPairs`. If `object` is a map
* or set, its entries are returned.
*
* @static
* @memberOf _
* @since 4.0.0
* @alias entriesIn
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the key-value pairs.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.toPairsIn(new Foo);
* // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
*/
var toPairsIn = createToPairs(keysIn);
/**
* An alternative to `_.reduce`; this method transforms `object` to a new
* `accumulator` object which is the result of running each of its own
* enumerable string keyed properties thru `iteratee`, with each invocation
* potentially mutating the `accumulator` object. If `accumulator` is not
* provided, a new object with the same `[[Prototype]]` will be used. The
* iteratee is invoked with four arguments: (accumulator, value, key, object).
* Iteratee functions may exit iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @since 1.3.0
* @category Object
* @param {Object} object The object to iterate over.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @param {*} [accumulator] The custom accumulator value.
* @returns {*} Returns the accumulated value.
* @example
*
* _.transform([2, 3, 4], function(result, n) {
* result.push(n *= n);
* return n % 2 == 0;
* }, []);
* // => [4, 9]
*
* _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
* (result[value] || (result[value] = [])).push(key);
* }, {});
* // => { '1': ['a', 'c'], '2': ['b'] }
*/
function transform(object, iteratee, accumulator) {
var isArr = isArray(object),
isArrLike = isArr || isBuffer(object) || isTypedArray(object);
iteratee = getIteratee(iteratee, 4);
if (accumulator == null) {
var Ctor = object && object.constructor;
if (isArrLike) {
accumulator = isArr ? new Ctor : [];
}
else if (isObject(object)) {
accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
}
else {
accumulator = {};
}
}
(isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
return iteratee(accumulator, value, index, object);
});
return accumulator;
}
/**
* Removes the property at `path` of `object`.
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Object
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to unset.
* @returns {boolean} Returns `true` if the property is deleted, else `false`.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 7 } }] };
* _.unset(object, 'a[0].b.c');
* // => true
*
* console.log(object);
* // => { 'a': [{ 'b': {} }] };
*
* _.unset(object, ['a', '0', 'b', 'c']);
* // => true
*
* console.log(object);
* // => { 'a': [{ 'b': {} }] };
*/
function unset(object, path) {
return object == null ? true : baseUnset(object, path);
}
/**
* This method is like `_.set` except that accepts `updater` to produce the
* value to set. Use `_.updateWith` to customize `path` creation. The `updater`
* is invoked with one argument: (value).
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.6.0
* @category Object
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to set.
* @param {Function} updater The function to produce the updated value.
* @returns {Object} Returns `object`.
* @example
*
* var object = { 'a': [{ 'b': { 'c': 3 } }] };
*
* _.update(object, 'a[0].b.c', function(n) { return n * n; });
* console.log(object.a[0].b.c);
* // => 9
*
* _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
* console.log(object.x[0].y.z);
* // => 0
*/
function update(object, path, updater) {
return object == null ? object : baseUpdate(object, path, castFunction(updater));
}
/**
* This method is like `_.update` except that it accepts `customizer` which is
* invoked to produce the objects of `path`. If `customizer` returns `undefined`
* path creation is handled by the method instead. The `customizer` is invoked
* with three arguments: (nsValue, key, nsObject).
*
* **Note:** This method mutates `object`.
*
* @static
* @memberOf _
* @since 4.6.0
* @category Object
* @param {Object} object The object to modify.
* @param {Array|string} path The path of the property to set.
* @param {Function} updater The function to produce the updated value.
* @param {Function} [customizer] The function to customize assigned values.
* @returns {Object} Returns `object`.
* @example
*
* var object = {};
*
* _.updateWith(object, '[0][1]', _.constant('a'), Object);
* // => { '0': { '1': 'a' } }
*/
function updateWith(object, path, updater, customizer) {
customizer = typeof customizer == 'function' ? customizer : undefined$1;
return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
}
/**
* Creates an array of the own enumerable string keyed property values of `object`.
*
* **Note:** Non-object values are coerced to objects.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property values.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.values(new Foo);
* // => [1, 2] (iteration order is not guaranteed)
*
* _.values('hi');
* // => ['h', 'i']
*/
function values(object) {
return object == null ? [] : baseValues(object, keys(object));
}
/**
* Creates an array of the own and inherited enumerable string keyed property
* values of `object`.
*
* **Note:** Non-object values are coerced to objects.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Object
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property values.
* @example
*
* function Foo() {
* this.a = 1;
* this.b = 2;
* }
*
* Foo.prototype.c = 3;
*
* _.valuesIn(new Foo);
* // => [1, 2, 3] (iteration order is not guaranteed)
*/
function valuesIn(object) {
return object == null ? [] : baseValues(object, keysIn(object));
}
/*------------------------------------------------------------------------*/
/**
* Clamps `number` within the inclusive `lower` and `upper` bounds.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Number
* @param {number} number The number to clamp.
* @param {number} [lower] The lower bound.
* @param {number} upper The upper bound.
* @returns {number} Returns the clamped number.
* @example
*
* _.clamp(-10, -5, 5);
* // => -5
*
* _.clamp(10, -5, 5);
* // => 5
*/
function clamp(number, lower, upper) {
if (upper === undefined$1) {
upper = lower;
lower = undefined$1;
}
if (upper !== undefined$1) {
upper = toNumber(upper);
upper = upper === upper ? upper : 0;
}
if (lower !== undefined$1) {
lower = toNumber(lower);
lower = lower === lower ? lower : 0;
}
return baseClamp(toNumber(number), lower, upper);
}
/**
* Checks if `n` is between `start` and up to, but not including, `end`. If
* `end` is not specified, it's set to `start` with `start` then set to `0`.
* If `start` is greater than `end` the params are swapped to support
* negative ranges.
*
* @static
* @memberOf _
* @since 3.3.0
* @category Number
* @param {number} number The number to check.
* @param {number} [start=0] The start of the range.
* @param {number} end The end of the range.
* @returns {boolean} Returns `true` if `number` is in the range, else `false`.
* @see _.range, _.rangeRight
* @example
*
* _.inRange(3, 2, 4);
* // => true
*
* _.inRange(4, 8);
* // => true
*
* _.inRange(4, 2);
* // => false
*
* _.inRange(2, 2);
* // => false
*
* _.inRange(1.2, 2);
* // => true
*
* _.inRange(5.2, 4);
* // => false
*
* _.inRange(-3, -2, -6);
* // => true
*/
function inRange(number, start, end) {
start = toFinite(start);
if (end === undefined$1) {
end = start;
start = 0;
} else {
end = toFinite(end);
}
number = toNumber(number);
return baseInRange(number, start, end);
}
/**
* Produces a random number between the inclusive `lower` and `upper` bounds.
* If only one argument is provided a number between `0` and the given number
* is returned. If `floating` is `true`, or either `lower` or `upper` are
* floats, a floating-point number is returned instead of an integer.
*
* **Note:** JavaScript follows the IEEE-754 standard for resolving
* floating-point values which can produce unexpected results.
*
* @static
* @memberOf _
* @since 0.7.0
* @category Number
* @param {number} [lower=0] The lower bound.
* @param {number} [upper=1] The upper bound.
* @param {boolean} [floating] Specify returning a floating-point number.
* @returns {number} Returns the random number.
* @example
*
* _.random(0, 5);
* // => an integer between 0 and 5
*
* _.random(5);
* // => also an integer between 0 and 5
*
* _.random(5, true);
* // => a floating-point number between 0 and 5
*
* _.random(1.2, 5.2);
* // => a floating-point number between 1.2 and 5.2
*/
function random(lower, upper, floating) {
if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
upper = floating = undefined$1;
}
if (floating === undefined$1) {
if (typeof upper == 'boolean') {
floating = upper;
upper = undefined$1;
}
else if (typeof lower == 'boolean') {
floating = lower;
lower = undefined$1;
}
}
if (lower === undefined$1 && upper === undefined$1) {
lower = 0;
upper = 1;
}
else {
lower = toFinite(lower);
if (upper === undefined$1) {
upper = lower;
lower = 0;
} else {
upper = toFinite(upper);
}
}
if (lower > upper) {
var temp = lower;
lower = upper;
upper = temp;
}
if (floating || lower % 1 || upper % 1) {
var rand = nativeRandom();
return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
}
return baseRandom(lower, upper);
}
/*------------------------------------------------------------------------*/
/**
* Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the camel cased string.
* @example
*
* _.camelCase('Foo Bar');
* // => 'fooBar'
*
* _.camelCase('--foo-bar--');
* // => 'fooBar'
*
* _.camelCase('__FOO_BAR__');
* // => 'fooBar'
*/
var camelCase = createCompounder(function(result, word, index) {
word = word.toLowerCase();
return result + (index ? capitalize(word) : word);
});
/**
* Converts the first character of `string` to upper case and the remaining
* to lower case.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to capitalize.
* @returns {string} Returns the capitalized string.
* @example
*
* _.capitalize('FRED');
* // => 'Fred'
*/
function capitalize(string) {
return upperFirst(toString(string).toLowerCase());
}
/**
* Deburrs `string` by converting
* [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
* and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
* letters to basic Latin letters and removing
* [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to deburr.
* @returns {string} Returns the deburred string.
* @example
*
* _.deburr('déjà vu');
* // => 'deja vu'
*/
function deburr(string) {
string = toString(string);
return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
}
/**
* Checks if `string` ends with the given target string.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to inspect.
* @param {string} [target] The string to search for.
* @param {number} [position=string.length] The position to search up to.
* @returns {boolean} Returns `true` if `string` ends with `target`,
* else `false`.
* @example
*
* _.endsWith('abc', 'c');
* // => true
*
* _.endsWith('abc', 'b');
* // => false
*
* _.endsWith('abc', 'b', 2);
* // => true
*/
function endsWith(string, target, position) {
string = toString(string);
target = baseToString(target);
var length = string.length;
position = position === undefined$1
? length
: baseClamp(toInteger(position), 0, length);
var end = position;
position -= target.length;
return position >= 0 && string.slice(position, end) == target;
}
/**
* Converts the characters "&", "<", ">", '"', and "'" in `string` to their
* corresponding HTML entities.
*
* **Note:** No other characters are escaped. To escape additional
* characters use a third-party library like [_he_](https://mths.be/he).
*
* Though the ">" character is escaped for symmetry, characters like
* ">" and "/" don't need escaping in HTML and have no special meaning
* unless they're part of a tag or unquoted attribute value. See
* [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
* (under "semi-related fun fact") for more details.
*
* When working with HTML you should always
* [quote attribute values](http://wonko.com/post/html-escaping) to reduce
* XSS vectors.
*
* @static
* @since 0.1.0
* @memberOf _
* @category String
* @param {string} [string=''] The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
* _.escape('fred, barney, & pebbles');
* // => 'fred, barney, &amp; pebbles'
*/
function escape(string) {
string = toString(string);
return (string && reHasUnescapedHtml.test(string))
? string.replace(reUnescapedHtml, escapeHtmlChar)
: string;
}
/**
* Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
* "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
* _.escapeRegExp('[lodash](https://lodash.com/)');
* // => '\[lodash\]\(https://lodash\.com/\)'
*/
function escapeRegExp(string) {
string = toString(string);
return (string && reHasRegExpChar.test(string))
? string.replace(reRegExpChar, '\\$&')
: string;
}
/**
* Converts `string` to
* [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the kebab cased string.
* @example
*
* _.kebabCase('Foo Bar');
* // => 'foo-bar'
*
* _.kebabCase('fooBar');
* // => 'foo-bar'
*
* _.kebabCase('__FOO_BAR__');
* // => 'foo-bar'
*/
var kebabCase = createCompounder(function(result, word, index) {
return result + (index ? '-' : '') + word.toLowerCase();
});
/**
* Converts `string`, as space separated words, to lower case.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the lower cased string.
* @example
*
* _.lowerCase('--Foo-Bar--');
* // => 'foo bar'
*
* _.lowerCase('fooBar');
* // => 'foo bar'
*
* _.lowerCase('__FOO_BAR__');
* // => 'foo bar'
*/
var lowerCase = createCompounder(function(result, word, index) {
return result + (index ? ' ' : '') + word.toLowerCase();
});
/**
* Converts the first character of `string` to lower case.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the converted string.
* @example
*
* _.lowerFirst('Fred');
* // => 'fred'
*
* _.lowerFirst('FRED');
* // => 'fRED'
*/
var lowerFirst = createCaseFirst('toLowerCase');
/**
* Pads `string` on the left and right sides if it's shorter than `length`.
* Padding characters are truncated if they can't be evenly divided by `length`.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to pad.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padded string.
* @example
*
* _.pad('abc', 8);
* // => ' abc '
*
* _.pad('abc', 8, '_-');
* // => '_-abc_-_'
*
* _.pad('abc', 3);
* // => 'abc'
*/
function pad(string, length, chars) {
string = toString(string);
length = toInteger(length);
var strLength = length ? stringSize(string) : 0;
if (!length || strLength >= length) {
return string;
}
var mid = (length - strLength) / 2;
return (
createPadding(nativeFloor(mid), chars) +
string +
createPadding(nativeCeil(mid), chars)
);
}
/**
* Pads `string` on the right side if it's shorter than `length`. Padding
* characters are truncated if they exceed `length`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to pad.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padded string.
* @example
*
* _.padEnd('abc', 6);
* // => 'abc '
*
* _.padEnd('abc', 6, '_-');
* // => 'abc_-_'
*
* _.padEnd('abc', 3);
* // => 'abc'
*/
function padEnd(string, length, chars) {
string = toString(string);
length = toInteger(length);
var strLength = length ? stringSize(string) : 0;
return (length && strLength < length)
? (string + createPadding(length - strLength, chars))
: string;
}
/**
* Pads `string` on the left side if it's shorter than `length`. Padding
* characters are truncated if they exceed `length`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to pad.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padded string.
* @example
*
* _.padStart('abc', 6);
* // => ' abc'
*
* _.padStart('abc', 6, '_-');
* // => '_-_abc'
*
* _.padStart('abc', 3);
* // => 'abc'
*/
function padStart(string, length, chars) {
string = toString(string);
length = toInteger(length);
var strLength = length ? stringSize(string) : 0;
return (length && strLength < length)
? (createPadding(length - strLength, chars) + string)
: string;
}
/**
* Converts `string` to an integer of the specified radix. If `radix` is
* `undefined` or `0`, a `radix` of `10` is used unless `value` is a
* hexadecimal, in which case a `radix` of `16` is used.
*
* **Note:** This method aligns with the
* [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
*
* @static
* @memberOf _
* @since 1.1.0
* @category String
* @param {string} string The string to convert.
* @param {number} [radix=10] The radix to interpret `value` by.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {number} Returns the converted integer.
* @example
*
* _.parseInt('08');
* // => 8
*
* _.map(['6', '08', '10'], _.parseInt);
* // => [6, 8, 10]
*/
function parseInt(string, radix, guard) {
if (guard || radix == null) {
radix = 0;
} else if (radix) {
radix = +radix;
}
return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
}
/**
* Repeats the given string `n` times.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to repeat.
* @param {number} [n=1] The number of times to repeat the string.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {string} Returns the repeated string.
* @example
*
* _.repeat('*', 3);
* // => '***'
*
* _.repeat('abc', 2);
* // => 'abcabc'
*
* _.repeat('abc', 0);
* // => ''
*/
function repeat(string, n, guard) {
if ((guard ? isIterateeCall(string, n, guard) : n === undefined$1)) {
n = 1;
} else {
n = toInteger(n);
}
return baseRepeat(toString(string), n);
}
/**
* Replaces matches for `pattern` in `string` with `replacement`.
*
* **Note:** This method is based on
* [`String#replace`](https://mdn.io/String/replace).
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to modify.
* @param {RegExp|string} pattern The pattern to replace.
* @param {Function|string} replacement The match replacement.
* @returns {string} Returns the modified string.
* @example
*
* _.replace('Hi Fred', 'Fred', 'Barney');
* // => 'Hi Barney'
*/
function replace() {
var args = arguments,
string = toString(args[0]);
return args.length < 3 ? string : string.replace(args[1], args[2]);
}
/**
* Converts `string` to
* [snake case](https://en.wikipedia.org/wiki/Snake_case).
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the snake cased string.
* @example
*
* _.snakeCase('Foo Bar');
* // => 'foo_bar'
*
* _.snakeCase('fooBar');
* // => 'foo_bar'
*
* _.snakeCase('--FOO-BAR--');
* // => 'foo_bar'
*/
var snakeCase = createCompounder(function(result, word, index) {
return result + (index ? '_' : '') + word.toLowerCase();
});
/**
* Splits `string` by `separator`.
*
* **Note:** This method is based on
* [`String#split`](https://mdn.io/String/split).
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to split.
* @param {RegExp|string} separator The separator pattern to split by.
* @param {number} [limit] The length to truncate results to.
* @returns {Array} Returns the string segments.
* @example
*
* _.split('a-b-c', '-', 2);
* // => ['a', 'b']
*/
function split(string, separator, limit) {
if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
separator = limit = undefined$1;
}
limit = limit === undefined$1 ? MAX_ARRAY_LENGTH : limit >>> 0;
if (!limit) {
return [];
}
string = toString(string);
if (string && (
typeof separator == 'string' ||
(separator != null && !isRegExp(separator))
)) {
separator = baseToString(separator);
if (!separator && hasUnicode(string)) {
return castSlice(stringToArray(string), 0, limit);
}
}
return string.split(separator, limit);
}
/**
* Converts `string` to
* [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
*
* @static
* @memberOf _
* @since 3.1.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the start cased string.
* @example
*
* _.startCase('--foo-bar--');
* // => 'Foo Bar'
*
* _.startCase('fooBar');
* // => 'Foo Bar'
*
* _.startCase('__FOO_BAR__');
* // => 'FOO BAR'
*/
var startCase = createCompounder(function(result, word, index) {
return result + (index ? ' ' : '') + upperFirst(word);
});
/**
* Checks if `string` starts with the given target string.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to inspect.
* @param {string} [target] The string to search for.
* @param {number} [position=0] The position to search from.
* @returns {boolean} Returns `true` if `string` starts with `target`,
* else `false`.
* @example
*
* _.startsWith('abc', 'a');
* // => true
*
* _.startsWith('abc', 'b');
* // => false
*
* _.startsWith('abc', 'b', 1);
* // => true
*/
function startsWith(string, target, position) {
string = toString(string);
position = position == null
? 0
: baseClamp(toInteger(position), 0, string.length);
target = baseToString(target);
return string.slice(position, position + target.length) == target;
}
/**
* Creates a compiled template function that can interpolate data properties
* in "interpolate" delimiters, HTML-escape interpolated data properties in
* "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
* properties may be accessed as free variables in the template. If a setting
* object is given, it takes precedence over `_.templateSettings` values.
*
* **Note:** In the development build `_.template` utilizes
* [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* for easier debugging.
*
* For more information on precompiling templates see
* [lodash's custom builds documentation](https://lodash.com/custom-builds).
*
* For more information on Chrome extension sandboxes see
* [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
*
* @static
* @since 0.1.0
* @memberOf _
* @category String
* @param {string} [string=''] The template string.
* @param {Object} [options={}] The options object.
* @param {RegExp} [options.escape=_.templateSettings.escape]
* The HTML "escape" delimiter.
* @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
* The "evaluate" delimiter.
* @param {Object} [options.imports=_.templateSettings.imports]
* An object to import into the template as free variables.
* @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
* The "interpolate" delimiter.
* @param {string} [options.sourceURL='lodash.templateSources[n]']
* The sourceURL of the compiled template.
* @param {string} [options.variable='obj']
* The data object variable name.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Function} Returns the compiled template function.
* @example
*
* // Use the "interpolate" delimiter to create a compiled template.
* var compiled = _.template('hello <%= user %>!');
* compiled({ 'user': 'fred' });
* // => 'hello fred!'
*
* // Use the HTML "escape" delimiter to escape data property values.
* var compiled = _.template('<b><%- value %></b>');
* compiled({ 'value': '<script>' });
* // => '<b>&lt;script&gt;</b>'
*
* // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
* var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
* compiled({ 'users': ['fred', 'barney'] });
* // => '<li>fred</li><li>barney</li>'
*
* // Use the internal `print` function in "evaluate" delimiters.
* var compiled = _.template('<% print("hello " + user); %>!');
* compiled({ 'user': 'barney' });
* // => 'hello barney!'
*
* // Use the ES template literal delimiter as an "interpolate" delimiter.
* // Disable support by replacing the "interpolate" delimiter.
* var compiled = _.template('hello ${ user }!');
* compiled({ 'user': 'pebbles' });
* // => 'hello pebbles!'
*
* // Use backslashes to treat delimiters as plain text.
* var compiled = _.template('<%= "\\<%- value %\\>" %>');
* compiled({ 'value': 'ignored' });
* // => '<%- value %>'
*
* // Use the `imports` option to import `jQuery` as `jq`.
* var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
* var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
* compiled({ 'users': ['fred', 'barney'] });
* // => '<li>fred</li><li>barney</li>'
*
* // Use the `sourceURL` option to specify a custom sourceURL for the template.
* var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
* compiled(data);
* // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
*
* // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
* var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
* compiled.source;
* // => function(data) {
* // var __t, __p = '';
* // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
* // return __p;
* // }
*
* // Use custom template delimiters.
* _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
* var compiled = _.template('hello {{ user }}!');
* compiled({ 'user': 'mustache' });
* // => 'hello mustache!'
*
* // Use the `source` property to inline compiled templates for meaningful
* // line numbers in error messages and stack traces.
* fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
* var JST = {\
* "main": ' + _.template(mainText).source + '\
* };\
* ');
*/
function template(string, options, guard) {
// Based on John Resig's `tmpl` implementation
// (http://ejohn.org/blog/javascript-micro-templating/)
// and Laura Doktorova's doT.js (https://github.com/olado/doT).
var settings = lodash.templateSettings;
if (guard && isIterateeCall(string, options, guard)) {
options = undefined$1;
}
string = toString(string);
options = assignInWith({}, options, settings, customDefaultsAssignIn);
var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
importsKeys = keys(imports),
importsValues = baseValues(imports, importsKeys);
var isEscaping,
isEvaluating,
index = 0,
interpolate = options.interpolate || reNoMatch,
source = "__p += '";
// Compile the regexp to match each delimiter.
var reDelimiters = RegExp(
(options.escape || reNoMatch).source + '|' +
interpolate.source + '|' +
(interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
(options.evaluate || reNoMatch).source + '|$'
, 'g');
// Use a sourceURL for easier debugging.
// The sourceURL gets injected into the source that's eval-ed, so be careful
// to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in
// and escape the comment, thus injecting code that gets evaled.
var sourceURL = '//# sourceURL=' +
(hasOwnProperty.call(options, 'sourceURL')
? (options.sourceURL + '').replace(/\s/g, ' ')
: ('lodash.templateSources[' + (++templateCounter) + ']')
) + '\n';
string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue);
// Escape characters that can't be included in string literals.
source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
// Replace delimiters with snippets.
if (escapeValue) {
isEscaping = true;
source += "' +\n__e(" + escapeValue + ") +\n'";
}
if (evaluateValue) {
isEvaluating = true;
source += "';\n" + evaluateValue + ";\n__p += '";
}
if (interpolateValue) {
source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
}
index = offset + match.length;
// The JS engine embedded in Adobe products needs `match` returned in
// order to produce the correct `offset` value.
return match;
});
source += "';\n";
// If `variable` is not specified wrap a with-statement around the generated
// code to add the data object to the top of the scope chain.
var variable = hasOwnProperty.call(options, 'variable') && options.variable;
if (!variable) {
source = 'with (obj) {\n' + source + '\n}\n';
}
// Throw an error if a forbidden character was found in `variable`, to prevent
// potential command injection attacks.
else if (reForbiddenIdentifierChars.test(variable)) {
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
}
// Cleanup code by stripping empty strings.
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
.replace(reEmptyStringMiddle, '$1')
.replace(reEmptyStringTrailing, '$1;');
// Frame code as the function body.
source = 'function(' + (variable || 'obj') + ') {\n' +
(variable
? ''
: 'obj || (obj = {});\n'
) +
"var __t, __p = ''" +
(isEscaping
? ', __e = _.escape'
: ''
) +
(isEvaluating
? ', __j = Array.prototype.join;\n' +
"function print() { __p += __j.call(arguments, '') }\n"
: ';\n'
) +
source +
'return __p\n}';
var result = attempt(function() {
return Function(importsKeys, sourceURL + 'return ' + source)
.apply(undefined$1, importsValues);
});
// Provide the compiled function's source by its `toString` method or
// the `source` property as a convenience for inlining compiled templates.
result.source = source;
if (isError(result)) {
throw result;
}
return result;
}
/**
* Converts `string`, as a whole, to lower case just like
* [String#toLowerCase](https://mdn.io/toLowerCase).
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the lower cased string.
* @example
*
* _.toLower('--Foo-Bar--');
* // => '--foo-bar--'
*
* _.toLower('fooBar');
* // => 'foobar'
*
* _.toLower('__FOO_BAR__');
* // => '__foo_bar__'
*/
function toLower(value) {
return toString(value).toLowerCase();
}
/**
* Converts `string`, as a whole, to upper case just like
* [String#toUpperCase](https://mdn.io/toUpperCase).
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the upper cased string.
* @example
*
* _.toUpper('--foo-bar--');
* // => '--FOO-BAR--'
*
* _.toUpper('fooBar');
* // => 'FOOBAR'
*
* _.toUpper('__foo_bar__');
* // => '__FOO_BAR__'
*/
function toUpper(value) {
return toString(value).toUpperCase();
}
/**
* Removes leading and trailing whitespace or specified characters from `string`.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to trim.
* @param {string} [chars=whitespace] The characters to trim.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {string} Returns the trimmed string.
* @example
*
* _.trim(' abc ');
* // => 'abc'
*
* _.trim('-_-abc-_-', '_-');
* // => 'abc'
*
* _.map([' foo ', ' bar '], _.trim);
* // => ['foo', 'bar']
*/
function trim(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined$1)) {
return baseTrim(string);
}
if (!string || !(chars = baseToString(chars))) {
return string;
}
var strSymbols = stringToArray(string),
chrSymbols = stringToArray(chars),
start = charsStartIndex(strSymbols, chrSymbols),
end = charsEndIndex(strSymbols, chrSymbols) + 1;
return castSlice(strSymbols, start, end).join('');
}
/**
* Removes trailing whitespace or specified characters from `string`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to trim.
* @param {string} [chars=whitespace] The characters to trim.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {string} Returns the trimmed string.
* @example
*
* _.trimEnd(' abc ');
* // => ' abc'
*
* _.trimEnd('-_-abc-_-', '_-');
* // => '-_-abc'
*/
function trimEnd(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined$1)) {
return string.slice(0, trimmedEndIndex(string) + 1);
}
if (!string || !(chars = baseToString(chars))) {
return string;
}
var strSymbols = stringToArray(string),
end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
return castSlice(strSymbols, 0, end).join('');
}
/**
* Removes leading whitespace or specified characters from `string`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to trim.
* @param {string} [chars=whitespace] The characters to trim.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {string} Returns the trimmed string.
* @example
*
* _.trimStart(' abc ');
* // => 'abc '
*
* _.trimStart('-_-abc-_-', '_-');
* // => 'abc-_-'
*/
function trimStart(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined$1)) {
return string.replace(reTrimStart, '');
}
if (!string || !(chars = baseToString(chars))) {
return string;
}
var strSymbols = stringToArray(string),
start = charsStartIndex(strSymbols, stringToArray(chars));
return castSlice(strSymbols, start).join('');
}
/**
* Truncates `string` if it's longer than the given maximum string length.
* The last characters of the truncated string are replaced with the omission
* string which defaults to "...".
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to truncate.
* @param {Object} [options={}] The options object.
* @param {number} [options.length=30] The maximum string length.
* @param {string} [options.omission='...'] The string to indicate text is omitted.
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
* @returns {string} Returns the truncated string.
* @example
*
* _.truncate('hi-diddly-ho there, neighborino');
* // => 'hi-diddly-ho there, neighbo...'
*
* _.truncate('hi-diddly-ho there, neighborino', {
* 'length': 24,
* 'separator': ' '
* });
* // => 'hi-diddly-ho there,...'
*
* _.truncate('hi-diddly-ho there, neighborino', {
* 'length': 24,
* 'separator': /,? +/
* });
* // => 'hi-diddly-ho there...'
*
* _.truncate('hi-diddly-ho there, neighborino', {
* 'omission': ' [...]'
* });
* // => 'hi-diddly-ho there, neig [...]'
*/
function truncate(string, options) {
var length = DEFAULT_TRUNC_LENGTH,
omission = DEFAULT_TRUNC_OMISSION;
if (isObject(options)) {
var separator = 'separator' in options ? options.separator : separator;
length = 'length' in options ? toInteger(options.length) : length;
omission = 'omission' in options ? baseToString(options.omission) : omission;
}
string = toString(string);
var strLength = string.length;
if (hasUnicode(string)) {
var strSymbols = stringToArray(string);
strLength = strSymbols.length;
}
if (length >= strLength) {
return string;
}
var end = length - stringSize(omission);
if (end < 1) {
return omission;
}
var result = strSymbols
? castSlice(strSymbols, 0, end).join('')
: string.slice(0, end);
if (separator === undefined$1) {
return result + omission;
}
if (strSymbols) {
end += (result.length - end);
}
if (isRegExp(separator)) {
if (string.slice(end).search(separator)) {
var match,
substring = result;
if (!separator.global) {
separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
}
separator.lastIndex = 0;
while ((match = separator.exec(substring))) {
var newEnd = match.index;
}
result = result.slice(0, newEnd === undefined$1 ? end : newEnd);
}
} else if (string.indexOf(baseToString(separator), end) != end) {
var index = result.lastIndexOf(separator);
if (index > -1) {
result = result.slice(0, index);
}
}
return result + omission;
}
/**
* The inverse of `_.escape`; this method converts the HTML entities
* `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
* their corresponding characters.
*
* **Note:** No other HTML entities are unescaped. To unescape additional
* HTML entities use a third-party library like [_he_](https://mths.be/he).
*
* @static
* @memberOf _
* @since 0.6.0
* @category String
* @param {string} [string=''] The string to unescape.
* @returns {string} Returns the unescaped string.
* @example
*
* _.unescape('fred, barney, &amp; pebbles');
* // => 'fred, barney, & pebbles'
*/
function unescape(string) {
string = toString(string);
return (string && reHasEscapedHtml.test(string))
? string.replace(reEscapedHtml, unescapeHtmlChar)
: string;
}
/**
* Converts `string`, as space separated words, to upper case.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the upper cased string.
* @example
*
* _.upperCase('--foo-bar');
* // => 'FOO BAR'
*
* _.upperCase('fooBar');
* // => 'FOO BAR'
*
* _.upperCase('__foo_bar__');
* // => 'FOO BAR'
*/
var upperCase = createCompounder(function(result, word, index) {
return result + (index ? ' ' : '') + word.toUpperCase();
});
/**
* Converts the first character of `string` to upper case.
*
* @static
* @memberOf _
* @since 4.0.0
* @category String
* @param {string} [string=''] The string to convert.
* @returns {string} Returns the converted string.
* @example
*
* _.upperFirst('fred');
* // => 'Fred'
*
* _.upperFirst('FRED');
* // => 'FRED'
*/
var upperFirst = createCaseFirst('toUpperCase');
/**
* Splits `string` into an array of its words.
*
* @static
* @memberOf _
* @since 3.0.0
* @category String
* @param {string} [string=''] The string to inspect.
* @param {RegExp|string} [pattern] The pattern to match words.
* @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
* @returns {Array} Returns the words of `string`.
* @example
*
* _.words('fred, barney, & pebbles');
* // => ['fred', 'barney', 'pebbles']
*
* _.words('fred, barney, & pebbles', /[^, ]+/g);
* // => ['fred', 'barney', '&', 'pebbles']
*/
function words(string, pattern, guard) {
string = toString(string);
pattern = guard ? undefined$1 : pattern;
if (pattern === undefined$1) {
return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
}
return string.match(pattern) || [];
}
/*------------------------------------------------------------------------*/
/**
* Attempts to invoke `func`, returning either the result or the caught error
* object. Any additional arguments are provided to `func` when it's invoked.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Util
* @param {Function} func The function to attempt.
* @param {...*} [args] The arguments to invoke `func` with.
* @returns {*} Returns the `func` result or error object.
* @example
*
* // Avoid throwing errors for invalid selectors.
* var elements = _.attempt(function(selector) {
* return document.querySelectorAll(selector);
* }, '>_>');
*
* if (_.isError(elements)) {
* elements = [];
* }
*/
var attempt = baseRest(function(func, args) {
try {
return apply(func, undefined$1, args);
} catch (e) {
return isError(e) ? e : new Error(e);
}
});
/**
* Binds methods of an object to the object itself, overwriting the existing
* method.
*
* **Note:** This method doesn't set the "length" property of bound functions.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {Object} object The object to bind and assign the bound methods to.
* @param {...(string|string[])} methodNames The object method names to bind.
* @returns {Object} Returns `object`.
* @example
*
* var view = {
* 'label': 'docs',
* 'click': function() {
* console.log('clicked ' + this.label);
* }
* };
*
* _.bindAll(view, ['click']);
* jQuery(element).on('click', view.click);
* // => Logs 'clicked docs' when clicked.
*/
var bindAll = flatRest(function(object, methodNames) {
arrayEach(methodNames, function(key) {
key = toKey(key);
baseAssignValue(object, key, bind(object[key], object));
});
return object;
});
/**
* Creates a function that iterates over `pairs` and invokes the corresponding
* function of the first predicate to return truthy. The predicate-function
* pairs are invoked with the `this` binding and arguments of the created
* function.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {Array} pairs The predicate-function pairs.
* @returns {Function} Returns the new composite function.
* @example
*
* var func = _.cond([
* [_.matches({ 'a': 1 }), _.constant('matches A')],
* [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
* [_.stubTrue, _.constant('no match')]
* ]);
*
* func({ 'a': 1, 'b': 2 });
* // => 'matches A'
*
* func({ 'a': 0, 'b': 1 });
* // => 'matches B'
*
* func({ 'a': '1', 'b': '2' });
* // => 'no match'
*/
function cond(pairs) {
var length = pairs == null ? 0 : pairs.length,
toIteratee = getIteratee();
pairs = !length ? [] : arrayMap(pairs, function(pair) {
if (typeof pair[1] != 'function') {
throw new TypeError(FUNC_ERROR_TEXT);
}
return [toIteratee(pair[0]), pair[1]];
});
return baseRest(function(args) {
var index = -1;
while (++index < length) {
var pair = pairs[index];
if (apply(pair[0], this, args)) {
return apply(pair[1], this, args);
}
}
});
}
/**
* Creates a function that invokes the predicate properties of `source` with
* the corresponding property values of a given object, returning `true` if
* all predicates return truthy, else `false`.
*
* **Note:** The created function is equivalent to `_.conformsTo` with
* `source` partially applied.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {Object} source The object of property predicates to conform to.
* @returns {Function} Returns the new spec function.
* @example
*
* var objects = [
* { 'a': 2, 'b': 1 },
* { 'a': 1, 'b': 2 }
* ];
*
* _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
* // => [{ 'a': 1, 'b': 2 }]
*/
function conforms(source) {
return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
}
/**
* Creates a function that returns `value`.
*
* @static
* @memberOf _
* @since 2.4.0
* @category Util
* @param {*} value The value to return from the new function.
* @returns {Function} Returns the new constant function.
* @example
*
* var objects = _.times(2, _.constant({ 'a': 1 }));
*
* console.log(objects);
* // => [{ 'a': 1 }, { 'a': 1 }]
*
* console.log(objects[0] === objects[1]);
* // => true
*/
function constant(value) {
return function() {
return value;
};
}
/**
* Checks `value` to determine whether a default value should be returned in
* its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
* or `undefined`.
*
* @static
* @memberOf _
* @since 4.14.0
* @category Util
* @param {*} value The value to check.
* @param {*} defaultValue The default value.
* @returns {*} Returns the resolved value.
* @example
*
* _.defaultTo(1, 10);
* // => 1
*
* _.defaultTo(undefined, 10);
* // => 10
*/
function defaultTo(value, defaultValue) {
return (value == null || value !== value) ? defaultValue : value;
}
/**
* Creates a function that returns the result of invoking the given functions
* with the `this` binding of the created function, where each successive
* invocation is supplied the return value of the previous.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Util
* @param {...(Function|Function[])} [funcs] The functions to invoke.
* @returns {Function} Returns the new composite function.
* @see _.flowRight
* @example
*
* function square(n) {
* return n * n;
* }
*
* var addSquare = _.flow([_.add, square]);
* addSquare(1, 2);
* // => 9
*/
var flow = createFlow();
/**
* This method is like `_.flow` except that it creates a function that
* invokes the given functions from right to left.
*
* @static
* @since 3.0.0
* @memberOf _
* @category Util
* @param {...(Function|Function[])} [funcs] The functions to invoke.
* @returns {Function} Returns the new composite function.
* @see _.flow
* @example
*
* function square(n) {
* return n * n;
* }
*
* var addSquare = _.flowRight([square, _.add]);
* addSquare(1, 2);
* // => 9
*/
var flowRight = createFlow(true);
/**
* This method returns the first argument it receives.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {*} value Any value.
* @returns {*} Returns `value`.
* @example
*
* var object = { 'a': 1 };
*
* console.log(_.identity(object) === object);
* // => true
*/
function identity(value) {
return value;
}
/**
* Creates a function that invokes `func` with the arguments of the created
* function. If `func` is a property name, the created function returns the
* property value for a given element. If `func` is an array or object, the
* created function returns `true` for elements that contain the equivalent
* source properties, otherwise it returns `false`.
*
* @static
* @since 4.0.0
* @memberOf _
* @category Util
* @param {*} [func=_.identity] The value to convert to a callback.
* @returns {Function} Returns the callback.
* @example
*
* var users = [
* { 'user': 'barney', 'age': 36, 'active': true },
* { 'user': 'fred', 'age': 40, 'active': false }
* ];
*
* // The `_.matches` iteratee shorthand.
* _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
* // => [{ 'user': 'barney', 'age': 36, 'active': true }]
*
* // The `_.matchesProperty` iteratee shorthand.
* _.filter(users, _.iteratee(['user', 'fred']));
* // => [{ 'user': 'fred', 'age': 40 }]
*
* // The `_.property` iteratee shorthand.
* _.map(users, _.iteratee('user'));
* // => ['barney', 'fred']
*
* // Create custom iteratee shorthands.
* _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
* return !_.isRegExp(func) ? iteratee(func) : function(string) {
* return func.test(string);
* };
* });
*
* _.filter(['abc', 'def'], /ef/);
* // => ['def']
*/
function iteratee(func) {
return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
}
/**
* Creates a function that performs a partial deep comparison between a given
* object and `source`, returning `true` if the given object has equivalent
* property values, else `false`.
*
* **Note:** The created function is equivalent to `_.isMatch` with `source`
* partially applied.
*
* Partial comparisons will match empty array and empty object `source`
* values against any array or object value, respectively. See `_.isEqual`
* for a list of supported value comparisons.
*
* **Note:** Multiple values can be checked by combining several matchers
* using `_.overSome`
*
* @static
* @memberOf _
* @since 3.0.0
* @category Util
* @param {Object} source The object of property values to match.
* @returns {Function} Returns the new spec function.
* @example
*
* var objects = [
* { 'a': 1, 'b': 2, 'c': 3 },
* { 'a': 4, 'b': 5, 'c': 6 }
* ];
*
* _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
* // => [{ 'a': 4, 'b': 5, 'c': 6 }]
*
* // Checking for several possible values
* _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));
* // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
*/
function matches(source) {
return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
}
/**
* Creates a function that performs a partial deep comparison between the
* value at `path` of a given object to `srcValue`, returning `true` if the
* object value is equivalent, else `false`.
*
* **Note:** Partial comparisons will match empty array and empty object
* `srcValue` values against any array or object value, respectively. See
* `_.isEqual` for a list of supported value comparisons.
*
* **Note:** Multiple values can be checked by combining several matchers
* using `_.overSome`
*
* @static
* @memberOf _
* @since 3.2.0
* @category Util
* @param {Array|string} path The path of the property to get.
* @param {*} srcValue The value to match.
* @returns {Function} Returns the new spec function.
* @example
*
* var objects = [
* { 'a': 1, 'b': 2, 'c': 3 },
* { 'a': 4, 'b': 5, 'c': 6 }
* ];
*
* _.find(objects, _.matchesProperty('a', 4));
* // => { 'a': 4, 'b': 5, 'c': 6 }
*
* // Checking for several possible values
* _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));
* // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
*/
function matchesProperty(path, srcValue) {
return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
}
/**
* Creates a function that invokes the method at `path` of a given object.
* Any additional arguments are provided to the invoked method.
*
* @static
* @memberOf _
* @since 3.7.0
* @category Util
* @param {Array|string} path The path of the method to invoke.
* @param {...*} [args] The arguments to invoke the method with.
* @returns {Function} Returns the new invoker function.
* @example
*
* var objects = [
* { 'a': { 'b': _.constant(2) } },
* { 'a': { 'b': _.constant(1) } }
* ];
*
* _.map(objects, _.method('a.b'));
* // => [2, 1]
*
* _.map(objects, _.method(['a', 'b']));
* // => [2, 1]
*/
var method = baseRest(function(path, args) {
return function(object) {
return baseInvoke(object, path, args);
};
});
/**
* The opposite of `_.method`; this method creates a function that invokes
* the method at a given path of `object`. Any additional arguments are
* provided to the invoked method.
*
* @static
* @memberOf _
* @since 3.7.0
* @category Util
* @param {Object} object The object to query.
* @param {...*} [args] The arguments to invoke the method with.
* @returns {Function} Returns the new invoker function.
* @example
*
* var array = _.times(3, _.constant),
* object = { 'a': array, 'b': array, 'c': array };
*
* _.map(['a[2]', 'c[0]'], _.methodOf(object));
* // => [2, 0]
*
* _.map([['a', '2'], ['c', '0']], _.methodOf(object));
* // => [2, 0]
*/
var methodOf = baseRest(function(object, args) {
return function(path) {
return baseInvoke(object, path, args);
};
});
/**
* Adds all own enumerable string keyed function properties of a source
* object to the destination object. If `object` is a function, then methods
* are added to its prototype as well.
*
* **Note:** Use `_.runInContext` to create a pristine `lodash` function to
* avoid conflicts caused by modifying the original.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {Function|Object} [object=lodash] The destination object.
* @param {Object} source The object of functions to add.
* @param {Object} [options={}] The options object.
* @param {boolean} [options.chain=true] Specify whether mixins are chainable.
* @returns {Function|Object} Returns `object`.
* @example
*
* function vowels(string) {
* return _.filter(string, function(v) {
* return /[aeiou]/i.test(v);
* });
* }
*
* _.mixin({ 'vowels': vowels });
* _.vowels('fred');
* // => ['e']
*
* _('fred').vowels().value();
* // => ['e']
*
* _.mixin({ 'vowels': vowels }, { 'chain': false });
* _('fred').vowels();
* // => ['e']
*/
function mixin(object, source, options) {
var props = keys(source),
methodNames = baseFunctions(source, props);
if (options == null &&
!(isObject(source) && (methodNames.length || !props.length))) {
options = source;
source = object;
object = this;
methodNames = baseFunctions(source, keys(source));
}
var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
isFunc = isFunction(object);
arrayEach(methodNames, function(methodName) {
var func = source[methodName];
object[methodName] = func;
if (isFunc) {
object.prototype[methodName] = function() {
var chainAll = this.__chain__;
if (chain || chainAll) {
var result = object(this.__wrapped__),
actions = result.__actions__ = copyArray(this.__actions__);
actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
result.__chain__ = chainAll;
return result;
}
return func.apply(object, arrayPush([this.value()], arguments));
};
}
});
return object;
}
/**
* Reverts the `_` variable to its previous value and returns a reference to
* the `lodash` function.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @returns {Function} Returns the `lodash` function.
* @example
*
* var lodash = _.noConflict();
*/
function noConflict() {
if (root._ === this) {
root._ = oldDash;
}
return this;
}
/**
* This method returns `undefined`.
*
* @static
* @memberOf _
* @since 2.3.0
* @category Util
* @example
*
* _.times(2, _.noop);
* // => [undefined, undefined]
*/
function noop() {
// No operation performed.
}
/**
* Creates a function that gets the argument at index `n`. If `n` is negative,
* the nth argument from the end is returned.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {number} [n=0] The index of the argument to return.
* @returns {Function} Returns the new pass-thru function.
* @example
*
* var func = _.nthArg(1);
* func('a', 'b', 'c', 'd');
* // => 'b'
*
* var func = _.nthArg(-2);
* func('a', 'b', 'c', 'd');
* // => 'c'
*/
function nthArg(n) {
n = toInteger(n);
return baseRest(function(args) {
return baseNth(args, n);
});
}
/**
* Creates a function that invokes `iteratees` with the arguments it receives
* and returns their results.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {...(Function|Function[])} [iteratees=[_.identity]]
* The iteratees to invoke.
* @returns {Function} Returns the new function.
* @example
*
* var func = _.over([Math.max, Math.min]);
*
* func(1, 2, 3, 4);
* // => [4, 1]
*/
var over = createOver(arrayMap);
/**
* Creates a function that checks if **all** of the `predicates` return
* truthy when invoked with the arguments it receives.
*
* Following shorthands are possible for providing predicates.
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {...(Function|Function[])} [predicates=[_.identity]]
* The predicates to check.
* @returns {Function} Returns the new function.
* @example
*
* var func = _.overEvery([Boolean, isFinite]);
*
* func('1');
* // => true
*
* func(null);
* // => false
*
* func(NaN);
* // => false
*/
var overEvery = createOver(arrayEvery);
/**
* Creates a function that checks if **any** of the `predicates` return
* truthy when invoked with the arguments it receives.
*
* Following shorthands are possible for providing predicates.
* Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
* Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {...(Function|Function[])} [predicates=[_.identity]]
* The predicates to check.
* @returns {Function} Returns the new function.
* @example
*
* var func = _.overSome([Boolean, isFinite]);
*
* func('1');
* // => true
*
* func(null);
* // => true
*
* func(NaN);
* // => false
*
* var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
* var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
*/
var overSome = createOver(arraySome);
/**
* Creates a function that returns the value at `path` of a given object.
*
* @static
* @memberOf _
* @since 2.4.0
* @category Util
* @param {Array|string} path The path of the property to get.
* @returns {Function} Returns the new accessor function.
* @example
*
* var objects = [
* { 'a': { 'b': 2 } },
* { 'a': { 'b': 1 } }
* ];
*
* _.map(objects, _.property('a.b'));
* // => [2, 1]
*
* _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
* // => [1, 2]
*/
function property(path) {
return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
}
/**
* The opposite of `_.property`; this method creates a function that returns
* the value at a given path of `object`.
*
* @static
* @memberOf _
* @since 3.0.0
* @category Util
* @param {Object} object The object to query.
* @returns {Function} Returns the new accessor function.
* @example
*
* var array = [0, 1, 2],
* object = { 'a': array, 'b': array, 'c': array };
*
* _.map(['a[2]', 'c[0]'], _.propertyOf(object));
* // => [2, 0]
*
* _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
* // => [2, 0]
*/
function propertyOf(object) {
return function(path) {
return object == null ? undefined$1 : baseGet(object, path);
};
}
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to, but not including, `end`. A step of `-1` is used if a negative
* `start` is specified without an `end` or `step`. If `end` is not specified,
* it's set to `start` with `start` then set to `0`.
*
* **Note:** JavaScript follows the IEEE-754 standard for resolving
* floating-point values which can produce unexpected results.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {number} [start=0] The start of the range.
* @param {number} end The end of the range.
* @param {number} [step=1] The value to increment or decrement by.
* @returns {Array} Returns the range of numbers.
* @see _.inRange, _.rangeRight
* @example
*
* _.range(4);
* // => [0, 1, 2, 3]
*
* _.range(-4);
* // => [0, -1, -2, -3]
*
* _.range(1, 5);
* // => [1, 2, 3, 4]
*
* _.range(0, 20, 5);
* // => [0, 5, 10, 15]
*
* _.range(0, -4, -1);
* // => [0, -1, -2, -3]
*
* _.range(1, 4, 0);
* // => [1, 1, 1]
*
* _.range(0);
* // => []
*/
var range = createRange();
/**
* This method is like `_.range` except that it populates values in
* descending order.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {number} [start=0] The start of the range.
* @param {number} end The end of the range.
* @param {number} [step=1] The value to increment or decrement by.
* @returns {Array} Returns the range of numbers.
* @see _.inRange, _.range
* @example
*
* _.rangeRight(4);
* // => [3, 2, 1, 0]
*
* _.rangeRight(-4);
* // => [-3, -2, -1, 0]
*
* _.rangeRight(1, 5);
* // => [4, 3, 2, 1]
*
* _.rangeRight(0, 20, 5);
* // => [15, 10, 5, 0]
*
* _.rangeRight(0, -4, -1);
* // => [-3, -2, -1, 0]
*
* _.rangeRight(1, 4, 0);
* // => [1, 1, 1]
*
* _.rangeRight(0);
* // => []
*/
var rangeRight = createRange(true);
/**
* This method returns a new empty array.
*
* @static
* @memberOf _
* @since 4.13.0
* @category Util
* @returns {Array} Returns the new empty array.
* @example
*
* var arrays = _.times(2, _.stubArray);
*
* console.log(arrays);
* // => [[], []]
*
* console.log(arrays[0] === arrays[1]);
* // => false
*/
function stubArray() {
return [];
}
/**
* This method returns `false`.
*
* @static
* @memberOf _
* @since 4.13.0
* @category Util
* @returns {boolean} Returns `false`.
* @example
*
* _.times(2, _.stubFalse);
* // => [false, false]
*/
function stubFalse() {
return false;
}
/**
* This method returns a new empty object.
*
* @static
* @memberOf _
* @since 4.13.0
* @category Util
* @returns {Object} Returns the new empty object.
* @example
*
* var objects = _.times(2, _.stubObject);
*
* console.log(objects);
* // => [{}, {}]
*
* console.log(objects[0] === objects[1]);
* // => false
*/
function stubObject() {
return {};
}
/**
* This method returns an empty string.
*
* @static
* @memberOf _
* @since 4.13.0
* @category Util
* @returns {string} Returns the empty string.
* @example
*
* _.times(2, _.stubString);
* // => ['', '']
*/
function stubString() {
return '';
}
/**
* This method returns `true`.
*
* @static
* @memberOf _
* @since 4.13.0
* @category Util
* @returns {boolean} Returns `true`.
* @example
*
* _.times(2, _.stubTrue);
* // => [true, true]
*/
function stubTrue() {
return true;
}
/**
* Invokes the iteratee `n` times, returning an array of the results of
* each invocation. The iteratee is invoked with one argument; (index).
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {number} n The number of times to invoke `iteratee`.
* @param {Function} [iteratee=_.identity] The function invoked per iteration.
* @returns {Array} Returns the array of results.
* @example
*
* _.times(3, String);
* // => ['0', '1', '2']
*
* _.times(4, _.constant(0));
* // => [0, 0, 0, 0]
*/
function times(n, iteratee) {
n = toInteger(n);
if (n < 1 || n > MAX_SAFE_INTEGER) {
return [];
}
var index = MAX_ARRAY_LENGTH,
length = nativeMin(n, MAX_ARRAY_LENGTH);
iteratee = getIteratee(iteratee);
n -= MAX_ARRAY_LENGTH;
var result = baseTimes(length, iteratee);
while (++index < n) {
iteratee(index);
}
return result;
}
/**
* Converts `value` to a property path array.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Util
* @param {*} value The value to convert.
* @returns {Array} Returns the new property path array.
* @example
*
* _.toPath('a.b.c');
* // => ['a', 'b', 'c']
*
* _.toPath('a[0].b.c');
* // => ['a', '0', 'b', 'c']
*/
function toPath(value) {
if (isArray(value)) {
return arrayMap(value, toKey);
}
return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
}
/**
* Generates a unique ID. If `prefix` is given, the ID is appended to it.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Util
* @param {string} [prefix=''] The value to prefix the ID with.
* @returns {string} Returns the unique ID.
* @example
*
* _.uniqueId('contact_');
* // => 'contact_104'
*
* _.uniqueId();
* // => '105'
*/
function uniqueId(prefix) {
var id = ++idCounter;
return toString(prefix) + id;
}
/*------------------------------------------------------------------------*/
/**
* Adds two numbers.
*
* @static
* @memberOf _
* @since 3.4.0
* @category Math
* @param {number} augend The first number in an addition.
* @param {number} addend The second number in an addition.
* @returns {number} Returns the total.
* @example
*
* _.add(6, 4);
* // => 10
*/
var add = createMathOperation(function(augend, addend) {
return augend + addend;
}, 0);
/**
* Computes `number` rounded up to `precision`.
*
* @static
* @memberOf _
* @since 3.10.0
* @category Math
* @param {number} number The number to round up.
* @param {number} [precision=0] The precision to round up to.
* @returns {number} Returns the rounded up number.
* @example
*
* _.ceil(4.006);
* // => 5
*
* _.ceil(6.004, 2);
* // => 6.01
*
* _.ceil(6040, -2);
* // => 6100
*/
var ceil = createRound('ceil');
/**
* Divide two numbers.
*
* @static
* @memberOf _
* @since 4.7.0
* @category Math
* @param {number} dividend The first number in a division.
* @param {number} divisor The second number in a division.
* @returns {number} Returns the quotient.
* @example
*
* _.divide(6, 4);
* // => 1.5
*/
var divide = createMathOperation(function(dividend, divisor) {
return dividend / divisor;
}, 1);
/**
* Computes `number` rounded down to `precision`.
*
* @static
* @memberOf _
* @since 3.10.0
* @category Math
* @param {number} number The number to round down.
* @param {number} [precision=0] The precision to round down to.
* @returns {number} Returns the rounded down number.
* @example
*
* _.floor(4.006);
* // => 4
*
* _.floor(0.046, 2);
* // => 0.04
*
* _.floor(4060, -2);
* // => 4000
*/
var floor = createRound('floor');
/**
* Computes the maximum value of `array`. If `array` is empty or falsey,
* `undefined` is returned.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Math
* @param {Array} array The array to iterate over.
* @returns {*} Returns the maximum value.
* @example
*
* _.max([4, 2, 8, 6]);
* // => 8
*
* _.max([]);
* // => undefined
*/
function max(array) {
return (array && array.length)
? baseExtremum(array, identity, baseGt)
: undefined$1;
}
/**
* This method is like `_.max` except that it accepts `iteratee` which is
* invoked for each element in `array` to generate the criterion by which
* the value is ranked. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Math
* @param {Array} array The array to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {*} Returns the maximum value.
* @example
*
* var objects = [{ 'n': 1 }, { 'n': 2 }];
*
* _.maxBy(objects, function(o) { return o.n; });
* // => { 'n': 2 }
*
* // The `_.property` iteratee shorthand.
* _.maxBy(objects, 'n');
* // => { 'n': 2 }
*/
function maxBy(array, iteratee) {
return (array && array.length)
? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
: undefined$1;
}
/**
* Computes the mean of the values in `array`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Math
* @param {Array} array The array to iterate over.
* @returns {number} Returns the mean.
* @example
*
* _.mean([4, 2, 8, 6]);
* // => 5
*/
function mean(array) {
return baseMean(array, identity);
}
/**
* This method is like `_.mean` except that it accepts `iteratee` which is
* invoked for each element in `array` to generate the value to be averaged.
* The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.7.0
* @category Math
* @param {Array} array The array to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {number} Returns the mean.
* @example
*
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
*
* _.meanBy(objects, function(o) { return o.n; });
* // => 5
*
* // The `_.property` iteratee shorthand.
* _.meanBy(objects, 'n');
* // => 5
*/
function meanBy(array, iteratee) {
return baseMean(array, getIteratee(iteratee, 2));
}
/**
* Computes the minimum value of `array`. If `array` is empty or falsey,
* `undefined` is returned.
*
* @static
* @since 0.1.0
* @memberOf _
* @category Math
* @param {Array} array The array to iterate over.
* @returns {*} Returns the minimum value.
* @example
*
* _.min([4, 2, 8, 6]);
* // => 2
*
* _.min([]);
* // => undefined
*/
function min(array) {
return (array && array.length)
? baseExtremum(array, identity, baseLt)
: undefined$1;
}
/**
* This method is like `_.min` except that it accepts `iteratee` which is
* invoked for each element in `array` to generate the criterion by which
* the value is ranked. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Math
* @param {Array} array The array to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {*} Returns the minimum value.
* @example
*
* var objects = [{ 'n': 1 }, { 'n': 2 }];
*
* _.minBy(objects, function(o) { return o.n; });
* // => { 'n': 1 }
*
* // The `_.property` iteratee shorthand.
* _.minBy(objects, 'n');
* // => { 'n': 1 }
*/
function minBy(array, iteratee) {
return (array && array.length)
? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
: undefined$1;
}
/**
* Multiply two numbers.
*
* @static
* @memberOf _
* @since 4.7.0
* @category Math
* @param {number} multiplier The first number in a multiplication.
* @param {number} multiplicand The second number in a multiplication.
* @returns {number} Returns the product.
* @example
*
* _.multiply(6, 4);
* // => 24
*/
var multiply = createMathOperation(function(multiplier, multiplicand) {
return multiplier * multiplicand;
}, 1);
/**
* Computes `number` rounded to `precision`.
*
* @static
* @memberOf _
* @since 3.10.0
* @category Math
* @param {number} number The number to round.
* @param {number} [precision=0] The precision to round to.
* @returns {number} Returns the rounded number.
* @example
*
* _.round(4.006);
* // => 4
*
* _.round(4.006, 2);
* // => 4.01
*
* _.round(4060, -2);
* // => 4100
*/
var round = createRound('round');
/**
* Subtract two numbers.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Math
* @param {number} minuend The first number in a subtraction.
* @param {number} subtrahend The second number in a subtraction.
* @returns {number} Returns the difference.
* @example
*
* _.subtract(6, 4);
* // => 2
*/
var subtract = createMathOperation(function(minuend, subtrahend) {
return minuend - subtrahend;
}, 0);
/**
* Computes the sum of the values in `array`.
*
* @static
* @memberOf _
* @since 3.4.0
* @category Math
* @param {Array} array The array to iterate over.
* @returns {number} Returns the sum.
* @example
*
* _.sum([4, 2, 8, 6]);
* // => 20
*/
function sum(array) {
return (array && array.length)
? baseSum(array, identity)
: 0;
}
/**
* This method is like `_.sum` except that it accepts `iteratee` which is
* invoked for each element in `array` to generate the value to be summed.
* The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Math
* @param {Array} array The array to iterate over.
* @param {Function} [iteratee=_.identity] The iteratee invoked per element.
* @returns {number} Returns the sum.
* @example
*
* var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
*
* _.sumBy(objects, function(o) { return o.n; });
* // => 20
*
* // The `_.property` iteratee shorthand.
* _.sumBy(objects, 'n');
* // => 20
*/
function sumBy(array, iteratee) {
return (array && array.length)
? baseSum(array, getIteratee(iteratee, 2))
: 0;
}
/*------------------------------------------------------------------------*/
// Add methods that return wrapped values in chain sequences.
lodash.after = after;
lodash.ary = ary;
lodash.assign = assign;
lodash.assignIn = assignIn;
lodash.assignInWith = assignInWith;
lodash.assignWith = assignWith;
lodash.at = at;
lodash.before = before;
lodash.bind = bind;
lodash.bindAll = bindAll;
lodash.bindKey = bindKey;
lodash.castArray = castArray;
lodash.chain = chain;
lodash.chunk = chunk;
lodash.compact = compact;
lodash.concat = concat;
lodash.cond = cond;
lodash.conforms = conforms;
lodash.constant = constant;
lodash.countBy = countBy;
lodash.create = create;
lodash.curry = curry;
lodash.curryRight = curryRight;
lodash.debounce = debounce;
lodash.defaults = defaults;
lodash.defaultsDeep = defaultsDeep;
lodash.defer = defer;
lodash.delay = delay;
lodash.difference = difference;
lodash.differenceBy = differenceBy;
lodash.differenceWith = differenceWith;
lodash.drop = drop;
lodash.dropRight = dropRight;
lodash.dropRightWhile = dropRightWhile;
lodash.dropWhile = dropWhile;
lodash.fill = fill;
lodash.filter = filter;
lodash.flatMap = flatMap;
lodash.flatMapDeep = flatMapDeep;
lodash.flatMapDepth = flatMapDepth;
lodash.flatten = flatten;
lodash.flattenDeep = flattenDeep;
lodash.flattenDepth = flattenDepth;
lodash.flip = flip;
lodash.flow = flow;
lodash.flowRight = flowRight;
lodash.fromPairs = fromPairs;
lodash.functions = functions;
lodash.functionsIn = functionsIn;
lodash.groupBy = groupBy;
lodash.initial = initial;
lodash.intersection = intersection;
lodash.intersectionBy = intersectionBy;
lodash.intersectionWith = intersectionWith;
lodash.invert = invert;
lodash.invertBy = invertBy;
lodash.invokeMap = invokeMap;
lodash.iteratee = iteratee;
lodash.keyBy = keyBy;
lodash.keys = keys;
lodash.keysIn = keysIn;
lodash.map = map;
lodash.mapKeys = mapKeys;
lodash.mapValues = mapValues;
lodash.matches = matches;
lodash.matchesProperty = matchesProperty;
lodash.memoize = memoize;
lodash.merge = merge;
lodash.mergeWith = mergeWith;
lodash.method = method;
lodash.methodOf = methodOf;
lodash.mixin = mixin;
lodash.negate = negate;
lodash.nthArg = nthArg;
lodash.omit = omit;
lodash.omitBy = omitBy;
lodash.once = once;
lodash.orderBy = orderBy;
lodash.over = over;
lodash.overArgs = overArgs;
lodash.overEvery = overEvery;
lodash.overSome = overSome;
lodash.partial = partial;
lodash.partialRight = partialRight;
lodash.partition = partition;
lodash.pick = pick;
lodash.pickBy = pickBy;
lodash.property = property;
lodash.propertyOf = propertyOf;
lodash.pull = pull;
lodash.pullAll = pullAll;
lodash.pullAllBy = pullAllBy;
lodash.pullAllWith = pullAllWith;
lodash.pullAt = pullAt;
lodash.range = range;
lodash.rangeRight = rangeRight;
lodash.rearg = rearg;
lodash.reject = reject;
lodash.remove = remove;
lodash.rest = rest;
lodash.reverse = reverse;
lodash.sampleSize = sampleSize;
lodash.set = set;
lodash.setWith = setWith;
lodash.shuffle = shuffle;
lodash.slice = slice;
lodash.sortBy = sortBy;
lodash.sortedUniq = sortedUniq;
lodash.sortedUniqBy = sortedUniqBy;
lodash.split = split;
lodash.spread = spread;
lodash.tail = tail;
lodash.take = take;
lodash.takeRight = takeRight;
lodash.takeRightWhile = takeRightWhile;
lodash.takeWhile = takeWhile;
lodash.tap = tap;
lodash.throttle = throttle;
lodash.thru = thru;
lodash.toArray = toArray;
lodash.toPairs = toPairs;
lodash.toPairsIn = toPairsIn;
lodash.toPath = toPath;
lodash.toPlainObject = toPlainObject;
lodash.transform = transform;
lodash.unary = unary;
lodash.union = union;
lodash.unionBy = unionBy;
lodash.unionWith = unionWith;
lodash.uniq = uniq;
lodash.uniqBy = uniqBy;
lodash.uniqWith = uniqWith;
lodash.unset = unset;
lodash.unzip = unzip;
lodash.unzipWith = unzipWith;
lodash.update = update;
lodash.updateWith = updateWith;
lodash.values = values;
lodash.valuesIn = valuesIn;
lodash.without = without;
lodash.words = words;
lodash.wrap = wrap;
lodash.xor = xor;
lodash.xorBy = xorBy;
lodash.xorWith = xorWith;
lodash.zip = zip;
lodash.zipObject = zipObject;
lodash.zipObjectDeep = zipObjectDeep;
lodash.zipWith = zipWith;
// Add aliases.
lodash.entries = toPairs;
lodash.entriesIn = toPairsIn;
lodash.extend = assignIn;
lodash.extendWith = assignInWith;
// Add methods to `lodash.prototype`.
mixin(lodash, lodash);
/*------------------------------------------------------------------------*/
// Add methods that return unwrapped values in chain sequences.
lodash.add = add;
lodash.attempt = attempt;
lodash.camelCase = camelCase;
lodash.capitalize = capitalize;
lodash.ceil = ceil;
lodash.clamp = clamp;
lodash.clone = clone;
lodash.cloneDeep = cloneDeep;
lodash.cloneDeepWith = cloneDeepWith;
lodash.cloneWith = cloneWith;
lodash.conformsTo = conformsTo;
lodash.deburr = deburr;
lodash.defaultTo = defaultTo;
lodash.divide = divide;
lodash.endsWith = endsWith;
lodash.eq = eq;
lodash.escape = escape;
lodash.escapeRegExp = escapeRegExp;
lodash.every = every;
lodash.find = find;
lodash.findIndex = findIndex;
lodash.findKey = findKey;
lodash.findLast = findLast;
lodash.findLastIndex = findLastIndex;
lodash.findLastKey = findLastKey;
lodash.floor = floor;
lodash.forEach = forEach;
lodash.forEachRight = forEachRight;
lodash.forIn = forIn;
lodash.forInRight = forInRight;
lodash.forOwn = forOwn;
lodash.forOwnRight = forOwnRight;
lodash.get = get;
lodash.gt = gt;
lodash.gte = gte;
lodash.has = has;
lodash.hasIn = hasIn;
lodash.head = head;
lodash.identity = identity;
lodash.includes = includes;
lodash.indexOf = indexOf;
lodash.inRange = inRange;
lodash.invoke = invoke;
lodash.isArguments = isArguments;
lodash.isArray = isArray;
lodash.isArrayBuffer = isArrayBuffer;
lodash.isArrayLike = isArrayLike;
lodash.isArrayLikeObject = isArrayLikeObject;
lodash.isBoolean = isBoolean;
lodash.isBuffer = isBuffer;
lodash.isDate = isDate;
lodash.isElement = isElement;
lodash.isEmpty = isEmpty;
lodash.isEqual = isEqual;
lodash.isEqualWith = isEqualWith;
lodash.isError = isError;
lodash.isFinite = isFinite;
lodash.isFunction = isFunction;
lodash.isInteger = isInteger;
lodash.isLength = isLength;
lodash.isMap = isMap;
lodash.isMatch = isMatch;
lodash.isMatchWith = isMatchWith;
lodash.isNaN = isNaN;
lodash.isNative = isNative;
lodash.isNil = isNil;
lodash.isNull = isNull;
lodash.isNumber = isNumber;
lodash.isObject = isObject;
lodash.isObjectLike = isObjectLike;
lodash.isPlainObject = isPlainObject;
lodash.isRegExp = isRegExp;
lodash.isSafeInteger = isSafeInteger;
lodash.isSet = isSet;
lodash.isString = isString;
lodash.isSymbol = isSymbol;
lodash.isTypedArray = isTypedArray;
lodash.isUndefined = isUndefined;
lodash.isWeakMap = isWeakMap;
lodash.isWeakSet = isWeakSet;
lodash.join = join;
lodash.kebabCase = kebabCase;
lodash.last = last;
lodash.lastIndexOf = lastIndexOf;
lodash.lowerCase = lowerCase;
lodash.lowerFirst = lowerFirst;
lodash.lt = lt;
lodash.lte = lte;
lodash.max = max;
lodash.maxBy = maxBy;
lodash.mean = mean;
lodash.meanBy = meanBy;
lodash.min = min;
lodash.minBy = minBy;
lodash.stubArray = stubArray;
lodash.stubFalse = stubFalse;
lodash.stubObject = stubObject;
lodash.stubString = stubString;
lodash.stubTrue = stubTrue;
lodash.multiply = multiply;
lodash.nth = nth;
lodash.noConflict = noConflict;
lodash.noop = noop;
lodash.now = now;
lodash.pad = pad;
lodash.padEnd = padEnd;
lodash.padStart = padStart;
lodash.parseInt = parseInt;
lodash.random = random;
lodash.reduce = reduce;
lodash.reduceRight = reduceRight;
lodash.repeat = repeat;
lodash.replace = replace;
lodash.result = result;
lodash.round = round;
lodash.runInContext = runInContext;
lodash.sample = sample;
lodash.size = size;
lodash.snakeCase = snakeCase;
lodash.some = some;
lodash.sortedIndex = sortedIndex;
lodash.sortedIndexBy = sortedIndexBy;
lodash.sortedIndexOf = sortedIndexOf;
lodash.sortedLastIndex = sortedLastIndex;
lodash.sortedLastIndexBy = sortedLastIndexBy;
lodash.sortedLastIndexOf = sortedLastIndexOf;
lodash.startCase = startCase;
lodash.startsWith = startsWith;
lodash.subtract = subtract;
lodash.sum = sum;
lodash.sumBy = sumBy;
lodash.template = template;
lodash.times = times;
lodash.toFinite = toFinite;
lodash.toInteger = toInteger;
lodash.toLength = toLength;
lodash.toLower = toLower;
lodash.toNumber = toNumber;
lodash.toSafeInteger = toSafeInteger;
lodash.toString = toString;
lodash.toUpper = toUpper;
lodash.trim = trim;
lodash.trimEnd = trimEnd;
lodash.trimStart = trimStart;
lodash.truncate = truncate;
lodash.unescape = unescape;
lodash.uniqueId = uniqueId;
lodash.upperCase = upperCase;
lodash.upperFirst = upperFirst;
// Add aliases.
lodash.each = forEach;
lodash.eachRight = forEachRight;
lodash.first = head;
mixin(lodash, (function() {
var source = {};
baseForOwn(lodash, function(func, methodName) {
if (!hasOwnProperty.call(lodash.prototype, methodName)) {
source[methodName] = func;
}
});
return source;
}()), { 'chain': false });
/*------------------------------------------------------------------------*/
/**
* The semantic version number.
*
* @static
* @memberOf _
* @type {string}
*/
lodash.VERSION = VERSION;
// Assign default placeholders.
arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
lodash[methodName].placeholder = lodash;
});
// Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
arrayEach(['drop', 'take'], function(methodName, index) {
LazyWrapper.prototype[methodName] = function(n) {
n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0);
var result = (this.__filtered__ && !index)
? new LazyWrapper(this)
: this.clone();
if (result.__filtered__) {
result.__takeCount__ = nativeMin(n, result.__takeCount__);
} else {
result.__views__.push({
'size': nativeMin(n, MAX_ARRAY_LENGTH),
'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
});
}
return result;
};
LazyWrapper.prototype[methodName + 'Right'] = function(n) {
return this.reverse()[methodName](n).reverse();
};
});
// Add `LazyWrapper` methods that accept an `iteratee` value.
arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
var type = index + 1,
isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
LazyWrapper.prototype[methodName] = function(iteratee) {
var result = this.clone();
result.__iteratees__.push({
'iteratee': getIteratee(iteratee, 3),
'type': type
});
result.__filtered__ = result.__filtered__ || isFilter;
return result;
};
});
// Add `LazyWrapper` methods for `_.head` and `_.last`.
arrayEach(['head', 'last'], function(methodName, index) {
var takeName = 'take' + (index ? 'Right' : '');
LazyWrapper.prototype[methodName] = function() {
return this[takeName](1).value()[0];
};
});
// Add `LazyWrapper` methods for `_.initial` and `_.tail`.
arrayEach(['initial', 'tail'], function(methodName, index) {
var dropName = 'drop' + (index ? '' : 'Right');
LazyWrapper.prototype[methodName] = function() {
return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
};
});
LazyWrapper.prototype.compact = function() {
return this.filter(identity);
};
LazyWrapper.prototype.find = function(predicate) {
return this.filter(predicate).head();
};
LazyWrapper.prototype.findLast = function(predicate) {
return this.reverse().find(predicate);
};
LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
if (typeof path == 'function') {
return new LazyWrapper(this);
}
return this.map(function(value) {
return baseInvoke(value, path, args);
});
});
LazyWrapper.prototype.reject = function(predicate) {
return this.filter(negate(getIteratee(predicate)));
};
LazyWrapper.prototype.slice = function(start, end) {
start = toInteger(start);
var result = this;
if (result.__filtered__ && (start > 0 || end < 0)) {
return new LazyWrapper(result);
}
if (start < 0) {
result = result.takeRight(-start);
} else if (start) {
result = result.drop(start);
}
if (end !== undefined$1) {
end = toInteger(end);
result = end < 0 ? result.dropRight(-end) : result.take(end - start);
}
return result;
};
LazyWrapper.prototype.takeRightWhile = function(predicate) {
return this.reverse().takeWhile(predicate).reverse();
};
LazyWrapper.prototype.toArray = function() {
return this.take(MAX_ARRAY_LENGTH);
};
// Add `LazyWrapper` methods to `lodash.prototype`.
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
isTaker = /^(?:head|last)$/.test(methodName),
lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
retUnwrapped = isTaker || /^find/.test(methodName);
if (!lodashFunc) {
return;
}
lodash.prototype[methodName] = function() {
var value = this.__wrapped__,
args = isTaker ? [1] : arguments,
isLazy = value instanceof LazyWrapper,
iteratee = args[0],
useLazy = isLazy || isArray(value);
var interceptor = function(value) {
var result = lodashFunc.apply(lodash, arrayPush([value], args));
return (isTaker && chainAll) ? result[0] : result;
};
if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
// Avoid lazy use if the iteratee has a "length" value other than `1`.
isLazy = useLazy = false;
}
var chainAll = this.__chain__,
isHybrid = !!this.__actions__.length,
isUnwrapped = retUnwrapped && !chainAll,
onlyLazy = isLazy && !isHybrid;
if (!retUnwrapped && useLazy) {
value = onlyLazy ? value : new LazyWrapper(this);
var result = func.apply(value, args);
result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined$1 });
return new LodashWrapper(result, chainAll);
}
if (isUnwrapped && onlyLazy) {
return func.apply(this, args);
}
result = this.thru(interceptor);
return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
};
});
// Add `Array` methods to `lodash.prototype`.
arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
var func = arrayProto[methodName],
chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
retUnwrapped = /^(?:pop|shift)$/.test(methodName);
lodash.prototype[methodName] = function() {
var args = arguments;
if (retUnwrapped && !this.__chain__) {
var value = this.value();
return func.apply(isArray(value) ? value : [], args);
}
return this[chainName](function(value) {
return func.apply(isArray(value) ? value : [], args);
});
};
});
// Map minified method names to their real names.
baseForOwn(LazyWrapper.prototype, function(func, methodName) {
var lodashFunc = lodash[methodName];
if (lodashFunc) {
var key = lodashFunc.name + '';
if (!hasOwnProperty.call(realNames, key)) {
realNames[key] = [];
}
realNames[key].push({ 'name': methodName, 'func': lodashFunc });
}
});
realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{
'name': 'wrapper',
'func': undefined$1
}];
// Add methods to `LazyWrapper`.
LazyWrapper.prototype.clone = lazyClone;
LazyWrapper.prototype.reverse = lazyReverse;
LazyWrapper.prototype.value = lazyValue;
// Add chain sequence methods to the `lodash` wrapper.
lodash.prototype.at = wrapperAt;
lodash.prototype.chain = wrapperChain;
lodash.prototype.commit = wrapperCommit;
lodash.prototype.next = wrapperNext;
lodash.prototype.plant = wrapperPlant;
lodash.prototype.reverse = wrapperReverse;
lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
// Add lazy aliases.
lodash.prototype.first = lodash.prototype.head;
if (symIterator) {
lodash.prototype[symIterator] = wrapperToIterator;
}
return lodash;
});
/*--------------------------------------------------------------------------*/
// Export lodash.
var _ = runInContext();
// Some AMD build optimizers, like r.js, check for condition patterns like:
if (freeModule) {
// Export for Node.js.
(freeModule.exports = _)._ = _;
// Export for CommonJS support.
freeExports._ = _;
}
else {
// Export to the global object.
root._ = _;
}
}.call(commonjsGlobal));
});
var CodeInstrumentation = /** @class */ (function (_super) {
__extends(CodeInstrumentation, _super);
function CodeInstrumentation(eventSandbox, messageSandbox) {
var _this = _super.call(this) || this;
_this._methodCallInstrumentation = new MethodCallInstrumentation(eventSandbox.message);
_this._locationAccessorsInstrumentation = new LocationAccessorsInstrumentation(messageSandbox);
_this._propertyAccessorsInstrumentation = new PropertyAccessorsInstrumentation();
return _this;
}
CodeInstrumentation.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
this._methodCallInstrumentation.attach(window);
this._locationAccessorsInstrumentation.attach(window);
this._propertyAccessorsInstrumentation.attach(window);
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
// NOTE: GH-260
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.getEval, {
value: function (evalFn) {
if (evalFn !== window.eval)
return evalFn;
var evalWrapper = function (script) {
if (typeof script === 'string')
script = processScript(script);
return evalFn(script);
};
nativeMethods.objectDefineProperty(evalWrapper, CodeInstrumentation.WRAPPED_EVAL_FN, { value: evalFn });
return evalWrapper;
},
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.processScript, {
value: function (script, isApply) {
if (isApply) {
if (script && script.length && typeof script[0] === 'string') {
var args = [processScript(script[0], false)];
// NOTE: shallow-copy the remaining args. Don't use arr.slice(),
// since it may leak the arguments object.
// See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments
for (var i = 1; i < script.length; i++)
args.push(script[i]);
return args;
}
}
else if (typeof script === 'string')
return processScript(script, false);
return script;
},
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.processHtml, {
value: function (win, html) {
if (typeof html === 'string')
html = processHtml("<html><body>".concat(html, "</body></html>"), { processedContext: win });
return html;
},
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.getProxyUrl, {
value: function (url, baseUrl) {
var storedBaseUrl = urlResolver.getBaseUrl(_this.document);
var shouldChangeBase = baseUrl && baseUrl !== storedBaseUrl;
if (shouldChangeBase)
urlResolver.updateBase(baseUrl, _this.document);
var proxyUrl = getProxyUrl(url, { resourceType: stringifyResourceType({ isScript: true }) });
if (shouldChangeBase)
urlResolver.updateBase(storedBaseUrl, _this.document);
return proxyUrl;
},
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.restArray, {
value: function (array, startIndex) { return nativeMethods.arraySlice.call(array, startIndex); },
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.arrayFrom, {
value: function (target) {
if (!target)
return target;
var shouldConvertToArray = !nativeMethods.isArray.call(nativeMethods.Array, target) &&
lodash.isFunction(target[Symbol.iterator]);
return shouldConvertToArray ? nativeMethods.arrayFrom.call(nativeMethods.Array, target) : target;
},
configurable: true,
});
nativeMethods.objectDefineProperty(window, SCRIPT_PROCESSING_INSTRUCTIONS.restObject, {
value: function (obj, excludeProps) {
var rest = {};
var keys = nativeMethods.objectKeys(obj);
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
if (excludeProps.indexOf(key) < 0)
rest[key] = obj[key];
}
return rest;
},
configurable: true,
});
};
CodeInstrumentation.WRAPPED_EVAL_FN = 'hammerhead|code-instrumentation|wrapped-eval-fn';
return CodeInstrumentation;
}(SandboxBase));
// -------------------------------------------------------------
var TIME_RADIX = 36;
var CLEAR_COOKIE_VALUE_STR = '=;path=/;expires=Thu, 01 Jan 1970 00:00:01 GMT';
var CLIENT_COOKIE_SYNC_KEY_FRAGMENT_COUNT = 8;
var KEY_VALUE_REGEX = /(?:^([^=]+)=([\s\S]*))?/;
var SYNCHRONIZATION_TYPE = {
server: 's',
client: 'c',
window: 'w',
};
var SYNCHRONIZATION_TYPE_RE = new RegExp("^[".concat(SYNCHRONIZATION_TYPE.server).concat(SYNCHRONIZATION_TYPE.client).concat(SYNCHRONIZATION_TYPE.window, "]+"));
function isSameCookies(cookie1, cookie2) {
return cookie1.sid === cookie2.sid &&
cookie1.key === cookie2.key &&
cookie1.domain === cookie2.domain &&
cookie1.path === cookie2.path;
}
function sortByOutdatedAndActual(parsedCookies) {
var outdated = [];
var actual = [];
for (var current = 0; current < parsedCookies.length; current++) {
var other = current + 1;
for (; other < parsedCookies.length; other++) {
if (isSameCookies(parsedCookies[current], parsedCookies[other])) {
if (parsedCookies[current].lastAccessed > parsedCookies[other].lastAccessed) {
var temp = parsedCookies[current];
parsedCookies[current] = parsedCookies[other];
parsedCookies[other] = temp;
}
outdated.push(parsedCookies[current]);
break;
}
}
if (other === parsedCookies.length)
actual.push(parsedCookies[current]);
}
return { outdated: outdated, actual: actual };
}
function stringifySyncType(cookie) {
return (cookie.isServerSync ? SYNCHRONIZATION_TYPE.server : '') +
(cookie.isClientSync ? SYNCHRONIZATION_TYPE.client : '') +
(cookie.isWindowSync ? SYNCHRONIZATION_TYPE.window : '');
}
function formatSyncCookieKey(cookie) {
var syncType = stringifySyncType(cookie);
var key = encodeURIComponent(cookie.key);
var domain = encodeURIComponent(cookie.domain);
var path = encodeURIComponent(cookie.path);
var expires = cookie.expires !== 'Infinity' ? cookie.expires.getTime().toString(TIME_RADIX) : '';
var lastAccessed = cookie.lastAccessed.getTime().toString(TIME_RADIX);
var maxAge = !lodash.isNil(cookie.maxAge) && !isNaN(Number(cookie.maxAge)) && String(cookie.maxAge) !== 'Infinity' ? cookie.maxAge.toString(TIME_RADIX) : '';
return "".concat(syncType, "|").concat(cookie.sid, "|").concat(key, "|").concat(domain, "|").concat(path, "|").concat(expires, "|").concat(lastAccessed, "|").concat(maxAge);
}
function parseClientSyncCookieStr(cookieStr) {
var cookies = cookieStr ? cookieStr.split(';') : '';
var parsedCookies = [];
for (var _i = 0, cookies_1 = cookies; _i < cookies_1.length; _i++) {
var cookie = cookies_1[_i];
var parsedCookie = parseSyncCookie(trim$1(cookie));
if (parsedCookie)
parsedCookies.push(parsedCookie);
}
return sortByOutdatedAndActual(parsedCookies);
}
function prepareSyncCookieProperties(cookie) {
cookie.syncKey = cookie.syncKey || formatSyncCookieKey(cookie);
cookie.cookieStr = cookie.cookieStr || "".concat(cookie.syncKey, "=").concat(cookie.value);
}
function formatSyncCookie(cookie) {
if (cookie.cookieStr)
return "".concat(cookie.cookieStr, ";path=/");
return "".concat(formatSyncCookieKey(cookie), "=").concat(cookie.value, ";path=/");
}
function parseSyncCookie(cookieStr) {
var _a = KEY_VALUE_REGEX.exec(cookieStr) || [], key = _a[1], value = _a[2];
var parsedKey = key !== void 0 && value !== void 0 && key.split('|');
if (parsedKey && parsedKey.length !== CLIENT_COOKIE_SYNC_KEY_FRAGMENT_COUNT)
return null;
return {
isServerSync: parsedKey[0].indexOf(SYNCHRONIZATION_TYPE.server) > -1,
isClientSync: parsedKey[0].indexOf(SYNCHRONIZATION_TYPE.client) > -1,
isWindowSync: parsedKey[0].indexOf(SYNCHRONIZATION_TYPE.window) > -1,
sid: parsedKey[1],
key: decodeURIComponent(parsedKey[2]),
domain: decodeURIComponent(parsedKey[3]),
path: decodeURIComponent(parsedKey[4]),
expires: parsedKey[5] ? new Date(parseInt(parsedKey[5], TIME_RADIX)) : 'Infinity',
lastAccessed: new Date(parseInt(parsedKey[6], TIME_RADIX)),
maxAge: parsedKey[7] ? parseInt(parsedKey[7], TIME_RADIX) : null,
syncKey: key,
value: value,
cookieStr: cookieStr,
};
}
function changeSyncType(parsedCookie, flags) {
var _a, _b;
if ('server' in flags)
parsedCookie.isServerSync = flags.server;
if ('client' in flags)
parsedCookie.isClientSync = flags.client;
if ('window' in flags)
parsedCookie.isWindowSync = flags.window;
var newSyncTypeStr = stringifySyncType(parsedCookie);
parsedCookie.syncKey = (_a = parsedCookie.syncKey) === null || _a === void 0 ? void 0 : _a.replace(SYNCHRONIZATION_TYPE_RE, newSyncTypeStr);
parsedCookie.cookieStr = (_b = parsedCookie.cookieStr) === null || _b === void 0 ? void 0 : _b.replace(SYNCHRONIZATION_TYPE_RE, newSyncTypeStr);
}
function isOutdatedSyncCookie(currentCookie, newCookie) {
return newCookie.isServerSync === currentCookie.isServerSync &&
newCookie.sid === currentCookie.sid &&
newCookie.key === currentCookie.key &&
newCookie.domain === currentCookie.domain &&
newCookie.path === currentCookie.path &&
newCookie.lastAccessed > currentCookie.lastAccessed;
}
function generateDeleteSyncCookieStr(cookie) {
return cookie.syncKey + CLEAR_COOKIE_VALUE_STR;
}
var sharedCookieUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
SYNCHRONIZATION_TYPE: SYNCHRONIZATION_TYPE,
parseClientSyncCookieStr: parseClientSyncCookieStr,
prepareSyncCookieProperties: prepareSyncCookieProperties,
formatSyncCookie: formatSyncCookie,
parseSyncCookie: parseSyncCookie,
changeSyncType: changeSyncType,
isOutdatedSyncCookie: isOutdatedSyncCookie,
generateDeleteSyncCookieStr: generateDeleteSyncCookieStr
});
var topOpenerWindow = null;
function getTopOpenerWindow() {
if (!topOpenerWindow) {
topOpenerWindow = window.top;
while (topOpenerWindow.opener && topOpenerWindow !== topOpenerWindow.opener)
topOpenerWindow = topOpenerWindow.opener.top;
}
return topOpenerWindow;
}
var SYNC_COOKIE_START_CMD = 'hammerhead|command|sync-cookie-start';
var SYNC_COOKIE_DONE_CMD = 'hammerhead|command|sync-cookie-done';
var SYNC_MESSAGE_TIMEOUT = 500;
var SYNC_MESSAGE_ATTEMPT_COUNT = 5;
var WindowSync = /** @class */ (function () {
function WindowSync(_cookieSandbox, _messageSandbox, _childWindowSandbox) {
this._cookieSandbox = _cookieSandbox;
this._messageSandbox = _messageSandbox;
this._childWindowSandbox = _childWindowSandbox;
this._win = null;
this._messageIdGenerator = null;
this._resolversMap = new Map(); // eslint-disable-line no-spaced-func
}
WindowSync._getCookieSandbox = function (win) {
try {
// eslint-disable-next-line no-restricted-properties
var cookieSandbox = win[INTERNAL_PROPS.hammerhead].sandbox.cookie;
return cookieSandbox.document && cookieSandbox;
}
catch (e) {
return null;
}
};
WindowSync.prototype._onMsgReceived = function (_a) {
var _this = this;
var message = _a.message, source = _a.source;
if (message.cmd === SYNC_COOKIE_START_CMD) {
this._cookieSandbox.syncWindowCookie(message.cookies);
if (this._win !== this._win.top)
this._messageSandbox.sendServiceMsg({ id: message.id, cmd: SYNC_COOKIE_DONE_CMD }, source);
else if (this._win !== getTopOpenerWindow()) {
this.syncBetweenWindows(message.cookies, source)
.then(function () { return _this._messageSandbox.sendServiceMsg({
id: message.id,
cmd: SYNC_COOKIE_DONE_CMD,
}, source); });
}
else
this.syncBetweenWindows(message.cookies, source);
}
else if (message.cmd === SYNC_COOKIE_DONE_CMD) {
var resolver = this._resolversMap.get(message.id);
if (resolver)
resolver();
}
};
WindowSync.prototype._getWindowsForSync = function (initiator, currentWindow, windows) {
if (windows === void 0) { windows = []; }
if (currentWindow !== initiator && currentWindow !== this._win.top)
windows.push(currentWindow);
// @ts-ignore
for (var _i = 0, _a = currentWindow.frames; _i < _a.length; _i++) {
var frameWindow = _a[_i];
this._getWindowsForSync(initiator, frameWindow, windows);
}
return windows;
};
WindowSync.prototype._sendSyncMessage = function (win, cmd, cookies) {
var _this = this;
var id = this._messageIdGenerator.increment();
var attempts = 0;
return new pinkie(function (resolve) {
var timeoutId = null;
var resolveWrapper = function () {
nativeMethods.clearTimeout.call(_this._win, timeoutId);
_this._resolversMap.delete(id);
resolve();
};
var sendMsg = function () {
// NOTE: The window was removed if the parent property is null.
if (attempts++ < SYNC_MESSAGE_ATTEMPT_COUNT || !win.parent) {
_this._messageSandbox.sendServiceMsg({ id: id, cmd: cmd, cookies: cookies }, win);
timeoutId = nativeMethods.setTimeout.call(_this._win, sendMsg, SYNC_MESSAGE_TIMEOUT * attempts);
}
else
resolveWrapper();
};
_this._resolversMap.set(id, resolveWrapper);
sendMsg();
});
};
WindowSync.prototype._delegateSyncBetweenWindowsToMainTopWindow = function (cookies) {
var topOpenerWindow = getTopOpenerWindow();
var cookieSandboxTop = WindowSync._getCookieSandbox(topOpenerWindow);
if (cookieSandboxTop) {
cookieSandboxTop.syncWindowCookie(cookies);
cookieSandboxTop.getWindowSync().syncBetweenWindows(cookies, this._win);
}
else
this._messageSandbox.sendServiceMsg({ cmd: SYNC_COOKIE_START_CMD, cookies: cookies }, topOpenerWindow);
};
WindowSync.prototype._removeSyncCookie = function (cookies) {
var doc = this._win.document;
var clientCookieStr = cookies[0].isClientSync && nativeMethods.documentCookieGetter.call(doc);
for (var _i = 0, cookies_1 = cookies; _i < cookies_1.length; _i++) {
var parsedCookie_1 = cookies_1[_i];
nativeMethods.documentCookieSetter.call(doc, generateDeleteSyncCookieStr(parsedCookie_1));
}
// NOTE: client cookie is passed one at a time
var parsedCookie = cookies[0];
if (clientCookieStr && CookieSandbox.isSyncCookieExists(parsedCookie, clientCookieStr)) {
changeSyncType(parsedCookie, { window: false });
nativeMethods.documentCookieSetter.call(doc, formatSyncCookie(parsedCookie));
}
};
WindowSync.prototype.syncBetweenWindows = function (cookies, initiator) {
var _this = this;
var topOpenerWindow = getTopOpenerWindow();
if (this._win !== this._win.top || this._win !== topOpenerWindow && !initiator) {
this._delegateSyncBetweenWindowsToMainTopWindow(cookies);
return pinkie.resolve();
}
var windowsForSync = this._getWindowsForSync(initiator, this._win);
var syncMessages = [];
if (this._win === topOpenerWindow) {
for (var _i = 0, _a = this._childWindowSandbox.getChildWindows(); _i < _a.length; _i++) {
var win = _a[_i];
var cookieSandbox = WindowSync._getCookieSandbox(win);
if (cookieSandbox)
syncMessages.push(cookieSandbox.getWindowSync().syncBetweenWindows(cookies, this._win));
else
syncMessages.push(this._sendSyncMessage(win, SYNC_COOKIE_START_CMD, cookies));
}
}
for (var _b = 0, windowsForSync_1 = windowsForSync; _b < windowsForSync_1.length; _b++) {
var win = windowsForSync_1[_b];
var cookieSandbox = WindowSync._getCookieSandbox(win);
if (cookieSandbox)
cookieSandbox.syncWindowCookie(cookies);
else
syncMessages.push(this._sendSyncMessage(win, SYNC_COOKIE_START_CMD, cookies));
}
if (syncMessages.length) {
var syncMessagesPromise = pinkie.all(syncMessages);
if (this._win === topOpenerWindow)
return syncMessagesPromise.then(function () { return _this._removeSyncCookie(cookies); });
return syncMessagesPromise.then();
}
this._removeSyncCookie(cookies);
return pinkie.resolve();
};
WindowSync.prototype.attach = function (win) {
var _this = this;
this._win = win;
this._messageSandbox.on(this._messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (e) { return _this._onMsgReceived(e); });
if (win === win.top) {
this._messageIdGenerator = this._messageIdGenerator || new IntegerIdGenerator();
this._resolversMap = this._resolversMap || new Map();
}
};
return WindowSync;
}());
var COOKIE_PAIR_REGEX = /^((?:=)?([^=;]*)\s*=\s*)?([^\n\r\0]*)/;
var TRAILING_SEMICOLON_REGEX = /;+$/;
var FIX_COOKIE_DATE = /((?:\s|,)[0-9]{1,2})(?:\s|-)([A-Za-z]{3})(?:\s|-)([0-9]{4}\s)/;
function parse(str) {
str = trim$1(str);
var trailingSemicolonCheck = TRAILING_SEMICOLON_REGEX.exec(str);
if (trailingSemicolonCheck)
str = str.slice(0, trailingSemicolonCheck.index);
var firstSemicolonIdx = str.indexOf(';');
var keyValueString = firstSemicolonIdx > -1 ? str.substr(0, firstSemicolonIdx) : str;
var keyValueParsingResult = COOKIE_PAIR_REGEX.exec(keyValueString);
if (!keyValueParsingResult)
return null;
var parsedCookie = {
key: keyValueParsingResult[1] ? trim$1(keyValueParsingResult[2]) : '',
value: trim$1(keyValueParsingResult[3]),
};
if (firstSemicolonIdx === -1)
return parsedCookie;
var attributesString = trim$1(str.slice(firstSemicolonIdx).replace(/^\s*;\s*/, ''));
if (attributesString.length === 0)
return parsedCookie;
var attrValStrings = attributesString.split(/\s*;\s*/);
while (attrValStrings.length) {
var attrValueStr = attrValStrings.shift();
var separatorIdx = attrValueStr.indexOf('=');
var key = null;
var value = null;
var date = null;
if (separatorIdx === -1)
key = attrValueStr;
else {
key = attrValueStr.substr(0, separatorIdx);
value = trim$1(attrValueStr.substr(separatorIdx + 1));
}
key = trim$1(key.toLowerCase());
switch (key) {
case 'expires':
value = value.replace(FIX_COOKIE_DATE, '$1 $2 $3');
date = getUTCDate(Date.parse(value));
if (date)
parsedCookie.expires = date;
break;
case 'max-age':
if (value)
parsedCookie.maxAge = Number(value);
break;
case 'path':
parsedCookie.path = value;
break;
case 'secure':
parsedCookie.secure = true;
break;
case 'httponly':
parsedCookie.httpOnly = true;
break;
case 'domain':
// NOTE: Remove leading '.'.
parsedCookie.domain = trim$1(value.replace(/^\./, ''));
break;
}
}
return parsedCookie;
}
function formatClientString(parsedCookie) {
// eslint-disable-next-line no-restricted-properties
var cookieStr = parsedCookie.value || '';
if (parsedCookie.key !== '')
cookieStr = parsedCookie.key + '=' + cookieStr;
return cookieStr;
}
function setDefaultValues(parsedCookie, _a) {
var hostname = _a.hostname, pathname = _a.pathname;
if (!parsedCookie.domain)
parsedCookie.domain = hostname; // eslint-disable-line no-restricted-properties
if (!parsedCookie.path || parsedCookie.path.charAt(0) !== '/') {
var path = pathname; // eslint-disable-line no-restricted-properties
var defaultPath = path.slice(0, path.lastIndexOf('/'));
parsedCookie.path = defaultPath || '/';
}
if (!parsedCookie.expires)
parsedCookie.expires = 'Infinity';
if (isNaN(parsedCookie.maxAge))
parsedCookie.maxAge = 'Infinity';
}
function domainMatch(currentDomain, cookieDomain) {
if (!cookieDomain)
return true;
currentDomain = currentDomain.toLowerCase();
cookieDomain = cookieDomain.toLowerCase();
if (currentDomain === cookieDomain)
return true;
var cookieDomainIdx = currentDomain.indexOf(cookieDomain);
return cookieDomainIdx > 0 &&
currentDomain.length === cookieDomain.length + cookieDomainIdx &&
currentDomain.charAt(cookieDomainIdx - 1) === '.';
}
function pathMatch(currentPath, cookiePath) {
if (!cookiePath || cookiePath.charAt(0) !== '/' || currentPath === cookiePath)
return true;
return currentPath.length > cookiePath.length && currentPath.indexOf(cookiePath) === 0 &&
(cookiePath.charAt(cookiePath.length - 1) === '/' || currentPath.charAt(cookiePath.length) === '/');
}
function getUTCDate(timestamp) {
if (!arguments.length)
timestamp = nativeMethods.dateNow();
else if (isNaN(timestamp))
return null;
// NOTE: remove milliseconds
timestamp = Math.floor(timestamp / 1000) * 1000;
return new nativeMethods.date(timestamp); // eslint-disable-line new-cap
}
var cookieUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
parse: parse,
formatClientString: formatClientString,
setDefaultValues: setDefaultValues,
domainMatch: domainMatch,
pathMatch: pathMatch,
getUTCDate: getUTCDate
});
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
// NOTE: At least 4096 bytes per cookie (as measured by the sum of the length of the cookie's name,
// value, and attributes). Specification https://tools.ietf.org/html/rfc6265#page-27 (GH-767)
var BYTES_PER_COOKIE_LIMIT = 4096;
var MIN_DATE_VALUE = new nativeMethods.date(0).toUTCString(); // eslint-disable-line new-cap
var CookieSandboxStrategyFactory = /** @class */ (function () {
function CookieSandboxStrategyFactory() {
}
CookieSandboxStrategyFactory.create = function (proxyless, document, windowSync) {
return proxyless ? new CookieSandboxProxylessStrategy() : new CookieSandboxProxyStrategy(document, windowSync);
};
return CookieSandboxStrategyFactory;
}());
var CookieSandboxProxylessStrategy = /** @class */ (function () {
function CookieSandboxProxylessStrategy() {
}
CookieSandboxProxylessStrategy.prototype.getCookie = function () {
return '';
};
CookieSandboxProxylessStrategy.prototype.setCookie = function () {
return void 0;
};
CookieSandboxProxylessStrategy.prototype.syncCookie = function () {
return void 0;
};
CookieSandboxProxylessStrategy.prototype.syncWindowCookie = function () {
return void 0;
};
CookieSandboxProxylessStrategy.prototype.removeAllSyncCookie = function () {
return void 0;
};
return CookieSandboxProxylessStrategy;
}());
var CookieSandboxProxyStrategy = /** @class */ (function () {
function CookieSandboxProxyStrategy(document, _windowSync) {
this.document = null;
this.document = document;
this._windowSync = _windowSync;
}
CookieSandboxProxyStrategy.prototype.getCookie = function () {
this.syncCookie(true);
// eslint-disable-next-line no-restricted-properties
return settings.get().cookie || '';
};
CookieSandboxProxyStrategy.prototype.setCookie = function (cookie) {
var setByClient = typeof cookie === 'string';
// NOTE: Cookie cannot be set in iframe without src in IE
// Also cookie cannot be set on a page with 'file:' protocol
// or if the length of cookie higher than limit
if (!this._canSetCookie(cookie, setByClient))
return;
var parsedCookie = setByClient ? parse(cookie) : cookie;
if (!parsedCookie || parsedCookie.httpOnly)
return;
var parsedDestLocation = getParsed();
// NOTE: All Hammerhad sessions have the same domain, so we need to validate the Domain attribute manually
// according to a test url.
// eslint-disable-next-line no-restricted-properties
if (!domainMatch(parsedDestLocation.hostname, parsedCookie.domain))
return;
// eslint-disable-next-line no-restricted-properties
if ((!parsedCookie.secure || parsedDestLocation.protocol === 'https:') &&
// eslint-disable-next-line no-restricted-properties
pathMatch(parsedDestLocation.pathname, parsedCookie.path)) {
var currentDate = getUTCDate();
var clientCookieStr = null;
if ((!parsedCookie.expires || parsedCookie.expires === 'Infinity' || parsedCookie.expires > currentDate) &&
(isNull(parsedCookie.maxAge) || isNaN(parsedCookie.maxAge) || parsedCookie.maxAge > 0))
clientCookieStr = formatClientString(parsedCookie);
CookieSandbox._updateClientCookieStr(parsedCookie.key, clientCookieStr);
}
if (setByClient) {
setDefaultValues(parsedCookie, parsedDestLocation);
this._syncClientCookie(parsedCookie);
this.syncCookie();
}
};
/* eslint-disable */
CookieSandboxProxyStrategy.prototype.syncCookie = function (gettingCookies) {
if (gettingCookies === void 0) { gettingCookies = false; }
var cookies = nativeMethods.documentCookieGetter.call(this.document);
var parsedCookies = parseClientSyncCookieStr(cookies);
var sessionId = settings.get().sessionId;
var serverSyncCookies = [];
for (var _i = 0, _a = parsedCookies.outdated; _i < _a.length; _i++) {
var outdatedCookie = _a[_i];
nativeMethods.documentCookieSetter.call(this.document, generateDeleteSyncCookieStr(outdatedCookie));
}
for (var _b = 0, _c = parsedCookies.actual; _b < _c.length; _b++) {
var parsedCookie = _c[_b];
if (parsedCookie.sid !== sessionId)
continue;
if (parsedCookie.isServerSync)
serverSyncCookies.push(parsedCookie);
else if (parsedCookie.isWindowSync)
this.setCookie(parsedCookie);
else if (gettingCookies && parsedCookie.isClientSync) {
var currentDate = getUTCDate();
var maxAge = !isNull(parsedCookie.maxAge) && Number(parsedCookie.maxAge);
var expires = Number(parsedCookie.expires);
if (!isNaN(maxAge) && isNumber(maxAge) && maxAge * 1000 <= currentDate.getTime() - parsedCookie.lastAccessed.getTime() ||
!isNaN(expires) && isNumber(expires) && expires < currentDate.getTime()) {
nativeMethods.documentCookieSetter.call(this.document, generateDeleteSyncCookieStr(parsedCookie));
CookieSandbox._updateClientCookieStr(parsedCookie.key, null);
}
}
}
if (serverSyncCookies.length)
this._syncServerCookie(serverSyncCookies);
};
CookieSandboxProxyStrategy.prototype._syncServerCookie = function (parsedCookies) {
for (var _i = 0, parsedCookies_1 = parsedCookies; _i < parsedCookies_1.length; _i++) {
var parsedCookie = parsedCookies_1[_i];
this.setCookie(parsedCookie);
nativeMethods.documentCookieSetter.call(this.document, generateDeleteSyncCookieStr(parsedCookie));
changeSyncType(parsedCookie, { server: false, window: true });
nativeMethods.documentCookieSetter.call(this.document, formatSyncCookie(parsedCookie));
}
this._windowSync.syncBetweenWindows(parsedCookies);
};
CookieSandboxProxyStrategy.prototype.syncWindowCookie = function (parsedCookies) {
var clientCookie = nativeMethods.documentCookieGetter.call(this.document);
for (var _i = 0, parsedCookies_2 = parsedCookies; _i < parsedCookies_2.length; _i++) {
var parsedCookie = parsedCookies_2[_i];
if (CookieSandbox.isSyncCookieExists(parsedCookie, clientCookie))
this.setCookie(parsedCookie);
}
};
CookieSandboxProxyStrategy.prototype.removeAllSyncCookie = function () {
var cookies = nativeMethods.documentCookieGetter.call(this.document);
var parsedCookies = parseClientSyncCookieStr(cookies);
var sessionId = settings.get().sessionId;
for (var _i = 0, _a = parsedCookies.outdated; _i < _a.length; _i++) {
var outdatedCookie = _a[_i];
nativeMethods.documentCookieSetter.call(this.document, generateDeleteSyncCookieStr(outdatedCookie));
}
for (var _b = 0, _c = parsedCookies.actual; _b < _c.length; _b++) {
var parsedCookie = _c[_b];
if (parsedCookie.sid === sessionId && (parsedCookie.isWindowSync || parsedCookie.isServerSync)) {
nativeMethods.documentCookieSetter.call(this.document, generateDeleteSyncCookieStr(parsedCookie));
if (parsedCookie.isClientSync) {
changeSyncType(parsedCookie, { window: false });
nativeMethods.documentCookieSetter.call(this.document, formatSyncCookie(parsedCookie));
}
}
}
};
CookieSandboxProxyStrategy.prototype._canSetCookie = function (cookie, setByClient) {
// eslint-disable-next-line no-restricted-properties
if (setByClient && (cookie.length > BYTES_PER_COOKIE_LIMIT || getParsed().protocol === 'file:'))
return false;
var clientCookie = "key".concat(nativeMethods.mathRandom.call(nativeMethods.math), "=value");
nativeMethods.documentCookieSetter.call(this.document, clientCookie);
var documentCookieIsEmpty = !nativeMethods.documentCookieGetter.call(this.document);
if (!documentCookieIsEmpty)
nativeMethods.documentCookieSetter.call(this.document, "".concat(clientCookie, ";expires=").concat(MIN_DATE_VALUE));
return !documentCookieIsEmpty;
};
CookieSandboxProxyStrategy.prototype._syncClientCookie = function (parsedCookie) {
parsedCookie.isClientSync = true;
parsedCookie.isWindowSync = true;
parsedCookie.sid = settings.get().sessionId;
parsedCookie.lastAccessed = getUTCDate();
prepareSyncCookieProperties(parsedCookie);
nativeMethods.documentCookieSetter.call(this.document, formatSyncCookie(parsedCookie));
this._windowSync.syncBetweenWindows([parsedCookie]);
};
return CookieSandboxProxyStrategy;
}());
var CookieSandbox = /** @class */ (function (_super) {
__extends(CookieSandbox, _super);
function CookieSandbox(messageSandbox, _unloadSandbox, childWindowSandbox) {
var _this = _super.call(this) || this;
_this._unloadSandbox = _unloadSandbox;
_this._windowSync = new WindowSync(_this, messageSandbox, childWindowSandbox);
return _this;
}
CookieSandbox._updateClientCookieStr = function (cookieKey, newCookieStr) {
var cookieStr = settings.get().cookie; // eslint-disable-line no-restricted-properties
var cookies = cookieStr ? cookieStr.split(';') : [];
var changedCookies = [];
var replaced = false;
var searchStr = cookieKey === '' ? null : cookieKey + '=';
// NOTE: Replace a cookie if it already exists.
for (var _i = 0, cookies_1 = cookies; _i < cookies_1.length; _i++) {
var cookie = cookies_1[_i];
cookie = trim$1(cookie);
var isCookieExists = searchStr ? cookie.indexOf(searchStr) === 0 : cookie.indexOf('=') === -1;
if (!isCookieExists)
changedCookies.push(cookie);
else if (newCookieStr !== null) {
changedCookies.push(newCookieStr);
replaced = true;
}
}
if (!replaced && newCookieStr !== null)
changedCookies.push(newCookieStr);
settings.get().cookie = changedCookies.join('; '); // eslint-disable-line no-restricted-properties
};
CookieSandbox.isSyncCookieExists = function (parsedCookie, clientCookieStr) {
var startIndex = clientCookieStr.indexOf(parsedCookie.cookieStr);
var endIndex = startIndex + parsedCookie.cookieStr.length;
return startIndex > -1 && (clientCookieStr.length === endIndex || clientCookieStr.charAt(endIndex) === ';');
};
CookieSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
this._windowSync.attach(window);
this._cookieStrategy = CookieSandboxStrategyFactory.create(this.proxyless, this.document, this._windowSync);
if (window === getTopOpenerWindow())
this._unloadSandbox.on(this._unloadSandbox.UNLOAD_EVENT, this._cookieStrategy.removeAllSyncCookie);
};
CookieSandbox.prototype.getWindowSync = function () {
return this._windowSync;
};
// Strategy methods
CookieSandbox.prototype.getCookie = function () {
return this._cookieStrategy.getCookie();
};
CookieSandbox.prototype.setCookie = function (cookie) {
this._cookieStrategy.setCookie(cookie);
};
CookieSandbox.prototype.syncCookie = function () {
this._cookieStrategy.syncCookie();
};
CookieSandbox.prototype.syncWindowCookie = function (parsedCookies) {
this._cookieStrategy.syncWindowCookie(parsedCookies);
};
return CookieSandbox;
}(SandboxBase));
var EDITING_OBSERVED_FLAG = 'hammerhead|editing-observed';
var PREVIOUS_VALUE_PROPERTY = 'hammerhead|previous-value';
var ElementEditingWatcher = /** @class */ (function () {
function ElementEditingWatcher(_eventSimulator) {
var _this = this;
this._eventSimulator = _eventSimulator;
this._onChange = function (e) { return _this.stopWatching(nativeMethods.eventTargetGetter.call(e)); };
this._onBlur = function (e) {
var target = nativeMethods.eventTargetGetter.call(e);
if (!_this.processElementChanging(target))
_this.stopWatching(target);
};
}
ElementEditingWatcher._getValue = function (el) {
if (isInputElement(el))
return nativeMethods.inputValueGetter.call(el);
else if (isTextAreaElement(el))
return nativeMethods.textAreaValueGetter.call(el);
// eslint-disable-next-line no-restricted-properties
return el.value;
};
ElementEditingWatcher.prototype.stopWatching = function (el) {
if (!el)
return;
nativeMethods.removeEventListener.call(el, 'blur', this._onBlur);
nativeMethods.removeEventListener.call(el, 'change', this._onChange);
if (el[EDITING_OBSERVED_FLAG] !== void 0)
delete el[EDITING_OBSERVED_FLAG];
if (el[PREVIOUS_VALUE_PROPERTY] !== void 0)
delete el[PREVIOUS_VALUE_PROPERTY];
};
ElementEditingWatcher.prototype.watchElementEditing = function (el) {
var _a;
if (!el || el[EDITING_OBSERVED_FLAG] || !isTextEditableElementAndEditingAllowed(el) || isShadowUIElement(el))
return;
nativeMethods.objectDefineProperties(el, (_a = {},
_a[EDITING_OBSERVED_FLAG] = { value: true, configurable: true, writable: true },
_a[PREVIOUS_VALUE_PROPERTY] = { value: ElementEditingWatcher._getValue(el), configurable: true, writable: true },
_a));
nativeMethods.addEventListener.call(el, 'blur', this._onBlur);
nativeMethods.addEventListener.call(el, 'change', this._onChange);
};
ElementEditingWatcher.prototype.restartWatchingElementEditing = function (el) {
if (el && el[EDITING_OBSERVED_FLAG])
el[PREVIOUS_VALUE_PROPERTY] = ElementEditingWatcher._getValue(el);
};
ElementEditingWatcher.prototype.processElementChanging = function (el) {
if (el && el[EDITING_OBSERVED_FLAG] && ElementEditingWatcher._getValue(el) !== el[PREVIOUS_VALUE_PROPERTY]) {
this._eventSimulator.change(el);
this.restartWatchingElementEditing(el);
return true;
}
return false;
};
ElementEditingWatcher.prototype.getElementSavedValue = function (el) {
return el[PREVIOUS_VALUE_PROPERTY];
};
ElementEditingWatcher.prototype.isEditingObserved = function (el) {
return el[EDITING_OBSERVED_FLAG];
};
return ElementEditingWatcher;
}());
var WINDOW_ACTIVATED_EVENT = 'hammerhead|event|window-activated';
var WINDOW_DEACTIVATED_EVENT = 'hammerhead|event|window-deactivated';
var ActiveWindowTracker = /** @class */ (function (_super) {
__extends(ActiveWindowTracker, _super);
function ActiveWindowTracker(_messageSandbox) {
var _this = _super.call(this) || this;
_this._messageSandbox = _messageSandbox;
_this._isIframeWindow = false;
_this._activeWindow = null;
_this._isActive = false;
return _this;
}
ActiveWindowTracker.prototype._notifyPrevActiveWindow = function () {
try {
if (this._activeWindow.top && this._activeWindow !== this._activeWindow.top) {
this._messageSandbox.sendServiceMsg({
cmd: WINDOW_DEACTIVATED_EVENT,
}, this._activeWindow);
}
}
catch (err) {
// NOTE: The error appears in IE when the corresponding iframe is removed.
}
};
ActiveWindowTracker.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
this._isIframeWindow = isIframeWindow(window);
this._activeWindow = !this._isIframeWindow ? window.top : null;
this._isActive = !this._isIframeWindow;
this._messageSandbox.on(this._messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (e) {
if (e.message.cmd === WINDOW_ACTIVATED_EVENT) {
_this._notifyPrevActiveWindow();
_this._isActive = false;
_this._activeWindow = e.source;
}
else if (e.message.cmd === WINDOW_DEACTIVATED_EVENT)
_this._isActive = false;
});
};
ActiveWindowTracker.prototype.isCurrentWindowActive = function () {
return this._isActive;
};
ActiveWindowTracker.prototype.makeCurrentWindowActive = function () {
this._isActive = true;
if (!this._isIframeWindow) {
this._notifyPrevActiveWindow();
this._activeWindow = this.window;
}
else {
this._messageSandbox.sendServiceMsg({
cmd: WINDOW_ACTIVATED_EVENT,
}, this.window.top);
}
};
return ActiveWindowTracker;
}(SandboxBase));
function nextTick () {
return new pinkie(function (resolve) { return nativeMethods.setTimeout.call(window, resolve, 0); });
}
var INTERNAL_FOCUS_BLUR_FLAG_PREFIX = 'hammerhead|event|internal-';
var PREVENT_FOCUS_ON_CHANGE = isChrome;
var eventsMap = {
bubbles: {
'focus': 'focusin',
'blur': 'focusout',
},
nonBubbles: {
'focusin': 'focus',
'focusout': 'blur',
},
};
var FocusBlurSandbox = /** @class */ (function (_super) {
__extends(FocusBlurSandbox, _super);
function FocusBlurSandbox(_listeners, _eventSimulator, messageSandbox, _timersSandbox, elementEditingWatcher) {
var _this = _super.call(this) || this;
_this._listeners = _listeners;
_this._eventSimulator = _eventSimulator;
_this._timersSandbox = _timersSandbox;
_this._topWindow = null;
_this._lastFocusedElement = null;
_this._scrollState = {};
_this._activeWindowTracker = new ActiveWindowTracker(messageSandbox);
_this._elementEditingWatcher = elementEditingWatcher;
return _this;
}
FocusBlurSandbox._getNativeMeth = function (el, event) {
if (isSVGElement(el)) {
if (event === 'focus')
return nativeMethods.svgFocus;
else if (event === 'blur')
return nativeMethods.svgBlur;
}
//@ts-ignore
return nativeMethods[event];
};
FocusBlurSandbox._restoreElementScroll = function (el, scroll) {
var newScroll = getElementScroll(el);
if (newScroll.left !== scroll.left)
setScrollLeft(el, scroll.left);
if (newScroll.top !== scroll.top)
setScrollTop(el, scroll.top);
};
FocusBlurSandbox.prototype._onChangeActiveElement = function (activeElement) {
if (this._lastFocusedElement === activeElement)
return;
if (this._lastFocusedElement &&
nativeMethods.getAttribute.call(this._lastFocusedElement, INTERNAL_ATTRIBUTES.focusPseudoClass))
nativeMethods.removeAttribute.call(this._lastFocusedElement, INTERNAL_ATTRIBUTES.focusPseudoClass);
if (isElementFocusable(activeElement) && !(isBodyElement(activeElement) &&
getTabIndex(activeElement) === null)) {
this._lastFocusedElement = activeElement;
nativeMethods.setAttribute.call(activeElement, INTERNAL_ATTRIBUTES.focusPseudoClass, true);
}
else
this._lastFocusedElement = null;
};
FocusBlurSandbox.prototype._shouldUseLabelHtmlForElement = function (el, type) {
return type === 'focus' && !!el.htmlFor && !isElementFocusable(el);
};
FocusBlurSandbox.prototype._getElementNonScrollableParentsScrollState = function (el) {
var scrollState = [];
var elementParents = getParents(el);
for (var _i = 0, elementParents_1 = elementParents; _i < elementParents_1.length; _i++) {
var elementParent = elementParents_1[_i];
if (get$1(elementParent, 'overflow') === 'hidden') {
scrollState.push({
element: elementParent,
state: getElementScroll(elementParent),
});
}
}
return scrollState;
};
FocusBlurSandbox.prototype._restoreElementNonScrollableParentsScrollState = function (scrollState) {
for (var _i = 0, scrollState_1 = scrollState; _i < scrollState_1.length; _i++) {
var scrollStateEntry = scrollState_1[_i];
FocusBlurSandbox._restoreElementScroll(scrollStateEntry.element, scrollStateEntry.state);
}
};
FocusBlurSandbox.prototype._saveScrollStateIfNecessary = function (el, preventScrolling) {
if (preventScrolling)
this._scrollState.windowScroll = getElementScroll(this.window);
if (isIE)
this._scrollState.elementNonScrollableParentsScrollState = this._getElementNonScrollableParentsScrollState(el);
};
FocusBlurSandbox.prototype._restoreScrollStateIfNecessary = function (preventScrolling) {
if (preventScrolling)
FocusBlurSandbox._restoreElementScroll(this.window, this._scrollState.windowScroll);
if (isIE)
this._restoreElementNonScrollableParentsScrollState(this._scrollState.elementNonScrollableParentsScrollState);
};
FocusBlurSandbox.prototype._restoreScrollStateAndRaiseEvent = function (el, type, callback, options, simulateEvent) {
this._restoreScrollStateIfNecessary(options.preventScrolling);
var curDocument = findDocument(el);
var activeElement = getActiveElement(curDocument);
// NOTE: If the element was not focused and has a parent with tabindex, we focus this parent.
var parent = nativeMethods.nodeParentNodeGetter.call(el);
var parentWithTabIndex = parent === document ? null : closest(parent, '[tabindex]');
if (type === 'focus' && activeElement !== el && parentWithTabIndex && options.forMouseEvent) {
// NOTE: In WebKit, Safari and MSEdge, calling the native focus event for a parent element
// raises page scrolling. We can't prevent it. Therefore, we need to restore a page scrolling value.
var needPreventScrolling = isWebKit || isSafari || isIE;
this._raiseEvent(parentWithTabIndex, 'focus', simulateEvent, {
preventScrolling: needPreventScrolling,
forMouseEvent: options.forMouseEvent,
});
}
// NOTE: Some browsers don't change document.activeElement after calling element.blur() if a browser
// window is in the background. That's why we call body.focus() without handlers. It should be called
// synchronously because client scripts may expect that document.activeElement will be changed immediately
// after element.blur() is called.
else if (type === 'blur' && activeElement === el && el !== curDocument.body)
this._raiseEvent(curDocument.body, 'focus', simulateEvent, { withoutHandlers: true });
else if (!isElementDisabled(el))
simulateEvent();
else
callback();
};
FocusBlurSandbox.prototype._raiseEvent = function (el, type, callback, options) {
// NOTE: We cannot use Promise because 'resolve' will be called async, but we need to resolve
// immediately in IE9 and IE10.
var _this = this;
var simulateEvent = function () {
// NOTE: The focus and blur events should be raised after activeElement is changed (B237489)
// in MSEdge, the focus/blur events are executed synchronously.
if (isIE && version < 12) {
_this.window.setTimeout(function () {
_this.window.setTimeout(function () {
delete el[FocusBlurSandbox.getInternalEventFlag(type)];
}, 0);
}, 0);
}
else
delete el[FocusBlurSandbox.getInternalEventFlag(type)];
if (!options.withoutHandlers) {
var bubblesEventType = eventsMap.bubbles[type];
var bubblesEventShouldRaiseFirstly = isIE11 || isMSEdge && version < 17 && type === 'blur';
if (options.isAsync) {
// NOTE: focusin, focusout events are synchronously
_this._eventSimulator[bubblesEventType](el, options.relatedTarget);
_this._timersSandbox.deferFunction(function () { return _this._eventSimulator[type](el, options.relatedTarget); });
}
else if (bubblesEventShouldRaiseFirstly) {
_this._eventSimulator[bubblesEventType](el, options.relatedTarget);
_this._eventSimulator[type](el, options.relatedTarget);
}
else {
_this._eventSimulator[type](el, options.relatedTarget);
_this._eventSimulator[bubblesEventType](el, options.relatedTarget);
}
}
else if (type === 'focus' && PREVENT_FOCUS_ON_CHANGE) {
var preventFocus = function (_e, _dispatched, _preventEvent, cancelHandlers, stopEventPropagation) {
cancelHandlers();
stopEventPropagation();
};
_this._listeners.addInternalEventBeforeListener(window, ['focus'], preventFocus);
_this._eventSimulator['focus'](el, options.relatedTarget);
_this._listeners.removeInternalEventBeforeListener(window, ['focus'], preventFocus);
}
callback();
};
if (el[type]) {
// NOTE: To guarantee that all focus/blur events are raised, we need to raise them manually.
this._saveScrollStateIfNecessary(el, options.preventScrolling);
if (isLabelElement(el) && this._shouldUseLabelHtmlForElement(el, type)) {
var htmlForElement = nativeMethods.getElementById.call(findDocument(el), el.htmlFor);
if (htmlForElement)
el = htmlForElement;
else {
callback();
return;
}
}
el[FocusBlurSandbox.getInternalEventFlag(type)] = true;
// NOTE: We should guarantee that activeElement will be changed, therefore we need to call the native
// focus/blur event.
if (!options.focusedOnChange)
FocusBlurSandbox._getNativeMeth(el, type).call(el);
if (isSafari && parseFloat(fullVersion) >= 15 && options.preventScrolling) {
nextTick()
.then(function () {
_this._restoreScrollStateAndRaiseEvent(el, type, callback, options, simulateEvent);
});
}
else
this._restoreScrollStateAndRaiseEvent(el, type, callback, options, simulateEvent);
}
else
simulateEvent();
};
FocusBlurSandbox.getInternalEventFlag = function (type) {
return INTERNAL_FOCUS_BLUR_FLAG_PREFIX + type;
};
FocusBlurSandbox.getNonBubblesEventType = function (bubblesEventType) {
return eventsMap.nonBubbles[bubblesEventType];
};
FocusBlurSandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
this._activeWindowTracker.attach(window);
this._topWindow = isCrossDomainWindows(window, window.top) ? window : window.top;
this._listeners.addInternalEventBeforeListener(window, ['focus', 'blur'], function () {
var activeElement = getActiveElement(_this.document);
_this._onChangeActiveElement(activeElement);
});
};
FocusBlurSandbox.prototype._raiseSelectionChange = function (callback, el) {
// NOTE: In MSEdge, the 'selectionchange' event doesn't occur immediately (it occurs with a some delay)
// so we should raise it right after the 'focus' event is raised.
if (isMSEdge && el && isTextEditableElement(el))
this._eventSimulator.selectionchange(el);
if (isFunction(callback))
callback();
};
FocusBlurSandbox.prototype.focus = function (el, callback, silent, forMouseEvent, isNativeFocus, preventScrolling) {
var _this = this;
// NOTE: el.focus() does not raise the event if the element is invisible. If the element is located
// within an invisible iframe, all browsers except Chrome do not raise the event (GH-442)
var raiseEventInIframe = !isNativeFocus || isWebKit ||
!isElementInInvisibleIframe(el);
var elDocument = (el[INTERNAL_PROPS.processedContext] || this.window).document;
// NOTE: In some cases focus event can be raised for the element in the iframe at the moment when the iframe is removed from the document.
// For example, in React application by its internal mechanism: https://github.com/DevExpress/testcafe-hammerhead/issues/2178
if (!elDocument.defaultView)
return null;
if (!raiseEventInIframe || isNativeFocus && !isElementVisible(el, elDocument))
return null;
var isElementInIframe$1 = isElementInIframe(el);
var iframeElement = isElementInIframe$1 ? getIframeByElement(el) : null;
var curDocument = findDocument(el);
var isBodyElement$1 = isBodyElement(el);
var activeElement = getActiveElement();
var activeElementDocument = findDocument(activeElement);
var withoutHandlers = false;
var needBlur = false;
var needBlurIframe = false;
var isContentEditable = isContentEditableElement(el);
var isCurrentWindowActive = this._activeWindowTracker.isCurrentWindowActive();
if (activeElement === el)
withoutHandlers = !(isBodyElement$1 && isContentEditable && !isCurrentWindowActive);
else
withoutHandlers = isBodyElement$1 && !(isContentEditable || isIE);
// NOTE: In IE, if you call focus() or blur() methods from script, an active element is changed immediately,
// but events are raised asynchronously after some timeout.
var isAsync = false;
var raiseFocusEvent = function () {
if (!isCurrentWindowActive && !isShadowUIElement(el))
_this._activeWindowTracker.makeCurrentWindowActive();
var raiseEventArgs = {
withoutHandlers: withoutHandlers || silent,
isAsync: isAsync,
forMouseEvent: forMouseEvent,
preventScrolling: preventScrolling,
relatedTarget: activeElement,
};
_this._raiseEvent(el, 'focus', function () {
if (!silent)
_this._elementEditingWatcher.watchElementEditing(el);
// NOTE: If we call focus for an unfocusable element (like 'div' or 'image') in iframe, we should
// specify document.active for this iframe manually, so we call focus without handlers.
if (isElementInIframe$1 && iframeElement &&
getActiveElement(_this._topWindow.document) !== iframeElement)
_this._raiseEvent(iframeElement, 'focus', function () { return _this._raiseSelectionChange(callback, el); }, { withoutHandlers: true, isAsync: isAsync });
else
_this._raiseSelectionChange(callback, el);
}, raiseEventArgs);
};
if (isNativeFocus && isIE) {
// NOTE: In IE, the focus() method does not have any effect if it is called in the focus event handler
// during the second event phase.
if ((this._eventSimulator.isSavedWindowsEventsExists() || version > 10) &&
this.window.event &&
this.window.event.type === 'focus' && this.window.event.srcElement === el) {
this._raiseSelectionChange(callback, el);
return null;
}
// NOTE: In MSEdge, the focus/blur events are executed synchronously.
if (version < 12)
isAsync = true;
}
if (activeElement && activeElement.tagName) {
if (activeElement !== el) {
// NOTE: B253685
if (curDocument !== activeElementDocument && activeElement === activeElementDocument.body)
needBlur = false;
else if (activeElement === curDocument.body) {
// NOTE: The Blur event is raised for the body only in IE. In addition, we must not call the
// blur function for the body because this moves the browser window into the background.
if (!silent && isIE) {
if (isAsync)
this._timersSandbox.setTimeout.call(this.window, function () { return _this._eventSimulator.blur(activeElement); }, 0);
else
this._eventSimulator.blur(activeElement);
}
}
else if (isElementFocusable(el))
needBlur = true;
}
// NOTE: B254260
needBlurIframe = curDocument !== activeElementDocument &&
isElementInIframe(activeElement, activeElementDocument);
}
// NOTE: We always call blur for iframe manually without handlers (B254260).
if (needBlurIframe && !needBlur) {
if (isIE) {
// NOTE: We should call blur for iframe with handlers in IE but we can't call the method 'blur'
// because activeElement !== element and handlers will not be called.
this._eventSimulator.blur(getIframeByElement(activeElement));
raiseFocusEvent();
}
else
this.blur(getIframeByElement(activeElement), raiseFocusEvent, true, isNativeFocus);
}
else if (needBlur) {
this.blur(activeElement, function (focusOnChange) {
if (needBlurIframe)
_this.blur(getIframeByElement(activeElement), raiseFocusEvent, true, isNativeFocus);
else if (!focusOnChange)
raiseFocusEvent();
else if (isFunction(callback))
callback();
}, silent, isNativeFocus, el);
}
else
raiseFocusEvent();
return null;
};
FocusBlurSandbox.prototype.blur = function (el, callback, withoutHandlers, isNativeBlur, relatedTarget) {
var curDocument = findDocument(el);
var activeElement = getActiveElement(curDocument);
// NOTE: In IE, if you call the focus() or blur() method from script, an active element is changed
// immediately but events are raised asynchronously after some timeout (in MSEdgethe focus/blur methods
// are executed synchronously).
var isAsync = isNativeBlur && isIE && version < 12;
if (activeElement !== el)
withoutHandlers = true;
var focusedOnChange = false;
if (!withoutHandlers) {
var focusOnChangeHandler = function (e) {
focusedOnChange = nativeMethods.eventTargetGetter.call(e) === el;
};
if (PREVENT_FOCUS_ON_CHANGE)
this._listeners.addInternalEventBeforeListener(window, ['focus'], focusOnChangeHandler);
this._elementEditingWatcher.processElementChanging(el);
if (PREVENT_FOCUS_ON_CHANGE)
this._listeners.removeInternalEventBeforeListener(window, ['focus'], focusOnChangeHandler);
this._elementEditingWatcher.stopWatching(el);
}
var raiseEventParameters = {
withoutHandlers: withoutHandlers,
isAsync: isAsync,
relatedTarget: relatedTarget,
focusedOnChange: focusedOnChange,
};
this._raiseEvent(el, 'blur', function () {
if (isFunction(callback))
callback(focusedOnChange);
}, raiseEventParameters);
};
FocusBlurSandbox.prototype.dispose = function () {
this._lastFocusedElement = null;
};
return FocusBlurSandbox;
}(SandboxBase));
var HoverSandbox = /** @class */ (function (_super) {
__extends(HoverSandbox, _super);
function HoverSandbox(_listeners) {
var _this = _super.call(this) || this;
_this._listeners = _listeners;
_this._hoverElementFixed = false;
_this._lastHoveredElement = null;
return _this;
}
HoverSandbox._setHoverMarker = function (newHoveredElement, jointParent) {
if (jointParent)
nativeMethods.setAttribute.call(jointParent, INTERNAL_ATTRIBUTES.hoverPseudoClass, '');
while (newHoveredElement && newHoveredElement.tagName) {
// NOTE: Assign a pseudo-class marker to the elements until the joint parent is found.
if (newHoveredElement !== jointParent) {
nativeMethods.setAttribute.call(newHoveredElement, INTERNAL_ATTRIBUTES.hoverPseudoClass, '');
var associatedElement = getAssociatedElement(newHoveredElement);
if (associatedElement)
nativeMethods.setAttribute.call(associatedElement, INTERNAL_ATTRIBUTES.hoverPseudoClass, '');
newHoveredElement = nativeMethods.nodeParentNodeGetter.call(newHoveredElement);
}
else
break;
}
};
// NOTE: In this method, we go up to the tree of elements and look for a joint parent for the
// previous and new hovered elements. Processing is needed only until that parent is found.
// In this case, we'll reduce the number of dom calls.
HoverSandbox.prototype._clearHoverMarkerUntilJointParent = function (newHoveredElement) {
var jointParent = null;
if (this._lastHoveredElement) {
var el = this._lastHoveredElement;
while (el && el.tagName && el.contains) {
var associatedElement = getAssociatedElement(el);
if (associatedElement)
nativeMethods.removeAttribute.call(associatedElement, INTERNAL_ATTRIBUTES.hoverPseudoClass);
// NOTE: Check that the current element is a joint parent for the hovered elements.
if (!el.contains(newHoveredElement)) {
nativeMethods.removeAttribute.call(el, INTERNAL_ATTRIBUTES.hoverPseudoClass);
el = nativeMethods.nodeParentNodeGetter.call(el);
}
else {
jointParent = el;
break;
}
}
if (jointParent)
nativeMethods.removeAttribute.call(jointParent, INTERNAL_ATTRIBUTES.hoverPseudoClass);
}
return jointParent;
};
HoverSandbox.prototype._onHover = function (e) {
var target = nativeMethods.eventTargetGetter.call(e);
var clientX = e.clientX, clientY = e.clientY;
var hoverIsDisabled = isIE &&
shouldIgnoreEventInsideIframe(target, clientX, clientY);
if (!hoverIsDisabled)
this._hover(target);
};
HoverSandbox.prototype._hover = function (el) {
if (!this._hoverElementFixed && !isShadowUIElement(el)) {
var jointParent = this._clearHoverMarkerUntilJointParent(el);
HoverSandbox._setHoverMarker(el, jointParent);
this._lastHoveredElement = el;
}
};
HoverSandbox.prototype.fixHoveredElement = function () {
this._hoverElementFixed = true;
};
HoverSandbox.prototype.freeHoveredElement = function () {
this._hoverElementFixed = false;
};
HoverSandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
this._listeners.addInternalEventBeforeListener(window, ['mouseover', 'touchstart'], function (e) { return _this._onHover(e); });
};
HoverSandbox.prototype.dispose = function () {
this._lastHoveredElement = null;
};
return HoverSandbox;
}(SandboxBase));
var Selection = /** @class */ (function () {
function Selection(eventSandbox) {
this.focusBlurSandbox = eventSandbox.focusBlur;
this.timersSandbox = eventSandbox.timers;
this.listeners = eventSandbox.listeners;
this.eventSimulator = eventSandbox.eventSimulator;
var selection = this;
var eventSimulator = this.eventSimulator;
var listeners = this.listeners;
var timersSandbox = this.timersSandbox;
this.setSelectionRangeWrapper = function () {
var selectionStart = arguments[0];
var selectionEnd = arguments[1];
var selectionDirection = arguments[2] || 'none';
var el = this;
var fn = isTextAreaElement(el) ? nativeMethods.textAreaSetSelectionRange : nativeMethods.setSelectionRange;
var activeElement = getActiveElement(findDocument(el));
var curDocument = findDocument(el);
var isElementActive = false;
var selectionSetter = function () {
// NOTE: These browsers cannot restore the `selectionStart` and `selectionEnd` properties when we change the `type` attribute.
// So we need to use our own mechanism to store the `selectionStart` and `selectionEnd` properties.
var useInternalSelection = isInputWithoutSelectionProperties(el);
var savedType = el.type;
var res;
if (useInternalSelection)
el.setAttribute('type', 'text');
// NOTE: In MSEdge, an error occurs when the setSelectionRange method is called for an input with
// 'display = none' and selectionStart !== selectionEnd in other IEs, the error doesn't occur, but
// as a result selectionStart === selectionEnd === 0.
try {
res = fn.call(el, selectionStart, selectionEnd, selectionDirection);
}
catch (e) {
res = fn.call(el, 0, 0, selectionDirection);
}
if (useInternalSelection) {
el[INTERNAL_PROPS.selection] = {
selectionStart: el.selectionStart,
selectionEnd: el.selectionEnd,
selectionDirection: el.selectionDirection,
};
el.setAttribute('type', savedType);
// HACK: (A problem with input type = 'number' after Chrome is updated to v.33.0.1750.117 and
// in Firefox 29.0. T101195) To set right selection: if the input type is 'number' or 'email',
// we need to change the type to text, and then restore it after setting selection.(B254340).
// However, the type is changed asynchronously in this case. To force type changing,we need to
// call blur, Then raise the focus event to make the element active.
if (isElementActive) {
selection.focusBlurSandbox.blur(el, null, true);
selection.focusBlurSandbox.focus(el, null, true);
// HACK: we should call focus for previous active element again because
// in Firefox 55.0.3 after first focus active element isn't changed
if (getActiveElement(findDocument(el)) !== el)
selection.focusBlurSandbox.focus(el, null, true);
}
}
// NOTE: In MSEdge, the 'selectionchange' event doesn't occur immediately (it occurs with a delay)
// So, we should raise it right after the 'setSelectionRange' method.
if (isMSEdge)
eventSimulator.selectionchange(el);
return res;
};
if (activeElement === el) {
isElementActive = true;
return selectionSetter();
}
var needFocus = isIE11 || isMSEdge &&
(version === 17 && !curDocument.hasFocus() || version > 17);
return selection.wrapSetterSelection(el, selectionSetter, needFocus);
};
this.selectWrapper = function () {
// NOTE: Non-standard IE Only class TextRange
// @ts-ignore
var element = this.parentElement();
if (!element || getActiveElement(findDocument(element)) === element)
return nativeMethods.select.call(this);
var result = null;
var focusRaised = false;
var focusHandler = function (e) {
if (nativeMethods.eventTargetGetter.call(e) === element || element.style.display === 'none')
focusRaised = true;
};
listeners.addInternalEventBeforeListener(document, ['focus'], focusHandler);
result = nativeMethods.select.call(this);
timersSandbox.setTimeout.call(window, function () {
timersSandbox.setTimeout.call(window, function () {
listeners.removeInternalEventBeforeListener(document, ['focus'], focusHandler);
if (!focusRaised)
eventSimulator.focus(element);
}, 0);
}, 0);
return result;
};
}
Selection.prototype.setSelection = function (el, start, end, direction) {
if (el.setSelectionRange)
el.setSelectionRange(start, end, direction);
else {
el.selectionStart = start;
el.selectionEnd = end;
}
};
Selection.prototype.getSelection = function (el) {
var internalSelection = el[INTERNAL_PROPS.selection];
return {
start: internalSelection ? internalSelection.selectionStart : el.selectionStart,
end: internalSelection ? internalSelection.selectionEnd : el.selectionEnd,
direction: internalSelection ? internalSelection.selectionDirection : el.selectionDirection,
};
};
Selection.prototype.wrapSetterSelection = function (el, selectionSetter, needFocus, isContentEditable) {
var _this = this;
var curDocument = findDocument(el);
var activeElement = getActiveElement(curDocument);
var result = null;
var focusRaised = false;
// NOTE: we should not call focus during selection setting
// if element has been focused already (TestCafe GH-2301)
needFocus = needFocus && activeElement !== el;
var focusHandler = function (e) {
if (nativeMethods.eventTargetGetter.call(e) === el || el.style.display === 'none')
focusRaised = true;
};
if (needFocus)
this.listeners.addInternalEventBeforeListener(document, ['focus'], focusHandler);
// The focus and blur events
Listeners.beforeDispatchEvent(el);
Listeners.beforeDispatchEvent(el);
result = selectionSetter();
// The focus and blur events
Listeners.afterDispatchEvent(el);
Listeners.afterDispatchEvent(el);
if (needFocus) {
activeElement = getActiveElement(curDocument);
if (activeElement !== el && (isWebKit || isMSEdge && version > 17)) {
if (focusRaised)
el[FocusBlurSandbox.getInternalEventFlag('focus')] = true;
el.focus();
}
// NOTE: In MSEdge, focus and blur are sync.
if (isIE11) {
this.timersSandbox.setTimeout.call(window, function () {
_this.timersSandbox.setTimeout.call(window, function () {
_this.listeners.removeInternalEventBeforeListener(document, ['focus'], focusHandler);
if (!focusRaised)
_this.eventSimulator.focus(el);
}, 0);
}, 0);
}
else {
this.listeners.removeInternalEventBeforeListener(document, ['focus'], focusHandler);
if (!focusRaised) {
// NOTE: In Firefox, raising the dispatchEvent 'focus' doesnt activate an element.
// We should call the native focus method.
if (isContentEditable && isFirefox)
this.focusBlurSandbox.focus(el, null, true, false, true);
else
this.eventSimulator.focus(el);
}
}
}
return result;
};
return Selection;
}());
// https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-item-kind
var DATA_TRANSFER_ITEM_KIND = {
string: 'string',
file: 'file',
};
// https://html.spec.whatwg.org/multipage/interaction.html#datatransferitem
var DataTransferItem = /** @class */ (function () {
function DataTransferItem(kind, type, data) {
nativeMethods.objectDefineProperty(this, 'kind', {
enumerable: true,
get: function () { return kind; },
});
nativeMethods.objectDefineProperty(this, 'type', {
enumerable: true,
get: function () { return type; },
});
nativeMethods.objectDefineProperty(this, 'getAsString', {
configurable: true,
enumerable: true,
get: function () {
return function (callback) {
if (!arguments.length)
throw new Error("Failed to execute 'getAsString' on 'DataTransferItem': 1 argument required, but only 0 present.");
if (!isFunction(callback))
return;
if (kind !== DATA_TRANSFER_ITEM_KIND.string)
return;
nativeMethods.setTimeout.call(window, function () { return callback(data); }, 0);
};
},
});
nativeMethods.objectDefineProperty(this, 'getAsFile', {
configurable: true,
enumerable: true,
get: function () {
return function () {
if (kind !== DATA_TRANSFER_ITEM_KIND.file)
return null;
return data;
};
},
});
}
return DataTransferItem;
}());
if (nativeMethods.DataTransferItem)
DataTransferItem.prototype = nativeMethods.DataTransferItem.prototype;
// https://html.spec.whatwg.org/multipage/interaction.html#drag-data-store-mode
var DATA_STORE_MODE = {
readwrite: 'readwrite',
readonly: 'readonly',
protected: 'protected',
};
function parseTextUriList(textUriList) {
textUriList = textUriList.replace(/\r\n$/, '');
var res = [];
if (textUriList === '')
return res;
textUriList = textUriList.split(/\r\n/);
for (var _i = 0, textUriList_1 = textUriList; _i < textUriList_1.length; _i++) {
var textUri = textUriList_1[_i];
if (textUri !== '#')
res.push(textUri);
}
return res;
}
function processFormat(format) {
if (format === 'text')
return 'text/plain';
if (format === 'url')
return 'text/uri-list';
return format;
}
// https://html.spec.whatwg.org/multipage/interaction.html#datatransferitemlist
var DataTransferItemList = /** @class */ (function () {
function DataTransferItemList(dataStore) {
var _this = this;
// Internals
var items = [];
var itemsData = [];
var getTypes = function () {
var res = [];
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
var item = items_1[_i];
res.push(item.type);
}
return res;
};
var updateIndexes = function () {
var idx = 0;
while (items[idx] !== void 0 || _this[idx] !== void 0) {
var item = items[idx];
nativeMethods.objectDefineProperty(_this, idx, {
enumerable: item !== void 0,
configurable: true,
value: item,
});
idx++;
}
};
var getItemData = function (format) {
var convertToUrl = false;
format = processFormat(format);
if (format === 'url')
convertToUrl = true;
var item = '';
for (var i = 0; i < items.length; i++) {
if (items[i].type === format)
item = itemsData[i];
}
if (convertToUrl && item)
item = parseTextUriList(item)[0];
return item;
};
var removeItem = function (format) {
format = processFormat(format);
for (var i = 0; i < items.length; i++) {
if (items[i].type === format) {
items.splice(i, 1);
itemsData.splice(i, 1);
break;
}
}
updateIndexes();
};
var addItem = function (data, type, allowReplace) {
var newItem = null;
if (typeof data === 'string') {
var typeLowerCase = type.toString().toLowerCase();
var itemData = getItemData(typeLowerCase);
if (!allowReplace && itemData)
throw new Error("Failed to execute 'add' on 'DataTransferItemList': An item already exists for type '".concat(typeLowerCase, "'."));
if (itemData)
removeItem(typeLowerCase);
newItem = new DataTransferItem(DATA_TRANSFER_ITEM_KIND.string, processFormat(type), data);
}
else
newItem = new DataTransferItem(DATA_TRANSFER_ITEM_KIND.file, null, data);
items.push(newItem);
itemsData.push(data);
updateIndexes();
return newItem;
};
// Internal API
this.getAndHideInternalMethods = function () {
var res = { getTypes: getTypes, getItemData: getItemData, removeItem: removeItem, addItem: addItem };
delete _this.getAndHideInternalMethods;
return res;
};
// API
nativeMethods.objectDefineProperty(this, 'length', {
enumerable: true,
get: function () { return items.length; },
});
nativeMethods.objectDefineProperty(this, 'remove', {
configurable: true,
enumerable: true,
get: function () {
return function (idx) {
if (dataStore.mode !== DATA_STORE_MODE.readwrite)
return;
items.splice(idx, 1);
itemsData.splice(idx, 1);
updateIndexes();
};
},
});
nativeMethods.objectDefineProperty(this, 'clear', {
configurable: true,
enumerable: true,
get: function () {
return function () {
if (dataStore.mode !== DATA_STORE_MODE.readwrite)
return;
items = [];
itemsData = [];
updateIndexes();
};
},
});
nativeMethods.objectDefineProperty(this, 'add', {
configurable: true,
enumerable: true,
get: function () {
return function (data, type) {
if (!arguments.length)
throw new Error("Failed to execute 'add' on 'DataTransferItemList': 1 argument required, but only 0 present.");
if (arguments.length === 1 && typeof data === 'string')
throw new Error("Failed to execute 'add' on 'DataTransferItemList': parameter 1 is not of type 'File'.");
if (dataStore.mode !== DATA_STORE_MODE.readwrite)
return void 0;
return addItem(data, type, false);
};
},
});
}
return DataTransferItemList;
}());
if (nativeMethods.DataTransferItemList)
DataTransferItemList.prototype = nativeMethods.DataTransferItemList.prototype;
// https://w3c.github.io/FileAPI/#filelist-section
var FileList$1 = /** @class */ (function () {
function FileList() {
nativeMethods.objectDefineProperty(this, 'length', {
enumerable: true,
get: function () { return 0; },
});
nativeMethods.objectDefineProperty(this, 'item', {
enumerable: true,
get: function () {
return function () {
return void 0;
};
},
});
}
return FileList;
}());
if (nativeMethods.FileList)
FileList$1.prototype = nativeMethods.FileList.prototype;
// https://html.spec.whatwg.org/multipage/interaction.html#dom-datatransfer-dropeffect
var DROP_EFFECT = {
none: 'none',
copy: 'copy',
link: 'link',
move: 'move',
};
// https://html.spec.whatwg.org/multipage/interaction.html#dom-datatransfer-effectallowed
var EFFECT_ALLOWED = {
uninitialized: 'uninitialized',
none: 'none',
copy: 'copy',
copyLink: 'copyLink',
copyMove: 'copyMove',
link: 'link',
linkMove: 'linkMove',
move: 'move',
all: 'all',
};
// NOTE: Although DataTransfer interface has a constructor, it is not possible to
// https://html.spec.whatwg.org/multipage/interaction.html#datatransfer
var DataTransfer = /** @class */ (function () {
function DataTransfer(dataStore) {
var dropEffect = DROP_EFFECT.none;
var effectAllowed = EFFECT_ALLOWED.uninitialized;
var itemList = new DataTransferItemList(dataStore);
var itemListInternals = itemList.getAndHideInternalMethods();
var fileList = new FileList$1();
var emptyItemList = new DataTransferItemList(dataStore);
var emptyListInternals = emptyItemList.getAndHideInternalMethods();
var getActualItemList = function () {
return dataStore.mode === DATA_STORE_MODE.protected ? emptyItemList : itemList;
};
var getActualItemListInternals = function () {
return dataStore.mode === DATA_STORE_MODE.protected ? emptyListInternals : itemListInternals;
};
nativeMethods.objectDefineProperty(this, 'dropEffect', {
configurable: true,
enumerable: true,
get: function () { return dropEffect; },
set: function (value) {
if (DROP_EFFECT[value])
dropEffect = DROP_EFFECT[value];
return value;
},
});
nativeMethods.objectDefineProperty(this, 'effectAllowed', {
configurable: true,
enumerable: true,
get: function () { return effectAllowed; },
set: function (value) {
if (EFFECT_ALLOWED[value])
effectAllowed = EFFECT_ALLOWED[value];
return value;
},
});
if (!isIE11) {
nativeMethods.objectDefineProperty(this, 'items', {
configurable: true,
enumerable: true,
get: getActualItemList,
});
}
nativeMethods.objectDefineProperty(this, 'types', {
configurable: true,
enumerable: true,
get: function () { return getActualItemListInternals().getTypes(); },
});
nativeMethods.objectDefineProperty(this, 'files', {
configurable: true,
enumerable: true,
get: function () { return fileList; },
});
if (!isIE11) {
this.setDragImage = function () {
// do nothing
};
}
this.getData = function (format) {
if (!arguments.length)
throw new Error("Failed to execute 'getData' on 'DataTransfer': 1 argument required, but only 0 present.");
format = format.toString().toLowerCase();
return getActualItemListInternals().getItemData(format);
};
this.setData = function (format, data) {
if (arguments.length < 2)
throw new Error("Failed to execute 'setData' on 'DataTransfer': 2 argument required, but only ".concat(arguments.length, " present."));
if (dataStore.mode !== DATA_STORE_MODE.readwrite)
return;
format = format.toString().toLowerCase();
itemListInternals.addItem(data, format, true);
};
this.clearData = function (format) {
if (dataStore.mode !== DATA_STORE_MODE.readwrite)
return;
if (format === void 0)
// @ts-ignore
itemList.clear();
else
itemListInternals.removeItem(format);
};
}
return DataTransfer;
}());
if (hasDataTransfer)
DataTransfer.prototype = nativeMethods.DataTransfer.prototype;
// https://html.spec.whatwg.org/multipage/interaction.html#the-drag-data-store
var DragDataStore = /** @class */ (function () {
function DragDataStore() {
this.mode = DATA_STORE_MODE.readwrite;
}
DragDataStore.prototype.setReadOnlyMode = function () {
this.mode = DATA_STORE_MODE.readonly;
};
DragDataStore.prototype.setProtectedMode = function () {
this.mode = DATA_STORE_MODE.protected;
};
return DragDataStore;
}());
var EventSandbox = /** @class */ (function (_super) {
__extends(EventSandbox, _super);
function EventSandbox(listeners, eventSimulator, elementEditingWatcher, unloadSandbox, messageSandbox, _shadowUI, timerSandbox) {
var _this = _super.call(this) || this;
_this._shadowUI = _shadowUI;
_this.EVENT_PREVENTED_EVENT = 'hammerhead|event|event-prevented';
_this.listeners = listeners;
_this.elementEditingWatcher = elementEditingWatcher;
_this.unload = unloadSandbox;
_this.timers = timerSandbox;
_this.eventSimulator = eventSimulator;
_this.focusBlur = new FocusBlurSandbox(listeners, eventSimulator, messageSandbox, timerSandbox, elementEditingWatcher);
_this.selection = new Selection(_this);
_this.hover = new HoverSandbox(listeners);
_this._shadowUI = _shadowUI;
_this.message = messageSandbox;
_this.DataTransfer = DataTransfer;
_this.DragDataStore = DragDataStore;
_this._overriddenMethods = null;
_this._onFocus = null;
_this._cancelInternalEvents = null;
_this._createOverriddenMethods();
_this._createInternalHandlers();
return _this;
}
EventSandbox.prototype._createOverriddenMethods = function () {
var selection = this.selection;
var focusBlurSandbox = this.focusBlur;
var eventSimulator = this.eventSimulator;
var sandbox = this;
this._overriddenMethods = {
dispatchEvent: function () {
Listeners.beforeDispatchEvent(this);
var res = isIE11 && isWindow(this)
? nativeMethods.windowDispatchEvent.apply(this, arguments)
: nativeMethods.dispatchEvent.apply(this, arguments);
Listeners.afterDispatchEvent(this);
return res;
},
click: function () {
Listeners.beforeDispatchEvent(this);
var res = eventSimulator.nativeClick(this, nativeMethods.click);
Listeners.afterDispatchEvent(this);
return res;
},
setSelectionRange: function () {
return selection.setSelectionRangeWrapper.apply(this, arguments);
},
select: function () {
return selection.selectWrapper.call(this);
},
focus: function () {
return focusBlurSandbox.focus(this, null, false, false, true);
},
blur: function () {
return focusBlurSandbox.blur(this, null, false, true);
},
preventDefault: function () {
sandbox.emit(sandbox.EVENT_PREVENTED_EVENT, this);
return nativeMethods.preventDefault.call(this);
},
};
};
EventSandbox.prototype._createInternalHandlers = function () {
var shadowUI = this._shadowUI;
var document = this.document;
var eventSimulator = this.eventSimulator;
this._onFocus = function (e) {
var focusedEl = nativeMethods.eventTargetGetter.call(e);
var activeEl = getActiveElement(document);
if (!isShadowUIElement(focusedEl) && !isShadowUIElement(activeEl))
shadowUI.setLastActiveElement(activeEl);
};
this._cancelInternalEvents = function (e, _dispatched, _preventEvent, _cancelHandlers, stopPropagation) {
// NOTE: We should cancel events raised by calling the native function (focus, blur) only if the
// element has a flag. If an event is dispatched, we shouldn't cancel it.
// After calling a native function two events were raised
// .focus() -> focus, focusin
// .blur() -> blur, focusout
// So we should prevent both events
var eventType = FocusBlurSandbox.getNonBubblesEventType(e.type) || e.type;
var internalEventFlag = FocusBlurSandbox.getInternalEventFlag(eventType);
var target = nativeMethods.eventTargetGetter.call(e);
if (target[internalEventFlag] && !e[eventSimulator.DISPATCHED_EVENT_FLAG])
stopPropagation();
};
};
EventSandbox.prototype._preventInputNativeDialogs = function (window) {
var shouldPreventClickEvents = isFirefox || isIE;
if (!shouldPreventClickEvents)
return;
// NOTE: Google Chrome and Safari don't open the native browser dialog when TestCafe clicks on the input.
// 'Click' is a complex emulated action that uses 'dispatchEvent' method internally.
// Another browsers open the native browser dialog in this case.
// This is why, we are forced to prevent the browser's open file dialog.
this.listeners.addInternalEventBeforeListener(window, ['click'], function (e, dispatched) {
if (dispatched && isInputWithNativeDialog(nativeMethods.eventTargetGetter.call(e)))
preventDefault(e, true);
});
};
EventSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
overrideFunction(window.HTMLInputElement.prototype, 'setSelectionRange', this._overriddenMethods.setSelectionRange);
overrideFunction(window.HTMLTextAreaElement.prototype, 'setSelectionRange', this._overriddenMethods.setSelectionRange);
if (isIE11) {
overrideFunction(window.Window.prototype, 'dispatchEvent', this._overriddenMethods.dispatchEvent);
overrideFunction(window.Document.prototype, 'dispatchEvent', this._overriddenMethods.dispatchEvent);
overrideFunction(window.HTMLElement.prototype, 'dispatchEvent', this._overriddenMethods.dispatchEvent);
overrideFunction(window.SVGElement.prototype, 'dispatchEvent', this._overriddenMethods.dispatchEvent);
}
else
overrideFunction(window.EventTarget.prototype, 'dispatchEvent', this._overriddenMethods.dispatchEvent);
overrideFunction(window.HTMLElement.prototype, 'focus', this._overriddenMethods.focus);
overrideFunction(window.HTMLElement.prototype, 'blur', this._overriddenMethods.blur);
overrideFunction(window.HTMLElement.prototype, 'click', this._overriddenMethods.click);
overrideFunction(window.Event.prototype, 'preventDefault', this._overriddenMethods.preventDefault);
// @ts-ignore Window constructor has no the focus method
window.Window.focus = this._overriddenMethods.focus;
// NOTE: we cannot use 'overrideFunction' here since the focus method may not exist
// @ts-ignore Window constructor has no the focus method
overrideStringRepresentation(window.Window.focus, nativeMethods.focus);
// @ts-ignore Window constructor has no the blur method
window.Window.blur = this._overriddenMethods.blur;
// NOTE: we cannot use 'overrideFunction' here since the blur method may not exist
// @ts-ignore Window constructor has no the blur method
overrideStringRepresentation(window.Window.blur, nativeMethods.blur);
// @ts-ignore TextRange exists only in IE
if (window.TextRange && window.TextRange.prototype.select)
// @ts-ignore TextRange exists only in IE
overrideFunction(window.TextRange.prototype, 'select', this._overriddenMethods.select);
this.listeners.initElementListening(document, DOM_EVENTS);
this.listeners.initElementListening(window, DOM_EVENTS.concat(['load', 'beforeunload', 'pagehide', 'unload', 'message']));
this.listeners.addInternalEventBeforeListener(window, ['focus'], this._onFocus);
this.listeners.addInternalEventBeforeListener(window, ['focus', 'blur', 'change', 'focusin', 'focusout'], this._cancelInternalEvents);
this._preventInputNativeDialogs(window);
this.unload.attach(window);
this.message.attach(window);
this.timers.attach(window);
this.focusBlur.attach(window);
this.hover.attach(window);
};
EventSandbox.prototype.reattach = function (window) {
this.listeners.restartElementListening(window.document);
this.listeners.restartElementListening(window);
};
return EventSandbox;
}(SandboxBase));
function extend(target) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
target = target || {};
var currentObj = null;
var copy = null;
if (typeof target !== 'object' && target.toString() !== '[object Function]')
target = {};
for (var i = 0; i < args.length; i++) {
currentObj = args[i];
if (currentObj !== null) {
for (var name_1 in currentObj) {
copy = currentObj[name_1];
if (target !== copy && copy !== void 0)
target[name_1] = copy;
}
}
}
return target;
}
var TOUCH_EVENT_RADIUS = 25;
var TOUCH_EVENT_FORCE = 0.5;
var POINTER_EVENT_BUTTON = {
noButton: -1,
leftButton: 0,
rightButton: 2,
};
// NOTE: (IE11 only) 'MouseEvent.detail' value always equals 0 for 'click' and 'dblclick' events.
// Otherwise, MouseEvent.detail behave as described in specification - https://www.w3.org/TR/uievents/#events-mouseevents
var DEFAULT_MOUSE_EVENT_DETAIL_PROP_VALUE = {
click: isIE ? 0 : 1,
dblclick: isIE ? 0 : 2,
mousedown: 1,
mouseup: 1,
};
var KEY_EVENT_NAME_RE = /^key\w+$/;
var MOUSE_EVENT_NAME_RE = /^((mouse\w+)|((dbl)?click)|(contextmenu)|(drag\w*)|(drop))$/;
var TOUCH_EVENT_NAME_RE = /^touch\w+$/;
var FOCUS_IN_OUT_EVENT_NAME_RE = /^focus(in|out)$/;
// NOTE: initTextEvent method required INPUT_METHOD param in IE
var DOM_INPUT_METHOD_KEYBOARD = 1;
var MOUSE_EVENTS_TO_FORCE_POINTER_EVENTS = [
'mouseover',
'mouseenter',
'mouseout',
];
var MOUSE_TO_POINTER_EVENT_TYPE_MAP = {
mousedown: 'pointerdown',
mouseup: 'pointerup',
mousemove: 'pointermove',
mouseover: 'pointerover',
mouseenter: 'pointerenter',
mouseout: 'pointerout',
};
var TOUCH_TO_POINTER_EVENT_TYPE_MAP = {
touchstart: 'pointerdown',
touchend: 'pointerup',
touchmove: 'pointermove',
};
var DISABLEABLE_HTML_ELEMENT_TYPE_CHECKERS = [
isButtonElement,
isFieldSetElement,
isInputElement,
isOptGroupElement,
isOptionElement,
isSelectElement,
isTextAreaElement,
];
var EventSimulator = /** @class */ (function () {
function EventSimulator() {
this.DISPATCHED_EVENT_FLAG = 'hammerhead|dispatched-event';
this.touchIdentifier = nativeMethods.dateNow();
// NOTE: (IE only) If event dispatching calls a native click function, we should clear the window.event
// property (which was set in the raiseDispatchEvent function). Otherwise, the window.event property will
// contain the dispatched event, not the native click event. We should restore the window.event value after
// the click is handled. (B237144)
this.savedWindowEvents = [];
this.savedNativeClickCount = 0;
this.browserWithNewEventsStyle = !isIE11;
}
EventSimulator._dispatchStorageEvent = function (el, args) {
var ev = nativeMethods.documentCreateEvent.call(document, 'StorageEvent');
ev.initStorageEvent('storage', args.canBubble, args.cancelable, args.key, args.oldValue, args.newValue, args.url, null);
nativeMethods.objectDefineProperty(ev, 'storageArea', {
get: function () { return args.storageArea; },
configurable: true,
});
if (args.key === null) {
nativeMethods.objectDefineProperty(ev, 'key', {
get: function () { return null; },
configurable: true,
});
}
return el.dispatchEvent(ev);
};
EventSimulator.prototype._dispatchTouchEvent = function (el, args) {
if (shouldIgnoreEventInsideIframe(el, args.clientX, args.clientY))
return true;
var ev = nativeMethods.documentCreateEvent.call(document, 'TouchEvent');
// HACK: A test for iOS by using initTouchEvent arguments.
// TODO: Replace it with a user agent analysis later.
if (ev.initTouchEvent) {
if (isIOS) {
ev.initTouchEvent(args.type, args.canBubble, args.cancelable, args.view, args.detail, args.screenX, args.screenY, args.pageX, args.pageY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, args.touches, args.targetTouches, args.changedTouches, args.scale === void 0 ? 1.0 : args.scale,
// NOTE: B237995
args.rotation === void 0 ? 0.0 : args.rotation);
}
else if (ev.initTouchEvent.length === 12) {
// NOTE: The Firefox.
ev.initTouchEvent(args.type, args.canBubble, args.cancelable, args.view, args.detail, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, args.touches, args.targetTouches, args.changedTouches);
}
else {
// NOTE: The default Android browser, Dolphin.
ev.initTouchEvent(args.touches, args.targetTouches, args.changedTouches, args.type, args.view, args.screenX, args.screenY, args.pageX - args.view.pageXOffset, args.pageY - args.view.pageYOffset, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey);
}
}
else {
ev = new nativeMethods.WindowTouchEvent(args.type, {
touches: args.touches,
targetTouches: args.targetTouches,
changedTouches: args.changedTouches,
ctrlKey: args.ctrlKey,
altKey: args.altKey,
shiftKey: args.shiftKey,
metaKey: args.metaKey,
bubbles: args.canBubble,
cancelable: args.cancelable,
cancelBubble: false,
defaultPrevented: false,
detail: args.detail,
view: args.view,
});
}
if (hasPointerEvents)
this._dispatchPointerEvent(el, args);
return el.dispatchEvent(ev);
};
EventSimulator._getUIEventArgs = function (type, options) {
if (options === void 0) { options = {}; }
var detail = 'detail' in options ? options.detail : DEFAULT_MOUSE_EVENT_DETAIL_PROP_VALUE[type];
return {
type: type,
composed: options.composed,
canBubble: options.canBubble !== false,
cancelable: options.cancelable !== false,
view: options.view || window,
detail: detail || 0,
ctrlKey: options.ctrlKey || false,
altKey: options.altKey || false,
shiftKey: options.shiftKey || false,
metaKey: options.metaKey || false,
};
};
EventSimulator._getStorageEventArgs = function (options) {
if (options === void 0) { options = {}; }
return extend(options, {
canBubble: options.canBubble !== false,
cancelable: options.cancelable !== false,
});
};
EventSimulator._getMouseEventArgs = function (type, options) {
if (options === void 0) { options = {}; }
return extend(EventSimulator._getUIEventArgs(type, options), {
screenX: options.screenX || 0,
screenY: options.screenY || 0,
clientX: options.clientX || 0,
clientY: options.clientY || 0,
button: options.button === void 0 ? BUTTON.left : options.button,
buttons: options.buttons === void 0 ? BUTTONS_PARAMETER.leftButton : options.buttons,
relatedTarget: options.relatedTarget || null,
which: options.which,
});
};
EventSimulator._getKeyEventArgs = function (type, options) {
var keyOptions = {
keyCode: options.keyCode || 0,
charCode: options.charCode || 0,
which: type === 'press' ? options.charCode : options.keyCode,
};
if ('keyIdentifier' in options)
keyOptions.keyIdentifier = options.keyIdentifier;
if ('key' in options)
keyOptions.key = options.key;
return extend(EventSimulator._getUIEventArgs(type, options), keyOptions);
};
EventSimulator._getModifiersAsString = function (args) {
var modifiersString = '';
for (var modifier in KEYBOARD_MODIFIERS_PARAMETER) {
if (nativeMethods.objectHasOwnProperty.call(KEYBOARD_MODIFIERS_PARAMETER, modifier) && args[modifier])
modifiersString += KEYBOARD_MODIFIERS_PARAMETER[modifier] + ' ';
}
return modifiersString;
};
EventSimulator._prepareMouseEventOptions = function (options) {
if (options === void 0) { options = {}; }
var buttons = options.buttons === void 0 ? BUTTONS_PARAMETER.noButton : options.buttons;
var button = BUTTON.left;
options.buttons = buttons;
options.button = options.button || button;
if (isWebKit) {
options.which = WHICH_PARAMETER.leftButton;
if (options.buttons === BUTTONS_PARAMETER.noButton)
options.which = WHICH_PARAMETER.noButton;
if (options.buttons === BUTTONS_PARAMETER.rightButton)
options.which = WHICH_PARAMETER.rightButton;
}
return options;
};
EventSimulator._isDisabled = function (node) {
return node && node.hasAttribute && nativeMethods.hasAttribute.call(node, 'disabled');
};
EventSimulator.prototype._simulateEvent = function (el, event, userOptions, options) {
var _this = this;
if (options === void 0) { options = {}; }
var args = null;
var dispatch = null;
// NOTE: We don't simulate a click on links with modifiers (ctrl, shift, ctrl+shift, alt),
// because it causes the opening of a browser window or additional tabs in it or loading files.
var isClickOnLink = event === 'click' && isAnchorElement(el);
var opts = extend(userOptions ? {
clientX: userOptions.clientX,
clientY: userOptions.clientY,
screenX: userOptions.screenX,
screenY: userOptions.screenY,
altKey: isClickOnLink ? false : userOptions.alt,
shiftKey: isClickOnLink ? false : userOptions.shift,
ctrlKey: isClickOnLink ? false : userOptions.ctrl,
metaKey: userOptions.meta,
button: userOptions.button,
which: userOptions.which,
buttons: userOptions.buttons,
relatedTarget: userOptions.relatedTarget,
} : {}, options);
opts.composed = isComposedEvent(event);
if (!opts.relatedTarget)
opts.relatedTarget = document.body;
if (event === 'storage') {
opts = extend(opts, userOptions);
args = EventSimulator._getStorageEventArgs(opts);
dispatch = EventSimulator._dispatchStorageEvent;
}
else if (MOUSE_EVENT_NAME_RE.test(event)) {
if (userOptions && userOptions.button !== void 0)
opts = extend(opts, { button: userOptions.button });
args = EventSimulator._getMouseEventArgs(event, opts);
// eslint-disable-next-line no-shadow
dispatch = function (el, args) { return _this._dispatchMouseRelatedEvents(el, args, userOptions); };
}
else if (KEY_EVENT_NAME_RE.test(event)) {
if (userOptions &&
(userOptions.keyCode !== void 0 || userOptions.charCode !== void 0)) {
opts = extend(opts, {
key: userOptions.key || void 0,
keyCode: userOptions.keyCode || 0,
charCode: userOptions.charCode || 0,
});
if ('keyIdentifier' in userOptions)
opts.keyIdentifier = userOptions.keyIdentifier;
if ('key' in userOptions)
opts.key = userOptions.key;
}
args = EventSimulator._getKeyEventArgs(event, opts);
// eslint-disable-next-line no-shadow
dispatch = function (el, args) { return _this._dispatchKeyEvent(el, args); };
}
else if (TOUCH_EVENT_NAME_RE.test(event)) {
args = this._getTouchEventArgs(event, extend(opts, { target: el }));
// eslint-disable-next-line no-shadow
dispatch = function (el, args) { return _this._dispatchTouchEvent(el, args); };
}
return dispatch(el, args);
};
EventSimulator.prototype._getTouchEventArgs = function (type, options) {
var _a, _b;
if (options === void 0) { options = {}; }
var args = extend(EventSimulator._getUIEventArgs(type, options), {
screenX: options.screenX || 0,
screenY: options.screenY || 0,
clientX: options.clientX || 0,
clientY: options.clientY || 0,
pageX: options.clientX || 0,
pageY: options.clientY || 0,
identifier: this._getTouchIdentifier(type),
});
if (nativeMethods.documentCreateTouch) {
if (isIOS)
args.touch = nativeMethods.documentCreateTouch.call(document, args.view, options.target, args.identifier, args.clientX, args.clientY, 0, 0);
else {
// NOTE: B237995
args.touch = nativeMethods.documentCreateTouch.call(document, args.view, options.target, args.identifier, args.pageX, args.pageY, args.screenX, args.screenY, args.clientX, args.clientY, null, null, args.rotation === void 0 ? 0 : args.rotation);
}
}
else {
args.touch = new nativeMethods.WindowTouch({
identifier: args.identifier,
target: options.target,
clientX: args.clientX,
clientY: args.clientY,
pageX: args.pageX,
pageY: args.pageY,
screenX: args.screenX,
screenY: args.screenY,
rotationAngle: 0,
radiusX: TOUCH_EVENT_RADIUS,
radiusY: TOUCH_EVENT_RADIUS,
force: TOUCH_EVENT_FORCE,
});
}
args.changedTouches = [args.touch];
// NOTE: T170088
args.touches = args.type === 'touchend' ? [] : args.changedTouches;
if (nativeMethods.documentCreateTouchList) {
args.changedTouches = (_a = nativeMethods.documentCreateTouchList).call.apply(_a, __spreadArray([document], args.changedTouches, false));
args.touches = (_b = nativeMethods.documentCreateTouchList).call.apply(_b, __spreadArray([document], args.touches, false));
}
args.targetTouches = args.touches;
return args;
};
EventSimulator.prototype._getTouchIdentifier = function (type) {
// NOTE: A touch point is created when the 'touchstart' event occurs. When the point' is moved,
// its id must not be changed (T112153).
if (type === 'touchstart')
this.touchIdentifier++;
return this.touchIdentifier;
};
EventSimulator.prototype._raiseNativeClick = function (el, originClick) {
// NOTE: B254199
var iframe = isElementInIframe(el) && getIframeByElement(el);
var curWindow = iframe ? nativeMethods.contentWindowGetter.call(iframe) : window;
var prevWindowEvent = curWindow.event;
if (isIE11)
delete curWindow.event;
originClick.call(el);
// NOTE: Window.event becomes empty when the click event handler
// triggers the click event for a different element in IE11.(GH-226).
if (isIE11 && prevWindowEvent) {
nativeMethods.objectDefineProperty(curWindow, 'event', {
get: function () { return prevWindowEvent; },
configurable: true,
});
}
};
EventSimulator.prototype._dispatchKeyEvent = function (el, args) {
var ev = null;
if (this.browserWithNewEventsStyle && nativeMethods.WindowKeyboardEvent) {
var eventArgs = {
bubbles: args.canBubble,
composed: args.composed,
cancelable: args.cancelable,
cancelBubble: false,
defaultPrevented: false,
view: args.view,
detail: args.detail,
ctrlKey: args.ctrlKey,
altKey: args.altKey,
shiftKey: args.shiftKey,
metaKey: args.metaKey,
keyCode: args.keyCode,
charCode: args.charCode,
which: args.which,
};
if ('keyIdentifier' in args)
eventArgs.keyIdentifier = args.keyIdentifier;
if ('key' in args)
eventArgs.key = args.key;
ev = new nativeMethods.WindowKeyboardEvent(args.type, eventArgs);
}
else if (nativeMethods.documentCreateEvent) {
ev = nativeMethods.documentCreateEvent.call(document, 'KeyboardEvent');
ev.initKeyboardEvent(args.type, args.canBubble, args.cancelable, args.view, '', 0, EventSimulator._getModifiersAsString(args), false, '');
}
if (ev) {
// NOTE: the window.event.keyCode, window.event.charCode, window.event.which and
// window.event.key properties are not assigned after KeyboardEvent is created
nativeMethods.objectDefineProperty(ev, 'keyCode', {
configurable: true,
enumerable: true,
get: function () { return args.keyCode; },
});
nativeMethods.objectDefineProperty(ev, 'charCode', {
configurable: true,
enumerable: true,
get: function () { return args.charCode; },
});
nativeMethods.objectDefineProperty(ev, 'which', {
configurable: true,
enumerable: true,
get: function () { return args.which; },
});
if ('key' in args) {
nativeMethods.objectDefineProperty(ev, 'key', {
configurable: true,
enumerable: true,
get: function () { return args.key; },
});
}
if ('keyIdentifier' in args) {
nativeMethods.objectDefineProperty(ev, 'keyIdentifier', {
configurable: true,
enumerable: true,
get: function () { return args.keyIdentifier; },
});
}
var defaultPrevented_1 = false;
var returnValue_1 = true;
// NOTE: the dispatchEvent method does not return false in the case when preventDefault method
// was called for events that were created with the KeyboardEvent constructor
if (this.browserWithNewEventsStyle) {
ev.preventDefault = function () {
defaultPrevented_1 = true;
nativeMethods.preventDefault.call(ev);
return false;
};
}
// NOTE: the dispatchEvent method does not return false when returnValue was set to false (only in MSEdge)
if (isMSEdge) {
nativeMethods.objectDefineProperty(ev, 'returnValue', {
get: function () { return returnValue_1; },
set: function (value) {
if (value === false)
ev.preventDefault();
returnValue_1 = value;
},
});
}
var res = this._raiseDispatchEvent(el, ev);
if (isMSEdge)
return returnValue_1 && !defaultPrevented_1;
else if (isIE)
return res;
return !defaultPrevented_1;
}
return null;
};
EventSimulator.prototype._getPointerEventTypeInfo = function (type) {
if (MOUSE_TO_POINTER_EVENT_TYPE_MAP[type]) {
return {
eventType: MOUSE_TO_POINTER_EVENT_TYPE_MAP[type],
pointerType: 'mouse',
};
}
if (TOUCH_TO_POINTER_EVENT_TYPE_MAP[type]) {
return {
eventType: TOUCH_TO_POINTER_EVENT_TYPE_MAP[type],
pointerType: 'touch',
};
}
return null;
};
EventSimulator.prototype._dispatchPointerEvent = function (el, args) {
var pointerEventTypeInfo = this._getPointerEventTypeInfo(args.type);
if (!pointerEventTypeInfo)
return;
var eventType = pointerEventTypeInfo.eventType, pointerType = pointerEventTypeInfo.pointerType;
var pointEvent = null;
var elPosition = getOffsetPosition(el);
var elBorders = getBordersWidth(el);
var elClientPosition = offsetToClientCoords({
x: elPosition.left + elBorders.left,
y: elPosition.top + elBorders.top,
});
var pointerArgs = extend({
width: 1,
height: 1,
pressure: 0,
tiltX: 0,
tiltY: 0,
// NOTE: This parameter must be "1" for “mouse”.
pointerId: 1,
pointerType: pointerType,
timeStamp: nativeMethods.dateNow(),
isPrimary: true,
}, args);
pointerArgs.type = eventType;
pointerArgs.offsetX = args.clientX - elClientPosition.x;
pointerArgs.offsetY = args.clientY - elClientPosition.y;
if (args.type === 'mousemove' || args.type === 'mouseover' || args.type === 'mouseout')
pointerArgs.button = args.buttons === BUTTONS_PARAMETER.noButton ? POINTER_EVENT_BUTTON.noButton : pointerArgs.button;
if (isIE11) {
pointerArgs.rotation = 0;
pointEvent = nativeMethods.documentCreateEvent.call(document, 'PointerEvent');
// NOTE: We set the relatedTarget argument to null because IE has a memory leak.
pointEvent.initPointerEvent(pointerArgs.type, pointerArgs.canBubble, pointerArgs.cancelable, window, pointerArgs.detail, pointerArgs.screenX, pointerArgs.screenY, pointerArgs.clientX, pointerArgs.clientY, pointerArgs.ctrlKey, pointerArgs.altKey, pointerArgs.shiftKey, pointerArgs.metaKey, pointerArgs.button, null, pointerArgs.offsetX, pointerArgs.offsetY, pointerArgs.width, pointerArgs.height, pointerArgs.pressure, pointerArgs.rotation, pointerArgs.tiltX, pointerArgs.tiltY, pointerArgs.pointerId, pointerArgs.pointerType, pointerArgs.timeStamp, pointerArgs.isPrimary);
// NOTE: After dispatching the pointer event, it doesn't contain the 'target' and 'relatedTarget' properties.
nativeMethods.objectDefineProperty(pointEvent, 'target', {
get: function () { return el; },
configurable: true,
});
nativeMethods.objectDefineProperty(pointEvent, 'relatedTarget', {
get: function () { return args.relatedTarget; },
configurable: true,
});
nativeMethods.objectDefineProperty(pointEvent, 'buttons', {
get: function () { return args.buttons; },
});
}
else {
pointerArgs.bubbles = true;
pointerArgs.cancelable = true;
pointEvent = new nativeMethods.WindowPointerEvent(eventType, pointerArgs);
}
this._raiseDispatchEvent(el, pointEvent);
};
EventSimulator.prototype._elementCanBeDisabled = function (el) {
for (var _i = 0, DISABLEABLE_HTML_ELEMENT_TYPE_CHECKERS_1 = DISABLEABLE_HTML_ELEMENT_TYPE_CHECKERS; _i < DISABLEABLE_HTML_ELEMENT_TYPE_CHECKERS_1.length; _i++) {
var elementCanBeDisabled = DISABLEABLE_HTML_ELEMENT_TYPE_CHECKERS_1[_i];
if (elementCanBeDisabled(el))
return true;
}
return false;
};
EventSimulator.prototype._dispatchMouseRelatedEvents = function (el, args, userOptions) {
if (userOptions === void 0) { userOptions = {}; }
if (args.type !== 'mouseover' && args.type !== 'mouseenter' && shouldIgnoreEventInsideIframe(el, args.clientX, args.clientY))
return true;
// NOTE: In IE, submit doesn't work if a click is simulated for some submit button's children (for example,
// img, B236676). In addition, if a test is being recorded in IE, the target of a click event is always a
// button, not a child, so the child does not receive the click event.
if (isIE) {
if (args.type === 'click' || args.type === 'mouseup' || args.type === 'mousedown') {
var elParent = nativeMethods.nodeParentNodeGetter.call(el);
var closestButton = closest(elParent, 'button');
if (elParent && closestButton) {
if (nativeMethods.getAttribute.call(closestButton, 'type') === 'submit')
el = closestButton;
}
}
}
if (hasPointerEvents && (!isTouchDevice || MOUSE_EVENTS_TO_FORCE_POINTER_EVENTS.includes(args.type)))
this._dispatchPointerEvent(el, args);
return this._dispatchMouseEvent(el, args, userOptions);
};
EventSimulator.prototype._dispatchMouseEvent = function (el, args, _a) {
var _this = this;
var dataTransfer = _a.dataTransfer, timeStamp = _a.timeStamp;
var disabledParent = findParent(el, false, function (node) {
return _this._elementCanBeDisabled(node) && EventSimulator._isDisabled(node);
});
var shouldNotRaiseEvents = (disabledParent && this._elementCanBeDisabled(el)) || // eslint-disable-line @typescript-eslint/no-extra-parens
(EventSimulator._isDisabled(el) && this._elementCanBeDisabled(el)); // eslint-disable-line @typescript-eslint/no-extra-parens
if (shouldNotRaiseEvents)
return null;
var event = null;
if (this.browserWithNewEventsStyle && nativeMethods.WindowMouseEvent) {
event = new nativeMethods.WindowMouseEvent(args.type, {
bubbles: args.canBubble,
composed: args.composed,
cancelable: args.cancelable,
view: window,
detail: args.detail,
screenX: args.screenX,
screenY: args.screenY,
clientX: args.clientX,
clientY: args.clientY,
ctrlKey: args.ctrlKey,
altKey: args.altKey,
shiftKey: args.shiftKey,
metaKey: args.metaKey,
button: args.button,
buttons: args.buttons,
relatedTarget: args.relatedTarget,
});
}
else {
event = nativeMethods.documentCreateEvent.call(document, 'MouseEvents');
event.initMouseEvent(args.type, args.canBubble, args.cancelable, window, args.detail, args.screenX, args.screenY, args.clientX, args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, args.button, args.relatedTarget);
nativeMethods.objectDefineProperty(event, 'buttons', {
get: function () { return args.buttons; },
});
}
// NOTE: T188166 (act.hover triggers the mouseenter event with the "which" parameter set to 1).
if (args.which !== void 0 && isWebKit) {
nativeMethods.objectDefineProperty(event, 'which', {
get: function () { return args.which; },
});
}
if (timeStamp && !isIE) {
nativeMethods.objectDefineProperty(event, 'timeStamp', {
get: function () { return timeStamp; },
});
}
if (dataTransfer) {
nativeMethods.objectDefineProperty(event, 'dataTransfer', {
configurable: true,
enumerable: true,
get: function () { return dataTransfer; },
});
}
return this._raiseDispatchEvent(el, event);
};
EventSimulator.prototype._dispatchFocusEvent = function (el, name, relatedTarget) {
if (relatedTarget === void 0) { relatedTarget = null; }
var event = null;
var bubbles = FOCUS_IN_OUT_EVENT_NAME_RE.test(name);
if (this.browserWithNewEventsStyle && nativeMethods.WindowFocusEvent) {
event = new nativeMethods.WindowFocusEvent(name, {
bubbles: bubbles,
composed: isComposedEvent(name),
cancelable: false,
cancelBubble: false,
relatedTarget: relatedTarget,
defaultPrevented: false,
});
}
else if (nativeMethods.documentCreateEvent) {
event = nativeMethods.documentCreateEvent.call(document, 'FocusEvent');
event.initFocusEvent(name, bubbles, true, null, 0, bubbles ? relatedTarget : null);
}
if (event) {
event[this.DISPATCHED_EVENT_FLAG] = true;
return this._raiseDispatchEvent(el, event);
}
return null;
};
EventSimulator.prototype._dispatchTextEvent = function (el, text) {
if (nativeMethods.WindowTextEvent && nativeMethods.documentCreateEvent) {
var event_1 = nativeMethods.documentCreateEvent.call(document, 'TextEvent');
var args = {
eventType: isIE11 ? 'textinput' : 'textInput',
bubbles: true,
cancelable: true,
view: window,
data: text,
inputMethod: DOM_INPUT_METHOD_KEYBOARD,
locale: navigator.language,
};
event_1.initTextEvent(args.eventType, args.bubbles, args.cancelable, args.view, args.data, args.inputMethod, args.locale);
return this._raiseDispatchEvent(el, event_1);
}
return null;
};
EventSimulator.prototype._dispatchInputEvent = function (el, type, data) {
if (!nativeMethods.WindowInputEvent)
return this._dispatchEvent(el, type, true);
var args = {
bubbles: true,
composed: isComposedEvent(type),
cancelable: true,
view: window,
inputType: 'insertText',
};
if (data !== void 0)
args.data = data;
var event = new nativeMethods.WindowInputEvent(type, args);
return this._raiseDispatchEvent(el, event);
};
EventSimulator.prototype._dispatchEvent = function (el, name, shouldBubble, flag) {
var ev = null;
if (nativeMethods.documentCreateEvent) {
ev = nativeMethods.documentCreateEvent.call(document, 'Events');
ev.initEvent(name, shouldBubble, true);
}
if (ev) {
if (flag)
ev[flag] = true;
return this._raiseDispatchEvent(el, ev);
}
return null;
};
EventSimulator.prototype._raiseDispatchEvent = function (el, ev) {
var iframe = isElementInIframe(el) && getIframeByElement(el);
var curWindow = iframe ? nativeMethods.contentWindowGetter.call(iframe) : window;
if (isIE11 && iframe && curWindow) {
// NOTE: In IE, when we raise an event by using the dispatchEvent function, the window.event object is null.
// If a real event happens, there is a window.event object, but it is not identical with the first argument
// of the event handler. The window.Event object is identical with the object that is created when we raise
// the event by using the fireEvent function. So, when we raise the event by using the dispatchEvent function,
// we need to set the window.event object manually. An exception for IE11: The window.event object is not null
// and its the same as in the event handler (only in window.top.event). Also, in iE11, window.event doesnt
// have the returnValue property, so its impossible to prevent the event by assigning window.event.returnValue
// to false.
// NOTE: In IE11, iframe's window.event object is null. We need to set
// iframe's window.event object manually by using window.event (B254199).
nativeMethods.objectDefineProperty(curWindow, 'event', {
get: function () { return window.event; },
configurable: true,
});
}
var res = el.dispatchEvent(ev);
// NOTE: GH-226
if (isIE11 && curWindow)
delete curWindow.event;
return res;
};
/* NOTE: options = {
[clientX: integer,]
[clientY: integer,]
[alt: true|false,]
[ctrl: true|false,]
[shift: true|false,]
[meta: true|false,]
[button: Util.BUTTON]
} */
EventSimulator.prototype.click = function (el, options) {
return this._simulateEvent(el, 'click', options, {
button: BUTTON.left,
buttons: BUTTONS_PARAMETER.noButton,
});
};
EventSimulator.prototype.nativeClick = function (el, originClick) {
this._raiseNativeClick(el, originClick);
};
EventSimulator.prototype.dblclick = function (el, options) {
return this._simulateEvent(el, 'dblclick', options, {
button: BUTTON.left,
buttons: BUTTONS_PARAMETER.noButton,
});
};
EventSimulator.prototype.rightclick = function (el, options) {
return this._simulateEvent(el, 'click', options, {
button: BUTTON.right,
buttons: BUTTONS_PARAMETER.rightButton,
});
};
EventSimulator.prototype.contextmenu = function (el, options) {
return this._simulateEvent(el, 'contextmenu', options, {
button: BUTTON.right,
buttons: BUTTONS_PARAMETER.noButton,
});
};
EventSimulator.prototype.mousedown = function (el, options) {
if (options === void 0) { options = {}; }
var button = options.button === void 0 ? BUTTON.left : options.button;
var buttons = button === BUTTON.left ? BUTTONS_PARAMETER.leftButton : BUTTONS_PARAMETER.rightButton;
options.button = button;
options.buttons = options.buttons === void 0 ? buttons : options.buttons;
return this._simulateEvent(el, 'mousedown', options);
};
EventSimulator.prototype.mouseup = function (el, options) {
if (options === void 0) { options = {}; }
var button = options.button === void 0 ? BUTTON.left : options.button;
return this._simulateEvent(el, 'mouseup', options, {
button: button,
buttons: BUTTONS_PARAMETER.noButton,
});
};
EventSimulator.prototype.mouseover = function (el, options) {
options = EventSimulator._prepareMouseEventOptions(options);
return this._simulateEvent(el, 'mouseover', options);
};
EventSimulator.prototype.mousemove = function (el, options) {
options = EventSimulator._prepareMouseEventOptions(options);
return this._simulateEvent(el, 'mousemove', options, { cancelable: false });
};
EventSimulator.prototype.mouseout = function (el, options) {
options = EventSimulator._prepareMouseEventOptions(options);
return this._simulateEvent(el, 'mouseout', options);
};
EventSimulator.prototype.mouseenter = function (el, options) {
options = EventSimulator._prepareMouseEventOptions(options);
return this._simulateEvent(el, 'mouseenter', options, { canBubble: false });
};
EventSimulator.prototype.mouseleave = function (el, options) {
options = EventSimulator._prepareMouseEventOptions(options);
return this._simulateEvent(el, 'mouseleave', options, { canBubble: false });
};
// NOTE: Keyboard events.
EventSimulator.prototype.keypress = function (el, options) {
return this._simulateEvent(el, 'keypress', options);
};
EventSimulator.prototype.keyup = function (el, options) {
return this._simulateEvent(el, 'keyup', options);
};
EventSimulator.prototype.keydown = function (el, options) {
return this._simulateEvent(el, 'keydown', options);
};
// NOTE: Control events.
// NOTE: "focus", "blur" and "selectionchange" shouldn't bubble (T229732),
// but "input", "change" and "submit" should do it (GH-318).
EventSimulator.prototype.blur = function (el, relatedTarget) {
return this._dispatchFocusEvent(el, 'blur', relatedTarget);
};
EventSimulator.prototype.focus = function (el, relatedTarget) {
return this._dispatchFocusEvent(el, 'focus', relatedTarget);
};
EventSimulator.prototype.focusin = function (el, relatedTarget) {
return this._dispatchFocusEvent(el, 'focusin', relatedTarget);
};
EventSimulator.prototype.focusout = function (el, relatedTarget) {
return this._dispatchFocusEvent(el, 'focusout', relatedTarget);
};
EventSimulator.prototype.storage = function (window, options) {
return this._simulateEvent(window, 'storage', options);
};
EventSimulator.prototype.change = function (el) {
return this._dispatchEvent(el, 'change', true, this.DISPATCHED_EVENT_FLAG);
};
EventSimulator.prototype.textInput = function (el, data) {
return this._dispatchTextEvent(el, data);
};
EventSimulator.prototype.beforeInput = function (el, data) {
return this._dispatchInputEvent(el, 'beforeinput', data);
};
EventSimulator.prototype.input = function (el, data) {
return this._dispatchInputEvent(el, 'input', data);
};
EventSimulator.prototype.submit = function (el) {
return this._dispatchEvent(el, 'submit', true);
};
EventSimulator.prototype.selectionchange = function (el) {
return this._dispatchEvent(el, 'selectionchange', false);
};
// NOTE: Touch events.
EventSimulator.prototype.touchstart = function (el, options) {
return this._simulateEvent(el, 'touchstart', options);
};
EventSimulator.prototype.touchend = function (el, options) {
return this._simulateEvent(el, 'touchend', options);
};
EventSimulator.prototype.touchmove = function (el, options) {
return this._simulateEvent(el, 'touchmove', options);
};
// NOTE: drag and drop
EventSimulator.prototype.dragstart = function (el, options) {
return this._simulateEvent(el, 'dragstart', options);
};
EventSimulator.prototype.drag = function (el, options) {
return this._simulateEvent(el, 'drag', options);
};
EventSimulator.prototype.dragenter = function (el, options) {
return this._simulateEvent(el, 'dragenter', options);
};
EventSimulator.prototype.dragover = function (el, options) {
return this._simulateEvent(el, 'dragover', options);
};
EventSimulator.prototype.dragleave = function (el, options) {
return this._simulateEvent(el, 'dragleave', options);
};
EventSimulator.prototype.drop = function (el, options) {
return this._simulateEvent(el, 'drop', options);
};
EventSimulator.prototype.dragend = function (el, options) {
return this._simulateEvent(el, 'dragend', options);
};
EventSimulator.prototype.isSavedWindowsEventsExists = function () {
return this.savedWindowEvents && this.savedWindowEvents.length;
};
return EventSimulator;
}());
var MessageType;
(function (MessageType) {
MessageType["Service"] = "hammerhead|service-msg";
MessageType["User"] = "hammerhead|user-msg";
})(MessageType || (MessageType = {}));
var CHECKED_PROPERTIES_FOR_NESTED_MESSAGE_DATA = [
'message',
'originUrl',
'targetUrl',
];
var MessageSandbox = /** @class */ (function (_super) {
__extends(MessageSandbox, _super);
function MessageSandbox(_listeners, _unloadSandbox) {
var _this = _super.call(this) || this;
_this._listeners = _listeners;
_this._unloadSandbox = _unloadSandbox;
_this.PING_DELAY = 200;
_this.PING_IFRAME_TIMEOUT = 7000;
_this.PING_IFRAME_MIN_TIMEOUT = 100;
_this.SERVICE_MSG_RECEIVED_EVENT = 'hammerhead|event|service-msg-received';
_this.RECEIVE_MSG_FN = 'hammerhead|receive-msg-function';
// NOTE: The window.top property may be changed after an iframe is removed from DOM in IE, so we save it.
_this.topWindow = null;
_this.window = null;
_this.storedOnMessageHandler = null;
_this.isWindowUnloaded = false;
_this.iframeInternalMsgQueue = [];
return _this;
}
MessageSandbox._parseMessageJSONData = function (str) {
if (!settings.get().proxyless)
return parse$1(str);
try {
return parse$1(str);
}
catch (err) {
return { type: MessageType.User, message: str };
}
};
MessageSandbox._getMessageData = function (e) {
var rawData = isMessageEvent(e) ? nativeMethods.messageEventDataGetter.call(e) : e.data;
return typeof rawData === 'string' ? MessageSandbox._parseMessageJSONData(rawData) : rawData;
};
// NOTE: some window may be unavailable for the sending message, for example, if it was removed.
// In some browsers, window.postMessage is equal null, but other throw exception by property access.
MessageSandbox._isWindowAvailable = function (window) {
try {
return !!window.postMessage;
}
catch (e) {
return false;
}
};
// @ts-ignore
MessageSandbox.prototype._onMessage = function (e) {
var data = MessageSandbox._getMessageData(e);
if (data.type === MessageType.Service && e.source) {
if (this.pingCmd && data.message.cmd === this.pingCmd && data.message.isPingResponse) {
this.pingCallback();
this.pingCallback = null;
this.pingCmd = null;
}
else
this.emit(this.SERVICE_MSG_RECEIVED_EVENT, { message: data.message, source: e.source, ports: e.ports });
}
};
MessageSandbox.prototype._onWindowMessage = function (e, originListener) {
var data = MessageSandbox._getMessageData(e);
if (data.type !== MessageType.Service) {
var originUrl = get$2();
if (data.targetUrl === '*' || sameOriginCheck(originUrl, data.targetUrl))
return callEventListener(this.window, originListener, e);
}
return null;
};
MessageSandbox._wrapMessage = function (type, message, targetUrl) {
var parsedDest = getParsed();
var originUrl = formatUrl({
/*eslint-disable no-restricted-properties*/
protocol: parsedDest.protocol,
host: parsedDest.host,
/*eslint-enable no-restricted-properties*/
});
return { message: message, originUrl: originUrl, targetUrl: targetUrl, type: type };
};
MessageSandbox._getOriginMessageData = function (data) {
if (data.message
&& typeof data.message === 'object'
&& nativeMethods.arrayEvery.call(CHECKED_PROPERTIES_FOR_NESTED_MESSAGE_DATA, function (checkedProperty) { return checkedProperty in data.message; }))
return data.message.message;
return data.message;
};
MessageSandbox.prototype._removeInternalMsgFromQueue = function (sendFunc) {
for (var index = 0, length_1 = this.iframeInternalMsgQueue.length; index < length_1; index++) {
if (this.iframeInternalMsgQueue[index].sendFunc === sendFunc) {
this.iframeInternalMsgQueue.splice(index, 1);
return true;
}
}
return false;
};
MessageSandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
// NOTE: The window.top property may be changed after an iframe is removed from DOM in IE, so we save it.
this.topWindow = window.top;
this.isWindowUnloaded = false;
this._unloadSandbox.on(this._unloadSandbox.UNLOAD_EVENT, function () {
_this.isWindowUnloaded = true;
while (_this.iframeInternalMsgQueue.length) {
var msgInfo = _this.iframeInternalMsgQueue[0];
nativeMethods.clearTimeout.call(_this.window, msgInfo.timeoutId);
msgInfo.sendFunc();
}
});
var onMessageHandler = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return fastApply(_this, '_onMessage', args);
};
var onWindowMessageHandler = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return fastApply(_this, '_onWindowMessage', args);
};
this._listeners.addInternalEventBeforeListener(window, ['message'], onMessageHandler);
this._listeners.setEventListenerWrapper(window, ['message'], onWindowMessageHandler);
// NOTE: In Google Chrome, iframes whose src contains html code raise the 'load' event twice.
// So, we need to define code instrumentation functions as 'configurable' so that they can be redefined.
nativeMethods.objectDefineProperty(window, this.RECEIVE_MSG_FN, {
value: onMessageHandler,
configurable: true,
});
if (!this.proxyless) {
// @ts-ignore
overrideDescriptor(window.MessageEvent.prototype, 'data', {
getter: function () {
var target = nativeMethods.eventTargetGetter.call(this);
var data = nativeMethods.messageEventDataGetter.call(this);
if (data && data.type !== MessageType.Service && isWindow(target))
return MessageSandbox._getOriginMessageData(data);
return data;
},
});
}
// @ts-ignore
var eventPropsOwner = nativeMethods.isEventPropsLocatedInProto ? window.Window.prototype : window;
overrideDescriptor(eventPropsOwner, 'onmessage', {
getter: function () { return _this.storedOnMessageHandler; },
setter: function (handler) {
_this.storedOnMessageHandler = isFunction(handler) ? handler : null;
nativeMethods.winOnMessageSetter.call(window, _this.storedOnMessageHandler
? function (e) { return _this._onWindowMessage(e, handler); }
: null);
},
});
};
MessageSandbox.prototype.postMessage = function (contentWindow, args) {
var targetUrl = args[1] || getOriginHeader();
// NOTE: Here, we pass all messages as "no preference" ("*").
// We do an origin check in "_onWindowMessage" to access the target origin.
args[1] = '*';
args[0] = MessageSandbox._wrapMessage(MessageType.User, args[0], targetUrl);
return fastApply(contentWindow, 'postMessage', args);
};
MessageSandbox.prototype.sendServiceMsg = function (msg, targetWindow, ports) {
var _this = this;
var message = MessageSandbox._wrapMessage(MessageType.Service, msg);
var canSendDirectly = !isCrossDomainWindows(targetWindow, this.window) && !!targetWindow[this.RECEIVE_MSG_FN];
if (!canSendDirectly)
return MessageSandbox._isWindowAvailable(targetWindow) && targetWindow.postMessage(message, '*', ports);
var sendFunc = function (force) {
// NOTE: In IE, this function is called on the timeout despite the fact that the timer has been cleared
// in the unload event handler, so we check whether the function is in the queue
if (force || _this._removeInternalMsgFromQueue(sendFunc)) {
// NOTE: The 'sendFunc' function may be called on timeout, so we must call 'canSendDirectly' again,
// because the iframe could become cross-domain in the meantime. Unfortunately, Chrome hangs when
// trying to call the 'isCrossDomainWindows' function, so we have to wrap it in 'try/catch'.
try {
targetWindow[_this.RECEIVE_MSG_FN]({
// NOTE: Cloning a message to prevent this modification.
data: parse$1(stringify(message)),
source: _this.window,
ports: ports,
});
}
// eslint-disable-next-line no-empty
catch (e) {
}
}
};
if (!this.isWindowUnloaded) {
// NOTE: Imitation of a delay for the postMessage method.
// We use the same-domain top window
// so that the function called by setTimeout is executed after removing the iframe
var topSameDomainWindow = getTopSameDomainWindow(this.window);
var timeoutId = nativeMethods.setTimeout.call(topSameDomainWindow, sendFunc, 10);
this.iframeInternalMsgQueue.push({ timeoutId: timeoutId, sendFunc: sendFunc });
}
else
sendFunc(true);
return null;
};
// NOTE: This code is used only in legacy API.
MessageSandbox.prototype.pingIframe = function (targetIframe, pingMessageCommand, shortWaiting) {
var _this = this;
return new pinkie(function (resolve, reject) {
var pingInterval = null;
var pingTimeout = null;
var targetWindow = null;
var sendPingRequest = function () {
targetWindow = nativeMethods.contentWindowGetter.call(targetIframe);
if (targetWindow) {
_this.sendServiceMsg({
cmd: _this.pingCmd,
isPingRequest: true,
}, targetWindow);
}
};
var cleanTimeouts = function () {
nativeMethods.clearInterval.call(_this.window, pingInterval);
nativeMethods.clearTimeout.call(_this.window, pingTimeout);
_this.pingCallback = null;
_this.pingCmd = null;
pingInterval = null;
pingTimeout = null;
};
pingTimeout = nativeMethods.setTimeout.call(_this.window, function () {
cleanTimeouts();
reject();
}, shortWaiting ? _this.PING_IFRAME_MIN_TIMEOUT : _this.PING_IFRAME_TIMEOUT);
_this.pingCallback = function () {
cleanTimeouts();
resolve();
};
_this.pingCmd = pingMessageCommand;
sendPingRequest();
pingInterval = nativeMethods.setInterval.call(_this.window, sendPingRequest, _this.PING_DELAY);
});
};
return MessageSandbox;
}(SandboxBase));
var NodeMutation = /** @class */ (function (_super) {
__extends(NodeMutation, _super);
function NodeMutation() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.BEFORE_DOCUMENT_CLEANED_EVENT = 'hammerhead|event|before-document-cleaned';
_this.DOCUMENT_CLEANED_EVENT = 'hammerhead|event|document-cleaned';
_this.DOCUMENT_CLOSED_EVENT = 'hammerhead|event|document-closed';
_this.BODY_CONTENT_CHANGED_EVENT = 'hammerhead|event|body-content-changed';
_this.BODY_CREATED_EVENT = 'hammerhead|event|body-created';
_this.IFRAME_ADDED_TO_DOM_EVENT = 'hammerhead|event|iframe-added-to-dom';
return _this;
}
NodeMutation.prototype.onIframeAddedToDOM = function (iframe) {
this.emit(this.IFRAME_ADDED_TO_DOM_EVENT, iframe);
};
NodeMutation.prototype.onBeforeDocumentCleaned = function (document) {
this.emit(this.BEFORE_DOCUMENT_CLEANED_EVENT, document);
};
NodeMutation.prototype.onDocumentCleaned = function (window, document) {
this.emit(this.DOCUMENT_CLEANED_EVENT, { window: window, document: document });
};
NodeMutation.prototype.onDocumentClosed = function (document) {
this.emit(this.DOCUMENT_CLOSED_EVENT, document);
};
NodeMutation.prototype.onBodyContentChanged = function (element) {
this.emit(this.BODY_CONTENT_CHANGED_EVENT, element);
};
NodeMutation.prototype.onBodyCreated = function (body) {
this.emit(this.BODY_CREATED_EVENT, body);
};
return NodeMutation;
}(EventEmitter));
// NOTE: When you call the focus and blur function for some elements in IE, the event handlers must be raised
// asynchronously, but before executing functions that are called by using the window.setTimeout function. So,
// we need to raise the handlers with a timeout, but do it before calling other asynchronous functions.
var TimersSandbox = /** @class */ (function (_super) {
__extends(TimersSandbox, _super);
function TimersSandbox() {
var _this = _super.call(this) || this;
_this.timeouts = [];
_this.deferredFunctions = [];
_this.setTimeout = nativeMethods.setTimeout;
return _this;
}
TimersSandbox.prototype._wrapTimeoutFunctionsArguments = function (args) {
var _this = this;
var isScriptFirstArg = typeof args[0] === 'string';
var func = !isScriptFirstArg ? args[0] : null;
var script = isScriptFirstArg ? processScript(args[0], false) : null;
if (isIE && version < 12) {
var timersSandbox_1 = this;
var fnToRun_1 = isScriptFirstArg ? function () {
// NOTE: We are switching eval to the global context with this assignment.
// Unlike eval, the setTimeout/setInterval functions always work in the global context.
var ev = _this.window.eval;
return ev(script);
} : func;
args[0] = function () {
return timersSandbox_1._callDeferredFunction(fnToRun_1, arguments);
};
}
else if (isScriptFirstArg)
args[0] = script;
return args;
};
TimersSandbox.prototype._callDeferredFunction = function (fn, args) {
if (this.timeouts.length) {
var curTimeouts = [];
var curHandlers = [];
for (var i = 0; i < this.timeouts.length; i++) {
curTimeouts.push(this.timeouts[i]);
curHandlers.push(this.deferredFunctions[i]);
}
this.timeouts = [];
this.deferredFunctions = [];
for (var j = 0; j < curTimeouts.length; j++) {
nativeMethods.clearInterval.call(this.window, curTimeouts[j]);
curHandlers[j]();
}
// NOTE: Handlers can create new deferred functions.
return this._callDeferredFunction(fn, args);
}
return fn.apply(this.window, args);
};
TimersSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
var timersSandbox = this;
overrideFunction(window, 'setTimeout', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return nativeMethods.setTimeout.apply(window, timersSandbox._wrapTimeoutFunctionsArguments(args));
});
overrideFunction(window, 'setInterval', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return nativeMethods.setInterval.apply(window, timersSandbox._wrapTimeoutFunctionsArguments(args));
});
// NOTE: We are saving the setTimeout wrapper for internal use in case the page-script replaces
// it with an invalid value.
this.setTimeout = window.setTimeout;
};
TimersSandbox.prototype.deferFunction = function (fn) {
var _this = this;
var deferredFunction = function () {
fn();
for (var i = 0; i < _this.deferredFunctions.length; i++) {
if (_this.deferredFunctions[i] === deferredFunction) {
_this.deferredFunctions.splice(i, 1);
_this.timeouts.splice(i, 1);
break;
}
}
};
this.deferredFunctions.push(deferredFunction);
this.timeouts.push(nativeMethods.setTimeout.call(window, deferredFunction, 0));
};
return TimersSandbox;
}(SandboxBase));
function createPropertyDesc(descBase) {
descBase.configurable = true;
descBase.enumerable = true;
return descBase;
}
var UnloadSandbox = /** @class */ (function (_super) {
__extends(UnloadSandbox, _super);
function UnloadSandbox(_listeners) {
var _this = _super.call(this) || this;
_this._listeners = _listeners;
_this.BEFORE_UNLOAD_EVENT = 'hammerhead|event|before-unload';
_this.BEFORE_BEFORE_UNLOAD_EVENT = 'hammerhead|event|before-before-unload';
_this.UNLOAD_EVENT = 'hammerhead|event|unload';
_this.beforeUnloadProperties = {
storedReturnValue: '',
prevented: false,
storedHandler: null,
nativeEventName: UnloadSandbox._getBeforeUnloadEventName(),
eventName: _this.BEFORE_UNLOAD_EVENT,
eventPropSetter: UnloadSandbox._getBeforeUnloadPropSetter(),
};
_this.unloadProperties = {
storedReturnValue: '',
prevented: false,
storedHandler: null,
nativeEventName: 'unload',
eventName: _this.UNLOAD_EVENT,
eventPropSetter: nativeMethods.winOnUnloadSetter,
};
return _this;
}
UnloadSandbox._getBeforeUnloadEventName = function () {
// NOTE: the ios devices do not support beforeunload event
// https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW5
return isIOS ? 'pagehide' : 'beforeunload';
};
UnloadSandbox._getBeforeUnloadPropSetter = function () {
// NOTE: the ios devices do not support beforeunload event
// https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW5
return isIOS ? nativeMethods.winOnPageHideSetter : nativeMethods.winOnBeforeUnloadSetter;
};
// NOTE: This handler has to be called after others.
UnloadSandbox.prototype._emitEvent = function (eventProperties) {
this.emit(eventProperties.eventName, {
returnValue: eventProperties.storedReturnValue,
prevented: eventProperties.prevented,
});
};
UnloadSandbox._prepareStoredReturnValue = function (returnValue) {
if (typeof returnValue === 'string')
return returnValue;
try {
return String(returnValue);
}
catch (_a) {
return '';
}
};
UnloadSandbox.prototype._createEventHandler = function (eventProperties) {
return function (e, originListener) {
// NOTE: Overriding the returnValue property to prevent a native dialog.
nativeMethods.objectDefineProperty(e, 'returnValue', createPropertyDesc({
get: function () { return eventProperties.storedReturnValue; },
set: function (value) {
// NOTE: In all browsers, if the property is set to any value, unload is prevented. In FireFox,
// only if a value is set to an empty string, the unload operation is prevented.
eventProperties.storedReturnValue = UnloadSandbox._prepareStoredReturnValue(value);
eventProperties.prevented = isFirefox ? value !== '' : true;
},
}));
nativeMethods.objectDefineProperty(e, 'preventDefault', createPropertyDesc({
get: function () { return function () {
eventProperties.prevented = true;
return true;
}; },
set: function () { return void 0; },
}));
// NOTE: need to pass `this` scope for https://github.com/DevExpress/testcafe/issues/6563
var res = originListener.call(this, e);
if (res !== void 0) {
eventProperties.storedReturnValue = UnloadSandbox._prepareStoredReturnValue(res);
eventProperties.prevented = true;
}
return void 0;
};
};
UnloadSandbox.prototype._reattachListener = function (eventProperties) {
var nativeAddEventListener = Listeners.getNativeAddEventListener(this.window);
var nativeRemoveEventListener = Listeners.getNativeRemoveEventListener(this.window);
// NOTE: reattach the Listener, it'll be the last in the queue.
nativeRemoveEventListener.call(this.window, eventProperties.nativeEventName, this);
nativeAddEventListener.call(this.window, eventProperties.nativeEventName, this);
};
UnloadSandbox.prototype._setEventListenerWrapper = function (eventProperties) {
this._listeners.setEventListenerWrapper(window, [eventProperties.nativeEventName], this._createEventHandler(eventProperties));
};
UnloadSandbox.prototype._addEventListener = function (eventProperties) {
var _this = this;
var nativeAddEventListener = Listeners.getNativeAddEventListener(window);
nativeAddEventListener.call(window, eventProperties.nativeEventName, this);
this._listeners.on(this._listeners.EVENT_LISTENER_ATTACHED_EVENT, function (e) {
if (e.el === window && e.eventType === eventProperties.nativeEventName)
_this._reattachListener(eventProperties);
});
};
UnloadSandbox.prototype._overrideEventDescriptor = function (eventProperties) {
var _this = this;
// @ts-ignore
var eventPropsOwner = nativeMethods.isEventPropsLocatedInProto ? window.Window.prototype : window;
// @ts-ignore
overrideDescriptor(eventPropsOwner, 'on' + eventProperties.nativeEventName, {
getter: function () { return eventProperties.storedHandler; },
setter: function (handler) { return _this.setOnEvent(eventProperties, window, handler); },
});
};
UnloadSandbox.prototype._attachEvent = function (eventProperties) {
this._setEventListenerWrapper(eventProperties);
this._addEventListener(eventProperties);
this._overrideEventDescriptor(eventProperties);
};
UnloadSandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
this._attachEvent(this.beforeUnloadProperties);
this._attachEvent(this.unloadProperties);
this._listeners.addInternalEventBeforeListener(window, [this.beforeUnloadProperties.nativeEventName], function () { return _this.emit(_this.BEFORE_BEFORE_UNLOAD_EVENT); });
};
UnloadSandbox.prototype.setOnEvent = function (eventProperties, window, handler) {
var _this = this;
if (isFunction(handler)) {
eventProperties.storedHandler = handler;
eventProperties.eventPropSetter.call(window, function (e) { return _this._createEventHandler(eventProperties)(e, handler); });
this._reattachListener(eventProperties);
}
else {
eventProperties.storedHandler = null;
eventProperties.eventPropSetter.call(window, null);
}
};
UnloadSandbox.prototype.handleEvent = function (e) {
if (e.type === this.beforeUnloadProperties.nativeEventName)
this._emitEvent(this.beforeUnloadProperties);
else if (e.type === this.unloadProperties.nativeEventName)
this._emitEvent(this.unloadProperties);
};
return UnloadSandbox;
}(SandboxBase));
var SandboxBaseWithDelayedSettings = /** @class */ (function (_super) {
__extends(SandboxBaseWithDelayedSettings, _super);
function SandboxBaseWithDelayedSettings(_waitHammerheadSettings) {
var _this = _super.call(this) || this;
_this._waitHammerheadSettings = _waitHammerheadSettings;
if (_waitHammerheadSettings) {
_waitHammerheadSettings.then(function () {
_this._waitHammerheadSettings = null;
});
}
return _this;
}
SandboxBaseWithDelayedSettings.prototype.gettingSettingInProgress = function () {
return !!this._waitHammerheadSettings;
};
SandboxBaseWithDelayedSettings.prototype.delayUntilGetSettings = function (action) {
return this._waitHammerheadSettings.then(action);
};
return SandboxBaseWithDelayedSettings;
}(SandboxBase));
// -------------------------------------------------------------
var AUTHENTICATE_PREFIX = '~~~TestCafe added this prefix to hide the authentication dialog box~~~';
var AUTHORIZATION_PREFIX = '~~~TestCafe added this prefix to control the authorization flow~~~';
function addAuthenticatePrefix(value) {
return AUTHENTICATE_PREFIX + value;
}
function hasAuthenticatePrefix(value) {
return value.indexOf(AUTHENTICATE_PREFIX) > -1;
}
function removeAuthenticatePrefix(value) {
return value.replace(AUTHENTICATE_PREFIX, '');
}
function isAuthenticateHeader(headerName) {
var headerNameStr = String(headerName).toLowerCase();
return headerNameStr === BUILTIN_HEADERS.wwwAuthenticate || headerNameStr === BUILTIN_HEADERS.proxyAuthenticate;
}
function addAuthorizationPrefix(value) {
return AUTHORIZATION_PREFIX + value;
}
function hasAuthorizationPrefix(value) {
return value.indexOf(AUTHORIZATION_PREFIX) > -1;
}
function removeAuthorizationPrefix(value) {
return value.replace(AUTHORIZATION_PREFIX, '');
}
function isAuthorizationHeader(headerName) {
var headerNameStr = String(headerName).toLowerCase();
return headerNameStr === BUILTIN_HEADERS.authorization || headerNameStr === BUILTIN_HEADERS.proxyAuthorization;
}
var sharedHeadersUtils = /*#__PURE__*/Object.freeze({
__proto__: null,
addAuthenticatePrefix: addAuthenticatePrefix,
hasAuthenticatePrefix: hasAuthenticatePrefix,
removeAuthenticatePrefix: removeAuthenticatePrefix,
isAuthenticateHeader: isAuthenticateHeader,
addAuthorizationPrefix: addAuthorizationPrefix,
hasAuthorizationPrefix: hasAuthorizationPrefix,
removeAuthorizationPrefix: removeAuthorizationPrefix,
isAuthorizationHeader: isAuthorizationHeader
});
var XHR_READY_STATES = ['UNSENT', 'OPENED', 'HEADERS_RECEIVED', 'LOADING', 'DONE'];
var XhrSandbox = /** @class */ (function (_super) {
__extends(XhrSandbox, _super);
function XhrSandbox(_cookieSandbox, waitHammerheadSettings) {
var _this = _super.call(this, waitHammerheadSettings) || this;
_this._cookieSandbox = _cookieSandbox;
_this.XHR_COMPLETED_EVENT = 'hammerhead|event|xhr-completed';
_this.XHR_ERROR_EVENT = 'hammerhead|event|xhr-error';
_this.BEFORE_XHR_SEND_EVENT = 'hammerhead|event|before-xhr-send';
return _this;
}
XhrSandbox.setRequestOptions = function (req, withCredentials, args) {
XhrSandbox.REQUESTS_OPTIONS.set(req, {
withCredentials: withCredentials,
openArgs: args,
headers: [],
});
};
XhrSandbox.createNativeXHR = function () {
var xhr = new nativeMethods.XMLHttpRequest();
xhr.open = nativeMethods.xhrOpen;
xhr.abort = nativeMethods.xhrAbort;
xhr.send = nativeMethods.xhrSend;
xhr.addEventListener = nativeMethods.xhrAddEventListener || nativeMethods.addEventListener;
xhr.removeEventListener = nativeMethods.xhrRemoveEventListener || nativeMethods.removeEventListener;
xhr.setRequestHeader = nativeMethods.xhrSetRequestHeader;
xhr.getResponseHeader = nativeMethods.xhrGetResponseHeader;
xhr.getAllResponseHeaders = nativeMethods.xhrGetAllResponseHeaders;
xhr.overrideMimeType = nativeMethods.xhrOverrideMimeType;
xhr.dispatchEvent = nativeMethods.xhrDispatchEvent || nativeMethods.dispatchEvent;
return xhr;
};
XhrSandbox.openNativeXhr = function (xhr, url, isAsync) {
xhr.open('POST', url, isAsync);
xhr.setRequestHeader(BUILTIN_HEADERS.cacheControl, 'no-cache, no-store, must-revalidate');
};
XhrSandbox._reopenXhr = function (xhr, reqOpts, proxyless) {
var url = reqOpts.openArgs[1];
var withCredentials = xhr.withCredentials;
reqOpts.withCredentials = withCredentials;
reqOpts.openArgs[1] = getAjaxProxyUrl(url, withCredentials ? Credentials.include : Credentials.sameOrigin, proxyless);
nativeMethods.xhrOpen.apply(xhr, reqOpts.openArgs);
reqOpts.openArgs[1] = url;
for (var _i = 0, _a = reqOpts.headers; _i < _a.length; _i++) {
var header = _a[_i];
nativeMethods.xhrSetRequestHeader.apply(xhr, header);
}
};
XhrSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
var xhrSandbox = this;
var xmlHttpRequestProto = window.XMLHttpRequest.prototype;
var emitXhrCompletedEvent = function () {
var nativeRemoveEventListener = nativeMethods.xhrRemoveEventListener || nativeMethods.removeEventListener;
xhrSandbox.emit(xhrSandbox.XHR_COMPLETED_EVENT, { xhr: this });
nativeRemoveEventListener.call(this, 'loadend', emitXhrCompletedEvent);
};
var syncCookieWithClientIfNecessary = function () {
if (this.readyState < this.HEADERS_RECEIVED)
return;
var nativeRemoveEventListener = nativeMethods.xhrRemoveEventListener || nativeMethods.removeEventListener;
xhrSandbox._cookieSandbox.syncCookie();
nativeRemoveEventListener.call(this, 'readystatechange', syncCookieWithClientIfNecessary);
};
var xmlHttpRequestWrapper = function () {
var nativeAddEventListener = nativeMethods.xhrAddEventListener || nativeMethods.addEventListener;
var xhr = new nativeMethods.XMLHttpRequest();
nativeAddEventListener.call(xhr, 'loadend', emitXhrCompletedEvent);
nativeAddEventListener.call(xhr, 'readystatechange', syncCookieWithClientIfNecessary);
return xhr;
};
for (var _i = 0, XHR_READY_STATES_1 = XHR_READY_STATES; _i < XHR_READY_STATES_1.length; _i++) {
var readyState = XHR_READY_STATES_1[_i];
nativeMethods.objectDefineProperty(xmlHttpRequestWrapper, readyState, nativeMethods.objectGetOwnPropertyDescriptor(nativeMethods.XMLHttpRequest, readyState));
}
// NOTE: We cannot just assign constructor property of the prototype of XMLHttpRequest starts from safari 9.0
overrideConstructor(window, 'XMLHttpRequest', xmlHttpRequestWrapper);
nativeMethods.objectDefineProperty(xmlHttpRequestProto, 'constructor', {
value: xmlHttpRequestWrapper,
});
overrideFunction(xmlHttpRequestProto, 'abort', function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (xhrSandbox.gettingSettingInProgress())
return void xhrSandbox.delayUntilGetSettings(function () { return _this.abort.apply(_this, args); });
nativeMethods.xhrAbort.apply(this, args);
xhrSandbox.emit(xhrSandbox.XHR_ERROR_EVENT, {
err: new Error('XHR aborted'),
xhr: this,
});
});
// NOTE: Redirect all requests to the Hammerhead proxy and ensure that requests don't
// violate Same Origin Policy.
overrideFunction(xmlHttpRequestProto, 'open', function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var url = args[1];
if (getProxyUrl(url, {}, xhrSandbox.proxyless) === url) {
XhrSandbox.setRequestOptions(this, this.withCredentials, args);
return void nativeMethods.xhrOpen.apply(this, args);
}
if (xhrSandbox.gettingSettingInProgress())
return void xhrSandbox.delayUntilGetSettings(function () { return _this.open.apply(_this, args); });
url = typeof url === 'string' ? url : String(url);
args[1] = getAjaxProxyUrl(url, this.withCredentials ? Credentials.include : Credentials.sameOrigin, xhrSandbox.proxyless);
nativeMethods.xhrOpen.apply(this, args);
args[1] = url;
XhrSandbox.setRequestOptions(this, this.withCredentials, args);
});
overrideFunction(xmlHttpRequestProto, 'send', function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (xhrSandbox.gettingSettingInProgress())
return void xhrSandbox.delayUntilGetSettings(function () { return _this.send.apply(_this, args); });
var reqOpts = XhrSandbox.REQUESTS_OPTIONS.get(this);
if (reqOpts && reqOpts.withCredentials !== this.withCredentials)
XhrSandbox._reopenXhr(this, reqOpts, xhrSandbox.proxyless);
xhrSandbox.emit(xhrSandbox.BEFORE_XHR_SEND_EVENT, { xhr: this });
nativeMethods.xhrSend.apply(this, args);
// NOTE: For xhr with the sync mode
if (this.readyState === this.DONE)
emitXhrCompletedEvent.call(this);
syncCookieWithClientIfNecessary.call(this);
});
overrideFunction(xmlHttpRequestProto, 'setRequestHeader', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (isAuthorizationHeader(args[0]))
args[1] = addAuthorizationPrefix(args[1]);
nativeMethods.xhrSetRequestHeader.apply(this, args);
var reqOpts = XhrSandbox.REQUESTS_OPTIONS.get(this);
if (reqOpts)
reqOpts.headers.push([String(args[0]), String(args[1])]);
});
if (nativeMethods.xhrResponseURLGetter) {
overrideDescriptor(window.XMLHttpRequest.prototype, 'responseURL', {
getter: function () {
var nativeResponseURL = nativeMethods.xhrResponseURLGetter.call(this);
return xhrSandbox.proxyless ? nativeResponseURL : getDestinationUrl(nativeResponseURL);
},
});
}
overrideFunction(xmlHttpRequestProto, 'getResponseHeader', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var value = nativeMethods.xhrGetResponseHeader.apply(this, args);
if (value && isAuthenticateHeader(args[0]))
value = removeAuthenticatePrefix(value);
return value;
});
overrideFunction(xmlHttpRequestProto, 'getAllResponseHeaders', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var allHeaders = nativeMethods.xhrGetAllResponseHeaders.apply(this, args);
while (hasAuthenticatePrefix(allHeaders))
allHeaders = removeAuthenticatePrefix(allHeaders);
return allHeaders;
});
};
XhrSandbox.REQUESTS_OPTIONS = new WeakMap();
return XhrSandbox;
}(SandboxBaseWithDelayedSettings));
function getCredentialsMode(credentialsOpt) {
credentialsOpt = String(credentialsOpt).toLowerCase();
switch (credentialsOpt) {
case 'omit': return Credentials.omit;
case 'same-origin': return Credentials.sameOrigin;
case 'include': return Credentials.include;
default: return Credentials.unknown;
}
}
var DEFAULT_REQUEST_CREDENTIALS = getCredentialsMode(nativeMethods.Request && new nativeMethods.Request(location.toString()).credentials);
var FetchSandbox = /** @class */ (function (_super) {
__extends(FetchSandbox, _super);
function FetchSandbox(cookieSandbox, waitHammerheadSettings) {
var _this = _super.call(this, waitHammerheadSettings) || this;
_this.cookieSandbox = cookieSandbox;
_this.FETCH_REQUEST_SENT_EVENT = 'hammerhead|event|fetch-request-sent-event';
return _this;
}
FetchSandbox._removeAuthHeadersPrefix = function (name, value) {
if (isAuthorizationHeader(name))
return removeAuthorizationPrefix(value);
else if (isAuthenticateHeader(name))
return removeAuthenticatePrefix(value);
return value;
};
FetchSandbox._processInit = function (init) {
var headers = init.headers;
if (!headers)
return init;
if (!isFetchHeaders(headers)) {
headers = headers ? new nativeMethods.Headers(headers) : new nativeMethods.Headers();
init.headers = headers;
}
var authorizationValue = nativeMethods.headersGet.call(headers, BUILTIN_HEADERS.authorization);
var proxyAuthorizationValue = nativeMethods.headersGet.call(headers, BUILTIN_HEADERS.proxyAuthorization);
if (authorizationValue !== null && !hasAuthorizationPrefix(authorizationValue))
nativeMethods.headersSet.call(headers, BUILTIN_HEADERS.authorization, addAuthorizationPrefix(authorizationValue));
if (proxyAuthorizationValue !== null && !hasAuthorizationPrefix(proxyAuthorizationValue))
nativeMethods.headersSet.call(headers, BUILTIN_HEADERS.proxyAuthorization, addAuthorizationPrefix(proxyAuthorizationValue));
return init;
};
FetchSandbox._processArguments = function (args, proxyless) {
var input = args[0], init = args[1];
var inputIsString = typeof input === 'string';
var optsCredentials = getCredentialsMode(init && init.credentials);
if (!isFetchRequest(input)) {
var url = inputIsString ? input : String(input);
var credentials = optsCredentials === Credentials.unknown ? DEFAULT_REQUEST_CREDENTIALS : optsCredentials;
args[0] = getAjaxProxyUrl(url, credentials, proxyless);
args[1] = FetchSandbox._processInit(init || {});
}
else {
if (optsCredentials !== Credentials.unknown)
args[0] = getAjaxProxyUrl(input.url, optsCredentials);
if (init && init.headers && input.destination !== 'worker')
args[1] = FetchSandbox._processInit(init);
}
};
FetchSandbox._processHeaderEntry = function (entry, isOnlyValue) {
if (isOnlyValue === void 0) { isOnlyValue = false; }
if (entry.done)
return entry;
/* eslint-disable no-restricted-properties */
var processedValue = FetchSandbox._removeAuthHeadersPrefix(entry.value[0], entry.value[1]);
if (isOnlyValue)
entry.value = processedValue;
else
entry.value[1] = processedValue;
/* eslint-enable no-restricted-properties */
return entry;
};
FetchSandbox._entriesWrapper = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var iterator = nativeMethods.headersEntries.apply(this, args);
var nativeNext = iterator.next;
iterator.next = function () { return FetchSandbox._processHeaderEntry(nativeNext.call(iterator)); };
return iterator;
};
FetchSandbox._valuesWrapper = function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var iterator = nativeMethods.headersEntries.apply(this, args);
var nativeNext = iterator.next;
iterator.next = function () { return FetchSandbox._processHeaderEntry(nativeNext.call(iterator), true); };
return iterator;
};
FetchSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window, window.document);
if (!nativeMethods.fetch)
return;
var sandbox = this;
if (!this.proxyless) {
overrideConstructor(window, 'Request', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
FetchSandbox._processArguments(args, sandbox.proxyless);
window.Headers.prototype.entries = window.Headers.prototype[Symbol.iterator] = nativeMethods.headersEntries;
var request = args.length === 1
? new nativeMethods.Request(args[0])
: new nativeMethods.Request(args[0], args[1]);
window.Headers.prototype.entries = window.Headers.prototype[Symbol.iterator] = FetchSandbox._entriesWrapper;
return request;
});
overrideDescriptor(window.Request.prototype, 'url', {
getter: function () {
var nativeRequestUrl = nativeMethods.requestUrlGetter.call(this);
return sandbox.proxyless ? nativeRequestUrl : getDestinationUrl(nativeRequestUrl);
},
});
overrideDescriptor(window.Request.prototype, 'referrer', {
getter: function () {
var nativeReferrer = nativeMethods.requestReferrerGetter.call(this);
return sandbox.proxyless ? nativeReferrer : getDestinationUrl(nativeReferrer);
},
});
overrideDescriptor(window.Response.prototype, 'url', {
getter: function () {
var nativeResponseUrl = nativeMethods.responseUrlGetter.call(this);
return sandbox.proxyless ? nativeResponseUrl : getDestinationUrl(nativeResponseUrl);
},
});
overrideFunction(window.Headers.prototype, 'entries', FetchSandbox._entriesWrapper);
overrideFunction(window.Headers.prototype, Symbol.iterator, FetchSandbox._entriesWrapper);
overrideFunction(window.Headers.prototype, 'values', FetchSandbox._valuesWrapper);
overrideFunction(window.Headers.prototype, 'forEach', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var callback = args[0];
if (isFunction(callback)) {
args[0] = function (value, name, headers) {
value = FetchSandbox._removeAuthHeadersPrefix(name, value);
callback.call(this, value, name, headers);
};
}
return nativeMethods.headersForEach.apply(this, args);
});
overrideFunction(window.Headers.prototype, 'get', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var value = nativeMethods.headersGet.apply(this, args);
return value && FetchSandbox._removeAuthHeadersPrefix(args[0], value);
});
overrideFunction(window.Headers.prototype, 'set', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (isAuthorizationHeader(args[0]))
args[1] = addAuthorizationPrefix(args[1]);
return nativeMethods.headersSet.apply(this, args);
});
}
overrideFunction(window, 'fetch', function () {
var _this = this;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (!sandbox.proxyless && sandbox.gettingSettingInProgress())
return sandbox.delayUntilGetSettings(function () { return _this.fetch.apply(_this, args); });
// NOTE: Safari processed the empty `fetch()` request without `Promise` rejection (GH-1613)
if (!args.length && !isSafari)
return nativeMethods.fetch.apply(this, args);
if (sandbox.proxyless) {
var fetchPromise_1 = nativeMethods.fetch.apply(this, args);
sandbox.emit(sandbox.FETCH_REQUEST_SENT_EVENT, fetchPromise_1);
return fetchPromise_1;
}
try {
FetchSandbox._processArguments(args, sandbox.proxyless);
}
catch (e) {
return nativeMethods.promiseReject.call(sandbox.window.Promise, e);
}
window.Headers.prototype.entries = window.Headers.prototype[Symbol.iterator] = nativeMethods.headersEntries;
var fetchPromise = nativeMethods.fetch.apply(this, args);
window.Headers.prototype.entries = window.Headers.prototype[Symbol.iterator] = FetchSandbox._entriesWrapper;
sandbox.emit(sandbox.FETCH_REQUEST_SENT_EVENT, fetchPromise);
return nativeMethods.promiseThen.call(fetchPromise, function (response) {
sandbox.cookieSandbox.syncCookie();
return response;
});
});
};
return FetchSandbox;
}(SandboxBaseWithDelayedSettings));
var STORAGE_WRAPPER_KEY = 'hammerhead|get-storage-wrapper';
var EMPTY_OLD_VALUE_ARG = isIE ? '' : null;
var storageWrappersInternalInfo = new WeakMap();
var KEY = 0;
var VALUE = 1;
var StorageInheritor = /** @class */ (function () {
function StorageInheritor() {
}
return StorageInheritor;
}());
StorageInheritor.prototype = Storage.prototype;
var StorageWrapper = /** @class */ (function (_super) {
__extends(StorageWrapper, _super);
function StorageWrapper(window, nativeStorage, nativeStorageKey) {
var _this = _super.call(this) || this;
storageWrappersInternalInfo.set(_this, {
win: window,
ctx: window,
lastState: null,
eventEmitter: new EventEmitter(),
nativeStorage: nativeStorage,
nativeStorageKey: nativeStorageKey,
});
_this.loadStorage();
return _this;
}
Object.defineProperty(StorageWrapper.prototype, "internal", {
get: function () {
return storageWrappersInternalInfo.get(this);
},
enumerable: false,
configurable: true
});
StorageWrapper.create = function (window, nativeStorage, nativeStorageKey) {
var storageWrapper = new StorageWrapper(window, nativeStorage, nativeStorageKey);
if (!window.Proxy)
// @ts-ignore
return storageWrapper;
return new nativeMethods.Proxy(storageWrapper, {
get: function (target, property) {
if (property === STORAGE_WRAPPER_KEY)
return target;
return target[property];
},
set: function (target, property, value) {
target['setItem'](property, value);
return true;
},
deleteProperty: function (target, key) {
target['removeItem'](key);
return true;
},
});
};
StorageWrapper.prototype.setContext = function (context) {
this.internal.ctx = context;
};
StorageWrapper.prototype.getContext = function () {
return this.internal.ctx;
};
StorageWrapper.prototype.saveToNativeStorage = function () {
var state = stringify(this.getCurrentState());
if (this.internal.nativeStorage[this.internal.nativeStorageKey] !== state)
this.internal.nativeStorage[this.internal.nativeStorageKey] = state;
};
StorageWrapper.prototype.getCurrentState = function () {
var addedProperties = nativeMethods.objectKeys(this);
var state = [[], []];
for (var _i = 0, addedProperties_1 = addedProperties; _i < addedProperties_1.length; _i++) {
var addedProperty = addedProperties_1[_i];
state[KEY].push(addedProperty);
state[VALUE].push(this[addedProperty]);
}
return state;
};
StorageWrapper.prototype.restore = function (storageStr) {
this.clearStorage();
this.loadStorage(storageStr);
};
StorageWrapper.prototype.clearStorage = function () {
var addedProperties = nativeMethods.objectKeys(this);
var changed = false;
for (var _i = 0, addedProperties_2 = addedProperties; _i < addedProperties_2.length; _i++) {
var addedProperty = addedProperties_2[_i];
delete this[addedProperty];
changed = true;
}
if (changed)
this.internal.lastState = this.getCurrentState();
return changed;
};
StorageWrapper.prototype.loadStorage = function (storageStateStr) {
if (!storageStateStr)
storageStateStr = this.internal.nativeStorage[this.internal.nativeStorageKey];
var storageState = parse$1(storageStateStr || '[[],[]]');
var storageStateLength = storageState[KEY].length;
for (var i = 0; i < storageStateLength; i++)
this[storageState[KEY][i]] = storageState[VALUE][i];
this.internal.lastState = storageState;
};
StorageWrapper.prototype.raiseStorageChanged = function (key, oldValue, newValue) {
var url = null;
try {
var parsedContextUrl = parseProxyUrl(this.internal.ctx.location.toString());
url = parsedContextUrl ? parsedContextUrl.destUrl : get$2();
}
catch (e) {
this.internal.ctx = this.internal.win;
url = get$2();
}
this.internal.eventEmitter.emit('change', { key: key, oldValue: oldValue, newValue: newValue, url: url });
};
StorageWrapper.prototype.checkStorageChanged = function () {
var lastState = this.internal.lastState;
var currentState = this.getCurrentState();
for (var i = 0; i < lastState[KEY].length; i++) {
var lastStateKey = lastState[KEY][i];
var lastStateValue = lastState[VALUE][i];
var keyIndex = currentState[KEY].indexOf(lastStateKey);
if (keyIndex !== -1) {
if (currentState[VALUE][keyIndex] !== lastStateValue)
this.raiseStorageChanged(currentState[KEY][keyIndex], lastStateValue, currentState[VALUE][keyIndex]);
currentState[KEY].splice(keyIndex, 1);
currentState[VALUE].splice(keyIndex, 1);
}
else
this.raiseStorageChanged(lastStateKey, lastStateValue, null);
}
for (var j = 0; j < currentState[KEY].length; j++)
this.raiseStorageChanged(currentState[KEY][j], EMPTY_OLD_VALUE_ARG, currentState[VALUE][j]);
this.internal.lastState = this.getCurrentState();
};
StorageWrapper.prototype.addChangeEventListener = function (fn) {
this.internal.eventEmitter.on('change', fn);
};
StorageWrapper.prototype.removeChangeEventListener = function (fn) {
this.internal.eventEmitter.off('change', fn);
};
StorageWrapper.prototype.unwrapProxy = function () {
if (nativeMethods.Proxy) {
var wrapper = this[STORAGE_WRAPPER_KEY];
return wrapper || this;
}
return this;
};
return StorageWrapper;
}(StorageInheritor));
var ourMethods = nativeMethods.objectKeys(StorageWrapper.prototype);
if (ourMethods.indexOf('internal') === -1)
ourMethods.push('internal');
for (var _i = 0, ourMethods_1 = ourMethods; _i < ourMethods_1.length; _i++) {
var method = ourMethods_1[_i];
if (method === 'constructor' || method === 'internal')
continue;
nativeMethods.objectDefineProperty(StorageWrapper.prototype, method, {
value: StorageWrapper.prototype[method],
configurable: false,
enumerable: false,
writable: false,
});
}
var internalDescriptor = nativeMethods.objectGetOwnPropertyDescriptor(StorageWrapper.prototype, 'internal');
internalDescriptor.configurable = false;
internalDescriptor.enumerable = false;
nativeMethods.objectDefineProperty(StorageWrapper.prototype, 'internal', internalDescriptor);
nativeMethods.objectDefineProperty(StorageWrapper.prototype, 'constructor', nativeMethods.objectGetOwnPropertyDescriptor(Storage.prototype, 'constructor'));
nativeMethods.objectDefineProperty(StorageWrapper, 'INTERNAL_METHODS', { value: ourMethods });
// -------------------------------------------------------------
// WARNING: this file is used by both the client and the server.
// Do not use any browser or node-specific API!
// -------------------------------------------------------------
/* eslint hammerhead/proto-methods: 2 */
var STORAGE_WRAPPER_PREFIX = 'hammerhead|storage-wrapper|';
function getStorageKey(sessionId, host) {
return STORAGE_WRAPPER_PREFIX + sessionId + '|' + host;
}
var API_KEY_PREFIX = 'hammerhead|api-key-prefix|';
var STORAGE_PROPS = nativeMethods.arrayConcat.call(nativeMethods.objectKeys(Storage.prototype), StorageWrapper.INTERNAL_METHODS);
var StorageSandboxStrategyBase = /** @class */ (function () {
function StorageSandboxStrategyBase() {
}
return StorageSandboxStrategyBase;
}());
var StorageSandboxProxylessStrategy = /** @class */ (function (_super) {
__extends(StorageSandboxProxylessStrategy, _super);
function StorageSandboxProxylessStrategy() {
return _super !== null && _super.apply(this, arguments) || this;
}
StorageSandboxProxylessStrategy.prototype.backup = function () {
return {
localStorage: stringify(this._getStorageKeysAndValues(localStorage)),
sessionStorage: stringify(this._getStorageKeysAndValues(sessionStorage)),
};
};
StorageSandboxProxylessStrategy.prototype.attach = function () {
return void 0;
};
StorageSandboxProxylessStrategy.prototype.lock = function () {
return void 0;
};
StorageSandboxProxylessStrategy.prototype.dispose = function () {
return void 0;
};
StorageSandboxProxylessStrategy.prototype.clear = function () {
return void 0;
};
StorageSandboxProxylessStrategy.prototype.restore = function () {
return void 0;
};
StorageSandboxProxylessStrategy.prototype._getStorageKeysAndValues = function (storage) {
var storageKeys = nativeMethods.objectKeys(storage);
var storageValues = [];
for (var _i = 0, storageKeys_1 = storageKeys; _i < storageKeys_1.length; _i++) {
var key = storageKeys_1[_i];
storageValues.push(storage[key]);
}
return [storageKeys, storageValues];
};
return StorageSandboxProxylessStrategy;
}(StorageSandboxStrategyBase));
var StorageSandboxProxyStrategy = /** @class */ (function (_super) {
__extends(StorageSandboxProxyStrategy, _super);
function StorageSandboxProxyStrategy(sandbox, window, listeners, eventSimulator, unloadSandbox) {
var _this = _super.call(this) || this;
_this.window = null;
_this.nativeMethods = nativeMethods;
_this.document = null;
_this.intervalId = null;
_this.isLocked = false;
_this.sandbox = sandbox;
_this.window = window;
_this._listeners = listeners;
_this._eventSimulator = eventSimulator;
_this._unloadSandbox = unloadSandbox;
return _this;
}
StorageSandboxProxyStrategy.prototype.backup = function () {
return {
localStorage: stringify(this.localStorageProxy.unwrapProxy().getCurrentState()),
sessionStorage: stringify(this.sessionStorageProxy.unwrapProxy().getCurrentState()),
};
};
StorageSandboxProxyStrategy.prototype.restore = function (_a) {
var localStorage = _a.localStorage, sessionStorage = _a.sessionStorage;
this.localStorageProxy.unwrapProxy().restore(localStorage);
this.sessionStorageProxy.unwrapProxy().restore(sessionStorage);
};
StorageSandboxProxyStrategy.prototype.attach = function (window) {
var _this = this;
this._overrideStorageProps();
this._createStorageWrappers();
var localStorageWrapper = this.localStorageProxy.unwrapProxy();
var sessionStorageWrapper = this.sessionStorageProxy.unwrapProxy();
this.intervalId = nativeMethods.setInterval.call(this.window, function () {
localStorageWrapper.checkStorageChanged();
sessionStorageWrapper.checkStorageChanged();
}, 10);
this.localStorageChangeHandler = function (e) { return _this._simulateStorageEvent(_this.localStorageProxy, e); };
this.sessionStorageChangeHandler = function (e) { return _this._simulateStorageEvent(_this.sessionStorageProxy, e); };
localStorageWrapper.addChangeEventListener(this.localStorageChangeHandler);
sessionStorageWrapper.addChangeEventListener(this.sessionStorageChangeHandler);
this._listeners.initElementListening(window, ['storage']);
this._listeners.addInternalEventBeforeListener(window, ['storage'], function (_, dispatched, preventEvent) { return !dispatched && preventEvent(); });
this._overrideStorageEvent();
this._overrideStoragesGetters();
};
StorageSandboxProxyStrategy.prototype.clear = function () {
var localStorageWrapper = this.localStorageProxy.unwrapProxy();
var sessionStorageWrapper = this.sessionStorageProxy.unwrapProxy();
nativeMethods.storageRemoveItem.call(localStorageWrapper.internal.nativeStorage, localStorageWrapper.internal.nativeStorageKey);
nativeMethods.storageRemoveItem.call(sessionStorageWrapper.internal.nativeStorage, sessionStorageWrapper.internal.nativeStorageKey);
};
StorageSandboxProxyStrategy.prototype.dispose = function () {
this.localStorageProxy.unwrapProxy().removeChangeEventListener(this.localStorageChangeHandler);
this.sessionStorageProxy.unwrapProxy().removeChangeEventListener(this.sessionStorageChangeHandler);
var topSameDomainWindow = getTopSameDomainWindow(this.window);
// NOTE: For removed iframe without src in IE11 window.top equals iframe's window
if (this.window === topSameDomainWindow && !topSameDomainWindow.frameElement)
nativeMethods.clearInterval.call(this.window, this.intervalId);
};
StorageSandboxProxyStrategy._wrapKey = function (key) {
var keyStr = String(key);
return STORAGE_PROPS.indexOf(keyStr) !== -1 ? API_KEY_PREFIX + keyStr : keyStr;
};
StorageSandboxProxyStrategy._unwrapKey = function (key) {
return key.replace(API_KEY_PREFIX, '');
};
StorageSandboxProxyStrategy.prototype._simulateStorageEvent = function (storageArea, e) {
if (this.sandbox.isDeactivated() || storageArea.unwrapProxy().getContext() === this.window)
return;
var event = e;
event.storageArea = storageArea;
this._eventSimulator.storage(this.window, event);
};
// NOTE: We are using a single storage wrapper instance for all same-domain windows.
// This wrapper is saved in the top same-domain window's sandbox.
StorageSandboxProxyStrategy.prototype._createStorageWrappers = function () {
var _this = this;
// eslint-disable-next-line no-restricted-properties
var host = getParsed().host;
var sessionId = settings.get().sessionId;
var storageKey = getStorageKey(sessionId, host);
var topSameDomainWindow = getTopSameDomainWindow(this.window);
var topSameDomainHammerhead = topSameDomainWindow[INTERNAL_PROPS.hammerhead];
var topSameDomainStorageSandbox = topSameDomainHammerhead.sandbox.storageSandbox;
// NOTE: Use the already created wrappers.
if (topSameDomainStorageSandbox !== this.sandbox) {
this.localStorageProxy = topSameDomainStorageSandbox.localStorageProxy;
this.sessionStorageProxy = topSameDomainStorageSandbox.sessionStorageProxy;
}
// NOTE: Or create new.
else {
var nativeLocalStorage = this.nativeMethods.winLocalStorageGetter.call(this.window);
var nativeSessionStorage = this.nativeMethods.winSessionStorageGetter.call(this.window);
this.localStorageProxy = StorageWrapper.create(this.window, nativeLocalStorage, storageKey);
this.sessionStorageProxy = StorageWrapper.create(this.window, nativeSessionStorage, storageKey);
var saveToNativeStorages = function () {
if (_this.isLocked)
return;
_this.localStorageProxy.unwrapProxy().saveToNativeStorage();
_this.sessionStorageProxy.unwrapProxy().saveToNativeStorage();
};
this._unloadSandbox.on(this._unloadSandbox.UNLOAD_EVENT, saveToNativeStorages);
// NOTE: In some case, a browser does not emit the onBeforeUnload event and we need manually watch navigation (GH-1999).
// Also, on iOS devices, we realize the BEFORE_UNLOAD_EVENT through the onPageHide event that browser emits too late
// and we do not have time to save the localStorage wrapper to the native localStorage (GH-1507).
hammerhead$1.pageNavigationWatch.on(hammerhead$1.pageNavigationWatch.PAGE_NAVIGATION_TRIGGERED_EVENT, saveToNativeStorages);
}
};
StorageSandboxProxyStrategy.prototype._overrideStorageEvent = function () {
// NOTE: IE11 has the StorageEvent property, but it is not a constructor
if (typeof StorageEvent === 'object')
return;
overrideConstructor(this.window, 'StorageEvent', function (type, opts) {
var storedArea = opts === null || opts === void 0 ? void 0 : opts.storageArea;
if (storedArea)
delete opts.storageArea;
var event;
if (arguments.length === 0)
event = new nativeMethods.StorageEvent();
else if (arguments.length === 1)
event = new nativeMethods.StorageEvent(type);
else
event = new nativeMethods.StorageEvent(type, opts);
if (storedArea) {
nativeMethods.objectDefineProperty(event, 'storageArea', {
get: function () { return storedArea; },
set: function () { return void 0; },
});
}
return event;
});
};
StorageSandboxProxyStrategy.prototype._overrideStorageProps = function () {
overrideFunction(window.Storage.prototype, 'clear', function () {
var storage = this.unwrapProxy();
if (!storage.clearStorage())
return;
storage.raiseStorageChanged(null, null, null);
});
overrideFunction(window.Storage.prototype, 'getItem', function (key) {
if (arguments.length === 0)
throw new TypeError("Failed to execute 'getItem' on 'Storage': 1 argument required, but only 0 present.");
var storage = this.unwrapProxy();
var validKey = StorageSandboxProxyStrategy._wrapKey(key);
return nativeMethods.objectHasOwnProperty.call(storage, validKey) ? storage[validKey] : null;
});
overrideFunction(window.Storage.prototype, 'key', function (keyNum) {
if (arguments.length === 0)
throw new TypeError("TypeError: Failed to execute 'key' on 'Storage': 1 argument required, but only 0 present.");
// NOTE: http://w3c-test.org/webstorage/storage_key.html
keyNum %= 0x100000000;
if (isNaN(keyNum))
keyNum = 0;
var storage = this.unwrapProxy();
var addedProperties = nativeMethods.objectKeys(storage);
var isValidNum = keyNum >= 0 && keyNum < addedProperties.length;
return isValidNum ? StorageSandboxProxyStrategy._unwrapKey(addedProperties[keyNum]) : null;
});
overrideFunction(window.Storage.prototype, 'removeItem', function (key) {
if (arguments.length === 0)
throw new TypeError("Failed to execute 'removeItem' on 'Storage': 1 argument required, but only 0 present.");
var storage = this.unwrapProxy();
var validKey = StorageSandboxProxyStrategy._wrapKey(key);
delete storage[validKey];
storage.checkStorageChanged();
});
overrideFunction(window.Storage.prototype, 'setItem', function (key, value) {
if (arguments.length < 2)
throw new TypeError("Failed to execute 'setItem' on 'Storage': 2 arguments required, but only ".concat(arguments.length, " present."));
var storage = this.unwrapProxy();
var validKey = StorageSandboxProxyStrategy._wrapKey(key);
storage[validKey] = String(value);
storage.checkStorageChanged();
});
overrideDescriptor(window.Storage.prototype, 'length', {
getter: function () {
return nativeMethods.objectKeys(this).length;
},
setter: null,
});
};
StorageSandboxProxyStrategy.prototype._overrideStoragesGetters = function () {
var _this = this;
var storagesPropsOwner = this.nativeMethods.getStoragesPropsOwner(window);
// NOTE: Storage properties is located in Window.prototype in the IE11 and these are non configurable.
// We define descriptors from a prototype with an overridden getter on a window instance.
// We don't need define descriptors again if these was overridden.
var shouldDefineStorageProps = !this.nativeMethods.isStoragePropsLocatedInProto ||
!this.nativeMethods.objectHasOwnProperty.call(window, 'localStorage');
if (!shouldDefineStorageProps)
return;
this.nativeMethods.objectDefineProperties(window, {
'localStorage': createOverriddenDescriptor(storagesPropsOwner, 'localStorage', {
// @ts-ignore
getter: function () {
_this.localStorageProxy.unwrapProxy().setContext(window);
return _this.localStorageProxy;
},
}),
'sessionStorage': createOverriddenDescriptor(storagesPropsOwner, 'sessionStorage', {
// @ts-ignore
getter: function () {
_this.sessionStorageProxy.unwrapProxy().setContext(window);
return _this.sessionStorageProxy;
},
}),
});
};
StorageSandboxProxyStrategy.prototype.lock = function () {
this.isLocked = true;
};
return StorageSandboxProxyStrategy;
}(StorageSandboxStrategyBase));
var StorageSandbox = /** @class */ (function (_super) {
__extends(StorageSandbox, _super);
function StorageSandbox(_listeners, _unloadSandbox, _eventSimulator) {
var _this = _super.call(this) || this;
_this._listeners = _listeners;
_this._unloadSandbox = _unloadSandbox;
_this._eventSimulator = _eventSimulator;
return _this;
}
Object.defineProperty(StorageSandbox.prototype, "localStorageProxy", {
get: function () {
return this.strategy.localStorageProxy;
},
enumerable: false,
configurable: true
});
Object.defineProperty(StorageSandbox.prototype, "sessionStorageProxy", {
get: function () {
return this.strategy.sessionStorageProxy;
},
enumerable: false,
configurable: true
});
StorageSandbox.prototype.clear = function () {
this.strategy.clear();
};
StorageSandbox.prototype.lock = function () {
this.strategy.lock();
};
StorageSandbox.prototype.backup = function () {
return this.strategy.backup();
};
StorageSandbox.prototype.restore = function (storagesBackup) {
this.strategy.restore(storagesBackup);
};
StorageSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
this.strategy = this.proxyless ? new StorageSandboxProxylessStrategy() : new StorageSandboxProxyStrategy(this, window, this._listeners, this._eventSimulator, this._unloadSandbox);
this.strategy.attach(window);
};
StorageSandbox.prototype.dispose = function () {
this.strategy.dispose();
};
return StorageSandbox;
}(SandboxBase));
var ElectronSandbox = /** @class */ (function (_super) {
__extends(ElectronSandbox, _super);
function ElectronSandbox() {
return _super !== null && _super.apply(this, arguments) || this;
}
ElectronSandbox._createFnWrapper = function (vm, nativeFn) {
return function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (typeof args[0] === 'string')
args[0] = processScript(args[0]);
return nativeFn.apply(vm, args);
};
};
ElectronSandbox._overrideElectronModulePaths = function (window) {
var electronRequire = window.require;
var path = electronRequire('path');
var destination = getParsed();
/*eslint-disable no-restricted-properties*/
if (destination.protocol !== 'file:')
return;
var pathname = window.process.platform === 'win32' && destination.pathname[0] === '/'
? destination.pathname.substr(1)
: destination.pathname;
/*eslint-enable no-restricted-properties*/
window.__filename = path.normalize(decodeURIComponent(pathname));
window.__dirname = path.dirname(window.__filename);
window.module.filename = window.__filename;
window.module.paths = window.module.paths.concat(electronRequire('module')._nodeModulePaths(window.__dirname));
};
ElectronSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
if (!window.require)
return;
var vm = window.require('vm');
if (!vm)
return;
var nativeMethods = this.nativeMethods;
if (nativeMethods.refreshElectronMeths(vm)) {
overrideFunction(vm, 'createScript', ElectronSandbox._createFnWrapper(vm, nativeMethods.createScript));
// NOTE: DebugContext has been removed in V8 and is not available in Node.js 10+
if (vm.runInDebugContext)
overrideFunction(vm, 'runInDebugContext', ElectronSandbox._createFnWrapper(vm, nativeMethods.runInDebugContext));
overrideFunction(vm, 'runInContext', ElectronSandbox._createFnWrapper(vm, nativeMethods.runInContext));
overrideFunction(vm, 'runInNewContext', ElectronSandbox._createFnWrapper(vm, nativeMethods.runInNewContext));
overrideFunction(vm, 'runInThisContext', ElectronSandbox._createFnWrapper(vm, nativeMethods.runInThisContext));
ElectronSandbox._overrideElectronModulePaths(window);
}
};
return ElectronSandbox;
}(SandboxBase));
var ConsoleSandbox = /** @class */ (function (_super) {
__extends(ConsoleSandbox, _super);
function ConsoleSandbox(_messageSandbox) {
var _this = _super.call(this) || this;
_this._messageSandbox = _messageSandbox;
_this.CONSOLE_METH_CALLED_EVENT = 'hammerhead|event|console-meth-called';
_this._serviceMsgReceivedEventCallback = function (_a) {
var message = _a.message;
if (message.cmd === _this.CONSOLE_METH_CALLED_EVENT)
_this.emit(_this.CONSOLE_METH_CALLED_EVENT, { meth: message.meth, line: message.line });
};
return _this;
}
ConsoleSandbox.prototype._toString = function (obj) {
try {
return String(obj);
}
catch (e) {
return 'object';
}
};
ConsoleSandbox.prototype._proxyConsoleMeth = function (meth) {
var _this = this;
overrideFunction(this.window.console, meth, function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (!isCrossDomainWindows(window, window.top)) {
var sendToTopWindow = isIframeWindow(window);
var line = nativeMethods.arrayMap.call(args, _this._toString).join(' ');
if (sendToTopWindow) {
_this.emit(_this.CONSOLE_METH_CALLED_EVENT, { meth: meth, line: line, inIframe: true });
_this._messageSandbox.sendServiceMsg({ meth: meth, line: line, cmd: _this.CONSOLE_METH_CALLED_EVENT }, window.top);
}
else
_this.emit(_this.CONSOLE_METH_CALLED_EVENT, { meth: meth, line: line });
}
_this.nativeMethods.consoleMeths[meth].apply(_this.nativeMethods.console, args);
});
};
ConsoleSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
this._proxyConsoleMeth('log');
this._proxyConsoleMeth('info');
this._proxyConsoleMeth('error');
this._proxyConsoleMeth('warn');
this._messageSandbox.on(this._messageSandbox.SERVICE_MSG_RECEIVED_EVENT, this._serviceMsgReceivedEventCallback);
};
return ConsoleSandbox;
}(SandboxBase));
var CSS_STYLE_IS_PROCESSED = 'hammerhead|style|is-processed';
var CSS_STYLE_PROXY_OBJECT = 'hammerhead|style|proxy-object';
var CSS_STYLE_PROXY_TARGET = 'hammerhead|style|proxy-target';
var StyleSandbox = /** @class */ (function (_super) {
__extends(StyleSandbox, _super);
function StyleSandbox() {
var _this = _super.call(this) || this;
_this.URL_PROPS = ['background', 'backgroundImage', 'borderImage',
'borderImageSource', 'listStyle', 'listStyleImage', 'cursor'];
_this.DASHED_URL_PROPS = StyleSandbox._generateDashedProps(_this.URL_PROPS);
_this.FEATURES = _this._detectBrowserFeatures();
return _this;
}
StyleSandbox._convertToDashed = function (prop) {
return prop.replace(/[A-Z]/g, '-$&').toLowerCase();
};
StyleSandbox._generateDashedProps = function (props) {
var dashedProps = [];
for (var _i = 0, props_1 = props; _i < props_1.length; _i++) {
var prop = props_1[_i];
var dashedProp = StyleSandbox._convertToDashed(prop);
if (prop !== dashedProp)
dashedProps.push(dashedProp);
}
return dashedProps;
};
StyleSandbox.prototype._detectBrowserFeatures = function () {
var features = {};
// NOTE: The CSS2Properties class is supported only in the Firefox
// and its prototype contains all property descriptors
// @ts-ignore
features.css2PropertiesProtoContainsAllProps = !!window.CSS2Properties;
// NOTE: The CSSStyleDeclaration class contains not dashed url properties only in the IE
features.cssStyleDeclarationProtoContainsUrlProps = this.nativeMethods.objectHasOwnProperty
// @ts-ignore
.call(window.CSSStyleDeclaration.prototype, 'background');
features.cssStyleDeclarationProtoContainsDashedProps = this.nativeMethods.objectHasOwnProperty
.call(window.CSSStyleDeclaration.prototype, 'background-image');
features.cssStyleDeclarationContainsAllProps = features.cssStyleDeclarationProtoContainsUrlProps &&
features.cssStyleDeclarationProtoContainsDashedProps;
if (!features.css2PropertiesProtoContainsAllProps && !features.cssStyleDeclarationProtoContainsUrlProps) {
var testDiv = this.nativeMethods.createElement.call(document, 'div');
var propertySetterIsCalled_1 = false;
var testDivDescriptor = this.nativeMethods.objectGetOwnPropertyDescriptor
// @ts-ignore
.call(window.Object, testDiv.style, 'background');
if (testDivDescriptor.configurable) {
// eslint-disable-next-line no-restricted-properties
delete testDivDescriptor.value;
delete testDivDescriptor.writable;
testDivDescriptor.set = function () {
propertySetterIsCalled_1 = true;
};
this.nativeMethods.objectDefineProperty(testDiv.style, 'background', testDivDescriptor);
testDiv.style.background = 'url';
}
// NOTE: A style instance contains all url properties.
// They are non-configurable in Safari less than 11.1.
// Their setter cannot be called in Safari 11.1.
features.propsCannotBeOverridden = !testDivDescriptor.configurable || !propertySetterIsCalled_1;
}
return features;
};
StyleSandbox.prototype._overrideStyleProp = function (proto, prop) {
var nativeMethods = this.nativeMethods;
var dashedProp = StyleSandbox._convertToDashed(prop);
overrideDescriptor(proto, prop, {
getter: function () {
var value = nativeMethods.styleGetPropertyValue.call(this, dashedProp);
return styleProcessor.cleanUp(value, parseProxyUrl);
},
setter: function (value) {
if (typeof value === 'string')
value = styleProcessor.process(value, getProxyUrl);
nativeMethods.styleSetProperty.call(this, dashedProp, value);
},
});
};
StyleSandbox.prototype._overrideStyleInstanceProp = function (style, prop) {
var nativeMethods = this.nativeMethods;
var dashedProp = StyleSandbox._convertToDashed(prop);
overrideDescriptor(style, prop, {
getter: function () {
var value = nativeMethods.styleGetPropertyValue.call(this, dashedProp);
return styleProcessor.cleanUp(value, parseProxyUrl);
},
setter: function (value) {
if (typeof value === 'string')
value = styleProcessor.process(value, getProxyUrl);
nativeMethods.styleSetProperty.call(this, dashedProp, value);
},
});
};
StyleSandbox.prototype._processStyleInstance = function (style) {
var isProcessed = style[CSS_STYLE_IS_PROCESSED];
if (!isProcessed) {
for (var _i = 0, _a = this.DASHED_URL_PROPS; _i < _a.length; _i++) {
var prop = _a[_i];
this._overrideStyleInstanceProp(style, prop);
}
if (!this.FEATURES.cssStyleDeclarationProtoContainsUrlProps) {
for (var _b = 0, _c = this.URL_PROPS; _b < _c.length; _b++) {
var prop = _c[_b];
this._overrideStyleInstanceProp(style, prop);
}
}
this.nativeMethods.objectDefineProperty(style, CSS_STYLE_IS_PROCESSED, { value: true });
}
return style;
};
StyleSandbox.prototype._getStyleProxy = function (style) {
var _this = this;
var proxyObject = style[CSS_STYLE_PROXY_OBJECT];
if (!proxyObject) {
proxyObject = new this.nativeMethods.Proxy(style, {
get: function (target, prop) {
if (_this.URL_PROPS.indexOf(prop) !== -1 || _this.DASHED_URL_PROPS.indexOf(prop) !== -1)
return styleProcessor.cleanUp(target[prop], parseProxyUrl);
if (prop === CSS_STYLE_PROXY_TARGET)
return target;
return target[prop];
},
set: function (target, prop, value) {
if (_this.URL_PROPS.indexOf(prop) !== -1 || _this.DASHED_URL_PROPS.indexOf(prop) !== -1) {
if (typeof value === 'string')
value = styleProcessor.process(value, getProxyUrl);
}
target[prop] = value;
return true;
},
});
this.nativeMethods.objectDefineProperty(style, CSS_STYLE_PROXY_OBJECT, { value: proxyObject });
}
return proxyObject;
};
StyleSandbox.prototype._overrideCSSStyleDeclarationFunctionsCtx = function (window) {
var styleDeclarationProto = window.CSSStyleDeclaration.prototype;
var _loop_1 = function (prop) {
var nativeFn = this_1.nativeMethods.objectGetOwnPropertyDescriptor.call(window.Object, styleDeclarationProto, prop).value; // eslint-disable-line no-restricted-properties
if (this_1.nativeMethods.objectHasOwnProperty.call(styleDeclarationProto, prop) &&
isFunction(nativeFn)) {
styleDeclarationProto[prop] = function () {
return nativeFn.apply(this[CSS_STYLE_PROXY_TARGET] || this, arguments);
};
// NOTE: we cannot use 'overrideFunction' here since the function may not exist
overrideStringRepresentation(styleDeclarationProto[prop], nativeFn);
}
};
var this_1 = this;
for (var prop in styleDeclarationProto) {
_loop_1(prop);
}
};
StyleSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window);
var nativeMethods = this.nativeMethods;
var styleSandbox = this;
overrideDescriptor(window[nativeMethods.htmlElementStylePropOwnerName].prototype, 'style', {
getter: this.FEATURES.css2PropertiesProtoContainsAllProps || this.FEATURES.cssStyleDeclarationContainsAllProps
? null
: function () {
var style = nativeMethods.htmlElementStyleGetter.call(this);
if (styleSandbox.FEATURES.propsCannotBeOverridden)
return styleSandbox._getStyleProxy(style);
return styleSandbox._processStyleInstance(style);
},
setter: nativeMethods.htmlElementStyleSetter ? function (value) {
var processedCss = styleProcessor.process(value, getProxyUrl);
nativeMethods.htmlElementStyleSetter.call(this, processedCss);
} : null,
});
if (this.FEATURES.css2PropertiesProtoContainsAllProps) {
for (var _i = 0, _a = this.URL_PROPS; _i < _a.length; _i++) {
var prop = _a[_i];
// @ts-ignore
this._overrideStyleProp(window.CSS2Properties.prototype, prop);
}
for (var _b = 0, _c = this.DASHED_URL_PROPS; _b < _c.length; _b++) {
var prop = _c[_b];
// @ts-ignore
this._overrideStyleProp(window.CSS2Properties.prototype, prop);
}
}
else {
if (this.FEATURES.cssStyleDeclarationProtoContainsUrlProps) {
for (var _d = 0, _e = this.URL_PROPS; _d < _e.length; _d++) {
var prop = _e[_d];
this._overrideStyleProp(window.CSSStyleDeclaration.prototype, prop);
}
}
if (this.FEATURES.cssStyleDeclarationProtoContainsDashedProps) {
for (var _f = 0, _g = this.DASHED_URL_PROPS; _f < _g.length; _f++) {
var prop = _g[_f];
this._overrideStyleProp(window.CSSStyleDeclaration.prototype, prop);
}
}
}
overrideDescriptor(window.CSSStyleDeclaration.prototype, 'cssText', {
getter: function () {
var cssText = nativeMethods.styleCssTextGetter.call(this);
return styleProcessor.cleanUp(cssText, parseProxyUrl);
},
setter: function (value) {
if (typeof value === 'string')
value = styleProcessor.process(value, getProxyUrl);
nativeMethods.styleCssTextSetter.call(this, value);
},
});
overrideFunction(window.CSSStyleSheet.prototype, 'insertRule', function (rule, index) {
var newRule = styleProcessor.process(rule, getProxyUrl);
return nativeMethods.styleInsertRule.call(this, newRule, index);
});
overrideFunction(window.CSSStyleDeclaration.prototype, 'getPropertyValue', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var value = nativeMethods.styleGetPropertyValue.apply(this, args);
return styleProcessor.cleanUp(value, parseProxyUrl);
});
overrideFunction(window.CSSStyleDeclaration.prototype, 'setProperty', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var value = args[1];
if (typeof value === 'string')
args[1] = styleProcessor.process(value, getProxyUrl);
return nativeMethods.styleSetProperty.apply(this, args);
});
overrideFunction(window.CSSStyleDeclaration.prototype, 'removeProperty', function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var oldValue = nativeMethods.styleRemoveProperty.apply(this, args);
return styleProcessor.cleanUp(oldValue, parseProxyUrl);
});
// NOTE: We need to override context of all functions from the CSSStyleDeclaration prototype if we use the Proxy feature.
// Can only call CSSStyleDeclaration.<function name> on instances of CSSStyleDeclaration
// The error above occurs if functions will be called on a proxy instance.
if (this.FEATURES.propsCannotBeOverridden)
this._overrideCSSStyleDeclarationFunctionsCtx(window);
};
return StyleSandbox;
}(SandboxBase));
var BROWSERTOOLS_CONSOLE_SAFEFUNC = '__BROWSERTOOLS_CONSOLE_SAFEFUNC';
var IEDebugSandbox = /** @class */ (function (_super) {
__extends(IEDebugSandbox, _super);
function IEDebugSandbox() {
var _this = _super.call(this) || this;
_this._isDebuggerInitiator = false;
return _this;
}
IEDebugSandbox.prototype._createFuncWrapper = function (func) {
var _this = this;
if (isFunction(func)) {
return function (fn, safeAssert) {
var ieDebugSandbox = _this;
return function () {
ieDebugSandbox._isDebuggerInitiator = true;
try {
var result = fn(arguments);
ieDebugSandbox._isDebuggerInitiator = false;
return result;
}
catch (e) {
safeAssert(e);
}
ieDebugSandbox._isDebuggerInitiator = false;
};
};
}
return func;
};
IEDebugSandbox.prototype.isDebuggerInitiator = function () {
return this._isDebuggerInitiator;
};
IEDebugSandbox.prototype.attach = function (window) {
var _this = this;
if (!isIE)
return;
var descriptor = this.nativeMethods.objectGetOwnPropertyDescriptor(window, BROWSERTOOLS_CONSOLE_SAFEFUNC);
var wrapper = void 0;
if (!descriptor || descriptor.value) { // eslint-disable-line no-restricted-properties
if (descriptor)
wrapper = this._createFuncWrapper(descriptor.value); // eslint-disable-line no-restricted-properties
this.nativeMethods.objectDefineProperty(window, BROWSERTOOLS_CONSOLE_SAFEFUNC, {
set: function (fn) {
wrapper = _this._createFuncWrapper(fn);
},
get: function () { return wrapper; },
});
}
};
return IEDebugSandbox;
}(SandboxBase));
function getRandomInt16Value () {
var array = new nativeMethods.Uint16Array(1);
nativeMethods.cryptoGetRandomValues.call(nativeMethods.crypto, array);
return array[0];
}
var DEFAULT_WINDOW_PARAMETERS = 'width=500px, height=500px';
var STORE_CHILD_WINDOW_CMD = 'hammerhead|command|store-child-window';
var ChildWindowSandbox = /** @class */ (function (_super) {
__extends(ChildWindowSandbox, _super);
function ChildWindowSandbox(_messageSandbox, _listeners) {
var _this = _super.call(this) || this;
_this._messageSandbox = _messageSandbox;
_this._listeners = _listeners;
_this.WINDOW_OPENED_EVENT = 'hammerhead|event|window-opened';
_this.BEFORE_WINDOW_OPEN_IN_SAME_TAB = 'hammerhead|event|before-window-open-in-same-tab';
return _this;
}
ChildWindowSandbox._shouldOpenInNewWindowOnElementAction = function (el, defaultTarget) {
var hasDownloadAttribute = typeof nativeMethods.getAttribute.call(el, 'download') === 'string';
if (hasDownloadAttribute)
return false;
var target = this._calculateTargetForElement(el);
return this._shouldOpenInNewWindow(target, defaultTarget);
};
ChildWindowSandbox._shouldOpenInNewWindow = function (target, defaultTarget) {
target = target || defaultTarget;
target = target.toLowerCase();
if (isKeywordTarget(target))
return target === '_blank';
return !findByName(target);
};
ChildWindowSandbox.prototype._openUrlInNewWindow = function (url, windowName, windowParams, window) {
var windowId = getRandomInt16Value().toString();
windowParams = windowParams || DEFAULT_WINDOW_PARAMETERS;
windowName = windowName || windowId;
var newPageUrl = getPageProxyUrl(url, windowId);
var targetWindow = window || this.window;
var openedWindow = nativeMethods.windowOpen.call(targetWindow, newPageUrl, windowName, windowParams);
this._tryToStoreChildWindow(openedWindow, getTopOpenerWindow());
this.emit(this.WINDOW_OPENED_EVENT, { windowId: windowId, window: openedWindow });
return { windowId: windowId, wnd: openedWindow };
};
ChildWindowSandbox._calculateTargetForElement = function (el) {
var base = nativeMethods.querySelector.call(findDocument(el), 'base');
return el.target || (base === null || base === void 0 ? void 0 : base.target);
};
ChildWindowSandbox.prototype.handleClickOnLinkOrArea = function (el) {
var _this = this;
if (!settings.get().allowMultipleWindows)
return;
this._listeners.initElementListening(el, ['click']);
this._listeners.addInternalEventAfterListener(el, ['click'], function (e) {
if (e.defaultPrevented)
return;
if (!ChildWindowSandbox._shouldOpenInNewWindowOnElementAction(el, defaultTarget.linkOrArea))
return;
// TODO: need to check that specified 'area' are clickable (initiated new page opening)
var url = nativeMethods.anchorHrefGetter.call(el);
e.preventDefault();
_this._openUrlInNewWindowIfNotPrevented(url, e);
});
};
ChildWindowSandbox.prototype._openUrlInNewWindowIfNotPrevented = function (url, e) {
var _this = this;
var eventBubbledToTop = false;
var isDefaultPrevented = false;
var openUrlInNewWindowIfNotPreventedHandler = function () {
eventBubbledToTop = true;
Listeners.getNativeRemoveEventListener(window).call(window, 'click', openUrlInNewWindowIfNotPreventedHandler);
if (!isDefaultPrevented)
_this._openUrlInNewWindow(url);
};
Listeners.getNativeAddEventListener(window).call(window, 'click', openUrlInNewWindowIfNotPreventedHandler);
// NOTE: additional attempt to open a new window if window.handler was prevented by
// `stopPropagation` or `stopImmediatePropagation` methods
var origPreventDefault = e.preventDefault;
e.preventDefault = function () {
isDefaultPrevented = true;
return origPreventDefault.call(e);
};
nextTick().then(function () {
if (!eventBubbledToTop)
openUrlInNewWindowIfNotPreventedHandler();
});
};
ChildWindowSandbox.prototype.handleWindowOpen = function (window, args) {
var url = args[0], target = args[1], parameters = args[2];
if (settings.get().allowMultipleWindows && ChildWindowSandbox._shouldOpenInNewWindow(target, defaultTarget.windowOpen)) {
var openedWindowInfo = this._openUrlInNewWindow(url, target, parameters, window);
return openedWindowInfo.wnd;
}
// NOTE: Safari stopped throwing the 'unload' event for this case starting from 14 version.
// We are forced using the pageNavigationWatch to guarantee working the storages transfer between pages.
if (isSafari && version >= 15)
this.emit(this.BEFORE_WINDOW_OPEN_IN_SAME_TAB, { url: url });
return nativeMethods.windowOpen.apply(window, args);
};
ChildWindowSandbox.prototype._handleFormSubmitting = function (window) {
var _this = this;
if (!settings.get().allowMultipleWindows)
return;
this._listeners.initElementListening(window, ['submit']);
this._listeners.addInternalEventBeforeListener(window, ['submit'], function (e) {
var form = nativeMethods.eventTargetGetter.call(e);
if (!isFormElement(form) ||
!ChildWindowSandbox._shouldOpenInNewWindowOnElementAction(form, defaultTarget.form))
return;
var aboutBlankUrl = getProxyUrl(SPECIAL_BLANK_PAGE);
var openedInfo = _this._openUrlInNewWindow(aboutBlankUrl);
var formAction = nativeMethods.formActionGetter.call(form);
var newWindowUrl = getPageProxyUrl(formAction, openedInfo.windowId);
nativeMethods.formActionSetter.call(form, newWindowUrl);
nativeMethods.formTargetSetter.call(form, openedInfo.windowId);
// TODO: On hammerhead start we need to clean up the window.name
// It's necessary for form submit.
// Also we need clean up the form target to the original value.
});
};
ChildWindowSandbox.prototype._tryToStoreChildWindow = function (win, topOpenerWindow) {
try {
topOpenerWindow[INTERNAL_PROPS.hammerhead].sandbox.childWindow.addWindow(win);
return true;
}
catch (e) {
return false;
}
};
ChildWindowSandbox.prototype._setupChildWindowCollecting = function (window) {
var _this = this;
if (isIframeWindow(window))
return;
var topOpenerWindow = getTopOpenerWindow();
if (window !== topOpenerWindow) {
if (!this._tryToStoreChildWindow(window, topOpenerWindow))
this._messageSandbox.sendServiceMsg({ cmd: STORE_CHILD_WINDOW_CMD }, topOpenerWindow);
}
else {
this._childWindows = new Set();
this._messageSandbox.on(this._messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (_a) {
var message = _a.message, source = _a.source;
if (message.cmd === STORE_CHILD_WINDOW_CMD)
_this._childWindows.add(source);
});
}
};
ChildWindowSandbox.prototype.addWindow = function (win) {
this._childWindows.add(win);
};
ChildWindowSandbox.prototype.getChildWindows = function () {
var _this = this;
var childWindows = [];
// eslint-disable-next-line hammerhead/proto-methods
this._childWindows.forEach(function (win) {
// NOTE: sort windows that can be closed
if (win.parent)
childWindows.push(win);
else
_this._childWindows.delete(win);
});
return childWindows;
};
ChildWindowSandbox.prototype.attach = function (window) {
_super.prototype.attach.call(this, window, window.document);
this._handleFormSubmitting(window);
this._setupChildWindowCollecting(window);
};
return ChildWindowSandbox;
}(SandboxBase));
var Sandbox = /** @class */ (function (_super) {
__extends(Sandbox, _super);
function Sandbox(transport) {
var _this = _super.call(this) || this;
create(window, _this);
add(window);
var ieDebugSandbox = new IEDebugSandbox();
var listeners = new Listeners();
var nodeMutation = new NodeMutation();
var unloadSandbox = new UnloadSandbox(listeners);
var messageSandbox = new MessageSandbox(listeners, unloadSandbox);
var eventSimulator = new EventSimulator();
var elementEditingWatcher = new ElementEditingWatcher(eventSimulator);
var timersSandbox = new TimersSandbox();
var childWindowSandbox = new ChildWindowSandbox(messageSandbox, listeners);
var cookieSandbox = new CookieSandbox(messageSandbox, unloadSandbox, childWindowSandbox);
// API
_this.ieDebug = ieDebugSandbox;
_this.cookie = cookieSandbox; // eslint-disable-line no-restricted-properties
_this.childWindow = childWindowSandbox;
_this.storageSandbox = new StorageSandbox(listeners, unloadSandbox, eventSimulator);
_this.xhr = new XhrSandbox(cookieSandbox);
_this.fetch = new FetchSandbox(cookieSandbox);
_this.iframe = new IframeSandbox(nodeMutation, cookieSandbox);
_this.shadowUI = new ShadowUISandbox(nodeMutation, messageSandbox, _this.iframe, ieDebugSandbox);
_this.upload = new UploadSandbox(listeners, eventSimulator, transport);
_this.event = new EventSandbox(listeners, eventSimulator, elementEditingWatcher, unloadSandbox, messageSandbox, _this.shadowUI, timersSandbox);
_this.node = new NodeSandbox$1(nodeMutation, _this.iframe, _this.event, _this.upload, _this.shadowUI, cookieSandbox, _this.childWindow);
_this.codeInstrumentation = new CodeInstrumentation(_this.event, messageSandbox);
_this.console = new ConsoleSandbox(messageSandbox);
_this.style = new StyleSandbox();
_this.unload = unloadSandbox;
if (isElectron)
_this.electron = new ElectronSandbox();
_this.windowStorage = windowStorage;
return _this;
}
// NOTE: In some cases, IE raises the "Can't execute code from a freed script" exception,
// so that we cannot use a sandbox created earlier and we have to create a new one.
Sandbox._canUseSandbox = function (sandbox) {
try {
//@ts-ignore
sandbox.off();
}
catch (e) {
return false;
}
return true;
};
Sandbox.prototype.onIframeDocumentRecreated = function (iframe) {
if (iframe) {
var contentWindow = nativeMethods.contentWindowGetter.call(iframe);
var contentDocument = nativeMethods.contentDocumentGetter.call(iframe);
// NOTE: Try to find an existing iframe sandbox.
var sandbox = get(contentWindow);
if (sandbox && Sandbox._canUseSandbox(sandbox)) {
if (!contentWindow[INTERNAL_PROPS.sandboxIsReattached] || sandbox.document !== contentDocument) {
// NOTE: Inform the sandbox so that it restores communication with the recreated document.
sandbox.reattach(contentWindow, contentDocument);
}
}
else {
// NOTE: Remove saved native methods for iframe
if (contentWindow[INTERNAL_PROPS.iframeNativeMethods])
delete contentWindow[INTERNAL_PROPS.iframeNativeMethods];
// NOTE: If the iframe sandbox is not found, this means that iframe is not initialized.
// In this case, we need to inject Hammerhead.
// HACK: IE10 cleans up overridden methods after the document.write method call.
this.nativeMethods.restoreDocumentMeths(contentWindow, contentDocument);
// NOTE: A sandbox for this iframe is not found (iframe is not yet initialized).
// Inform IFrameSandbox about this, and it injects Hammerhead.
this.iframe.onIframeBeganToRun(iframe);
}
}
};
Sandbox.prototype.reattach = function (window, document) {
nativeMethods.objectDefineProperty(window, INTERNAL_PROPS.sandboxIsReattached, { value: true, configurable: false });
// NOTE: Assign the existing sandbox to the cleared document.
if (isIE)
this.nativeMethods.refreshIfNecessary(document, window);
urlResolver.init(document);
this.event.reattach(window);
this.shadowUI.attach(window);
// NOTE: T182337
this.codeInstrumentation.attach(window);
this.node.doc.attach(window, document);
this.console.attach(window);
this.childWindow.attach(window);
};
Sandbox.prototype.attach = function (window) {
var _this = this;
_super.prototype.attach.call(this, window);
nativeMethods.objectDefineProperty(window, INTERNAL_PROPS.sandboxIsReattached, { value: true, configurable: false });
urlResolver.init(this.document);
// NOTE: Eval Hammerhead code script.
this.iframe.on(this.iframe.EVAL_HAMMERHEAD_SCRIPT_EVENT, function (e) {
// @ts-ignore
nativeMethods.contentWindowGetter.call(e.iframe).eval("(".concat(initHammerheadClient.toString(), ")();//# sourceURL=hammerhead.js"));
});
// NOTE: We need to reattach a sandbox to the recreated iframe document.
this.node.mutation.on(this.node.mutation.DOCUMENT_CLEANED_EVENT, function (e) { return _this.reattach(e.window, e.document); });
this.ieDebug.attach(window);
this.iframe.attach(window);
this.xhr.attach(window);
this.fetch.attach(window);
this.storageSandbox.attach(window);
this.codeInstrumentation.attach(window);
this.shadowUI.attach(window);
this.event.attach(window);
this.node.attach(window);
this.upload.attach(window);
this.cookie.attach(window); // eslint-disable-line no-restricted-properties
this.console.attach(window);
this.style.attach(window);
this.childWindow.attach(window);
if (this.electron)
this.electron.attach(window);
this.unload.on(this.unload.UNLOAD_EVENT, function () { return _this.dispose(); });
};
Sandbox.prototype._removeInternalProperties = function () {
var removeListeningElement = this.event.listeners.listeningCtx.removeListeningElement;
removeListeningElement(this.window);
removeListeningElement(this.document);
var childNodes = nativeMethods.querySelectorAll.call(this.document, '*');
var length = nativeMethods.nodeListLengthGetter.call(childNodes);
for (var i = 0; i < length; i++) {
var childNode = childNodes[i];
delete childNode[INTERNAL_PROPS.processedContext];
removeListeningElement(childNode);
}
};
Sandbox.prototype.dispose = function () {
this.event.hover.dispose();
this.event.focusBlur.dispose();
dispose$1();
dispose();
urlResolver.dispose(this.document);
this.storageSandbox.dispose();
this._removeInternalProperties();
};
return Sandbox;
}(SandboxBase));
var SERVICE_MESSAGES_WAITING_INTERVAL = 50;
var TransportBase = /** @class */ (function () {
function TransportBase() {
this._shouldAddReferer = TransportBase._shouldAddReferer();
this._activeServiceMsgCount = 0;
}
TransportBase._shouldAddReferer = function () {
var frameElement = getFrameElement(window);
return frameElement && isIframeWithoutSrc(frameElement);
};
TransportBase._getStoredMessages = function () {
var nativeLocalStorage = nativeMethods.winLocalStorageGetter.call(window);
var storedMessagesStr = nativeMethods.storageGetItem.call(nativeLocalStorage, settings.get().sessionId);
return storedMessagesStr ? parse$1(storedMessagesStr) : [];
};
TransportBase._storeMessage = function (msg) {
var storedMessages = TransportBase._getStoredMessages();
var nativeLocalStorage = nativeMethods.winLocalStorageGetter.call(window);
storedMessages.push(msg);
nativeMethods.storageSetItem.call(nativeLocalStorage, settings.get().sessionId, stringify(storedMessages));
};
TransportBase._removeMessageFromStore = function (cmd) {
var messages = TransportBase._getStoredMessages();
var initialMsgLength = messages.length;
var nativeLocalStorage = nativeMethods.winLocalStorageGetter.call(window);
for (var i = 0; i < messages.length; i++) {
if (messages[i].cmd === cmd) {
messages.splice(i, 1);
break;
}
}
// NOTE: this condition is needed for proxyless mode to preserve saving any data to localStorage
// TODO: research why this works in proxy mode and does not work in proxyless
if (messages.length < initialMsgLength)
nativeMethods.storageSetItem.call(nativeLocalStorage, settings.get().sessionId, stringify(messages));
};
TransportBase.prototype.batchUpdate = function () {
var storedMessages = TransportBase._getStoredMessages();
if (!storedMessages.length)
return pinkie.resolve();
var tasks = [];
var nativeLocalStorage = nativeMethods.winLocalStorageGetter.call(window);
nativeMethods.storageRemoveItem.call(nativeLocalStorage, settings.get().sessionId);
for (var _i = 0, storedMessages_1 = storedMessages; _i < storedMessages_1.length; _i++) {
var storedMessage = storedMessages_1[_i];
tasks.push(this.queuedAsyncServiceMsg(storedMessage));
}
return pinkie.all(tasks);
};
TransportBase.prototype.waitForServiceMessagesCompleted = function (timeout) {
var _this = this;
return new pinkie(function (resolve) {
if (!_this._activeServiceMsgCount) {
resolve();
return;
}
var intervalId = null;
var timeoutId = nativeMethods.setTimeout.call(window, function () {
nativeMethods.clearInterval.call(window, intervalId);
resolve();
}, timeout);
intervalId = nativeMethods.setInterval.call(window, function () {
if (_this._activeServiceMsgCount)
return;
nativeMethods.clearInterval.call(window, intervalId);
nativeMethods.clearTimeout.call(window, timeoutId);
resolve();
}, SERVICE_MESSAGES_WAITING_INTERVAL);
});
};
return TransportBase;
}());
function createUnresolvablePromise () {
return new pinkie(noop);
}
var TransportLegacy = /** @class */ (function (_super) {
__extends(TransportLegacy, _super);
function TransportLegacy() {
var _this = _super.call(this) || this;
_this._msgQueue = {};
return _this;
}
TransportLegacy.prototype._performRequest = function (msg, callback) {
var _this = this;
msg.sessionId = settings.get().sessionId;
if (this._shouldAddReferer)
msg.referer = settings.get().referer;
var sendMsg = function (forced) {
_this._activeServiceMsgCount++;
var isAsyncRequest = !forced;
var transport = _this;
var request = XhrSandbox.createNativeXHR();
var msgCallback = function () {
// NOTE: The 500 status code is returned by server when an error occurred into service message handler
if (this.status === 500 && this.responseText) {
msg.disableResending = true;
errorHandler.call(this); // eslint-disable-line no-use-before-define
return;
}
transport._activeServiceMsgCount--;
var response = this.responseText && parse$1(this.responseText);
request = null;
callback(null, response);
};
var errorHandler = function () {
if (msg.disableResending) {
transport._activeServiceMsgCount--;
var errorMsg = "XHR request failed with ".concat(request.status, " status code.");
if (this.responseText)
errorMsg += "\nError message: ".concat(this.responseText);
callback(new Error(errorMsg));
return;
}
if (isWebKit || isFirefox) {
TransportBase._storeMessage(msg);
msgCallback.call(this);
}
else
sendMsg(true);
};
XhrSandbox.openNativeXhr(request, settings.get().serviceMsgUrl, isAsyncRequest);
if (forced) {
request.addEventListener('readystatechange', function () {
if (this.readyState !== 4)
return;
msgCallback.call(this);
});
}
else {
request.addEventListener('load', msgCallback);
request.addEventListener('abort', errorHandler);
request.addEventListener('error', errorHandler);
request.addEventListener('timeout', errorHandler);
}
request.send(stringify(msg));
};
TransportBase._removeMessageFromStore(msg.cmd);
sendMsg();
};
TransportLegacy.prototype.queuedAsyncServiceMsg = function (msg) {
var _this = this;
if (!this._msgQueue[msg.cmd])
this._msgQueue[msg.cmd] = pinkie.resolve();
var isRejectingAllowed = msg.allowRejecting;
msg.allowRejecting = true;
this._msgQueue[msg.cmd] = this._msgQueue[msg.cmd]
.catch(noop)
.then(function () { return _this.asyncServiceMsg(msg); });
return this._msgQueue[msg.cmd]
.catch(function (err) {
if (isRejectingAllowed)
return pinkie.reject(err);
return createUnresolvablePromise();
});
};
TransportLegacy.prototype.asyncServiceMsg = function (msg) {
var _this = this;
return new pinkie(function (resolve, reject) {
_this._performRequest(msg, function (err, data) {
if (!err)
resolve(data);
else if (msg.allowRejecting)
reject(err);
});
});
};
TransportLegacy.prototype.start = function (messageSandbox) {
// NOTE: There is no special logic here.
};
return TransportLegacy;
}(TransportBase));
var SET_INITIAL_WORKER_SETTINGS_CMD = 'hammerhead|transport|set-initial-worker-settings';
var HANDLE_PORT_CMD = 'hammerhead|transport|handle-port';
var GET_MESSAGE_PORT = 'hammerhead|command|get-message-port';
var SET_MESSAGE_PORT = 'hammerhead|command|set-message-port';
var TransportInWorker = /** @class */ (function (_super) {
__extends(TransportInWorker, _super);
function TransportInWorker() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this._transportWorker = null;
_this._idGenerator = new IntegerIdGenerator();
_this._messageCallbacks = new Map();
_this._queue = [];
return _this;
}
TransportInWorker.prototype._processQueue = function () {
for (var _i = 0, _a = this._queue; _i < _a.length; _i++) {
var msgWrapper = _a[_i];
this._transportWorker.postMessage(msgWrapper);
}
this._queue.length = 0;
};
TransportInWorker.prototype._onWorkerMessage = function (e) {
var _a = e.data, id = _a.id, result = _a.result;
if (!this._messageCallbacks.has(id))
return;
this._messageCallbacks.get(id)(result.err, result.data);
this._messageCallbacks.delete(id);
};
TransportInWorker.prototype.asyncServiceMsg = function (msg, queued) {
var _this = this;
if (queued === void 0) { queued = false; }
return new pinkie(function (resolve, reject) {
var id = _this._idGenerator.increment();
++_this._activeServiceMsgCount;
if (_this._shouldAddReferer)
msg.referer = settings.get().referer;
_this._messageCallbacks.set(id, function (err, data) {
--_this._activeServiceMsgCount;
if (!err)
resolve(data);
else {
if (!msg.disableResending && (isWebKit || isFirefox)) {
TransportBase._removeMessageFromStore(msg.cmd);
TransportBase._storeMessage(msg);
resolve();
}
if (msg.allowRejecting)
reject(new Error(err));
}
});
if (_this._transportWorker)
_this._transportWorker.postMessage({ id: id, queued: queued, msg: msg });
else
_this._queue.push({ id: id, queued: queued, msg: msg });
});
};
TransportInWorker.prototype.queuedAsyncServiceMsg = function (msg) {
return this.asyncServiceMsg(msg, true);
};
TransportInWorker.prototype.start = function (messageSandbox) {
var _this = this;
if (window === window.top) {
// @ts-ignore
this._transportWorker = new nativeMethods.Worker(settings.get().transportWorkerUrl, { name: 'Transport' });
this._transportWorker.postMessage({
cmd: SET_INITIAL_WORKER_SETTINGS_CMD,
sessionId: settings.get().sessionId,
serviceMsgUrl: settings.get().serviceMsgUrl,
});
this._transportWorker.addEventListener('message', function (e) { return _this._onWorkerMessage(e); });
this._processQueue();
}
else
messageSandbox.sendServiceMsg({ cmd: GET_MESSAGE_PORT }, window.top);
messageSandbox.on(messageSandbox.SERVICE_MSG_RECEIVED_EVENT, function (_a) {
var message = _a.message, source = _a.source, ports = _a.ports;
if (message.cmd === GET_MESSAGE_PORT) {
var channel = new nativeMethods.MessageChannel();
messageSandbox.sendServiceMsg({ cmd: SET_MESSAGE_PORT }, source, [channel.port1]);
_this._transportWorker.postMessage({ cmd: HANDLE_PORT_CMD }, [channel.port2]);
}
else if (message.cmd === SET_MESSAGE_PORT) {
_this._transportWorker = ports[0];
_this._transportWorker.onmessage = function (e) { return _this._onWorkerMessage(e); };
_this._processQueue();
}
});
};
return TransportInWorker;
}(TransportBase));
var Transport = /** @class */ (function () {
function Transport() {
}
Transport.prototype.start = function (messageSandbox, useWorker) {
if (useWorker === void 0) { useWorker = true; }
this._implementation = useWorker
? new TransportInWorker()
: new TransportLegacy();
this._implementation.start(messageSandbox);
};
Transport.prototype.asyncServiceMsg = function (msg) {
return this._implementation.asyncServiceMsg(msg);
};
Transport.prototype.queuedAsyncServiceMsg = function (msg) {
return this._implementation.queuedAsyncServiceMsg(msg);
};
// NOTE: for testcafe-legacy-api
Transport.prototype.batchUpdate = function () {
return this._implementation.batchUpdate();
};
// NOTE: for testcafe-legacy-api
Transport.prototype.waitForServiceMessagesCompleted = function (timeout) {
return this._implementation.waitForServiceMessagesCompleted(timeout);
};
return Transport;
}());
var PageNavigationWatch = /** @class */ (function (_super) {
__extends(PageNavigationWatch, _super);
function PageNavigationWatch(_eventSandbox, _codeInstrumentation, _elementSandbox, _childWindowSandbox) {
var _this = _super.call(this) || this;
_this._eventSandbox = _eventSandbox;
_this._codeInstrumentation = _codeInstrumentation;
_this._elementSandbox = _elementSandbox;
_this._childWindowSandbox = _childWindowSandbox;
_this.PAGE_NAVIGATION_TRIGGERED_EVENT = 'hammerhead|event|page-navigation-triggered';
_this._lastLocationValue = window.location.toString();
return _this;
}
PageNavigationWatch.prototype._formWatch = function (elementSandbox, eventSandbox) {
var onFormSubmit = function (form) {
var targetWindow = PageNavigationWatch._getTargetWindow(form);
PageNavigationWatch._onNavigationTriggeredInWindow(targetWindow, nativeMethods.formActionGetter.call(form));
};
// NOTE: fires when form.submit() is called
elementSandbox.on(elementSandbox.BEFORE_FORM_SUBMIT_EVENT, function (e) { return onFormSubmit(e.form); });
// NOTE: fires when the form is submitted by clicking the submit button
eventSandbox.listeners.initElementListening(window, ['submit']);
eventSandbox.listeners.addInternalEventBeforeListener(window, ['submit'], function (e) {
var prevented = false;
var target = nativeMethods.eventTargetGetter.call(e);
if (!isFormElement(target))
return;
var onPreventDefault = function (preventedEvent) {
prevented = prevented || preventedEvent === e;
};
eventSandbox.on(eventSandbox.EVENT_PREVENTED_EVENT, onPreventDefault);
nextTick()
.then(function () {
eventSandbox.off(eventSandbox.EVENT_PREVENTED_EVENT, onPreventDefault);
// NOTE: the defaultPrevented flag is saved between event raises in all browsers
// except IE. In IE, it is reset to false before the next handler is executed.
if (!e.defaultPrevented && !prevented)
onFormSubmit(target);
});
});
};
PageNavigationWatch._getTargetWindow = function (el) {
var target = nativeMethods.getAttribute.call(el, DomProcessor.getStoredAttrName('target')) ||
nativeMethods.getAttribute.call(el, 'target') ||
'_self';
switch (target) {
case '_top':
return window.top;
case '_parent':
return window.parent;
case '_self':
return window;
default:
return findByName(target);
}
};
PageNavigationWatch.prototype._linkWatch = function (eventSandbox) {
eventSandbox.listeners.initElementListening(window, ['click']);
eventSandbox.listeners.addInternalEventBeforeListener(window, ['click'], function (e) {
var target = nativeMethods.eventTargetGetter.call(e);
var link = isAnchorElement(target) ? target : closest(target, 'a');
if (link && !isShadowUIElement(link)) {
var prevented_1 = false;
var targetWindow_1 = PageNavigationWatch._getTargetWindow(link);
var href_1 = nativeMethods.anchorHrefGetter.call(link);
var onPreventDefault_1 = function (preventedEvent) {
prevented_1 = prevented_1 || preventedEvent === e;
};
eventSandbox.on(eventSandbox.EVENT_PREVENTED_EVENT, onPreventDefault_1);
nextTick()
.then(function () {
eventSandbox.off(eventSandbox.EVENT_PREVENTED_EVENT, onPreventDefault_1);
// NOTE: the defaultPrevented flag is saved between event raises in all browsers
// except IE. In IE, it is reset to false before the next handler is executed.
if (!e.defaultPrevented && !prevented_1)
PageNavigationWatch._onNavigationTriggeredInWindow(targetWindow_1, href_1);
});
}
});
};
PageNavigationWatch.prototype._locationWatch = function (codeInstrumentation) {
var _this = this;
var locationAccessorsInstrumentation = codeInstrumentation._locationAccessorsInstrumentation;
var locationChangedHandler = function (newLocation) { return _this.onNavigationTriggered(newLocation); };
locationAccessorsInstrumentation.on(locationAccessorsInstrumentation.LOCATION_CHANGED_EVENT, locationChangedHandler);
};
PageNavigationWatch._onNavigationTriggeredInWindow = function (win, url) {
try {
win[INTERNAL_PROPS.hammerhead].pageNavigationWatch.onNavigationTriggered(url);
}
// eslint-disable-next-line no-empty
catch (e) {
}
};
PageNavigationWatch.prototype._childWindowWatch = function (childWindow) {
var self = this;
childWindow.on(childWindow.BEFORE_WINDOW_OPEN_IN_SAME_TAB, function (_a) {
var url = _a.url;
self.onNavigationTriggered(url);
});
};
PageNavigationWatch.prototype.onNavigationTriggered = function (url) {
var currentLocation = this._lastLocationValue;
this._lastLocationValue = window.location.toString();
if (url !== currentLocation && (url.charAt(0) === '#' || isChangedOnlyHash(currentLocation, url)) ||
DomProcessor.isJsProtocol(url))
return;
var parsedProxyUrl = parseProxyUrl$1(url);
if (!parsedProxyUrl)
return;
this.emit(this.PAGE_NAVIGATION_TRIGGERED_EVENT, parsedProxyUrl.destUrl);
};
PageNavigationWatch.prototype.start = function () {
this._locationWatch(this._codeInstrumentation);
this._linkWatch(this._eventSandbox);
this._formWatch(this._elementSandbox, this._eventSandbox);
this._childWindowWatch(this._childWindowSandbox);
};
return PageNavigationWatch;
}(EventEmitter));
var SCRIPT_SELECTOR = ".".concat(SHADOW_UI_CLASS_NAME.script);
function removeInjectedScript () {
var injectedScript = nativeMethods.querySelector.call(document, SCRIPT_SELECTOR);
if (injectedScript)
removeElement(injectedScript);
}
var Hammerhead = /** @class */ (function () {
function Hammerhead() {
var _this = this;
this.win = null;
this.transport = new Transport();
this.sandbox = new Sandbox(this.transport);
this.pageNavigationWatch = new PageNavigationWatch(this.sandbox.event, this.sandbox.codeInstrumentation, this.sandbox.node.element, this.sandbox.childWindow);
this.EVENTS = {
beforeFormSubmit: this.sandbox.node.element.BEFORE_FORM_SUBMIT_EVENT,
beforeBeforeUnload: this.sandbox.event.unload.BEFORE_BEFORE_UNLOAD_EVENT,
beforeUnload: this.sandbox.event.unload.BEFORE_UNLOAD_EVENT,
unload: this.sandbox.event.unload.UNLOAD_EVENT,
bodyCreated: this.sandbox.node.mutation.BODY_CREATED_EVENT,
documentCleaned: this.sandbox.node.mutation.DOCUMENT_CLEANED_EVENT,
uncaughtJsError: this.sandbox.node.win.UNCAUGHT_JS_ERROR_EVENT,
unhandledRejection: this.sandbox.node.win.UNHANDLED_REJECTION_EVENT,
startFileUploading: this.sandbox.upload.START_FILE_UPLOADING_EVENT,
endFileUploading: this.sandbox.upload.END_FILE_UPLOADING_EVENT,
evalIframeScript: this.sandbox.iframe.EVAL_EXTERNAL_SCRIPT_EVENT,
xhrCompleted: this.sandbox.xhr.XHR_COMPLETED_EVENT,
xhrError: this.sandbox.xhr.XHR_ERROR_EVENT,
beforeXhrSend: this.sandbox.xhr.BEFORE_XHR_SEND_EVENT,
fetchSent: this.sandbox.fetch.FETCH_REQUEST_SENT_EVENT,
pageNavigationTriggered: this.pageNavigationWatch.PAGE_NAVIGATION_TRIGGERED_EVENT,
scriptElementAdded: this.sandbox.node.element.SCRIPT_ELEMENT_ADDED_EVENT,
consoleMethCalled: this.sandbox.console.CONSOLE_METH_CALLED_EVENT,
windowOpened: this.sandbox.childWindow.WINDOW_OPENED_EVENT,
};
this.PROCESSING_INSTRUCTIONS = {
dom: {
script: SCRIPT_PROCESSING_INSTRUCTIONS,
internal_attributes: INTERNAL_ATTRIBUTES,
internal_props: INTERNAL_PROPS, // eslint-disable-line camelcase
},
};
this.SHADOW_UI_CLASS_NAME = SHADOW_UI_CLASS_NAME;
this.SESSION_COMMAND = ServiceCommands;
this.EventEmitter = EventEmitter;
// Methods
this.doUpload = function (input, filePaths) { return _this.sandbox.upload.doUpload(input, filePaths); };
this.createNativeXHR = XhrSandbox.createNativeXHR;
this.processScript = processScript;
// Modules
this.Promise = pinkie;
this.json = json;
this.nativeMethods = this.sandbox.nativeMethods;
this.shadowUI = this.sandbox.shadowUI;
this.storages = this.sandbox.storageSandbox;
this.eventSandbox = {
listeners: this.sandbox.event.listeners,
hover: this.sandbox.event.hover,
focusBlur: this.sandbox.event.focusBlur,
elementEditingWatcher: this.sandbox.event.elementEditingWatcher,
eventSimulator: this.sandbox.event.eventSimulator,
selection: this.sandbox.event.selection,
message: this.sandbox.event.message,
timers: this.sandbox.event.timers,
DataTransfer: this.sandbox.event.DataTransfer,
DragDataStore: this.sandbox.event.DragDataStore,
};
var processingUtils = {
script: scriptProcessingUtils,
header: headerProcessingUtils,
instrumentation: instrumentationProcessingUtils,
};
this.utils = {
browser: browserUtils,
dom: domUtils,
event: eventUtils,
position: positionUtils,
style: styleUtils,
types: typeUtils,
trim: trim$1,
extend: extend,
html: htmlUtils,
url: urlUtils,
featureDetection: featureDetection,
destLocation: destLocationUtils,
overriding: overridingUtils,
cookie: cookieUtils,
getMimeType: getMimeType,
urlResolver: urlResolver,
processing: processingUtils,
removeInjectedScript: removeInjectedScript,
};
this.sharedUtils = {
cookie: sharedCookieUtils,
url: sharedUrlUtils,
headers: sharedHeadersUtils,
stackProcessing: sharedStackProcessingUtils,
selfRemovingScripts: sharedSelfRemovingScripts,
};
this.settings = settings;
this.sandboxes = {
XhrSandbox: XhrSandbox,
StyleSandbox: StyleSandbox,
ShadowUISandbox: ShadowUISandbox,
ElectronSandbox: ElectronSandbox,
UploadSandbox: UploadSandbox,
ChildWindowSandbox: ChildWindowSandbox,
};
this.sandboxUtils = {
hiddenInfo: hiddenInfoUtils,
listeningContext: listeningContextUtils,
backup: sandboxBackupUtils,
domMutationTracker: domMutationTracker,
defaultTarget: defaultTarget,
UploadInfoManager: UploadInfoManager,
FileListWrapper: FileListWrapper,
EventListeners: Listeners,
StorageWrapper: StorageWrapper,
CodeInstrumentation: CodeInstrumentation,
LocationInstrumentation: LocationAccessorsInstrumentation,
LocationWrapper: LocationWrapper,
};
this.processors = {
styleProcessor: styleProcessor,
domProcessor: domProcessor,
DomProcessor: DomProcessor,
};
}
Hammerhead.prototype._getEventOwner = function (evtName) {
switch (evtName) {
case this.EVENTS.pageNavigationTriggered:
return this.pageNavigationWatch;
case this.EVENTS.beforeUnload:
case this.EVENTS.beforeBeforeUnload:
case this.EVENTS.unload:
return this.sandbox.event.unload;
case this.EVENTS.bodyCreated:
case this.EVENTS.documentCleaned:
return this.sandbox.node.mutation;
case this.EVENTS.uncaughtJsError:
case this.EVENTS.unhandledRejection:
return this.sandbox.node.win;
case this.EVENTS.startFileUploading:
case this.EVENTS.endFileUploading:
return this.sandbox.upload;
case this.EVENTS.evalIframeScript:
return this.sandbox.iframe;
case this.EVENTS.xhrCompleted:
case this.EVENTS.xhrError:
case this.EVENTS.beforeXhrSend:
return this.sandbox.xhr;
case this.EVENTS.beforeFormSubmit:
case this.EVENTS.scriptElementAdded:
return this.sandbox.node.element;
case this.EVENTS.fetchSent:
return this.sandbox.fetch;
case this.EVENTS.consoleMethCalled:
return this.sandbox.console;
case this.EVENTS.windowOpened:
return this.sandbox.childWindow;
default:
return null;
}
};
Hammerhead._cleanLocalStorageServiceData = function (sessionId, window) {
var nativeLocalStorage = nativeMethods.winLocalStorageGetter.call(window);
nativeMethods.storageRemoveItem.call(nativeLocalStorage, sessionId);
};
Hammerhead._setProxylessForComponents = function (value) {
var components = [
domProcessor,
urlResolver,
styleProcessor,
];
for (var i = 0; i < components.length; i++)
components[i].proxyless = value;
};
Hammerhead.prototype.on = function (evtName, handler) {
var eventOwner = this._getEventOwner(evtName);
if (eventOwner)
eventOwner.on(evtName, handler);
};
Hammerhead.prototype.off = function (evtName, handler) {
var eventOwner = this._getEventOwner(evtName);
if (eventOwner)
eventOwner.off(evtName, handler);
};
Hammerhead.prototype.navigateTo = function (url, forceReload) {
var _this = this;
var proxyless = !!settings.get().proxyless;
var navigationUrl = getNavigationUrl(url, this.win, proxyless);
if (!navigationUrl)
return;
// @ts-ignore
this.win.location = navigationUrl;
if (forceReload) {
this.sandbox.node.win.on(this.sandbox.node.win.HASH_CHANGE_EVENT, function () {
_this.win.location.reload();
});
}
};
Hammerhead.prototype.start = function (initSettings, win) {
this.win = win || window;
settings.set(initSettings);
if (initSettings.isFirstPageLoad)
Hammerhead._cleanLocalStorageServiceData(initSettings.sessionId, this.win);
domProcessor.forceProxySrcForImage = initSettings.forceProxySrcForImage;
domProcessor.allowMultipleWindows = initSettings.allowMultipleWindows;
Hammerhead._setProxylessForComponents(initSettings.proxyless);
this.transport.start(this.eventSandbox.message, !initSettings.proxyless);
this.sandbox.attach(this.win);
this.pageNavigationWatch.start();
};
return Hammerhead;
}());
var hammerhead = new Hammerhead();
// NOTE: The 'load' event is raised after calling document.close for a same-domain iframe
// So, we need to define the '%hammerhead%' variable as 'configurable' so that it can be redefined.
nativeMethods.objectDefineProperty(window, INTERNAL_PROPS.hammerhead, {
value: hammerhead,
configurable: true,
});
var hammerhead$1 = hammerhead;
return hammerhead$1;
})();
})();
window['%hammerhead%'].utils.removeInjectedScript();