<commit_before>/* eslint no-restricted-syntax:0 */
import lodashIsEqual from 'lodash/isEqual';

const ACTION_TYPE = '@redux-memoize/action';

const DEFAULT_META = {
  ttl: 200,
  enabled: true,
  isEqual: lodashIsEqual,
};

function isPromise(v) {
  return v && typeof v.then === 'function';
}

const canUseDOM = !!(
  typeof window !== 'undefined' && window.document && window.document.createElement
);

function deepGet(map, args, isEqual) {
  for (const key of map.keys()) {
    if (isEqual(key, args)) {
      return map.get(key);
    }
  }
  return null;
}

export default function createMemoizeMiddleware(options = {}) {
  const {
    // default disableTTL is true on server side, to prevent memory leak (use GC to remove cache)
    disableTTL = !canUseDOM,
    ...globalOptions
  } = options;

  const cache = new Map();
  const middleware = ({ dispatch, getState }) => next => (action) => {
    if (typeof action === 'object' && action.type === ACTION_TYPE) {
      const { fn, args } = action.payload;
      const { ttl, enabled, isEqual } = {
        ...DEFAULT_META,
        ...globalOptions,
        ...(action.meta || {}),
      };
      let taskCache = cache.get(fn);
      if (!taskCache) {
        taskCache = new Map();
        cache.set(fn, taskCache);
      }

      if (typeof enabled === 'function' ? enabled(getState) : enabled) {
        let task = deepGet(taskCache, args, isEqual);
        if (!task) {
          const result = dispatch(fn(...args));
          task = isPromise(result) ? result : Promise.resolve(result);
          const finalTTL = typeof ttl === 'function' ? ttl(getState) : ttl;
          if (finalTTL) {
            taskCache.set(args, task);
            if (!disableTTL) {
              setTimeout(() => {
                taskCache.delete(args);
              }, finalTTL);
            }
          }
        }
        return task;
      }
      const result = dispatch(fn(...args));
      return isPromise(result) ? result : Promise.resolve(result);
    }
    return next(action);
  };
  middleware.getAll = () => {
    const result = [];
    for (const fnCache of cache.values()) {
      for (const value of fnCache.values()) {
        result.push(value);
      }
    }
    return result;
  };
  return middleware;
}

export function memoize(opts, fn) {
  let func;
  let options;
  if (arguments.length < 2) {
    options = null;
    func = opts;
  } else {
    options = typeof opts === 'object' ? opts : { ttl: opts };
    func = fn;<commit_msg>use Array.from instead of for...of<commit_after>import lodashIsEqual from 'lodash/isEqual';

const ACTION_TYPE = '@redux-memoize/action';

const DEFAULT_META = {
  ttl: 200,
  enabled: true,
  isEqual: lodashIsEqual,
};

function isPromise(v) {
  return v && typeof v.then === 'function';
}

const canUseDOM = !!(
  typeof window !== 'undefined' && window.document && window.document.createElement
);

function deepGet(map, args, isEqual) {
  const keys = Array.from(map.keys());
  for (let i = 0, len = keys.length; i < len; i += 1) {
    const key = keys[i];
    if (isEqual(key, args)) {
      return map.get(key);
    }
  }
  return null;
}

export default function createMemoizeMiddleware(options = {}) {
  const {
    // default disableTTL is true on server side, to prevent memory leak (use GC to remove cache)
    disableTTL = !canUseDOM,
    ...globalOptions
  } = options;

  const cache = new Map();
  const middleware = ({ dispatch, getState }) => next => (action) => {
    if (typeof action === 'object' && action.type === ACTION_TYPE) {
      const { fn, args } = action.payload;
      const { ttl, enabled, isEqual } = {
        ...DEFAULT_META,
        ...globalOptions,
        ...(action.meta || {}),
      };
      let taskCache = cache.get(fn);
      if (!taskCache) {
        taskCache = new Map();
        cache.set(fn, taskCache);
      }

      if (typeof enabled === 'function' ? enabled(getState) : enabled) {
        let task = deepGet(taskCache, args, isEqual);
        if (!task) {
          const result = dispatch(fn(...args));
          task = isPromise(result) ? result : Promise.resolve(result);
          const finalTTL = typeof ttl === 'function' ? ttl(getState) : ttl;
          if (finalTTL) {
            taskCache.set(args, task);
            if (!disableTTL) {
              setTimeout(() => {
                taskCache.delete(args);
              }, finalTTL);
            }
          }
        }
        return task;
      }
      const result = dispatch(fn(...args));
      return isPromise(result) ? result : Promise.resolve(result);
    }
    return next(action);
  };
  middleware.getAll = () => {
    const result = [];
    const cacheValues = Array.from(cache.values());
    cacheValues.forEach((fnCache) => {
      Array.from(fnCache.values()).forEach((value) => {
        result.push(value);
      });
    });
    return result;
  };
  return middleware;
}

export function memoize(opts, fn) {
  let func;
  let options;
  if (arguments.length < 2) {
    options = null;
    func = opts;
  } else {
    options = typeof opts === 'object' ? opts : { ttl: opts };
    func = fn;
{'fraction_non_alphanumeric': 0.14857477547832879, 'fraction_numerical': 0.002147598594299102, 'mean_word_length': 2.31800518134715, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5122466', 'n_tokens_mistral': 1593, 'n_tokens_neox': 1576, 'n_words': 406}