text: (function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global = global || self, global.Hibug = factory());
  }(this, function () { 'use strict';
  
    function _defineProperty(obj, key, value) {
      if (key in obj) {
        Object.defineProperty(obj, key, {
          value: value,
          enumerable: true,
          configurable: true,
          writable: true
        });
      } else {
        obj[key] = value;
      }
  
      return obj;
    }
  
    function _objectSpread(target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i] != null ? arguments[i] : {};
        var ownKeys = Object.keys(source);
  
        if (typeof Object.getOwnPropertySymbols === 'function') {
          ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {
            return Object.getOwnPropertyDescriptor(source, sym).enumerable;
          }));
        }
  
        ownKeys.forEach(function (key) {
          _defineProperty(target, key, source[key]);
        });
      }
  
      return target;
    }
  
    /**
     * constant
     * 管理错误类型
     */
    const CAUGHT_ERROR = 'caughtError'; // 调用 caughtError 装饰器主动捕获的错误
  
    const UNCAUGHT_ERROR = 'uncaughtError'; // 意料之外的错误
  
    const RESOURCE_ERROR = 'resourceError'; // 资源加载错误
  
    const GRAMMAR_ERROR = 'grammarError'; // 语法错误
  
    const PROMISE_ERROR = 'promiseError'; // promise 错误，可能包含 render 等错误
  
    const AJAX_ERROR = 'ajaxError'; // ajax 错误
  
    const FETCH_ERROR = 'fetchError'; // fetch 错误
  
    const WEBSOCKET_ERROR = 'websocketError'; // websocket 错误
  
    const REPORT_INFO = 'reportInfo'; // 主动上报的信息
  
    const UNKNOWN_ERROR = 'unknownError'; // 未知错误
  
    /**
     * Removes all key-value entries from the list cache.
     *
     * @private
     * @name clear
     * @memberOf ListCache
     */
    function listCacheClear() {
      this.__data__ = [];
      this.size = 0;
    }
  
    var _listCacheClear = listCacheClear;
  
    /**
     * 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;
    }
  
    var eq_1 = eq;
  
    /**
     * 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_1(array[length][0], key)) {
          return length;
        }
      }
  
      return -1;
    }
  
    var _assocIndexOf = assocIndexOf;
  
    /** 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;
    }
  
    var _listCacheDelete = listCacheDelete;
  
    /**
     * 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];
    }
  
    var _listCacheGet = listCacheGet;
  
    /**
     * 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;
    }
  
    var _listCacheHas = listCacheHas;
  
    /**
     * 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;
    }
  
    var _listCacheSet = listCacheSet;
  
    /**
     * 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;
    var _ListCache = ListCache;
  
    /**
     * Removes all key-value entries from the stack.
     *
     * @private
     * @name clear
     * @memberOf Stack
     */
  
  
    function stackClear() {
      this.__data__ = new _ListCache();
      this.size = 0;
    }
  
    var _stackClear = stackClear;
  
    /**
     * 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;
    }
  
    var _stackDelete = stackDelete;
  
    /**
     * 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);
    }
  
    var _stackGet = stackGet;
  
    /**
     * 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);
    }
  
    var _stackHas = stackHas;
  
    var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
  
    function createCommonjsModule(fn, module) {
    	return module = { exports: {} }, fn(module, module.exports), module.exports;
    }
  
    /** Detect free variable `global` from Node.js. */
    var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
    var _freeGlobal = freeGlobal;
  
    /** 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')();
    var _root = root;
  
    /** Built-in value references. */
  
  
    var Symbol = _root.Symbol;
    var _Symbol = Symbol;
  
    /** Used for built-in method references. */
  
  
    var objectProto = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty = objectProto.hasOwnProperty;
    /**
     * Used to resolve the
     * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
     * of values.
     */
  
    var nativeObjectToString = objectProto.toString;
    /** Built-in value references. */
  
    var symToStringTag = _Symbol ? _Symbol.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.call(value, symToStringTag),
          tag = value[symToStringTag];
  
      try {
        value[symToStringTag] = undefined;
        var unmasked = true;
      } catch (e) {}
  
      var result = nativeObjectToString.call(value);
  
      if (unmasked) {
        if (isOwn) {
          value[symToStringTag] = tag;
        } else {
          delete value[symToStringTag];
        }
      }
  
      return result;
    }
  
    var _getRawTag = getRawTag;
  
    /** Used for built-in method references. */
    var objectProto$1 = Object.prototype;
    /**
     * Used to resolve the
     * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
     * of values.
     */
  
    var nativeObjectToString$1 = objectProto$1.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$1.call(value);
    }
  
    var _objectToString = objectToString;
  
    /** `Object#toString` result references. */
  
  
    var nullTag = '[object Null]',
        undefinedTag = '[object Undefined]';
    /** Built-in value references. */
  
    var symToStringTag$1 = _Symbol ? _Symbol.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$1 && symToStringTag$1 in Object(value) ? _getRawTag(value) : _objectToString(value);
    }
  
    var _baseGetTag = baseGetTag;
  
    /**
     * 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');
    }
  
    var isObject_1 = isObject;
  
    /** `Object#toString` result references. */
  
  
    var asyncTag = '[object AsyncFunction]',
        funcTag = '[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_1(value)) {
        return false;
      } // The use of `Object#toString` avoids issues with the `typeof` operator
      // in Safari 9 which returns 'object' for typed arrays and other constructors.
  
  
      var tag = _baseGetTag(value);
      return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
    }
  
    var isFunction_1 = isFunction;
  
    /** Used to detect overreaching core-js shims. */
  
  
    var coreJsData = _root['__core-js_shared__'];
    var _coreJsData = coreJsData;
  
    /** 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;
    }
  
    var _isMasked = isMasked;
  
    /** Used for built-in method references. */
    var funcProto = Function.prototype;
    /** Used to resolve the decompiled source of functions. */
  
    var funcToString = funcProto.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.call(func);
        } catch (e) {}
  
        try {
          return func + '';
        } catch (e) {}
      }
  
      return '';
    }
  
    var _toSource = toSource;
  
    /**
     * 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$2 = 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$1 = objectProto$2.hasOwnProperty;
    /** Used to detect if a method is native. */
  
    var reIsNative = RegExp('^' + funcToString$1.call(hasOwnProperty$1).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_1(value) || _isMasked(value)) {
        return false;
      }
  
      var pattern = isFunction_1(value) ? reIsNative : reIsHostCtor;
      return pattern.test(_toSource(value));
    }
  
    var _baseIsNative = baseIsNative;
  
    /**
     * 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];
    }
  
    var _getValue = getValue;
  
    /**
     * 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;
    }
  
    var _getNative = getNative;
  
    /* Built-in method references that are verified to be native. */
  
  
    var Map = _getNative(_root, 'Map');
    var _Map = Map;
  
    /* Built-in method references that are verified to be native. */
  
  
    var nativeCreate = _getNative(Object, 'create');
    var _nativeCreate = nativeCreate;
  
    /**
     * Removes all key-value entries from the hash.
     *
     * @private
     * @name clear
     * @memberOf Hash
     */
  
  
    function hashClear() {
      this.__data__ = _nativeCreate ? _nativeCreate(null) : {};
      this.size = 0;
    }
  
    var _hashClear = hashClear;
  
    /**
     * 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;
    }
  
    var _hashDelete = hashDelete;
  
    /** Used to stand-in for `undefined` hash values. */
  
  
    var HASH_UNDEFINED = '__lodash_hash_undefined__';
    /** Used for built-in method references. */
  
    var objectProto$3 = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$2 = objectProto$3.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 ? undefined : result;
      }
  
      return hasOwnProperty$2.call(data, key) ? data[key] : undefined;
    }
  
    var _hashGet = hashGet;
  
    /** Used for built-in method references. */
  
  
    var objectProto$4 = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$3 = objectProto$4.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$3.call(data, key);
    }
  
    var _hashHas = hashHas;
  
    /** 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;
    }
  
    var _hashSet = hashSet;
  
    /**
     * 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;
    var _Hash = Hash;
  
    /**
     * 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()
      };
    }
  
    var _mapCacheClear = mapCacheClear;
  
    /**
     * 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;
    }
  
    var _isKeyable = isKeyable;
  
    /**
     * 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;
    }
  
    var _getMapData = getMapData;
  
    /**
     * 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;
    }
  
    var _mapCacheDelete = mapCacheDelete;
  
    /**
     * 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);
    }
  
    var _mapCacheGet = mapCacheGet;
  
    /**
     * 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);
    }
  
    var _mapCacheHas = mapCacheHas;
  
    /**
     * 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;
    }
  
    var _mapCacheSet = mapCacheSet;
  
    /**
     * 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;
    var _MapCache = MapCache;
  
    /** 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;
    }
  
    var _stackSet = stackSet;
  
    /**
     * 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 _Stack = Stack;
  
    /** Used to stand-in for `undefined` hash values. */
    var HASH_UNDEFINED$2 = '__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$2);
  
      return this;
    }
  
    var _setCacheAdd = setCacheAdd;
  
    /**
     * 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);
    }
  
    var _setCacheHas = setCacheHas;
  
    /**
     *
     * 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;
    var _SetCache = SetCache;
  
    /**
     * 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;
    }
  
    var _arraySome = arraySome;
  
    /**
     * 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);
    }
  
    var _cacheHas = cacheHas;
  
    /** Used to compose bitmasks for value comparisons. */
  
  
    var COMPARE_PARTIAL_FLAG = 1,
        COMPARE_UNORDERED_FLAG = 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,
          arrLength = array.length,
          othLength = other.length;
  
      if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
        return false;
      } // Assume cyclic values are equal.
  
  
      var stacked = stack.get(array);
  
      if (stacked && stack.get(other)) {
        return stacked == other;
      }
  
      var index = -1,
          result = true,
          seen = bitmask & COMPARE_UNORDERED_FLAG ? 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;
    }
  
    var _equalArrays = equalArrays;
  
    /** Built-in value references. */
  
  
    var Uint8Array = _root.Uint8Array;
    var _Uint8Array = Uint8Array;
  
    /**
     * 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;
    }
  
    var _mapToArray = mapToArray;
  
    /**
     * 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;
    }
  
    var _setToArray = setToArray;
  
    /** Used to compose bitmasks for value comparisons. */
  
  
    var COMPARE_PARTIAL_FLAG$1 = 1,
        COMPARE_UNORDERED_FLAG$1 = 2;
    /** `Object#toString` result references. */
  
    var boolTag = '[object Boolean]',
        dateTag = '[object Date]',
        errorTag = '[object Error]',
        mapTag = '[object Map]',
        numberTag = '[object Number]',
        regexpTag = '[object RegExp]',
        setTag = '[object Set]',
        stringTag = '[object String]',
        symbolTag = '[object Symbol]';
    var arrayBufferTag = '[object ArrayBuffer]',
        dataViewTag = '[object DataView]';
    /** Used to convert symbols to primitives and strings. */
  
    var symbolProto = _Symbol ? _Symbol.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:
          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_1(+object, +other);
  
        case errorTag:
          return object.name == other.name && object.message == other.message;
  
        case regexpTag:
        case stringTag:
          // Coerce regexes to strings and treat strings, primitives and objects,
          // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
          // for more details.
          return object == other + '';
  
        case mapTag:
          var convert = _mapToArray;
  
        case setTag:
          var isPartial = bitmask & COMPARE_PARTIAL_FLAG$1;
          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$1; // 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;
    }
  
    var _equalByTag = equalByTag;
  
    /**
     * 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;
    }
  
    var _arrayPush = arrayPush;
  
    /**
     * 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;
    var isArray_1 = isArray;
  
    /**
     * 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_1(object) ? result : _arrayPush(result, symbolsFunc(object));
    }
  
    var _baseGetAllKeys = baseGetAllKeys;
  
    /**
     * 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;
    }
  
    var _arrayFilter = arrayFilter;
  
    /**
     * 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 [];
    }
  
    var stubArray_1 = stubArray;
  
    /** Used for built-in method references. */
  
  
    var objectProto$5 = Object.prototype;
    /** Built-in value references. */
  
    var propertyIsEnumerable = objectProto$5.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_1 : function (object) {
      if (object == null) {
        return [];
      }
  
      object = Object(object);
      return _arrayFilter(nativeGetSymbols(object), function (symbol) {
        return propertyIsEnumerable.call(object, symbol);
      });
    };
    var _getSymbols = getSymbols;
  
    /**
     * 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;
    }
  
    var _baseTimes = baseTimes;
  
    /**
     * 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';
    }
  
    var isObjectLike_1 = isObjectLike;
  
    /** `Object#toString` result references. */
  
  
    var argsTag = '[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_1(value) && _baseGetTag(value) == argsTag;
    }
  
    var _baseIsArguments = baseIsArguments;
  
    /** Used for built-in method references. */
  
  
    var objectProto$6 = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$4 = objectProto$6.hasOwnProperty;
    /** Built-in value references. */
  
    var propertyIsEnumerable$1 = objectProto$6.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_1(value) && hasOwnProperty$4.call(value, 'callee') && !propertyIsEnumerable$1.call(value, 'callee');
    };
    var isArguments_1 = isArguments;
  
    /**
     * 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;
    }
  
    var stubFalse_1 = stubFalse;
  
    var isBuffer_1 = createCommonjsModule(function (module, exports) {
    /** Detect free variable `exports`. */
  
  
    var freeExports =  exports && !exports.nodeType && exports;
    /** Detect free variable `module`. */
  
    var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
    /** Detect the popular CommonJS extension `module.exports`. */
  
    var moduleExports = freeModule && freeModule.exports === freeExports;
    /** Built-in value references. */
  
    var Buffer = moduleExports ? _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_1;
    module.exports = isBuffer;
    });
  
    /** 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;
    }
  
    var _isIndex = isIndex;
  
    /** 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;
    }
  
    var isLength_1 = isLength;
  
    /** `Object#toString` result references. */
  
  
    var argsTag$1 = '[object Arguments]',
        arrayTag = '[object Array]',
        boolTag$1 = '[object Boolean]',
        dateTag$1 = '[object Date]',
        errorTag$1 = '[object Error]',
        funcTag$1 = '[object Function]',
        mapTag$1 = '[object Map]',
        numberTag$1 = '[object Number]',
        objectTag = '[object Object]',
        regexpTag$1 = '[object RegExp]',
        setTag$1 = '[object Set]',
        stringTag$1 = '[object String]',
        weakMapTag = '[object WeakMap]';
    var arrayBufferTag$1 = '[object ArrayBuffer]',
        dataViewTag$1 = '[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] = typedArrayTags[arrayBufferTag$1] = typedArrayTags[boolTag$1] = typedArrayTags[dataViewTag$1] = typedArrayTags[dateTag$1] = typedArrayTags[errorTag$1] = typedArrayTags[funcTag$1] = typedArrayTags[mapTag$1] = typedArrayTags[numberTag$1] = typedArrayTags[objectTag] = typedArrayTags[regexpTag$1] = typedArrayTags[setTag$1] = typedArrayTags[stringTag$1] = typedArrayTags[weakMapTag] = 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_1(value) && isLength_1(value.length) && !!typedArrayTags[_baseGetTag(value)];
    }
  
    var _baseIsTypedArray = baseIsTypedArray;
  
    /**
     * 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);
      };
    }
  
    var _baseUnary = baseUnary;
  
    var _nodeUtil = createCommonjsModule(function (module, exports) {
    /** Detect free variable `exports`. */
  
  
    var freeExports =  exports && !exports.nodeType && exports;
    /** Detect free variable `module`. */
  
    var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
    /** Detect the popular CommonJS extension `module.exports`. */
  
    var moduleExports = freeModule && freeModule.exports === freeExports;
    /** Detect free variable `process` from Node.js. */
  
    var freeProcess = moduleExports && _freeGlobal.process;
    /** Used to access faster Node.js helpers. */
  
    var nodeUtil = function () {
      try {
        // Use `util.types` for Node.js 10+.
        var types = freeModule && freeModule.require && freeModule.require('util').types;
  
        if (types) {
          return types;
        } // Legacy `process.binding('util')` for Node.js < 10.
  
  
        return freeProcess && freeProcess.binding && freeProcess.binding('util');
      } catch (e) {}
    }();
  
    module.exports = nodeUtil;
    });
  
    /* 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;
    var isTypedArray_1 = isTypedArray;
  
    /** Used for built-in method references. */
  
  
    var objectProto$7 = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$5 = objectProto$7.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_1(value),
          isArg = !isArr && isArguments_1(value),
          isBuff = !isArr && !isArg && isBuffer_1(value),
          isType = !isArr && !isArg && !isBuff && isTypedArray_1(value),
          skipIndexes = isArr || isArg || isBuff || isType,
          result = skipIndexes ? _baseTimes(value.length, String) : [],
          length = result.length;
  
      for (var key in value) {
        if ((inherited || hasOwnProperty$5.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;
    }
  
    var _arrayLikeKeys = arrayLikeKeys;
  
    /** Used for built-in method references. */
    var objectProto$8 = 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$8;
      return value === proto;
    }
  
    var _isPrototype = isPrototype;
  
    /**
     * 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));
      };
    }
  
    var _overArg = overArg;
  
    /* Built-in method references for those with the same name as other `lodash` methods. */
  
  
    var nativeKeys = _overArg(Object.keys, Object);
    var _nativeKeys = nativeKeys;
  
    /** Used for built-in method references. */
  
  
    var objectProto$9 = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$6 = objectProto$9.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$6.call(object, key) && key != 'constructor') {
          result.push(key);
        }
      }
  
      return result;
    }
  
    var _baseKeys = baseKeys;
  
    /**
     * 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_1(value.length) && !isFunction_1(value);
    }
  
    var isArrayLike_1 = isArrayLike;
  
    /**
     * 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_1(object) ? _arrayLikeKeys(object) : _baseKeys(object);
    }
  
    var keys_1 = keys;
  
    /**
     * 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_1, _getSymbols);
    }
  
    var _getAllKeys = getAllKeys;
  
    /** Used to compose bitmasks for value comparisons. */
  
  
    var COMPARE_PARTIAL_FLAG$2 = 1;
    /** Used for built-in method references. */
  
    var objectProto$a = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$7 = objectProto$a.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$2,
          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$7.call(other, key))) {
          return false;
        }
      } // Assume cyclic values are equal.
  
  
      var stacked = stack.get(object);
  
      if (stacked && stack.get(other)) {
        return stacked == other;
      }
  
      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;
    }
  
    var _equalObjects = equalObjects;
  
    /* Built-in method references that are verified to be native. */
  
  
    var DataView = _getNative(_root, 'DataView');
    var _DataView = DataView;
  
    /* Built-in method references that are verified to be native. */
  
  
    var Promise = _getNative(_root, 'Promise');
    var _Promise = Promise;
  
    /* Built-in method references that are verified to be native. */
  
  
    var Set = _getNative(_root, 'Set');
    var _Set = Set;
  
    /* Built-in method references that are verified to be native. */
  
  
    var WeakMap = _getNative(_root, 'WeakMap');
    var _WeakMap = WeakMap;
  
    /** `Object#toString` result references. */
  
  
    var mapTag$2 = '[object Map]',
        objectTag$1 = '[object Object]',
        promiseTag = '[object Promise]',
        setTag$2 = '[object Set]',
        weakMapTag$1 = '[object WeakMap]';
    var dataViewTag$2 = '[object DataView]';
    /** Used to detect maps, sets, and weakmaps. */
  
    var dataViewCtorString = _toSource(_DataView),
        mapCtorString = _toSource(_Map),
        promiseCtorString = _toSource(_Promise),
        setCtorString = _toSource(_Set),
        weakMapCtorString = _toSource(_WeakMap);
    /**
     * Gets the `toStringTag` of `value`.
     *
     * @private
     * @param {*} value The value to query.
     * @returns {string} Returns the `toStringTag`.
     */
  
    var getTag = _baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
  
    if (_DataView && getTag(new _DataView(new ArrayBuffer(1))) != dataViewTag$2 || _Map && getTag(new _Map()) != mapTag$2 || _Promise && getTag(_Promise.resolve()) != promiseTag || _Set && getTag(new _Set()) != setTag$2 || _WeakMap && getTag(new _WeakMap()) != weakMapTag$1) {
      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$2;
  
            case mapCtorString:
              return mapTag$2;
  
            case promiseCtorString:
              return promiseTag;
  
            case setCtorString:
              return setTag$2;
  
            case weakMapCtorString:
              return weakMapTag$1;
          }
        }
  
        return result;
      };
    }
  
    var _getTag = getTag;
  
    /** Used to compose bitmasks for value comparisons. */
  
  
    var COMPARE_PARTIAL_FLAG$3 = 1;
    /** `Object#toString` result references. */
  
    var argsTag$2 = '[object Arguments]',
        arrayTag$1 = '[object Array]',
        objectTag$2 = '[object Object]';
    /** Used for built-in method references. */
  
    var objectProto$b = Object.prototype;
    /** Used to check objects for own properties. */
  
    var hasOwnProperty$8 = objectProto$b.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_1(object),
          othIsArr = isArray_1(other),
          objTag = objIsArr ? arrayTag$1 : _getTag(object),
          othTag = othIsArr ? arrayTag$1 : _getTag(other);
      objTag = objTag == argsTag$2 ? objectTag$2 : objTag;
      othTag = othTag == argsTag$2 ? objectTag$2 : othTag;
      var objIsObj = objTag == objectTag$2,
          othIsObj = othTag == objectTag$2,
          isSameTag = objTag == othTag;
  
      if (isSameTag && isBuffer_1(object)) {
        if (!isBuffer_1(other)) {
          return false;
        }
  
        objIsArr = true;
        objIsObj = false;
      }
  
      if (isSameTag && !objIsObj) {
        stack || (stack = new _Stack());
        return objIsArr || isTypedArray_1(object) ? _equalArrays(object, other, bitmask, customizer, equalFunc, stack) : _equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
      }
  
      if (!(bitmask & COMPARE_PARTIAL_FLAG$3)) {
        var objIsWrapped = objIsObj && hasOwnProperty$8.call(object, '__wrapped__'),
            othIsWrapped = othIsObj && hasOwnProperty$8.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);
    }
  
    var _baseIsEqualDeep = baseIsEqualDeep;
  
    /**
     * 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_1(value) && !isObjectLike_1(other)) {
        return value !== value && other !== other;
      }
  
      return _baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
    }
  
    var _baseIsEqual = baseIsEqual;
  
    /**
     * Performs a deep comparison between two values to determine if they are
     * equivalent.
     *
     * **Note:** This method supports comparing arrays, array buffers, booleans,
     * date objects, error objects, maps, numbers, `Object` objects, regexes,
     * sets, strings, symbols, and typed arrays. `Object` objects are compared
     * by their own, not inherited, enumerable properties. Functions and DOM
     * nodes are compared by strict equality, i.e. `===`.
     *
     * @static
     * @memberOf _
     * @since 0.1.0
     * @category Lang
     * @param {*} value The value to compare.
     * @param {*} other The other value to compare.
     * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
     * @example
     *
     * var object = { 'a': 1 };
     * var other = { 'a': 1 };
     *
     * _.isEqual(object, other);
     * // => true
     *
     * object === other;
     * // => false
     */
  
  
    function isEqual(value, other) {
      return _baseIsEqual(value, other);
    }
  
    var isEqual_1 = isEqual;
  
    let timer;
  
    function debounce(func, delay) {
      return function () {
        const context = this;
        const args = arguments;
        timer && clearTimeout(timer);
        timer = setTimeout(() => {
          func.apply(context, args);
        }, delay);
      };
    }
  
    function print(info, type = 2) {
      const list = [{
        type: 0,
        msg: 'log',
        style: 'background: #e4f1eb; color: #fff; padding: 2px 4px; border-radius: 2px'
      }, {
        type: 1,
        msg: 'info',
        style: 'background: #007fff; color: #fff; padding: 2px 4px; border-radius: 2px'
      }, {
        type: 2,
        msg: 'error',
        style: 'background: #d9634d; color: #fff; padding: 2px 4px; border-radius: 2px'
      }];
      list.forEach(item => {
        type === item.type && console[item.msg](`%c${item.msg}`, item.style, info); // eslint-disable-line
      });
    }
  
    /**
     * getBaseInfo
     * 获取用户名、ID、时间戳、其他自定义信息等
     *
     * @returns {Object}
     * @private
     */
    function getBaseInfo() {
      var config = window.$HibugConfig;
      var date = new Date();
      var time = "".concat(date.getFullYear(), "\u5E74").concat(date.getMonth() + 1, "\u6708").concat(date.getDate(), "\u65E5").concat(date.getHours(), "\u65F6").concat(date.getMinutes(), "\u5206").concat(date.getSeconds(), "\u79D2");
      var result = {
        time: time,
        userAgent: window.navigator.userAgent,
        url: window.location.href,
        title: document.title,
        preUrl: document.referrer && document.referrer !== window.location.href ? document.referrer : ''
      };
  
      if (config === null || config === void 0 ? void 0 : config.others) {
        result = _objectSpread({}, result, config.others);
      }
  
      return result;
    }
  
    var reg = /^(https?:\/\/)?(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(.+)?$/;
    /**
     * request
     * 上报
     *
     * @param {Array} data
     * @private
     */
  
    function report(data) {
      try {
        var config = window.$HibugConfig;
  
        if (config === null || config === void 0 ? void 0 : config.report) {
          if (typeof config.enabledDev === 'boolean') {
            var isDev = reg.test(window.location.host) || window.location.host.indexOf('localhost') > -1 || !window.location.host;
  
            if (config.enabledDev && isDev) {
              config.report(data);
            }
          } else if (Array.isArray(config.enabledDev) && config.enabledDev.length) {
            var iter = config.enabledDev.find(function (v) {
              return window.location.host && v.indexOf(window.location.host) > -1;
            });
            if (!iter) config.report(data);
          } else {
            config.report(data);
          }
        }
      } catch (e) {
        print("\u53D1\u9001\u65E5\u5FD7\u5931\u8D25 errorInfo:".concat(e));
      }
    }
  
    var errorList = []; // 发生错误一段时间后发送请求 防抖控制指定时间内只发送一次请求
  
    var request = function request(delay) {
      return debounce(function () {
        print(errorList, 0);
        report(errorList);
      }, delay).call();
    };
    /**
     * handleError
     * 错误处理
     *
     * @param {Object} error
     * @private
     */
  
  
    function handleError(error) {
      print(error);
  
      if (errorList.length) {
        // 防止重复上报
        errorList.forEach(function (e) {
          if (!isEqual_1(error.desc, e.desc)) {
            errorList.push(_objectSpread({}, getBaseInfo(), error));
          }
        });
      } else {
        errorList.push(_objectSpread({}, getBaseInfo(), error));
      } // 控制错误数量在指定条数以内
  
  
      var config = window.$HibugConfig;
  
      if ((config === null || config === void 0 ? void 0 : config.error) && (!(config === null || config === void 0 ? void 0 : config.mode) || config.mode === 'immediately') && errorList.length && errorList.length <= config.maxError) {
        request(config && config.delay || 2000);
      }
    }
  
    /**
      * getError
      * uncaughtError
      *
      * @param   {String}    type    错误类型 分为一般错误和未catch的promise错误
      * @param   {Object}    e       错误对象
      * @returns {boolean}
      * @private
      */
  
    function getError(_ref) {
      var type = _ref.type,
          e = _ref.e;
  
      try {
        if (type === 'default') {
          var msg = e.message,
              filename = e.filename,
              row = e.lineno,
              col = e.colno,
              error = e.error;
  
          if (msg) {
            if (error) {
              // 在 react 内 一般会捕获到语法错误导致的 react-dom 渲染错误
              var message = {
                type: UNCAUGHT_ERROR,
                desc: {
                  message: msg,
                  filename: filename,
                  row: row,
                  col: col,
                  error: error.stack || error
                }
              };
              handleError(message);
            }
          } else {
            var immutableTarget = e.target || e.srcElement;
            var target = e.target || e.srcElement;
  
            if (immutableTarget) {
              // resourceError
              var outerHTML = immutableTarget.outerHTML;
  
              var selector = function () {
                // 获取出错元素在同级元素的 index
                // 储存错误元素前元素
                var elements = [];
  
                for (var i = 0; target && target.nodeType === Node.ELEMENT_NODE && target.nodeType !== Node.DOCUMENT_TYPE_NODE; target = target.previousSibling) {
                  i && elements.push(target);
                  i += 1;
                }
  
                return e && e.path.reverse().map(function (node) {
                  return (node.localName || '') + (node.id ? "#".concat(node.id) : '') + (node.className ? ".".concat(node.className) : '') + (node.outerHTML === outerHTML ? ":nth-child(".concat(elements.length, ")") : '');
                }).filter(function (v) {
                  return v;
                }).join(' > ');
              }();
  
              var _message = {
                type: RESOURCE_ERROR,
                desc: {
                  outerHTML: outerHTML,
                  src: immutableTarget && immutableTarget.src,
                  tagName: immutableTarget && immutableTarget.tagName,
                  id: immutableTarget && immutableTarget.id,
                  className: immutableTarget && immutableTarget.className,
                  name: immutableTarget && immutableTarget.name,
                  type: immutableTarget && immutableTarget.type,
                  selector: selector,
                  timeStamp: e.timeStamp
                }
              };
              handleError(_message);
            } else if (typeof e === 'string') {
              var _message2 = {
                type: GRAMMAR_ERROR,
                desc: e
              };
              handleError(_message2);
            }
          }
        } else if (type === 'promise') {
          // 捕获没有 catch 的 Promise 错误
          var _message3 = {
            type: PROMISE_ERROR,
            desc: {
              message: e.reason.message || e.reason,
              error: e.reason.stack || e.reason
            }
          };
          handleError(_message3);
        }
  
        return false;
      } catch (err) {
        var _message4 = {
          type: UNKNOWN_ERROR,
          desc: 'unknown error'
        };
        handleError(_message4);
      }
    } // 用于上报自定义信息
  
  
    function reportInfo(info, include) {
      if (!window.$HibugAuth) {
        console.error('Hibug: 检测到未执行 Hibug.init()');
        return;
      }
  
      var config = window.$HibugConfig;
      var message = {
        type: REPORT_INFO,
        desc: info
      };
  
      if (config.include) {
        if (typeof config.include === 'function') {
          if (include) {
            // 传入筛选选项 include 且 reportInfo 传入第二个参数 true
            config.include() && handleError(message);
          } else {
            // 传入筛选选项 include 但 reportInfo 未传入第二个参数 true, 此时走正常逻辑
            handleError(message);
          }
        } else {
          console.error('Hibug: 参数 include 类型必须为 function');
        }
      } else if (!config.include && include) {
        console.error('Hibug: Hibug.init 未传入参数 include');
      } else if (!config.include && !include) {
        // 未传入筛选选项 include 且 reportInfo 未传入第二个参数 true
        handleError(message);
      }
    } // 使用装饰器 用于单独捕获错误
  
  
    function caughtError(target, name, descriptor) {
      var _window;
  
      if (!((_window = window) === null || _window === void 0 ? void 0 : _window.$HibugAuth)) {
        console.error('Hibug: 检测到未执行 Hibug.init()');
        return;
      }
  
      if (typeof descriptor.value === 'function') {
        /**
         * 捕获 `class` 内方法错误
         * class Math {
         *    @log  // Decorator
         *    plus(a, b) {
         *      return a + b;
         *    }
         *  }
         */
        return _objectSpread({}, descriptor, {
          value: function value() {
            try {
              return descriptor.value && descriptor.value.apply(this, arguments);
            } catch (e) {
              // 此处可捕获到方法内的错误 上报错误
              var message = {
                type: CAUGHT_ERROR,
                desc: {
                  method: name,
                  params: arguments,
                  error: e.stack || e
                }
              };
              handleError(message);
              throw e;
            }
          }
        });
      }
  
      if (typeof descriptor.initializer === 'function') {
        /**
         * 捕获 `class` 内 `arrow function method` 错误
         * class Math {
         *    @log  // Decorator
         *    plus = (a, b) => {
         *      return a + b;
         *    }
         *  }
         */
        return {
          enumerable: true,
          configurable: true,
          get: function get() {
            // `arrow function method` 由于是箭头函数没有 `arguments` 所以获取不到参数
            // 捕获不到异常 只能靠全局捕获 建议不要使用 `arrow function method`
            return descriptor.initializer && descriptor.initializer.apply(this);
          }
        };
      }
    }
  
    /**
     * getHttpRequestError
     * ajax/fetch/websocket Error
     *
     * @private
     */
  
    function getHttpRequestError() {
      // 通过封装原生 Ajax/Fetch 请求，捕获错误信息
      var ignore = window.$HibugConfig.ignore;
  
      if (window.XMLHttpRequest) {
        var AJAX = {
          url: '',
          method: '',
          open: window.XMLHttpRequest.prototype.open,
          send: window.XMLHttpRequest.prototype.send,
          init: function init() {
            var that = this;
  
            window.XMLHttpRequest.prototype.open = function () {
              that.url = arguments[1];
              that.method = arguments[0];
              that.open.apply(this, arguments);
            };
  
            window.XMLHttpRequest.prototype.send = function () {
              this.addEventListener('readystatechange', function () {
                if (this.readyState === 4) {
                  // 判断当前 http 请求是否在 ignore 中
                  var isIgnore = ignore.filter(function (u) {
                    return that.url.indexOf(u) > -1;
                  });
  
                  if ((!this.status || this.status >= 400) && !isIgnore.length) {
                    var message = {
                      type: AJAX_ERROR,
                      desc: {
                        req: {
                          url: that.url,
                          method: that.method,
                          data: arguments[0] || {}
                        },
                        res: {
                          status: this.status,
                          statusText: this.statusText,
                          response: this.response
                        }
                      }
                    };
                    handleError(message);
                  }
                }
              });
              that.send.apply(this, arguments);
            };
          }
        };
        AJAX.init();
      }
  
      if (window.fetch) {
        var FETCH = {
          backup: window.fetch,
          init: function init() {
            window.fetch = function (url, conf) {
              return FETCH.backup.apply(this, arguments).then(function (res) {
                var isIgnore = ignore.filter(function (u) {
                  return url.indexOf(u) > -1;
                });
  
                if ((!res.status || res.status >= 400) && !isIgnore.length) {
                  var message = {
                    type: FETCH_ERROR,
                    desc: {
                      req: {
                        url: url,
                        method: conf && conf.method || 'GET',
                        data: conf && conf.body || {}
                      },
                      res: {
                        status: res.status,
                        statusText: res.statusText // fetch 只能通过 res.json() 获取返回值且只能调用一次 此处不能获取返回值
  
                      }
                    }
                  };
                  handleError(message);
                }
  
                return res;
              })["catch"](function (err) {
                var message = {
                  type: FETCH_ERROR,
                  desc: err
                };
                handleError(message);
              });
            };
          }
        };
        FETCH.init();
      }
  
      if (window.WebSocket) {
        var WEBSOCKET = {
          url: '',
          backup: Object.getOwnPropertyDescriptor(window.WebSocket.prototype, 'onerror'),
          init: function init() {
            var that = this;
            Object.defineProperty(window.WebSocket.prototype, 'onerror', {
              set: function set() {
                try {
                  var arg = arguments[0];
                  that.backup.set.apply(this, [function (e) {
                    var message = {
                      type: WEBSOCKET_ERROR,
                      desc: {
                        url: e.target.url
                      }
                    };
                    handleError(message);
                    arg.apply(this, arguments);
                  }]);
                } catch (e) {
                  return that.backup.set.apply(this, arguments);
                }
              }
            });
          }
        };
        WEBSOCKET.init();
      }
    }
  
    /**
     * getPerformance
     * 获取页面性能信息
     */
  
    function getPerformance() {
      try {
        var _window;
  
        if (!((_window = window) === null || _window === void 0 ? void 0 : _window.performance)) return new Error('performance is not supported');
        var timing = window.performance.timing;
        var connectEnd = timing.connectEnd,
            connectStart = timing.connectStart,
            domComplete = timing.domComplete,
            domContentLoadedEventEnd = timing.domContentLoadedEventEnd,
            domContentLoadedEventStart = timing.domContentLoadedEventStart,
            domInteractive = timing.domInteractive,
            domLoading = timing.domLoading,
            domainLookupEnd = timing.domainLookupEnd,
            domainLookupStart = timing.domainLookupStart,
            fetchStart = timing.fetchStart,
            loadEventEnd = timing.loadEventEnd,
            loadEventStart = timing.loadEventStart,
            navigationStart = timing.navigationStart,
            redirectEnd = timing.redirectEnd,
            redirectStart = timing.redirectStart,
            requestStart = timing.requestStart,
            responseEnd = timing.responseEnd,
            responseStart = timing.responseStart,
            secureConnectionStart = timing.secureConnectionStart,
            unloadEventEnd = timing.unloadEventEnd,
            unloadEventStart = timing.unloadEventStart;
        return {
          // 重定向 = redirectEnd - redirectStart
          redirect: redirectEnd - redirectStart || 0,
          // 应用缓存 = domainLookupStart - fetchStart
          cache: domainLookupStart - fetchStart || 0,
          // DNS解析 = domainLookupEnd - domainLookupStart
          dns: domainLookupEnd - domainLookupStart || 0,
          // TCP链接 = connectEnd - connectStart
          tcp: connectEnd - connectStart || 0,
          // 安全链接 = connectEnd - secureConnectionStart
          secureConnection: secureConnectionStart ? connectEnd - secureConnectionStart : 0,
          // request = responseEnd - requestStart
          request: responseEnd - requestStart || 0,
          // 白屏/首屏渲染(跳转到response之间) = responseStart - navigationStart
          first: responseStart - navigationStart || 0,
          // unload = unloadEventEnd - unloadEventStart
          unload: unloadEventEnd - unloadEventStart || 0,
          // 总体网络交互(开始跳转到服务器资源下载完成) = responseEnd - navigationStart
          network: responseEnd - navigationStart || 0,
          // DOM结构解析(未加载图片 样式 等) = domInteractive - domLoading
          domInteractive: domInteractive - domLoading || 0,
          // 脚本执行 = domContentLoadedEventEnd - domContentLoadedEventStart
          script: domContentLoadedEventEnd - domContentLoadedEventStart || 0,
          // DOM加载(不包括结构解析) = domComplete - domInteractive
          dom: domComplete - domInteractive || 0,
          // onload = loadEventEnd - loadEventStart
          onload: loadEventEnd - loadEventStart || 0,
          // 合计 = loadEventEnd - navigationStart
          total: loadEventEnd - navigationStart || 0
        };
      } catch (e) {
        print(e);
      }
    }
  
    function getResource() {
      try {
        if (window) {
          if (!window.performance) return new Error('performance is not supported');
          var resource = performance.getEntriesByType('resource');
          if (!resource || !resource.length) return [];
          return resource.map(function (item) {
            return {
              name: item.name,
              // 路径
              type: item.initiatorType,
              // 类型
              duration: item.duration || 0,
              // 持续时间
              decodedBodySize: item.decodedBodySize || 0,
              // 返回数据大小
              nextHopProtocol: item.nextHopProtocol // script img fetchrequest xmlhttprequest other
  
            };
          });
        }
      } catch (e) {
        print(e);
      }
    }
  
    function UUID() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
        const r = Math.random() * 16 | 0; // eslint-disable-line
  
        const v = c === 'x' ? r : r & 0x3 | 0x8; // eslint-disable-line
  
        return v.toString(16);
      });
    }
  
    function getUV() {
      try {
        if (window.localStorage) {
          var now = new Date();
          var UV = localStorage.getItem('$HibugUV') || '';
          var time = localStorage.getItem('$HibugUVTime') || '';
  
          if (!UV && !time || now.getTime() > time * 1) {
            UV = UUID();
            localStorage.setItem('$HibugUV', UV);
            var today = "".concat(now.getFullYear(), "/").concat(now.getMonth() + 1, "/").concat(now.getDate(), " 23:59:59");
            localStorage.setItem('$HibugUVTime', new Date(today).getTime());
          }
  
          return UV;
        }
      } catch (e) {
        print(e);
      }
    }
  
    var listener = window.addEventListener;
  
    function _init() {
      var _hibugConfig = window.$HibugConfig;
      /**
       * 可捕获语法错误和网络错误 无法捕获 Promise 错误
       * @param {String}  msg    错误信息
       * @param {String}  url    出错文件
       * @param {Number}  row    行号
       * @param {Number}  col    列号
       * @param {Object}  error  错误详细信息
       */
  
      listener && listener('error', function (e) {
        getError({
          type: 'default',
          e: e
        });
      }, true);
      /**
       * 可捕获 Promise 错误
       * react render 内发生 `Cannot read property 'xxx' of undefined` 可从此处捕获到
       */
  
      listener && listener('unhandledrejection', function (e) {
        e.preventDefault();
        getError({
          type: 'promise',
          e: e
        });
      }, true); // ajax/fetch Error
  
      getHttpRequestError(); // 文档卸载前执行发送日志操作
  
      if ((_hibugConfig === null || _hibugConfig === void 0 ? void 0 : _hibugConfig.mode) === 'beforeunload') {
        listener && listener('unload', function () {
          if ((errorList === null || errorList === void 0 ? void 0 : errorList.length) && errorList.length <= _hibugConfig.maxError) {
            report(errorList);
          }
        }, true);
      }
  
      if (_hibugConfig === null || _hibugConfig === void 0 ? void 0 : _hibugConfig.performance) {
        listener && listener('load', function () {
          var performance = getPerformance();
          var resource = getResource();
          var UV = getUV();
  
          var data = _objectSpread({}, getBaseInfo());
  
          if (performance) data.performance = performance;
          if (resource === null || resource === void 0 ? void 0 : resource.length) data.resource = resource;
          if (UV) data.UV = UV;
          report(data);
        }, true);
      }
    }
  
    function Hibug() {}
  
    Hibug.init = function (conf) {
      var _window, _window2;
  
      if (!window) {
        console.error('Hibug: 检测到当前环境不支持 Hibug！');
        return;
      }
  
      window.$HibugAuth = true;
  
      if (!((_window = window) === null || _window === void 0 ? void 0 : _window.$HibugConfig)) {
        // default config
        window.$HibugConfig = {
          delay: 2000,
          // 错误处理间隔时间
          report: function report() {},
          // 上报错误的方法
          enabledDev: false,
          // 开发环境下上传错误
          maxError: 10,
          // 最大上传错误数量
          mode: 'immediately',
          // 信息发送模式 immediately 立即发送 beforeunload 页面注销前发送
          ignore: [],
          // 忽略指定错误 目前只支持忽略 HTTP 请求错误
          error: true,
          // 是否上报错误信息
          performance: false,
          // 是否上报性能信息
          include: null // 用于收集指定用户的特定信息
  
        };
      }
  
      if (conf) {
        window.$HibugConfig = _objectSpread({}, window.$HibugConfig, conf);
      }
  
      if ((_window2 = window) === null || _window2 === void 0 ? void 0 : _window2.$HibugAuth) _init();
    };
  
    Hibug.reportInfo = reportInfo;
    Hibug.caughtError = caughtError;
  
    return Hibug;
  
  }));
  