reviver = function reviver(options) {
  var refs = [];
  var root;
  return function revive(key, value) {
    // last iteration = root
    if (key === '') {
      root = value; // restore cyclic refs

      refs.forEach(function (_ref) {
        var target = _ref.target,
            container = _ref.container,
            replacement = _ref.replacement;
        var replacementArr = isJSON(replacement) ? JSON.parse(replacement) : replacement.split('.');

        if (replacementArr.length === 0) {
          // eslint-disable-next-line no-param-reassign
          container[target] = root;
        } else {
          // eslint-disable-next-line no-param-reassign
          container[target] = lodash_get__WEBPACK_IMPORTED_MODULE_4___default()(root, replacementArr);
        }
      });
    }

    if (key === '_constructor-name_') {
      return value;
    } // deal with instance names


    if (isObject(value) && value['_constructor-name_'] && options.allowFunction) {
      var name = value['_constructor-name_'];

      if (name !== 'Object') {
        // eslint-disable-next-line no-new-func
        var Fn = new Function("return function ".concat(name.replace(/[\W_]+/g, ''), "(){}"))();
        Object.setPrototypeOf(value, new Fn());
      } // eslint-disable-next-line no-param-reassign


      delete value['_constructor-name_'];
      return value;
    }

    if (typeof value === 'string' && value.startsWith('_function_') && options.allowFunction) {
      var _ref2 = value.match(/_function_([^|]*)\|(.*)/) || [],
          _ref3 = _slicedToArray(_ref2, 3),
          _name = _ref3[1],
          source = _ref3[2]; // eslint-disable-next-line no-useless-escape


      var sourceSanitized = source.replace(/[(\(\))|\\| |\]|`]*$/, '');

      if (!options.lazyEval) {
        // eslint-disable-next-line no-eval
        return eval("(".concat(sourceSanitized, ")"));
      } // lazy eval of the function


      var result = function result() {
        // eslint-disable-next-line no-eval
        var f = eval("(".concat(sourceSanitized, ")"));
        return f.apply(void 0, arguments);
      };

      Object.defineProperty(result, 'toString', {
        value: function value() {
          return sourceSanitized;
        }
      });
      Object.defineProperty(result, 'name', {
        value: _name
      });
      return result;
    }

    if (typeof value === 'string' && value.startsWith('_regexp_') && options.allowRegExp) {
      // this split isn't working correctly
      var _ref4 = value.match(/_regexp_([^|]*)\|(.*)/) || [],
          _ref5 = _slicedToArray(_ref4, 3),
          flags = _ref5[1],
          _source = _ref5[2];

      return new RegExp(_source, flags);
    }

    if (typeof value === 'string' && value.startsWith('_date_') && options.allowDate) {
      return new Date(value.replace('_date_', ''));
    }

    if (typeof value === 'string' && value.startsWith('_duplicate_')) {
      refs.push({
        target: key,
        container: this,
        replacement: value.replace(/^_duplicate_/, '')
      });
      return null;
    }

    if (typeof value === 'string' && value.startsWith('_symbol_') && options.allowSymbol) {
      return Symbol(value.replace('_symbol_', ''));
    }

    if (typeof value === 'string' && value.startsWith('_gsymbol_') && options.allowSymbol) {
      return Symbol["for"](value.replace('_gsymbol_', ''));
    }

    if (typeof value === 'string' && value === '_-Infinity_') {
      return -Infinity;
    }

    if (typeof value === 'string' && value === '_Infinity_') {
      return Infinity;
    }

    if (typeof value === 'string' && value === '_NaN_') {
      return NaN;
    }

    if (typeof value === 'string' && value.startsWith('_bigint_') && typeof BigInt === 'function') {
      return BigInt(value.replace('_bigint_', ''));
    }

    return value;
  };
}
Topological sorting function

@param {Array} edges
@returns {Array}