mirror of
https://github.com/pysunday/sdenv.git
synced 2025-04-12 03:37:16 +08:00
5202 lines
153 KiB
Plaintext
5202 lines
153 KiB
Plaintext
var SdenvExtend = (function () {
|
||
|
||
/**
|
||
* Removes all key-value entries from the list cache.
|
||
*
|
||
* @private
|
||
* @name clear
|
||
* @memberOf ListCache
|
||
*/
|
||
function listCacheClear() {
|
||
this.__data__ = [];
|
||
this.size = 0;
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var arrayProto = Array.prototype;
|
||
|
||
/** Built-in value references. */
|
||
var splice = arrayProto.splice;
|
||
|
||
/**
|
||
* 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 : 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;
|
||
}
|
||
|
||
/**
|
||
* 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]);
|
||
}
|
||
}
|
||
|
||
// Add methods to `ListCache`.
|
||
ListCache.prototype.clear = listCacheClear;
|
||
ListCache.prototype['delete'] = listCacheDelete;
|
||
ListCache.prototype.get = listCacheGet;
|
||
ListCache.prototype.has = listCacheHas;
|
||
ListCache.prototype.set = listCacheSet;
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/** Detect free variable `global` from Node.js. */
|
||
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
|
||
|
||
/** 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')();
|
||
|
||
/** Built-in value references. */
|
||
var Symbol$1 = root.Symbol;
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$e = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$b = objectProto$e.hasOwnProperty;
|
||
|
||
/**
|
||
* Used to resolve the
|
||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||
* of values.
|
||
*/
|
||
var nativeObjectToString$1 = objectProto$e.toString;
|
||
|
||
/** Built-in value references. */
|
||
var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : undefined;
|
||
|
||
/**
|
||
* 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$b.call(value, symToStringTag$1),
|
||
tag = value[symToStringTag$1];
|
||
|
||
try {
|
||
value[symToStringTag$1] = undefined;
|
||
var unmasked = true;
|
||
} catch (e) {}
|
||
|
||
var result = nativeObjectToString$1.call(value);
|
||
if (unmasked) {
|
||
if (isOwn) {
|
||
value[symToStringTag$1] = tag;
|
||
} else {
|
||
delete value[symToStringTag$1];
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$d = Object.prototype;
|
||
|
||
/**
|
||
* Used to resolve the
|
||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||
* of values.
|
||
*/
|
||
var nativeObjectToString = objectProto$d.toString;
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/** `Object#toString` result references. */
|
||
var nullTag = '[object Null]',
|
||
undefinedTag = '[object Undefined]';
|
||
|
||
/** Built-in value references. */
|
||
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : undefined;
|
||
|
||
/**
|
||
* 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 ? undefinedTag : nullTag;
|
||
}
|
||
return (symToStringTag && symToStringTag in Object(value))
|
||
? getRawTag(value)
|
||
: objectToString(value);
|
||
}
|
||
|
||
/**
|
||
* 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');
|
||
}
|
||
|
||
/** `Object#toString` result references. */
|
||
var asyncTag = '[object AsyncFunction]',
|
||
funcTag$1 = '[object Function]',
|
||
genTag = '[object GeneratorFunction]',
|
||
proxyTag = '[object Proxy]';
|
||
|
||
/**
|
||
* 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$1 || tag == genTag || tag == asyncTag || tag == proxyTag;
|
||
}
|
||
|
||
/** Used to detect overreaching core-js shims. */
|
||
var coreJsData = root['__core-js_shared__'];
|
||
|
||
/** 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) : '';
|
||
}());
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var funcProto$2 = Function.prototype;
|
||
|
||
/** Used to resolve the decompiled source of functions. */
|
||
var funcToString$2 = funcProto$2.toString;
|
||
|
||
/**
|
||
* 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$2.call(func);
|
||
} catch (e) {}
|
||
try {
|
||
return (func + '');
|
||
} catch (e) {}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
/**
|
||
* Used to match `RegExp`
|
||
* [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
|
||
*/
|
||
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
|
||
|
||
/** Used to detect host constructors (Safari). */
|
||
var reIsHostCtor = /^\[object .+?Constructor\]$/;
|
||
|
||
/** Used for built-in method references. */
|
||
var funcProto$1 = Function.prototype,
|
||
objectProto$c = Object.prototype;
|
||
|
||
/** Used to resolve the decompiled source of functions. */
|
||
var funcToString$1 = funcProto$1.toString;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$a = objectProto$c.hasOwnProperty;
|
||
|
||
/** Used to detect if a method is native. */
|
||
var reIsNative = RegExp('^' +
|
||
funcToString$1.call(hasOwnProperty$a).replace(reRegExpChar, '\\$&')
|
||
.replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
|
||
);
|
||
|
||
/**
|
||
* 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));
|
||
}
|
||
|
||
/**
|
||
* 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 : object[key];
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/* Built-in method references that are verified to be native. */
|
||
var Map = getNative(root, 'Map');
|
||
|
||
/* Built-in method references that are verified to be native. */
|
||
var nativeCreate = getNative(Object, 'create');
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used to stand-in for `undefined` hash values. */
|
||
var HASH_UNDEFINED$2 = '__lodash_hash_undefined__';
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$b = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$9 = objectProto$b.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$2 ? undefined : result;
|
||
}
|
||
return hasOwnProperty$9.call(data, key) ? data[key] : undefined;
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$a = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$8 = objectProto$a.hasOwnProperty;
|
||
|
||
/**
|
||
* 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) : hasOwnProperty$8.call(data, key);
|
||
}
|
||
|
||
/** Used to stand-in for `undefined` hash values. */
|
||
var HASH_UNDEFINED$1 = '__lodash_hash_undefined__';
|
||
|
||
/**
|
||
* 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) ? HASH_UNDEFINED$1 : value;
|
||
return this;
|
||
}
|
||
|
||
/**
|
||
* 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]);
|
||
}
|
||
}
|
||
|
||
// Add methods to `Hash`.
|
||
Hash.prototype.clear = hashClear;
|
||
Hash.prototype['delete'] = hashDelete;
|
||
Hash.prototype.get = hashGet;
|
||
Hash.prototype.has = hashHas;
|
||
Hash.prototype.set = hashSet;
|
||
|
||
/**
|
||
* 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
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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]);
|
||
}
|
||
}
|
||
|
||
// Add methods to `MapCache`.
|
||
MapCache.prototype.clear = mapCacheClear;
|
||
MapCache.prototype['delete'] = mapCacheDelete;
|
||
MapCache.prototype.get = mapCacheGet;
|
||
MapCache.prototype.has = mapCacheHas;
|
||
MapCache.prototype.set = mapCacheSet;
|
||
|
||
/** Used as the size to enable large array optimizations. */
|
||
var LARGE_ARRAY_SIZE = 200;
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
// Add methods to `Stack`.
|
||
Stack.prototype.clear = stackClear;
|
||
Stack.prototype['delete'] = stackDelete;
|
||
Stack.prototype.get = stackGet;
|
||
Stack.prototype.has = stackHas;
|
||
Stack.prototype.set = stackSet;
|
||
|
||
var defineProperty = (function() {
|
||
try {
|
||
var func = getNative(Object, 'defineProperty');
|
||
func({}, '', {});
|
||
return func;
|
||
} catch (e) {}
|
||
}());
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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 && !eq(object[key], value)) ||
|
||
(value === undefined && !(key in object))) {
|
||
baseAssignValue(object, key, value);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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();
|
||
|
||
/** Detect free variable `exports`. */
|
||
var freeExports$2 = typeof exports == 'object' && exports && !exports.nodeType && exports;
|
||
|
||
/** Detect free variable `module`. */
|
||
var freeModule$2 = freeExports$2 && typeof module == 'object' && module && !module.nodeType && module;
|
||
|
||
/** Detect the popular CommonJS extension `module.exports`. */
|
||
var moduleExports$2 = freeModule$2 && freeModule$2.exports === freeExports$2;
|
||
|
||
/** Built-in value references. */
|
||
var Buffer$1 = moduleExports$2 ? root.Buffer : undefined,
|
||
allocUnsafe = Buffer$1 ? Buffer$1.allocUnsafe : undefined;
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Built-in value references. */
|
||
var Uint8Array = root.Uint8Array;
|
||
|
||
/**
|
||
* 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 `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);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Built-in value references. */
|
||
var objectCreate = Object.create;
|
||
|
||
/**
|
||
* 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;
|
||
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));
|
||
};
|
||
}
|
||
|
||
/** Built-in value references. */
|
||
var getPrototype = overArg(Object.getPrototypeOf, Object);
|
||
|
||
var getPrototype$1 = getPrototype;
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$9 = Object.prototype;
|
||
|
||
/**
|
||
* 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$9;
|
||
|
||
return value === proto;
|
||
}
|
||
|
||
/**
|
||
* 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$1(object))
|
||
: {};
|
||
}
|
||
|
||
/**
|
||
* 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';
|
||
}
|
||
|
||
/** `Object#toString` result references. */
|
||
var argsTag$2 = '[object Arguments]';
|
||
|
||
/**
|
||
* 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$2;
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$8 = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$7 = objectProto$8.hasOwnProperty;
|
||
|
||
/** Built-in value references. */
|
||
var propertyIsEnumerable$1 = objectProto$8.propertyIsEnumerable;
|
||
|
||
/**
|
||
* 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$7.call(value, 'callee') &&
|
||
!propertyIsEnumerable$1.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;
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var MAX_SAFE_INTEGER$1 = 9007199254740991;
|
||
|
||
/**
|
||
* 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$1;
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Detect free variable `exports`. */
|
||
var freeExports$1 = typeof exports == 'object' && exports && !exports.nodeType && exports;
|
||
|
||
/** Detect free variable `module`. */
|
||
var freeModule$1 = freeExports$1 && typeof module == 'object' && module && !module.nodeType && module;
|
||
|
||
/** Detect the popular CommonJS extension `module.exports`. */
|
||
var moduleExports$1 = freeModule$1 && freeModule$1.exports === freeExports$1;
|
||
|
||
/** Built-in value references. */
|
||
var Buffer = moduleExports$1 ? root.Buffer : undefined;
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;
|
||
|
||
/**
|
||
* 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;
|
||
|
||
/** `Object#toString` result references. */
|
||
var objectTag$3 = '[object Object]';
|
||
|
||
/** Used for built-in method references. */
|
||
var funcProto = Function.prototype,
|
||
objectProto$7 = Object.prototype;
|
||
|
||
/** Used to resolve the decompiled source of functions. */
|
||
var funcToString = funcProto.toString;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$6 = objectProto$7.hasOwnProperty;
|
||
|
||
/** Used to infer the `Object` constructor. */
|
||
var objectCtorString = funcToString.call(Object);
|
||
|
||
/**
|
||
* 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$3) {
|
||
return false;
|
||
}
|
||
var proto = getPrototype$1(value);
|
||
if (proto === null) {
|
||
return true;
|
||
}
|
||
var Ctor = hasOwnProperty$6.call(proto, 'constructor') && proto.constructor;
|
||
return typeof Ctor == 'function' && Ctor instanceof Ctor &&
|
||
funcToString.call(Ctor) == objectCtorString;
|
||
}
|
||
|
||
/** `Object#toString` result references. */
|
||
var argsTag$1 = '[object Arguments]',
|
||
arrayTag$1 = '[object Array]',
|
||
boolTag$1 = '[object Boolean]',
|
||
dateTag$1 = '[object Date]',
|
||
errorTag$1 = '[object Error]',
|
||
funcTag = '[object Function]',
|
||
mapTag$2 = '[object Map]',
|
||
numberTag$1 = '[object Number]',
|
||
objectTag$2 = '[object Object]',
|
||
regexpTag$1 = '[object RegExp]',
|
||
setTag$2 = '[object Set]',
|
||
stringTag$1 = '[object String]',
|
||
weakMapTag$1 = '[object WeakMap]';
|
||
|
||
var arrayBufferTag$1 = '[object ArrayBuffer]',
|
||
dataViewTag$2 = '[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 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$1] = typedArrayTags[arrayTag$1] =
|
||
typedArrayTags[arrayBufferTag$1] = typedArrayTags[boolTag$1] =
|
||
typedArrayTags[dataViewTag$2] = typedArrayTags[dateTag$1] =
|
||
typedArrayTags[errorTag$1] = typedArrayTags[funcTag] =
|
||
typedArrayTags[mapTag$2] = typedArrayTags[numberTag$1] =
|
||
typedArrayTags[objectTag$2] = typedArrayTags[regexpTag$1] =
|
||
typedArrayTags[setTag$2] = typedArrayTags[stringTag$1] =
|
||
typedArrayTags[weakMapTag$1] = false;
|
||
|
||
/**
|
||
* 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 `_.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);
|
||
};
|
||
}
|
||
|
||
/** Detect free variable `exports`. */
|
||
var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
|
||
|
||
/** Detect free variable `module`. */
|
||
var freeModule = freeExports && typeof module == '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 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
|
||
|
||
/**
|
||
* 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;
|
||
|
||
/**
|
||
* 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];
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$6 = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$5 = objectProto$6.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$5.call(object, key) && eq(objValue, value)) ||
|
||
(value === undefined && !(key in object))) {
|
||
baseAssignValue(object, key, value);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
|
||
if (newValue === undefined) {
|
||
newValue = source[key];
|
||
}
|
||
if (isNew) {
|
||
baseAssignValue(object, key, newValue);
|
||
} else {
|
||
assignValue(object, key, newValue);
|
||
}
|
||
}
|
||
return object;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var MAX_SAFE_INTEGER = 9007199254740991;
|
||
|
||
/** Used to detect unsigned integer values. */
|
||
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$5 = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$4 = objectProto$5.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$4.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;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$4 = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$3 = objectProto$4.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$3.call(object, key)))) {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
* 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));
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
|
||
var isCommon = newValue === undefined;
|
||
|
||
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 `_.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;
|
||
|
||
if (newValue === undefined) {
|
||
newValue = srcValue;
|
||
}
|
||
assignMergeValue(object, key, newValue);
|
||
}
|
||
}, keysIn);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeMax = Math.max;
|
||
|
||
/**
|
||
* 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 ? (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);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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
|
||
});
|
||
};
|
||
|
||
var baseSetToString$1 = baseSetToString;
|
||
|
||
/** Used to detect hot functions by number of calls within a span of milliseconds. */
|
||
var HOT_COUNT = 800,
|
||
HOT_SPAN = 16;
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeNow = Date.now;
|
||
|
||
/**
|
||
* 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, arguments);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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$1);
|
||
|
||
/**
|
||
* 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 + '');
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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,
|
||
guard = length > 2 ? sources[2] : undefined;
|
||
|
||
customizer = (assigner.length > 3 && typeof customizer == 'function')
|
||
? (length--, customizer)
|
||
: undefined;
|
||
|
||
if (guard && isIterateeCall(sources[0], sources[1], guard)) {
|
||
customizer = length < 3 ? undefined : customizer;
|
||
length = 1;
|
||
}
|
||
object = Object(object);
|
||
while (++index < length) {
|
||
var source = sources[index];
|
||
if (source) {
|
||
assigner(object, source, index, customizer);
|
||
}
|
||
}
|
||
return object;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
});
|
||
|
||
const sdenv = {
|
||
adapt: {}, // 适配专用网站方法
|
||
tools: {}, // 内部工具
|
||
utils: {}, // 外部方法
|
||
config: {
|
||
proxyOpen: false, // 是否允许开启代理
|
||
randomReturn: undefined, // 随机数值固定
|
||
randomFixed: false, // 固定日期与随机数,文件:@/config/dateAndRandom.json
|
||
// 强制setInterval的时间设置,如设置的足够大让执行函数不运行,其中:undefined表示通过框架拦截并计算运行时间,0表示不拦截且使用原时间
|
||
timeInterval: undefined,
|
||
timeTimeout: undefined, // 与timeInterval功能类似,区别是控制setTimeout
|
||
isNode: typeof window === 'undefined', // node环境标识
|
||
},
|
||
memory: {
|
||
runinfo: { // 程序运行时间节点
|
||
start: new Date().getTime(), // 代码开始运行
|
||
isDied: false, // 窗口生命是否已经结束
|
||
},
|
||
timeout: null, // 存放处理setTimeout/setInterval的类
|
||
sdEval: eval, // node内置eval
|
||
sdWindow: typeof window !== 'undefined' ? window : global,
|
||
sdFunction: Function,
|
||
sdDate: Date,
|
||
sdMath: Math,
|
||
SdenvExtend: null, // node环境缓存sdenv-extend插件,用于浏览器环境使用
|
||
},
|
||
cache: {
|
||
dynamicCode: [], // 缓存动态生成代码
|
||
runloop: {}, // 缓存循环代码运行时
|
||
/*
|
||
缓存循环执行顺序
|
||
sdenv.cache.runsArr
|
||
.map((it, num) => ({idx: it.idx, num, ...it.val}))
|
||
.reduce((ans, it) => (
|
||
ans[it.idx] === undefined ? ans[it.idx] = [it] : ans[it.idx].push(it), ans
|
||
), {})
|
||
*/
|
||
runsArr: [],
|
||
runsObj: [], // 缓存循环递归树
|
||
runtime: {}, // 存放运行时数据的代理
|
||
monitor: {}, // 监控变量对象
|
||
}, // 存储缓存数据
|
||
datas: {
|
||
dateAndRandom: {}, // 随机数相关数据
|
||
},
|
||
};
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** `Object#toString` result references. */
|
||
var symbolTag$1 = '[object Symbol]';
|
||
|
||
/**
|
||
* 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$1);
|
||
}
|
||
|
||
/** Used to match property names within property paths. */
|
||
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
|
||
reIsPlainProp = /^\w*$/;
|
||
|
||
/**
|
||
* 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));
|
||
}
|
||
|
||
/** Error message constants. */
|
||
var FUNC_ERROR_TEXT = 'Expected a function';
|
||
|
||
/**
|
||
* 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;
|
||
|
||
/** Used as the maximum memoize cache size. */
|
||
var MAX_MEMOIZE_SIZE = 500;
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used to match property names within property paths. */
|
||
var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
|
||
|
||
/** Used to match backslashes in property paths. */
|
||
var reEscapeChar = /\\(\\)?/g;
|
||
|
||
/**
|
||
* 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;
|
||
});
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var INFINITY$2 = 1 / 0;
|
||
|
||
/** Used to convert symbols to primitives and strings. */
|
||
var symbolProto$1 = Symbol$1 ? Symbol$1.prototype : undefined,
|
||
symbolToString = symbolProto$1 ? symbolProto$1.toString : undefined;
|
||
|
||
/**
|
||
* 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$2) ? '-0' : result;
|
||
}
|
||
|
||
/**
|
||
* 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$1(value) {
|
||
return value == null ? '' : baseToString(value);
|
||
}
|
||
|
||
/**
|
||
* 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$1(value));
|
||
}
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var INFINITY$1 = 1 / 0;
|
||
|
||
/**
|
||
* 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$1) ? '-0' : result;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used to stand-in for `undefined` hash values. */
|
||
var HASH_UNDEFINED = '__lodash_hash_undefined__';
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
*
|
||
* 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]);
|
||
}
|
||
}
|
||
|
||
// Add methods to `SetCache`.
|
||
SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
|
||
SetCache.prototype.has = setCacheHas;
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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 to compose bitmasks for value comparisons. */
|
||
var COMPARE_PARTIAL_FLAG$5 = 1,
|
||
COMPARE_UNORDERED_FLAG$3 = 2;
|
||
|
||
/**
|
||
* 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$5,
|
||
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$3) ? new SetCache : undefined;
|
||
|
||
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) {
|
||
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;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used to compose bitmasks for value comparisons. */
|
||
var COMPARE_PARTIAL_FLAG$4 = 1,
|
||
COMPARE_UNORDERED_FLAG$2 = 2;
|
||
|
||
/** `Object#toString` result references. */
|
||
var boolTag = '[object Boolean]',
|
||
dateTag = '[object Date]',
|
||
errorTag = '[object Error]',
|
||
mapTag$1 = '[object Map]',
|
||
numberTag = '[object Number]',
|
||
regexpTag = '[object RegExp]',
|
||
setTag$1 = '[object Set]',
|
||
stringTag = '[object String]',
|
||
symbolTag = '[object Symbol]';
|
||
|
||
var arrayBufferTag = '[object ArrayBuffer]',
|
||
dataViewTag$1 = '[object DataView]';
|
||
|
||
/** Used to convert symbols to primitives and strings. */
|
||
var symbolProto = Symbol$1 ? Symbol$1.prototype : undefined,
|
||
symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
|
||
|
||
/**
|
||
* 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$1:
|
||
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$1:
|
||
var convert = mapToArray;
|
||
|
||
case setTag$1:
|
||
var isPartial = bitmask & COMPARE_PARTIAL_FLAG$4;
|
||
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$2;
|
||
|
||
// 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;
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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));
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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 [];
|
||
}
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$3 = Object.prototype;
|
||
|
||
/** Built-in value references. */
|
||
var propertyIsEnumerable = objectProto$3.propertyIsEnumerable;
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeGetSymbols = Object.getOwnPropertySymbols;
|
||
|
||
/**
|
||
* 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);
|
||
});
|
||
};
|
||
|
||
var getSymbols$1 = getSymbols;
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeKeys = overArg(Object.keys, Object);
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$2 = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$2 = objectProto$2.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$2.call(object, key) && key != 'constructor') {
|
||
result.push(key);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* 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 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$1);
|
||
}
|
||
|
||
/** Used to compose bitmasks for value comparisons. */
|
||
var COMPARE_PARTIAL_FLAG$3 = 1;
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto$1 = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty$1 = objectProto$1.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$3,
|
||
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$1.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
|
||
? (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;
|
||
}
|
||
|
||
/* Built-in method references that are verified to be native. */
|
||
var DataView = getNative(root, 'DataView');
|
||
|
||
var DataView$1 = DataView;
|
||
|
||
/* Built-in method references that are verified to be native. */
|
||
var Promise$1 = getNative(root, 'Promise');
|
||
|
||
var Promise$2 = Promise$1;
|
||
|
||
/* Built-in method references that are verified to be native. */
|
||
var Set = getNative(root, 'Set');
|
||
|
||
var Set$1 = Set;
|
||
|
||
/* Built-in method references that are verified to be native. */
|
||
var WeakMap = getNative(root, 'WeakMap');
|
||
|
||
var WeakMap$1 = WeakMap;
|
||
|
||
/** `Object#toString` result references. */
|
||
var mapTag = '[object Map]',
|
||
objectTag$1 = '[object Object]',
|
||
promiseTag = '[object Promise]',
|
||
setTag = '[object Set]',
|
||
weakMapTag = '[object WeakMap]';
|
||
|
||
var dataViewTag = '[object DataView]';
|
||
|
||
/** Used to detect maps, sets, and weakmaps. */
|
||
var dataViewCtorString = toSource(DataView$1),
|
||
mapCtorString = toSource(Map),
|
||
promiseCtorString = toSource(Promise$2),
|
||
setCtorString = toSource(Set$1),
|
||
weakMapCtorString = toSource(WeakMap$1);
|
||
|
||
/**
|
||
* 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$1 && getTag(new DataView$1(new ArrayBuffer(1))) != dataViewTag) ||
|
||
(Map && getTag(new Map) != mapTag) ||
|
||
(Promise$2 && getTag(Promise$2.resolve()) != promiseTag) ||
|
||
(Set$1 && getTag(new Set$1) != setTag) ||
|
||
(WeakMap$1 && getTag(new WeakMap$1) != weakMapTag)) {
|
||
getTag = function(value) {
|
||
var result = baseGetTag(value),
|
||
Ctor = result == objectTag$1 ? value.constructor : undefined,
|
||
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;
|
||
};
|
||
}
|
||
|
||
var getTag$1 = getTag;
|
||
|
||
/** Used to compose bitmasks for value comparisons. */
|
||
var COMPARE_PARTIAL_FLAG$2 = 1;
|
||
|
||
/** `Object#toString` result references. */
|
||
var argsTag = '[object Arguments]',
|
||
arrayTag = '[object Array]',
|
||
objectTag = '[object Object]';
|
||
|
||
/** Used for built-in method references. */
|
||
var objectProto = Object.prototype;
|
||
|
||
/** Used to check objects for own properties. */
|
||
var hasOwnProperty = objectProto.hasOwnProperty;
|
||
|
||
/**
|
||
* 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$1(object),
|
||
othTag = othIsArr ? arrayTag : getTag$1(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$2)) {
|
||
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 `_.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);
|
||
}
|
||
|
||
/** Used to compose bitmasks for value comparisons. */
|
||
var COMPARE_PARTIAL_FLAG$1 = 1,
|
||
COMPARE_UNORDERED_FLAG$1 = 2;
|
||
|
||
/**
|
||
* 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 && !(key in object)) {
|
||
return false;
|
||
}
|
||
} else {
|
||
var stack = new Stack;
|
||
if (customizer) {
|
||
var result = customizer(objValue, srcValue, key, object, source, stack);
|
||
}
|
||
if (!(result === undefined
|
||
? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG$1 | COMPARE_UNORDERED_FLAG$1, customizer, stack)
|
||
: result
|
||
)) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/**
|
||
* 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 || (key in Object(object)));
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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 : baseGet(object, path);
|
||
return result === undefined ? defaultValue : result;
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/**
|
||
* 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));
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/** Used to compose bitmasks for value comparisons. */
|
||
var COMPARE_PARTIAL_FLAG = 1,
|
||
COMPARE_UNORDERED_FLAG = 2;
|
||
|
||
/**
|
||
* 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 && objValue === srcValue)
|
||
? hasIn(object, path)
|
||
: baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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 : object[key];
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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 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 `_.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);
|
||
}
|
||
|
||
/**
|
||
* 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;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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 `_.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 `_.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;
|
||
}
|
||
|
||
/**
|
||
* 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,
|
||
valIsNull = value === null,
|
||
valIsReflexive = value === value,
|
||
valIsSymbol = isSymbol(value);
|
||
|
||
var othIsDefined = other !== undefined,
|
||
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;
|
||
}
|
||
|
||
/**
|
||
* 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(baseIteratee));
|
||
|
||
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);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 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 : orders;
|
||
if (!isArray(orders)) {
|
||
orders = orders == null ? [] : [orders];
|
||
}
|
||
return baseOrderBy(collection, iteratees, orders);
|
||
}
|
||
|
||
function addConstant(object, property, value) {
|
||
Object.defineProperty(object, property, {
|
||
configurable: false,
|
||
enumerable: true,
|
||
writable: false,
|
||
value
|
||
});
|
||
}
|
||
|
||
function addConstants(Constructor, propertyMap) {
|
||
for (const property in propertyMap) {
|
||
const value = propertyMap[property];
|
||
addConstant(Constructor, property, value);
|
||
}
|
||
}
|
||
|
||
function mixin(target, source, allowKeys = []) {
|
||
const keys = Reflect.ownKeys(source);
|
||
for (let i = 0; i < keys.length; ++i) {
|
||
if (keys[i] in target && !allowKeys.includes(keys[i])) {
|
||
continue;
|
||
}
|
||
Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i]));
|
||
}
|
||
}
|
||
|
||
function addRuntimeData(name, key, val) {
|
||
// 添加运行时数据
|
||
if (!sdenv.cache.runtime[name]) sdenv.cache.runtime[name] = {};
|
||
const runtimeData = sdenv.cache.runtime[name];
|
||
if (!runtimeData[key]) runtimeData[key] = [];
|
||
runtimeData[key].push(val);
|
||
return val;
|
||
}
|
||
|
||
function getRuntimeData(name, key) {
|
||
return get(sdenv, ['cache.runtime', name, key]
|
||
.filter((it) => it !== undefined)
|
||
.join('.'));
|
||
}
|
||
|
||
function compressText(text, max = 100) {
|
||
if (text.length <= max) {
|
||
return text;
|
||
}
|
||
|
||
const truncatedText = text.replace(/[\r\n]+/g, ' ').replace(/\s+/g, ' ');
|
||
return `${truncatedText.slice(0, max)}......`;
|
||
}
|
||
|
||
const isAlive = () => {
|
||
// 窗口是否还活跃
|
||
return !sdenv.memory.runinfo.isDied;
|
||
};
|
||
|
||
const isDied = () => {
|
||
// 窗口是否还活跃
|
||
return sdenv.memory.runinfo.isDied;
|
||
};
|
||
|
||
const setDied = () => {
|
||
// 设置窗口为死亡状态
|
||
sdenv.memory.runinfo.isDied = true;
|
||
};
|
||
|
||
const exit = (params) => {
|
||
const win = sdenv.memory.sdWindow;
|
||
setDied();
|
||
if (params.url) win.onbeforeunload?.(params.url);
|
||
};
|
||
|
||
let originToString = Function.toString;
|
||
const canToStrigArr = [];
|
||
const toString = function() {
|
||
if (canToStrigArr.includes(this.name)) {
|
||
return `function ${this.name || ''}() { [native code] }`;
|
||
}
|
||
return originToString.apply(this);
|
||
};
|
||
|
||
const setFuncNative = function(func, name) {
|
||
// 修改函数的toString方法返回native code标识
|
||
if (!func) return undefined;
|
||
func.name = name || func.name || '';
|
||
canToStrigArr.push(func.name);
|
||
Object.defineProperty(func, 'toString', {
|
||
enumerable: false,
|
||
configurable: true,
|
||
writable: true,
|
||
value: toString,
|
||
});
|
||
return func;
|
||
};
|
||
|
||
const setFuncName = function(func, name) {
|
||
// 修改方法的name属性值
|
||
Object.defineProperty(func, 'name', {
|
||
configurable: true,
|
||
enumerable: false,
|
||
writable: false,
|
||
value: name
|
||
});
|
||
return func;
|
||
};
|
||
|
||
const setNativeFuncName = function(func, name) {
|
||
setFuncName(func, name);
|
||
setFuncNative(func, name);
|
||
return func;
|
||
};
|
||
setNativeFuncName(toString, 'toString');
|
||
|
||
const _setFuncInit = function() {
|
||
// 修改Function指向与toString原型链指向
|
||
const win = sdenv.memory.sdWindow;
|
||
originToString = win.Function.toString;
|
||
toString.__proto__ = win.Function.prototype;
|
||
};
|
||
|
||
const setObjNative = function(obj, name) {
|
||
// 修改函数的toString方法返回native code标识
|
||
Object.defineProperty(obj, 'toString', {
|
||
enumerable: false,
|
||
configurable: true,
|
||
writable: true,
|
||
value() {
|
||
return `[object ${name}]`;
|
||
}
|
||
});
|
||
return obj;
|
||
};
|
||
|
||
const setObjName = function(obj, name) {
|
||
/*
|
||
修改toString的显示,如:
|
||
window.navigator.webkitPersistentStorage.toString() === '[object DeprecatedStorageQuota]'
|
||
*/
|
||
Object.defineProperty(obj, Symbol.toStringTag, {
|
||
configurable: true,
|
||
enumerable: false,
|
||
writable: false,
|
||
value: name
|
||
});
|
||
return obj;
|
||
};
|
||
|
||
const setNativeObjName = function(obj, name) {
|
||
setObjName(obj, name);
|
||
setObjNative(obj, name);
|
||
return obj;
|
||
};
|
||
|
||
function getNativeProto(funcname, objname, attrs = {}) {
|
||
// 自动生成原型函数并返回基于原始数据与该原型函数的实例化对象
|
||
const func = setNativeFuncName(() => {
|
||
throw new TypeError('Illegal constructor');
|
||
}, funcname);
|
||
const obj = setNativeObjName({
|
||
__proto__: func,
|
||
...attrs,
|
||
}, funcname);
|
||
return [func, obj];
|
||
}
|
||
|
||
function addUtil(func, name) {
|
||
sdenv.utils[name || func.name] = func;
|
||
return func;
|
||
}
|
||
|
||
function getUtil(name) {
|
||
return sdenv.utils[name];
|
||
}
|
||
|
||
/* eslint-disable no-debugger */
|
||
|
||
function monitor(tar, name, config = {}) {
|
||
const win = sdenv.memory.sdWindow;
|
||
const {
|
||
getLog, // 开启get日志
|
||
setLog, // 开启set日志
|
||
getKeys = [], // 触发get的debugger的键集合
|
||
setKeys = [], // 触发set的debugger的键集合
|
||
keys = [], // 触发debugger的键集合
|
||
getCb, // get的回调,设置的debugger更友好
|
||
setCb, // set的回调,设置的debugger更友好
|
||
cb, // 回调,设置的debugger更友好
|
||
parse = (key, val) => val,
|
||
} = config;
|
||
if (!sdenv.cache.monitor[name]) sdenv.cache.monitor[name] = [];
|
||
const newTar = new win.Proxy(tar, {
|
||
get(target, property, receiver) {
|
||
if (getLog) win.console.log(`${name} Getting ${property}`);
|
||
if (getKeys.includes(property) || keys.includes(property)) debugger;
|
||
(getCb || cb)?.(property, name);
|
||
return Reflect.get(target, property, receiver);
|
||
},
|
||
set(target, property, value, receiver) {
|
||
const show = [
|
||
win,
|
||
win.Math,
|
||
win.navigation
|
||
].includes(value) && value.toString ? value.toString() : value;
|
||
if (setLog) win.console.log(`${name} Setting ${property} to ${show}`);
|
||
if (setKeys.includes(property) || keys.includes(property)) debugger;
|
||
(setCb || cb)?.(property, value, name);
|
||
return Reflect.set(target, property, parse(property, value), receiver);
|
||
}
|
||
});
|
||
sdenv.cache.monitor[name].push(newTar);
|
||
return newTar;
|
||
}
|
||
|
||
function monitorFunction(tar, name, config = {}) {
|
||
const win = sdenv.memory.sdWindow;
|
||
const {
|
||
log, // 开启日志
|
||
isDebugger, // 是否在调用时触发debugger
|
||
cb, // 回调,设置的debugger更友好
|
||
} = config;
|
||
if (!sdenv.cache.monitor[name]) sdenv.cache.monitor[name] = [];
|
||
const newTar = new win.Proxy(tar, {
|
||
apply(target, thisArg, argArray) {
|
||
const result = Reflect.apply(target, thisArg, argArray);
|
||
if (log) win.console.log(`${name} Apply ${argArray}`);
|
||
if (isDebugger) debugger;
|
||
cb?.(argArray, result, name);
|
||
return result;
|
||
}
|
||
});
|
||
sdenv.cache.monitor[name].push(newTar);
|
||
return newTar;
|
||
}
|
||
|
||
function getMonitor(name) {
|
||
if (name) return sdenv.cache.monitor[name];
|
||
return sdenv.cache.monitor
|
||
}
|
||
|
||
const proxy = function (obj, objname) {
|
||
function get_attribute_type(value) {
|
||
return Object.prototype.toString.call(value);
|
||
}
|
||
function get_method_handler(watchName) {
|
||
return {
|
||
apply(target, thisArg, argArray) {
|
||
const result = Reflect.apply(target, thisArg, argArray);
|
||
if (thisArg === console && target.name === 'log') {
|
||
return result;
|
||
}
|
||
if (target.name === 'toString') {
|
||
return result;
|
||
}
|
||
console.log(`[${watchName}] apply function name is [${target.name}], argArray is [${argArray}], result is [${result}].`);
|
||
return result
|
||
},
|
||
construct(target, argArray, newTarget) {
|
||
const result = Reflect.construct(target, argArray, newTarget);
|
||
console.log(`[${watchName}] construct function name is [${target.name}], argArray is [${argArray}], result is [${(result)}].`);
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
|
||
function get_obj_handler(WatchName) {
|
||
return {
|
||
get(target, propKey) {
|
||
try {
|
||
if (sdenv.config.proxy_proto === false && propKey === '__proto__') {
|
||
console.log(`getting propKey-> ${WatchName}.${propKey} value-> ${(target[propKey])}`);
|
||
return target[propKey]
|
||
}
|
||
|
||
const result = Reflect.get(target, propKey, target);
|
||
const result_type = get_attribute_type(result);
|
||
|
||
if (result instanceof Object) {
|
||
if (Object.getOwnPropertyDescriptor(target, propKey)?.writable === false) {
|
||
console.log(`【getting】${WatchName}.${propKey.toString()} it is non-writable`);
|
||
} else {
|
||
if (typeof result === 'function') {
|
||
console.log(`【getting】${WatchName}.${propKey} value-> ${sdenv.tools.compressText(String(result))} typeof-> ${result_type}`);
|
||
return new Proxy(result, get_method_handler(WatchName))
|
||
}
|
||
console.log(`\n【getting】${WatchName}.${propKey} value-> ${sdenv.tools.compressText(String(result))} typeof-> ${result_type}`);
|
||
return new Proxy(result, get_obj_handler(`${WatchName}.${propKey}`))
|
||
}
|
||
}
|
||
console.log(`\n【getting】${WatchName}.${propKey.description ?? propKey} result-> ${result} typeof-> ${result_type}`);
|
||
return result;
|
||
} catch (e) {
|
||
console.error(`[${WatchName}] getting error`);
|
||
console.error(e.stack);
|
||
}
|
||
},
|
||
set(target, propKey, value, receiver) {
|
||
const value_type = get_attribute_type(value);
|
||
if (value instanceof Object) {
|
||
console.log(`\n【setting】${WatchName}.${propKey} value-> ${sdenv.tools.compressText(String(value))} typeof-> ${value_type}`);
|
||
} else {
|
||
console.log(`\n【setting】${WatchName}.${propKey} value-> ${sdenv.tools.compressText(String(value))} typeof-> ${value_type}`);
|
||
}
|
||
return Reflect.set(target, propKey, value, receiver);
|
||
},
|
||
has(target, propKey) {
|
||
const result = Reflect.has(target, propKey);
|
||
console.log(`【has】${WatchName}.${propKey}, result-> ${result}`);
|
||
return result;
|
||
},
|
||
deleteProperty(target, propKey) {
|
||
const result = Reflect.deleteProperty(target, propKey);
|
||
console.log(`【delete】${WatchName}.${propKey}, result-> ${result}`);
|
||
return result;
|
||
},
|
||
getOwnPropertyDescriptor(target, propKey) {
|
||
const result = Reflect.getOwnPropertyDescriptor(target, propKey);
|
||
try {
|
||
console.log(`【getOwnPropertyDescriptor】${WatchName}.${propKey.toString()} result-> ${(String(result))}`);
|
||
} catch (e) {
|
||
console.error(e.stack);
|
||
}
|
||
return result;
|
||
},
|
||
defineProperty(target, propKey, attributes) {
|
||
const result = Reflect.defineProperty(target, propKey, attributes);
|
||
try {
|
||
console.log(`【defineProperty】${WatchName}.${propKey} attributes is [${(attributes)}], result is [${result}]`);
|
||
} catch (e) {
|
||
console.error(`[${WatchName}] defineProperty error`);
|
||
console.error(e.stack);
|
||
}
|
||
return result;
|
||
},
|
||
getPrototypeOf(target) {
|
||
const result = Reflect.getPrototypeOf(target);
|
||
console.log(`[${WatchName}] getPrototypeOf result is [${(result)}]`);
|
||
return result;
|
||
},
|
||
setPrototypeOf(target, proto) {
|
||
const result = Reflect.setPrototypeOf(target, proto);
|
||
console.log(`[${WatchName}] setPrototypeOf proto is [${(proto)}], result is [${result}]`);
|
||
return result;
|
||
},
|
||
preventExtensions(target) {
|
||
const result = Reflect.preventExtensions(target);
|
||
console.log(`[${WatchName}] preventExtensions, result is [${result}]`);
|
||
return result;
|
||
},
|
||
isExtensible(target) {
|
||
const result = Reflect.isExtensible(target);
|
||
console.log(`[${WatchName}] isExtensible, result is [${result}]`);
|
||
return result;
|
||
},
|
||
ownKeys(target) {
|
||
const result = Reflect.ownKeys(target);
|
||
try {
|
||
console.log(`[${WatchName}] invoke ownkeys, result is [${String((result))}]`);
|
||
} catch (e) {
|
||
console.error(e.stack);
|
||
}
|
||
return result
|
||
}
|
||
}
|
||
}
|
||
if (sdenv.config.proxyOpen === false) {
|
||
return obj
|
||
}
|
||
if (typeof obj === 'function') {
|
||
return new Proxy(obj, get_method_handler(objname));
|
||
}
|
||
return new Proxy(obj, get_obj_handler(objname));
|
||
};
|
||
|
||
let cache$8 = undefined;
|
||
|
||
function timeoutHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$8) {
|
||
cache$8 = win.setTimeout;
|
||
}
|
||
const { log, cb, time, filter = () => true } = config;
|
||
win.setTimeout = sdenv.tools.setNativeFuncName(new Proxy(cache$8, {
|
||
apply: function (target, thisArg, params) {
|
||
if (!filter || !filter(...params)) return;
|
||
const [func, timeout] = params;
|
||
const funcStr = func.param ? JSON.stringify(func.param) : sdenv.tools.compressText(func.toString());
|
||
if (log) win.console.log(`【TIMEOUT APPLY】增加setTimeout事件,时间:${timeout}, 方法: ${funcStr}`);
|
||
if (time !== undefined) {
|
||
if (typeof time !== 'number') throw new Error(`time配置如果存在值则必须是数字`);
|
||
return Reflect.apply(target, thisArg, [
|
||
() => {
|
||
if (log) win.console.log(`【TIMEOUT RUN】setTimeout执行,时间:${timeout},方法:${funcStr}`);
|
||
func();
|
||
if (log) win.console.log(`【TIMEOUT RUNED】setTimeout执行,时间:${timeout},方法:${funcStr}`);
|
||
},
|
||
time || timeout,
|
||
]);
|
||
}
|
||
return sdenv.tools.addTimeout(func, timeout);
|
||
},
|
||
}), 'setTimeout');
|
||
win.document.addEventListener('readystatechange', function() {
|
||
if (log) win.console.log(`【READY STATE】${win.document.readyState}`);
|
||
});
|
||
}
|
||
|
||
const getTimeout = () => cache$8;
|
||
|
||
const currentTask = function () {
|
||
this.cache = null;
|
||
this.add = (item) => {
|
||
if (!this.cache) return false;
|
||
if (this.cache.task.includes(item)) return
|
||
this.cache.task.push(item);
|
||
};
|
||
this.set = (task) => this.cache = task;
|
||
this.get = () => this.cache;
|
||
this.getTime = () => {
|
||
if (!this.cache) return false;
|
||
return this.cache.time;
|
||
};
|
||
this.getTask = (idx) => {
|
||
if (!this.cache) return false;
|
||
if (typeof idx === 'number') return this.cache.task[idx]
|
||
return this.cache.task;
|
||
};
|
||
this.clear = () => this.cache = null;
|
||
};
|
||
|
||
class Timeout {
|
||
constructor() {
|
||
this.index = [];
|
||
this.timeouts = {};
|
||
this.lastOp = sdenv.memory.runinfo.start;
|
||
this.isLock = false;
|
||
this.id = 0;
|
||
this.currentTask = new currentTask();
|
||
}
|
||
|
||
addTimeout(func, time, type = 'timeout', idx = this.index.length) {
|
||
let timekey = new sdenv.memory.sdDate().getTime() - sdenv.memory.runinfo.start + time;
|
||
const obj = {
|
||
func, // 方法
|
||
type, // 类型: timeout interval
|
||
flag: 0, // 执行状态: -1(取消执行)0(未执行)1(执行中)2(已执行)
|
||
time, // 延时时间
|
||
expect_time: timekey, // 预期执行时间
|
||
real_time: null, // 实际执行时间
|
||
index: idx, // 编号
|
||
id: this.id++,
|
||
};
|
||
if (this.index[idx]) {
|
||
this.index[idx] = obj;
|
||
} else {
|
||
this.index.push(obj);
|
||
}
|
||
if (time === 0 && this.currentTask.get()) {
|
||
timekey = this.currentTask.getTime();
|
||
this.timeouts[timekey].push(obj);
|
||
this.currentTask.add(obj);
|
||
} else {
|
||
if (this.timeouts[timekey] === undefined) this.timeouts[timekey] = [];
|
||
this.timeouts[timekey].push(obj);
|
||
if (isAlive()) this.exec();
|
||
}
|
||
// const win = sdenv.memory.sdWindow;
|
||
// win.console.log(`程序时间${timekey}处${type}回调添加成功`);
|
||
return idx;
|
||
}
|
||
|
||
addInterval(func, time, idx = undefined) {
|
||
const self = this;
|
||
const newFunc = function() {
|
||
try {
|
||
func();
|
||
} catch (err) {
|
||
console.error(err);
|
||
} finally {
|
||
if (self.index[idx].flag !== -1) self.addInterval(func, time, idx);
|
||
}
|
||
};
|
||
idx = this.addTimeout(newFunc, time, 'interval', idx);
|
||
return idx;
|
||
}
|
||
|
||
remove(idx) {
|
||
if (typeof idx !== 'number' || !this.index[idx]) return false;
|
||
if (this.index[idx].flag === 0) {
|
||
this.index[idx].flag = -1;
|
||
} else if ([-1, 2].includes(this.index[idx].flag)) {
|
||
return undefined;
|
||
} else if (this.index[idx].flag === 1) {
|
||
return false;
|
||
}
|
||
return undefined
|
||
}
|
||
|
||
exec() {
|
||
if (this.isLock) return;
|
||
this.isLock = true;
|
||
getTimeout()(() => {
|
||
this.isLock = false;
|
||
this.run();
|
||
}, 0);
|
||
}
|
||
|
||
run() {
|
||
const win = sdenv.memory.sdWindow;
|
||
const times = Object.keys(this.timeouts).filter((key) => {
|
||
if (Number(key) + sdenv.memory.runinfo.start <= this.lastOp) return false;
|
||
return true;
|
||
});
|
||
if (times.length === 0) return false;
|
||
this.lastOp = Number(times[0]) + sdenv.memory.runinfo.start;
|
||
this.currentTask.set({
|
||
task: this.timeouts[times[0]],
|
||
time: times[0],
|
||
});
|
||
for(let i = 0; this.currentTask.getTask(i); i++) {
|
||
const cfg = this.currentTask.getTask(i);
|
||
if (isDied() || cfg.flag === -1) return;
|
||
const funcStr = cfg.func.param ? JSON.stringify(cfg.func.param) : sdenv.tools.compressText(cfg.func.toString());
|
||
win.console.log(`【TIMEOUT RUN】执行程序时间${times[0]}处${cfg.type}回调,延时:${cfg.time},编号:${cfg.id},方法:${funcStr}`);
|
||
cfg.flag = 1;
|
||
cfg.real_time = new sdenv.memory.sdDate().getTime() - sdenv.memory.runinfo.start;
|
||
try {
|
||
cfg.func();
|
||
win.console.log(`【TIMEOUT RUNED】执行程序时间${times[0]}处${cfg.type}回调,延时:${cfg.time},编号:${cfg.id},方法:${funcStr}`);
|
||
} catch (e) {
|
||
console.error(e);
|
||
}
|
||
cfg.flag = 2;
|
||
}
|
||
this.currentTask.clear();
|
||
if (isDied()) return undefined;
|
||
if (times.length > 1) {
|
||
this.run();
|
||
} else {
|
||
this.exec();
|
||
}
|
||
return undefined;
|
||
}
|
||
}
|
||
|
||
sdenv.memory.timeout = new Timeout();
|
||
|
||
const addTimeout = function(func, time) {
|
||
return sdenv.memory.timeout.addTimeout(func, Number(time || 0), 'timeout')
|
||
};
|
||
|
||
const addInterval = function(func, time) {
|
||
return sdenv.memory.timeout.addInterval(func, time);
|
||
};
|
||
|
||
const removeTimeout = function(idx) {
|
||
return sdenv.memory.timeout.remove(idx);
|
||
};
|
||
|
||
const removeInterval = function(idx) {
|
||
return sdenv.memory.timeout.remove(idx);
|
||
};
|
||
|
||
var tools = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
_setFuncInit: _setFuncInit,
|
||
addConstant: addConstant,
|
||
addConstants: addConstants,
|
||
addInterval: addInterval,
|
||
addRuntimeData: addRuntimeData,
|
||
addTimeout: addTimeout,
|
||
addUtil: addUtil,
|
||
compressText: compressText,
|
||
exit: exit,
|
||
getMonitor: getMonitor,
|
||
getNativeProto: getNativeProto,
|
||
getRuntimeData: getRuntimeData,
|
||
getUtil: getUtil,
|
||
isAlive: isAlive,
|
||
isDied: isDied,
|
||
mixin: mixin,
|
||
monitor: monitor,
|
||
monitorFunction: monitorFunction,
|
||
proxy: proxy,
|
||
removeInterval: removeInterval,
|
||
removeTimeout: removeTimeout,
|
||
setDied: setDied,
|
||
setFuncName: setFuncName,
|
||
setFuncNative: setFuncNative,
|
||
setNativeFuncName: setNativeFuncName,
|
||
setNativeObjName: setNativeObjName,
|
||
setObjName: setObjName,
|
||
setObjNative: setObjNative
|
||
});
|
||
|
||
// 循环体执行监控
|
||
|
||
const preLoop = {};
|
||
|
||
function loopRunInit() {
|
||
const win = sdenv.memory.sdWindow;
|
||
const runloop = sdenv.cache.runloop = { current: 1 };
|
||
|
||
let log = false;
|
||
|
||
addUtil((key, idx, name, runlist = '', lens = 0) => {
|
||
/*
|
||
* 初始化一个循环
|
||
* key: 循环体的case的变量名
|
||
* idx: 初始化下标
|
||
* name: 循环方法名称
|
||
* runlist: 循环任务名或者循环任务队列
|
||
* lens: 任务队列长度
|
||
* */
|
||
const arr = [];
|
||
const current = runloop.current++;
|
||
if (!runloop[key]) {
|
||
runloop[key] = [];
|
||
}
|
||
const loopobj = {
|
||
idx, // 启动的下标
|
||
name, // 函数名
|
||
data: arr, // 实际运行队列
|
||
current, // 启动编号
|
||
idxs: [], // 实际运行下标队列
|
||
list: Array.isArray(runlist) ? runlist.join() : runlist, // 预期运行队列
|
||
lens: lens || (Array.isArray(runlist) ? runlist.length : -1), // 预期运行队列长度
|
||
pre: { // 上一次循环信息
|
||
current: preLoop.cur,
|
||
curloop: preLoop.num,
|
||
},
|
||
param: {}, // 需要记录的关键数据
|
||
};
|
||
if (preLoop.loop) {
|
||
preLoop.loop.param[preLoop.loop.data.length - 1] = {
|
||
next: current // 档次编号记录到父循环中
|
||
};
|
||
}
|
||
runloop[key].push(loopobj);
|
||
if (log) win.console.log(`【RUN TASK】current:${current}`);
|
||
return {
|
||
addLoop: (id, it, _key) => {
|
||
loopobj.data.push(it);
|
||
loopobj.idxs.push(id);
|
||
Object.assign(preLoop, {
|
||
key: _key,
|
||
cur: current,
|
||
num: arr.length,
|
||
loop: loopobj,
|
||
});
|
||
},
|
||
curLoop: () => arr.length,
|
||
current,
|
||
loopobj,
|
||
openLog: () => (log = true),
|
||
closeLog: () => (log = false),
|
||
isLog: () => log,
|
||
}
|
||
}, 'initLoop');
|
||
|
||
// 上一个循环的信息
|
||
addUtil(() => ({ ...preLoop }), 'getPreLoop');
|
||
|
||
addUtil((copy) => {
|
||
// 返回循环体运行数据,copy为复制方法,非浏览器环境需要手动传入
|
||
const data = JSON.parse(JSON.stringify(runloop));
|
||
const ascii = {};
|
||
Object.entries(data).forEach(([key, item]) => {
|
||
if (!Array.isArray(item)) return;
|
||
ascii[key] = {};
|
||
item.forEach((each) => {
|
||
each.data.forEach((it) => {
|
||
if (ascii[key][it] === undefined) ascii[key][it] = 0;
|
||
ascii[key][it]++;
|
||
});
|
||
each.data = each.data.join();
|
||
each.idxs = each.idxs.join();
|
||
});
|
||
ascii[key] = orderBy(Object.entries(ascii[key]).map(([code, num]) => ({ code, num })), 'num', 'desc');
|
||
});
|
||
if (copy) {
|
||
copy(JSON.stringify(data));
|
||
console.log('运行时数据复制成功');
|
||
}
|
||
return { ascii, ...data };
|
||
}, 'getLoopData');
|
||
}
|
||
|
||
// 修改任务树增加任务名称等信息
|
||
|
||
function parse(val, keyMap = {}, deep = 0, deeps = [0]) {
|
||
// 任务列表、主要子树、次要子树、监控值变化的配置
|
||
if (keyMap._count === undefined) keyMap._count = 0;
|
||
const { taskKey, oneKey, twoKey, monitor = {} } = keyMap;
|
||
const str = val[taskKey];
|
||
val.str = str;
|
||
val.val = {};
|
||
if (!str) {
|
||
val.arr = [];
|
||
val[taskKey] = [];
|
||
} else {
|
||
val.arr = str.split('').map((it) => it.charCodeAt());
|
||
if (keyMap._count > 0) val[taskKey] = [...val.arr]; // 最外层让瑞数自己处理
|
||
}
|
||
val.idx = `${deeps.join('>')}-${keyMap._count++}`;
|
||
val[oneKey] = val[oneKey].map((it, idx) => {
|
||
if (it) {
|
||
parse(it, keyMap, deep + 1, [...deeps, 'one', idx]);
|
||
return sdenv.tools.monitor(it, it.idx, { setLog: true, ...monitor });
|
||
}
|
||
return it;
|
||
});
|
||
val[twoKey] = val[twoKey].map((it, idx) => {
|
||
if (it) {
|
||
parse(it, keyMap, deep + 1, [...deeps, 'two', idx]);
|
||
return sdenv.tools.monitor(it, it.idx, { setLog: true, ...monitor });
|
||
}
|
||
return it;
|
||
});
|
||
return val;
|
||
}
|
||
|
||
const parseTaskTree = function(...params) {
|
||
sdenv.cache.runsObj = parse(...params); // 任务树
|
||
sdenv.cache.runsArr = []; // 任务运行时队列
|
||
};
|
||
|
||
var index$1 = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
parseTaskTree: parseTaskTree
|
||
});
|
||
|
||
var adapt = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
rs: index$1
|
||
});
|
||
|
||
let cache$7 = undefined;
|
||
|
||
const evalmap = {
|
||
'!new function(){eval("this.a=1")}().a': 'false',
|
||
};
|
||
|
||
function evalHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$7) {
|
||
cache$7 = win.eval;
|
||
}
|
||
const { cb, log } = config;
|
||
win.eval = sdenv.tools.setNativeFuncName(new Proxy(cache$7, {
|
||
apply(target, thisArg, params) {
|
||
if (log) win.console.log(`【EVAL APPLY】参数:${params.map(it => sdenv.tools.compressText(JSON.stringify(it)))}`);
|
||
const new_params = params.map((param) => {
|
||
if (typeof evalmap[param] === 'string') return evalmap[param];
|
||
if (param.includes('debugger')) {
|
||
param = param.replace(/debugger/g, '');
|
||
}
|
||
if (param.includes('sdDebugger')) {
|
||
param = param.replace(/sdDebugger/g, 'debugger');
|
||
}
|
||
return param
|
||
});
|
||
const dynamicCode = {
|
||
type: 'eval',
|
||
params,
|
||
tar_params: new_params,
|
||
};
|
||
cb?.(dynamicCode);
|
||
sdenv.cache.dynamicCode.push({ ...dynamicCode });
|
||
return Reflect.apply(target, thisArg, new_params);
|
||
},
|
||
}), 'eval');
|
||
}
|
||
|
||
let cache$6 = undefined;
|
||
|
||
function funcHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$6) {
|
||
cache$6 = win.Function;
|
||
}
|
||
const { log, cb } = config;
|
||
win.Function = sdenv.tools.setNativeFuncName(new Proxy(cache$6, {
|
||
apply(target, thisArg, params) {
|
||
const new_params = params.map((param) => {
|
||
if (param.includes('debugger')) {
|
||
param = param.replace(/debugger/g, '');
|
||
}
|
||
if (param.includes('sdDebugger')) {
|
||
param = param.replace(/sdDebugger/g, 'debugger');
|
||
}
|
||
return param
|
||
});
|
||
if (log) win.console.log(`【FUNCTION APPLY】参数:${params.map(it => sdenv.tools.compressText(JSON.stringify(it)))}`);
|
||
const dynamicCode = {
|
||
type: 'Function',
|
||
params,
|
||
tar_params: new_params,
|
||
};
|
||
cb?.(dynamicCode);
|
||
sdenv.cache.dynamicCode.push({ ...dynamicCode });
|
||
return Reflect.apply(target, thisArg, new_params);
|
||
}
|
||
}), 'Function');
|
||
win.Function.prototype.constructor = win.Function;
|
||
sdenv.tools.setNativeFuncName(win.Function.prototype, '');
|
||
}
|
||
|
||
const delay$1 = (ms) => new Promise(resolve => sdenv.memory.sdWindow.setTimeout(resolve, ms));
|
||
|
||
let cache$5 = undefined;
|
||
|
||
function eventHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$5) {
|
||
cache$5 = win.addEventListener;
|
||
}
|
||
const { addLog, runLog, log, addCb, runCb, cb, filter = () => true } = config;
|
||
win.addEventListener = sdenv.tools.setNativeFuncName(new Proxy(cache$5, {
|
||
apply: function (target, thisArg, params) {
|
||
if (!filter || !filter(...params)) return;
|
||
const [type, callback] = params;
|
||
const funcStr = callback.param ? JSON.stringify(callback.param) : sdenv.tools.compressText(callback.toString());
|
||
if (addLog || log) win.console.log(`【ADD EVENT】事件名:${type}, 方法:${funcStr}`);
|
||
(addCb || cb)?.(...params);
|
||
return Reflect.apply(target, thisArg, [
|
||
type,
|
||
async () => {
|
||
// load事件需要等下一次事件循环时执行: 延时为0的定时任务先执行
|
||
if (type === 'load') await delay$1(0);
|
||
(runCb || cb)?.(...params);
|
||
if (runLog || log) win.console.log(`【RUN EVENT】事件名:${type}, 方法:${funcStr}`);
|
||
callback();
|
||
},
|
||
]);
|
||
},
|
||
}), 'addEventListener');
|
||
}
|
||
|
||
let cache$4 = undefined;
|
||
|
||
function cookieHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$4) {
|
||
cache$4 = {
|
||
cookieGet: Object.getOwnPropertyDescriptor(win.Document.prototype, 'cookie').get,
|
||
cookieSet: Object.getOwnPropertyDescriptor(win.Document.prototype, 'cookie').set,
|
||
};
|
||
}
|
||
const {
|
||
getLog, // 开启get日志
|
||
setLog, // 开启set日志
|
||
log,
|
||
getCb, // get的回调,设置的debugger更友好
|
||
setCb, // set的回调,设置的debugger更友好
|
||
cb, // 回调,设置的debugger更友好
|
||
parse = (val) => val,
|
||
} = config;
|
||
Object.defineProperty(win.document, 'cookie', {
|
||
configurable: false,
|
||
enumerable: false,
|
||
get() {
|
||
const cookie = cache$4.cookieGet.call(win.document);
|
||
if (getLog || log) win.console.log(`【GET COOKIE】长:${cookie.length} 值:${cookie}`);
|
||
(getCb || cb)?.(cookie);
|
||
return cookie;
|
||
},
|
||
set(val) {
|
||
if (setLog || log) win.console.log(`【SET COOKIE】长:${val.length} 值:${val}`);
|
||
(setCb || cb)?.(val);
|
||
cache$4.cookieSet.call(win.document, parse(val));
|
||
}
|
||
});
|
||
}
|
||
|
||
/** Used to match a single whitespace character. */
|
||
var reWhitespace = /\s/;
|
||
|
||
/**
|
||
* 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 to match leading whitespace. */
|
||
var reTrimStart = /^\s+/;
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var NAN = 0 / 0;
|
||
|
||
/** 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 octal string values. */
|
||
var reIsOctal = /^0o[0-7]+$/i;
|
||
|
||
/** Built-in method references without a dependency on `root`. */
|
||
var freeParseInt = parseInt;
|
||
|
||
/**
|
||
* 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);
|
||
}
|
||
|
||
/** Used as references for various `Number` constants. */
|
||
var INFINITY = 1 / 0,
|
||
MAX_INTEGER = 1.7976931348623157e+308;
|
||
|
||
/**
|
||
* 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;
|
||
}
|
||
|
||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||
var nativeIsFinite = root.isFinite,
|
||
nativeMin = Math.min;
|
||
|
||
/**
|
||
* 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$1(number) + 'e').split('e'),
|
||
value = func(pair[0] + 'e' + (+pair[1] + precision));
|
||
|
||
pair = (toString$1(value) + 'e').split('e');
|
||
return +(pair[0] + 'e' + (+pair[1] - precision));
|
||
}
|
||
return func(number);
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 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');
|
||
|
||
/*
|
||
charging: 是否正在充电, true表示正在充电
|
||
chargingTime: 充满需要多久时间, 0表示已经充满,未充电总是为Infinity
|
||
dischargingTime: 可以用多久,正在充电时总为Infinity
|
||
level: 电量,1表示100%电量
|
||
*/
|
||
|
||
const level = round(Math.random(), 2); // 电量
|
||
const chargingTime = (1 - level) * 100 * 300; // 充满时间
|
||
const dischargingTime = level * 100 * 443; // 可用时间
|
||
|
||
const charging = {
|
||
charging_success: { // 正在充电,电量100%
|
||
charging: true,
|
||
chargingTime: 0,
|
||
dischargingTime: Infinity,
|
||
level: 1,
|
||
},
|
||
discharging_success: { // 未充电,电量100%
|
||
charging: false,
|
||
chargingTime: Infinity,
|
||
dischargingTime: Infinity,
|
||
level: 1,
|
||
},
|
||
charging_ing: { // 正在充电
|
||
charging: true,
|
||
chargingTime,
|
||
dischargingTime: Infinity,
|
||
level,
|
||
},
|
||
discharging_ing: { // 未充电
|
||
charging: false,
|
||
chargingTime: Infinity,
|
||
dischargingTime: dischargingTime,
|
||
level,
|
||
}
|
||
};
|
||
|
||
function batteryHandle(config) {
|
||
if (typeof config === 'string') {
|
||
config = charging[config] || {};
|
||
} else if (typeof config !== 'object') {
|
||
config = {};
|
||
}
|
||
const win = sdenv.memory.sdWindow;
|
||
win.navigator.getBattery = sdenv.tools.setNativeFuncName(() => {
|
||
return new Promise((resolve, reject) => {
|
||
resolve({
|
||
onchargingchange: null,
|
||
onchargingtimechange: null,
|
||
ondischargingtimechange: null,
|
||
onlevelchange: null,
|
||
...charging.charging_success,
|
||
...config,
|
||
});
|
||
});
|
||
}, 'getBattery');
|
||
}
|
||
|
||
/*
|
||
downlink:设备下行速速,单位兆
|
||
effectiveType:网络类型,如:"slow-2g"、"2g"、"3g"、"4g"
|
||
rrt:设备的往返延时,单位毫秒
|
||
saveData:是否为节流模式
|
||
type:网络连接类型,有些浏览器有有些没有,如:"bluetooth"(蓝牙1)、"cellular"(蜂窝网络2)、"ethernet"(以太网3)、"none"(无网络连接)、"wifi"(wifi连接4)、"wimax5"
|
||
*/
|
||
|
||
function connectionHandle(config) {
|
||
const win = sdenv.memory.sdWindow;
|
||
if (typeof config !== 'object') {
|
||
config = {};
|
||
}
|
||
sdenv.tools.addConstants(win.navigator.connection, {
|
||
downlink: 6.66,
|
||
effectiveType: "4g",
|
||
onchange: null,
|
||
rtt: 0,
|
||
saveData: false,
|
||
...config,
|
||
});
|
||
}
|
||
|
||
let cache$3 = undefined;
|
||
|
||
function DateAndRandom({ datas }) {
|
||
sdenv.memory.sdWindow;
|
||
this.data = datas || {};
|
||
if (this.data?.firstMap && Object.values(this.data.firstMap).some((it) => !it)) {
|
||
throw new Error('日期首位配置错误请检查');
|
||
}
|
||
this.runs = [];
|
||
Object.assign(this, cache$3);
|
||
}
|
||
DateAndRandom.prototype.shift = function (name) {
|
||
const { firstMap } = this.data;
|
||
let val = this.data[name].shift();
|
||
if (typeof firstMap[name] === 'number') {
|
||
val += firstMap[name];
|
||
}
|
||
this.runs.push(val);
|
||
return val;
|
||
};
|
||
DateAndRandom.prototype.wrapFun = function (funcName, def) {
|
||
const name = `_${funcName}`;
|
||
if (!this[name]) return undefined;
|
||
if (def === undefined && !Array.isArray(this.data[name])) this.data[name] = [];
|
||
const self = this;
|
||
return setNativeFuncName(function() {
|
||
if (def !== undefined) return def;
|
||
if (self.data.firstMap?.[name]) {
|
||
if (!self.data[name].length) {
|
||
throw new Error(`DateAndRandom的${name}数据不够`);
|
||
}
|
||
return self.shift(name);
|
||
}
|
||
const val = self[name].call(this);
|
||
self.data[name].push(val);
|
||
return val
|
||
}, funcName);
|
||
};
|
||
DateAndRandom.prototype.wrapClass = function (className, cla) {
|
||
const win = sdenv.memory.sdWindow;
|
||
const name = `_${className}`;
|
||
if (!Array.isArray(this.data[name])) this.data[name] = [];
|
||
const self = this;
|
||
return setNativeFuncName(new Proxy(cla, {
|
||
construct(target, argumentsList, newTarget) {
|
||
if (self.data.firstMap?.[name]) {
|
||
if (!self.data[name].length) {
|
||
throw new Error(`DateAndRandom的${name}数据不够`);
|
||
}
|
||
return new cla(self.shift(name));
|
||
}
|
||
const val = Reflect.construct(target, argumentsList, newTarget);
|
||
self.data[name].push(win.Date.prototype.valueOf.call(val));
|
||
return val;
|
||
},
|
||
apply(target, argumentsList, newTarget) {
|
||
const val = Reflect.apply(target, argumentsList, newTarget);
|
||
return val;
|
||
}
|
||
}), cla.name || className);
|
||
};
|
||
DateAndRandom.prototype.getData = function (copy) {
|
||
const ret = Object.entries(this.data).reduce((ans, [key, val]) => {
|
||
if (key === 'firstMap' || !val.length) return ans;
|
||
if (key === '_random') {
|
||
ans[key] = val;
|
||
ans.firstMap[key] = true;
|
||
return ans;
|
||
}
|
||
const first = val[0];
|
||
ans.firstMap[key] = first;
|
||
ans[key] = val.map((it) => it - first);
|
||
return ans;
|
||
}, { firstMap: {} });
|
||
if (copy) {
|
||
copy(JSON.stringify(ret));
|
||
console.log('日期与随机数数据复制成功');
|
||
}
|
||
return ret;
|
||
};
|
||
|
||
function dateAndRandomHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$3) {
|
||
cache$3 = {
|
||
_now: win.Date.now,
|
||
_parse: win.Date.parse,
|
||
_valueOf: win.Date.prototype.valueOf,
|
||
_getTime: win.Date.prototype.getTime,
|
||
_toString: win.Date.prototype.toString,
|
||
_random: win.Math.random,
|
||
};
|
||
}
|
||
const { randomReturn = sdenv.config.randomReturn } = config;
|
||
const dateAndRandom = new DateAndRandom(config);
|
||
sdenv.tools.addUtil(dateAndRandom.getData.bind(dateAndRandom), 'getDateData');
|
||
win.Date = dateAndRandom.wrapClass('newdate', win.Date);
|
||
win.Date.now = dateAndRandom.wrapFun('now');
|
||
win.Date.parse = dateAndRandom.wrapFun('parse');
|
||
win.Math.random = dateAndRandom.wrapFun('random', randomReturn);
|
||
}
|
||
|
||
const delay = (ms) => new Promise(resolve => sdenv.memory.sdWindow.setTimeout(resolve, ms));
|
||
|
||
let cache$2 = undefined;
|
||
|
||
function ovserverHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$2) {
|
||
cache$2 = win.MutationObserver;
|
||
}
|
||
const { newLog, addLog, runLog, log, addCb, runCb, newCb, cb, filter = () => true } = config;
|
||
win.MutationObserver = sdenv.tools.setNativeFuncName(new Proxy(cache$2, {
|
||
construct: function (target, argArray, newTarget) {
|
||
const [func] = argArray;
|
||
const funcStr = func.param ? JSON.stringify(func.param) : sdenv.tools.compressText(func.toString());
|
||
if (newLog || log) win.console.log(`【NEW OVSERVER】方法:${funcStr}`);
|
||
(newCb || cb)?.(...argArray);
|
||
const result = Reflect.construct(target, [async (...params) => {
|
||
if (!filter || !filter(...argArray)) return;
|
||
if (runLog || log) win.console.log(`【RUN OVSERVER】方法:${funcStr}`);
|
||
(runCb || cb)?.(...params[0]);
|
||
await delay(0);
|
||
func(...params);
|
||
}], newTarget);
|
||
result.observe = new Proxy(result.observe, {
|
||
apply: function (target, thisArg, params) {
|
||
if (addLog || log) win.console.log(`【ADD OVSERVER】方法:${funcStr}`);
|
||
(addCb || cb)?.(...params);
|
||
return Reflect.apply(target, thisArg, params);
|
||
}
|
||
});
|
||
return result;
|
||
},
|
||
}), 'MutationObserver');
|
||
}
|
||
|
||
let cache$1 = undefined;
|
||
|
||
function intervalHandle(config) {
|
||
if (typeof config !== 'object') config = {};
|
||
const win = sdenv.memory.sdWindow;
|
||
if (!cache$1) {
|
||
cache$1 = win.setInterval;
|
||
}
|
||
const { log, cb, time, filter = () => true } = config;
|
||
win.setInterval = sdenv.tools.setNativeFuncName(new Proxy(cache$1, {
|
||
apply: function (target, thisArg, params) {
|
||
if (!filter || !filter(...params)) return;
|
||
const [func, timeout] = params;
|
||
const funcStr = func.param ? JSON.stringify(func.param) : sdenv.tools.compressText(func.toString());
|
||
if (log) win.console.log(`【INTERVAL APPLY】增加setInterval事件,时间:${timeout}, 方法:${funcStr}`);
|
||
if (time !== undefined) {
|
||
if (typeof time !== 'number') throw new Error(`time配置如果存在值则必须是数字`);
|
||
return Reflect.apply(target, thisArg, [
|
||
() => {
|
||
if (log) win.console.log(`【INTERVAL RUN】setInterval执行,时间:${timeout},方法:${funcStr}`);
|
||
func();
|
||
if (log) win.console.log(`【INTERVAL RUNED】setInterval执行,时间:${timeout},方法:${funcStr}`);
|
||
},
|
||
time || timeout,
|
||
]);
|
||
}
|
||
return sdenv.tools.addInterval(func, timeout);
|
||
},
|
||
}), 'setInterval');
|
||
}
|
||
|
||
const getInterval = () => cache$1;
|
||
|
||
var handles = /*#__PURE__*/Object.freeze({
|
||
__proto__: null,
|
||
batteryHandle: batteryHandle,
|
||
connectionHandle: connectionHandle,
|
||
cookieHandle: cookieHandle,
|
||
dateAndRandomHandle: dateAndRandomHandle,
|
||
evalHandle: evalHandle,
|
||
eventHandle: eventHandle,
|
||
funcHandle: funcHandle,
|
||
getInterval: getInterval,
|
||
getTimeout: getTimeout,
|
||
intervalHandle: intervalHandle,
|
||
ovserverHandle: ovserverHandle,
|
||
timeoutHandle: timeoutHandle
|
||
});
|
||
|
||
function setWindow(win) {
|
||
if (!win) return;
|
||
Object.assign(sdenv.memory, {
|
||
sdWindow: win,
|
||
sdEval: win.eval,
|
||
sdFunction: win.Function,
|
||
sdDate: win.Date,
|
||
sdMath: win.Math,
|
||
});
|
||
if (sdenv.config.isNode) {
|
||
// 修改setFunc工具中的Function指向到window.Function
|
||
_setFuncInit();
|
||
Object.setPrototypeOf(win.window, win.Window.prototype);
|
||
}
|
||
}
|
||
|
||
let cache = undefined;
|
||
|
||
class index {
|
||
constructor(config, win = undefined) {
|
||
const obj = win ? win.Object : Object;
|
||
if (!cache) cache = obj;
|
||
if (!obj.sdenv) {
|
||
merge(sdenv, config || {});
|
||
obj.prototype.sdenv = () => sdenv;
|
||
setWindow(win);
|
||
merge(sdenv.tools, tools);
|
||
merge(sdenv.adapt, adapt); // 会用到前面tools的方法
|
||
loopRunInit();
|
||
}
|
||
Object.assign(this, obj.sdenv());
|
||
}
|
||
|
||
static sdenv() {
|
||
if (cache) return cache.sdenv();
|
||
console.error('sdenv还未被初始化!');
|
||
}
|
||
|
||
getHandle(name) {
|
||
const handleName = `${name}Handle`;
|
||
if (!handles[handleName]) return;
|
||
return (...params) => {
|
||
handles[handleName](...params);
|
||
return this;
|
||
}
|
||
}
|
||
|
||
getTools(name) {
|
||
if (!sdenv.tools[name]) return;
|
||
return (...params) => {
|
||
sdenv.tools[name](...params);
|
||
return this;
|
||
}
|
||
}
|
||
|
||
getUtils(name) {
|
||
if (!sdenv.utils[name]) return;
|
||
return (...params) => {
|
||
sdenv.utils[name](...params);
|
||
return this;
|
||
}
|
||
}
|
||
}
|
||
|
||
return index;
|
||
|
||
})();
|
||
SdenvExtend.version = 'V1.2.1'
|