Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

micro-memoize

Package Overview
Dependencies
Maintainers
1
Versions
92
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

micro-memoize - npm Package Compare versions

Comparing version
2.1.2
to
3.0.0-beta.0
+799
__tests__/index.ts
// external dependencies
import { deepEqual } from 'fast-equals';
import memoize from '../src';
import { isSameValueZero } from '../src/utils';
describe('memoize', () => {
it('will return the function if already memoized', () => {
const fn = () => {};
fn.isMemoized = true;
const memoized = memoize(fn);
expect(memoized).toBe(fn);
});
it('will return the memoized function', () => {
let callCount = 0;
const fn = (one: any, two: any) => {
callCount++;
return {
one,
two,
};
};
const memoized = memoize(fn);
expect(memoized.cache).toEqual({
keys: [],
size: 0,
values: [],
});
expect(memoized.cacheSnapshot).toEqual({
keys: [],
size: 0,
values: [],
});
expect(memoized.isMemoized).toEqual(true);
expect(memoized.options).toEqual({
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
maxSize: 1,
transformKey: undefined,
});
new Array(1000).fill('z').forEach(() => {
const result = memoized('one', 'two');
expect(result).toEqual({
one: 'one',
two: 'two',
});
});
expect(callCount).toEqual(1);
expect(memoized.cache).toEqual({
keys: [['one', 'two']],
size: 1,
values: [
{
one: 'one',
two: 'two',
},
],
});
});
it('will return the memoized function that can have multiple cached key => value pairs', () => {
let callCount = 0;
const fn = (one: any, two: any) => {
callCount++;
return {
one,
two,
};
};
const maxSize = 3;
const memoized = memoize(fn, { maxSize });
expect(memoized.cache).toEqual({
keys: [],
size: 0,
values: [],
});
expect(memoized.cacheSnapshot).toEqual({
keys: [],
size: 0,
values: [],
});
expect(memoized.isMemoized).toEqual(true);
expect(memoized.options.maxSize).toEqual(maxSize);
expect(memoized('one', 'two')).toEqual({
one: 'one',
two: 'two',
});
expect(memoized('two', 'three')).toEqual({
one: 'two',
two: 'three',
});
expect(memoized('three', 'four')).toEqual({
one: 'three',
two: 'four',
});
expect(memoized('four', 'five')).toEqual({
one: 'four',
two: 'five',
});
expect(memoized('two', 'three')).toEqual({
one: 'two',
two: 'three',
});
expect(memoized('three', 'four')).toEqual({
one: 'three',
two: 'four',
});
expect(callCount).toEqual(4);
expect(memoized.cache).toEqual({
keys: [['three', 'four'], ['two', 'three'], ['four', 'five']],
size: 3,
values: [
{
one: 'three',
two: 'four',
},
{
one: 'two',
two: 'three',
},
{
one: 'four',
two: 'five',
},
],
});
});
it('will return the memoized function that will use the custom isEqual method', () => {
let callCount = 0;
const fn = (one: any, two: any) => {
callCount++;
return {
one,
two,
};
};
const memoized = memoize(fn, { isEqual: deepEqual });
expect(memoized.options.isEqual).toBe(deepEqual);
expect(
memoized(
{ deep: { value: 'value' } },
{ other: { deep: { value: 'value' } } },
),
).toEqual({
one: { deep: { value: 'value' } },
two: { other: { deep: { value: 'value' } } },
});
expect(
memoized(
{ deep: { value: 'value' } },
{ other: { deep: { value: 'value' } } },
),
).toEqual({
one: { deep: { value: 'value' } },
two: { other: { deep: { value: 'value' } } },
});
expect(callCount).toEqual(1);
expect(memoized.cache).toEqual({
keys: [
[{ deep: { value: 'value' } }, { other: { deep: { value: 'value' } } }],
],
size: 1,
values: [
{
one: { deep: { value: 'value' } },
two: { other: { deep: { value: 'value' } } },
},
],
});
});
it('will return the memoized function that will use the transformKey method', () => {
let callCount = 0;
const fn = (one: any, two: any) => {
callCount++;
return {
one,
two,
};
};
const transformKey = function (args: any[]) {
return [JSON.stringify(args)];
};
const memoized = memoize(fn, {
transformKey,
});
expect(memoized.options.transformKey).toBe(transformKey);
const fnArg1 = () => {};
const fnArg2 = () => {};
const fnArg3 = () => {};
expect(memoized({ one: 'one' }, fnArg1)).toEqual({
one: { one: 'one' },
two: fnArg1,
});
expect(memoized({ one: 'one' }, fnArg2)).toEqual({
one: { one: 'one' },
two: fnArg1,
});
expect(memoized({ one: 'one' }, fnArg3)).toEqual({
one: { one: 'one' },
two: fnArg1,
});
expect(callCount).toEqual(1);
expect(memoized.cache).toEqual({
keys: [['[{"one":"one"},null]']],
size: 1,
values: [
{
one: { one: 'one' },
two: fnArg1,
},
],
});
});
it('will return the memoized function that will use the transformKey method with a custom isEqual', () => {
let callCount = 0;
const fn = (one: any, two: any) => {
callCount++;
return {
one,
two,
};
};
const isEqual = function (key1: any, key2: any) {
return key1.args === key2.args;
};
const transformKey = function (args: any[]) {
return [
{
args: JSON.stringify(args),
},
];
};
const memoized = memoize(fn, {
isEqual,
transformKey,
});
expect(memoized.options.isEqual).toBe(isEqual);
expect(memoized.options.transformKey).toBe(transformKey);
const fnArg1 = () => {};
const fnArg2 = () => {};
const fnArg3 = () => {};
expect(memoized({ one: 'one' }, fnArg1)).toEqual({
one: { one: 'one' },
two: fnArg1,
});
expect(memoized({ one: 'one' }, fnArg2)).toEqual({
one: { one: 'one' },
two: fnArg1,
});
expect(memoized({ one: 'one' }, fnArg3)).toEqual({
one: { one: 'one' },
two: fnArg1,
});
expect(callCount).toEqual(1);
expect(memoized.cache).toEqual({
keys: [
[
{
args: '[{"one":"one"},null]',
},
],
],
size: 1,
values: [
{
one: { one: 'one' },
two: fnArg1,
},
],
});
});
it('will return a memoized method that will auto-remove the key from cache if isPromise is true and the promise is rejected', async () => {
const timeout = 200;
const error = new Error('boom');
const fn = async () => {
await new Promise((resolve: Function) => {
setTimeout(resolve, timeout);
});
throw error;
};
const isPromise = true;
const memoized = memoize(fn, { isPromise });
expect(memoized.options.isPromise).toEqual(isPromise);
const spy = jest.fn();
memoized('foo').catch(spy);
expect(memoized.cacheSnapshot.keys.length).toEqual(1);
expect(memoized.cacheSnapshot.values.length).toEqual(1);
await new Promise((resolve: Function) => {
setTimeout(resolve, timeout + 50);
});
expect(memoized.cacheSnapshot).toEqual({
keys: [],
size: 0,
values: [],
});
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith(error);
});
it('will fire the onCacheChange method passed with the cache when it is added to', () => {
const fn = (one: any, two: any) => ({
one,
two,
});
const onCacheChange = jest.fn();
const memoized = memoize(fn, { onCacheChange });
expect(memoized.options.onCacheChange).toBe(onCacheChange);
memoized('foo');
expect(onCacheChange).toHaveBeenCalledTimes(1);
expect(onCacheChange).toHaveBeenCalledWith(
memoized.cache,
{
onCacheChange,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
maxSize: 1,
transformKey: undefined,
},
memoized,
);
});
it('will fire the onCacheChange method passed with the cache when it is updated', () => {
const fn = (one: any, two: any) => ({
one,
two,
});
const onCacheChange = jest.fn();
const maxSize = 2;
const memoized = memoize(fn, {
maxSize,
onCacheChange,
});
expect(memoized.options.onCacheChange).toBe(onCacheChange);
memoized('foo', 'bar');
expect(onCacheChange).toHaveBeenCalledTimes(1);
expect(onCacheChange).toHaveBeenCalledWith(
{
keys: [['foo', 'bar']],
size: 1,
values: [
{
one: 'foo',
two: 'bar',
},
],
},
{
maxSize,
onCacheChange,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheChange.mockReset();
memoized('bar', 'foo');
expect(onCacheChange).toHaveBeenCalledTimes(1);
expect(onCacheChange).toHaveBeenCalledWith(
{
keys: [['bar', 'foo'], ['foo', 'bar']],
size: 2,
values: [
{
one: 'bar',
two: 'foo',
},
{
one: 'foo',
two: 'bar',
},
],
},
{
maxSize,
onCacheChange,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheChange.mockReset();
memoized('bar', 'foo');
expect(onCacheChange).toHaveBeenCalledTimes(0);
onCacheChange.mockReset();
memoized('foo', 'bar');
expect(onCacheChange).toHaveBeenCalledTimes(1);
expect(onCacheChange).toHaveBeenCalledWith(
{
keys: [['foo', 'bar'], ['bar', 'foo']],
size: 2,
values: [
{
one: 'foo',
two: 'bar',
},
{
one: 'bar',
two: 'foo',
},
],
},
{
maxSize,
onCacheChange,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheChange.mockReset();
memoized('foo', 'bar');
expect(onCacheChange).toHaveBeenCalledTimes(0);
});
it('will not fire the onCacheHit method passed with the cache when it is added to', () => {
const fn = (one: any, two: any) => ({
one,
two,
});
const onCacheHit = jest.fn();
const memoized = memoize(fn, { onCacheHit });
expect(memoized.options.onCacheHit).toBe(onCacheHit);
memoized('foo');
expect(onCacheHit).toHaveBeenCalledTimes(0);
});
it('will fire the onCacheHit method passed with the cache when it is updated', () => {
const fn = (one: any, two: any) => ({
one,
two,
});
const onCacheHit = jest.fn();
const maxSize = 2;
const memoized = memoize(fn, {
maxSize,
onCacheHit,
});
expect(memoized.options.onCacheHit).toBe(onCacheHit);
memoized('foo', 'bar');
expect(onCacheHit).toHaveBeenCalledTimes(0);
memoized('bar', 'foo');
expect(onCacheHit).toHaveBeenCalledTimes(0);
memoized('bar', 'foo');
expect(onCacheHit).toHaveBeenCalledTimes(1);
expect(onCacheHit).toHaveBeenCalledWith(
{
keys: [['bar', 'foo'], ['foo', 'bar']],
size: 2,
values: [
{
one: 'bar',
two: 'foo',
},
{
one: 'foo',
two: 'bar',
},
],
},
{
maxSize,
onCacheHit,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheHit.mockReset();
memoized('foo', 'bar');
expect(onCacheHit).toHaveBeenCalledTimes(1);
expect(onCacheHit).toHaveBeenCalledWith(
{
keys: [['foo', 'bar'], ['bar', 'foo']],
size: 2,
values: [
{
one: 'foo',
two: 'bar',
},
{
one: 'bar',
two: 'foo',
},
],
},
{
maxSize,
onCacheHit,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheHit.mockReset();
memoized('foo', 'bar');
expect(onCacheHit).toHaveBeenCalledTimes(1);
expect(onCacheHit).toHaveBeenCalledWith(
{
keys: [['foo', 'bar'], ['bar', 'foo']],
size: 2,
values: [
{
one: 'foo',
two: 'bar',
},
{
one: 'bar',
two: 'foo',
},
],
},
{
maxSize,
onCacheHit,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
});
it('will fire the onCacheAdd method passed with the cache when it is added but not when hit', () => {
const fn = (one: any, two: any) => ({
one,
two,
});
const onCacheAdd = jest.fn();
const memoized = memoize(fn, { onCacheAdd });
expect(memoized.options.onCacheAdd).toBe(onCacheAdd);
memoized('foo');
expect(onCacheAdd).toHaveBeenCalledTimes(1);
memoized('foo');
expect(onCacheAdd).toHaveBeenCalledTimes(1);
});
it('will fire the onCacheAdd method passed with the cache when it is added but never again', () => {
const fn = (one: any, two: any) => ({
one,
two,
});
const onCacheAdd = jest.fn();
const maxSize = 2;
const memoized = memoize(fn, {
maxSize,
onCacheAdd,
});
expect(memoized.options.onCacheAdd).toBe(onCacheAdd);
memoized('foo', 'bar');
expect(onCacheAdd).toHaveBeenCalledTimes(1);
expect(onCacheAdd).toHaveBeenCalledWith(
{
keys: [['foo', 'bar']],
size: 1,
values: [
{
one: 'foo',
two: 'bar',
},
],
},
{
maxSize,
onCacheAdd,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheAdd.mockReset();
memoized('bar', 'foo');
expect(onCacheAdd).toHaveBeenCalledTimes(1);
expect(onCacheAdd).toHaveBeenCalledWith(
{
keys: [['bar', 'foo'], ['foo', 'bar']],
size: 2,
values: [
{
one: 'bar',
two: 'foo',
},
{
one: 'foo',
two: 'bar',
},
],
},
{
maxSize,
onCacheAdd,
isEqual: isSameValueZero,
isMatchingKey: undefined,
isPromise: false,
transformKey: undefined,
},
memoized,
);
onCacheAdd.mockReset();
memoized('bar', 'foo');
expect(onCacheAdd).toHaveBeenCalledTimes(0);
onCacheAdd.mockReset();
memoized('foo', 'bar');
expect(onCacheAdd).toHaveBeenCalledTimes(0);
memoized('foo', 'bar');
expect(onCacheAdd).toHaveBeenCalledTimes(0);
});
test('if recursive calls to self will be respected at runtime', () => {
const calc = memoize(
(object: { [key: string]: any }, metadata: { c: number }) =>
Object.keys(object).reduce((totals: { [key: string]: number }, key) => {
if (Array.isArray(object[key])) {
totals[key] = object[key].map(
(subObject: { [key: string]: number }) =>
calc(subObject, metadata),
);
} else {
totals[key] = object[key].a + object[key].b + metadata.c;
}
return totals;
}, {}),
{
maxSize: 10,
},
);
const data = {
fifth: {
a: 4,
b: 5,
},
first: [
{
second: {
a: 1,
b: 2,
},
},
{
third: [
{
fourth: {
a: 2,
b: 3,
},
},
],
},
],
};
const metadata = {
c: 6,
};
const result1 = calc(data, metadata);
const result2 = calc(data, metadata);
expect(result1).toEqual(result2);
});
});
import {
createAreKeysEqual,
createGetKeyIndex,
createUpdateAsyncCache,
isSameValueZero,
mergeOptions,
orderByLru,
} from '../src/utils';
describe('areKeysEqual', () => {
it('will return false when the length of the keys are different', () => {
const isEqual = (o1: any, o2: any) => o1 === o2;
const areKeysEqual = createAreKeysEqual(isEqual);
const keys1: any[] = [];
const keys2 = ['key'];
expect(areKeysEqual(keys1, keys2)).toEqual(false);
});
it('will return false when the keys have different values', () => {
const isEqual = (o1: any, o2: any) => o1 === o2;
const areKeysEqual = createAreKeysEqual(isEqual);
const keys1 = ['key'];
const keys2 = ['other key'];
expect(areKeysEqual(keys1, keys2)).toEqual(false);
});
it('will return true when the keys have equal values', () => {
const isEqual = (o1: any, o2: any) => o1 === o2;
const areKeysEqual = createAreKeysEqual(isEqual);
const keys1 = ['key'];
const keys2 = ['key'];
expect(areKeysEqual(keys1, keys2)).toEqual(true);
});
});
describe('getKeyIndex', () => {
it('will return the index of the match found', () => {
const isEqual = (o1: any, o2: any) => o1 === o2;
const getKeyIndex = createGetKeyIndex({ isEqual, maxSize: 2 });
const allKeys = [['key'], ['other key']];
const keyToMatch = ['other key'];
const result = getKeyIndex(allKeys, keyToMatch);
expect(result).toEqual(1);
});
it('will return -1 of no match found', () => {
const isEqual = (o1: any, o2: any) => o1 === o2;
const getKeyIndex = createGetKeyIndex({ isEqual });
const allKeys = [['key'], ['other key']];
const keyToMatch = ['not present key'];
const result = getKeyIndex(allKeys, keyToMatch);
expect(result).toEqual(-1);
});
it('will use the isMatchingKey method if passed', () => {
const isEqual = (o1: any, o2: any) => o1 === o2;
const isMatchingKey = (o1: any, o2: any) => {
const existingKey = o1[0];
const key = o2[0];
return (
existingKey.hasOwnProperty('foo') &&
key.hasOwnProperty('foo') &&
(existingKey.bar === 'bar' || key.bar === 'baz')
);
};
const getKeyIndex = createGetKeyIndex({ isEqual, isMatchingKey });
const allKeys = [
[
{
bar: 'bar',
foo: 'foo',
},
],
];
const keyToMatch = [
{
bar: 'baz',
foo: 'bar',
},
];
const result = getKeyIndex(allKeys, keyToMatch);
expect(result).toEqual(0);
});
});
describe('isSameValueZero', () => {
it('will return true when the objects are equal', () => {
const object1 = {};
const object2 = object1;
expect(isSameValueZero(object1, object2)).toEqual(true);
});
it('will return true when the objects are NaN', () => {
const object1 = NaN;
const object2 = NaN;
expect(isSameValueZero(object1, object2)).toEqual(true);
});
it('will return false when the objects are different', () => {
const object1 = {};
const object2 = {};
expect(isSameValueZero(object1, object2)).toEqual(false);
});
});
describe('mergeOptions', () => {
it('will merge the extra and provided options into a new object', () => {
const extraOptions = {
extra: 'options',
};
const providedOptions = {
provided: 'options',
};
const result = mergeOptions(extraOptions, providedOptions);
expect(result).not.toBe(extraOptions);
expect(result).not.toBe(providedOptions);
expect(result).toEqual({ ...extraOptions, ...providedOptions });
});
});
describe('orderByLru', () => {
it('will do nothing if the itemIndex is 0', () => {
const cache = {
keys: [['first'], ['second'], ['third']],
size: 3,
values: ['first', 'second', 'third'],
};
const itemIndex = 0;
const key = cache.keys[itemIndex];
const value = cache.values[itemIndex];
const maxSize = 3;
orderByLru(cache, key, value, itemIndex, maxSize);
expect(cache).toEqual({
...cache,
keys: [['first'], ['second'], ['third']],
values: ['first', 'second', 'third'],
});
});
it('will place the itemIndex first in order when non-zero', () => {
const cache = {
keys: [['first'], ['second'], ['third']],
size: 3,
values: ['first', 'second', 'third'],
};
const itemIndex = 1;
const key = cache.keys[itemIndex];
const value = cache.values[itemIndex];
const maxSize = 3;
orderByLru(cache, key, value, itemIndex, maxSize);
expect(cache).toEqual({
...cache,
keys: [['second'], ['first'], ['third']],
values: ['second', 'first', 'third'],
});
});
it('will add the new item to the array when the itemIndex is the array length', () => {
const cache = {
keys: [['first'], ['second'], ['third']],
size: 3,
values: ['first', 'second', 'third'],
};
const itemIndex = cache.keys.length;
const key = ['key'];
const value = 'new';
const maxSize = 4;
orderByLru(cache, key, value, itemIndex, maxSize);
expect(cache).toEqual({
...cache,
keys: [key, ['first'], ['second'], ['third']],
values: [value, 'first', 'second', 'third'],
});
});
});
describe('updateAsyncCache', () => {
it('will fire cache callbacks if resolved', async () => {
const timeout = 200;
const fn = async () => {
await new Promise((resolve: Function) => {
setTimeout(resolve, timeout);
});
return 'resolved';
};
const key = ['foo'];
const memoized = () => {};
const value = fn();
const cache = {
keys: [key],
size: 1,
values: [value],
};
const options = {
isEqual: isSameValueZero,
onCacheChange: jest.fn(),
onCacheHit: jest.fn(),
};
createUpdateAsyncCache(options)(cache, memoized);
// this is just to prevent the unhandled rejection noise
cache.values[0].catch(() => {});
expect(cache.keys.length).toEqual(1);
expect(cache.values.length).toEqual(1);
expect(cache.values[0]).toEqual(value);
await new Promise((resolve: Function) => {
setTimeout(resolve, timeout + 50);
});
expect(cache.keys.length).toEqual(1);
expect(cache.values.length).toEqual(1);
expect(cache.values[0]).toEqual(value);
expect(options.onCacheHit).toHaveBeenCalledTimes(1);
expect(options.onCacheHit).toHaveBeenCalledWith(cache, options, memoized);
expect(options.onCacheChange).toHaveBeenCalledTimes(1);
expect(options.onCacheChange).toHaveBeenCalledWith(
cache,
options,
memoized,
);
});
it('will remove the key from cache when the promise is rejected', async () => {
const timeout = 200;
const fn = async () => {
await new Promise((resolve: Function, reject: Function) => {
setTimeout(() => reject(new Error('boom')), timeout);
});
};
const key = ['foo'];
const value = fn();
const cache = {
get size() {
return cache.keys.length;
},
keys: [key],
values: [value],
};
const options = {
isEqual: isSameValueZero,
onCacheChange: jest.fn(),
onCacheHit: jest.fn(),
};
const memoized = () => {};
createUpdateAsyncCache(options)(cache, memoized);
const catcher = jest.fn();
cache.values[0].catch(catcher);
expect(cache.keys.length).toEqual(1);
expect(cache.values.length).toEqual(1);
expect(cache.values[0]).toEqual(value);
await new Promise((resolve: Function) => {
setTimeout(resolve, timeout + 50);
});
expect(catcher).toHaveBeenCalledTimes(1);
expect(cache).toEqual({
keys: [],
size: 0,
values: [],
});
expect(options.onCacheHit).toHaveBeenCalledTimes(0);
expect(options.onCacheChange).toHaveBeenCalledTimes(0);
});
it('will not remove the key from cache when the promise is rejected but the key no longer exists', async () => {
const timeout = 200;
const fn = async () => {
await new Promise((resolve: Function, reject: Function) => {
setTimeout(() => reject(new Error('boom')), timeout);
});
};
const key = ['foo'];
const value = fn();
const cache = {
get size() {
return cache.keys.length;
},
keys: [key],
values: [value],
};
const options = {
isEqual: isSameValueZero,
onCacheChange: jest.fn(),
onCacheHit: jest.fn(),
};
const memoized = () => {};
createUpdateAsyncCache(options)(cache, memoized);
const newValue = cache.values[0];
const catcher = jest.fn();
newValue.catch(catcher);
expect(cache.keys.length).toEqual(1);
expect(cache.values.length).toEqual(1);
expect(cache.values[0]).toEqual(value);
cache.keys = [['bar']];
// @ts-ignore
cache.values = [Promise.resolve('baz')];
await new Promise((resolve: Function) => {
setTimeout(resolve, timeout + 50);
});
expect(catcher).toHaveBeenCalledTimes(1);
expect(options.onCacheHit).toHaveBeenCalledTimes(0);
expect(options.onCacheChange).toHaveBeenCalledTimes(0);
});
});
/*
* memoize.js
* by @philogb and @addyosmani
* with further optimizations by @mathias
* and @DmitryBaranovsk
* perf tests: http://bit.ly/q3zpG3
* Released under an MIT license.
*/
module.exports = function memoize(fn) {
return function(...args) {
let index = args.length,
hash = '',
currentArg = null;
currentArg = null;
while (index--) {
currentArg = args[index];
hash += currentArg === Object(currentArg) ? JSON.stringify(currentArg) : currentArg;
fn.memoize || (fn.memoize = {});
}
return hash in fn.memoize ? fn.memoize[hash] : (fn.memoize[hash] = fn.apply(this, args));
};
};
"Name","Overall (average)","Single (average)","Multiple (average)","single primitive","single array","single object","multiple primitive","multiple array","multiple object"
"micro-memoize","43,702,165","51,789,026","35,615,304","57,637,984","48,611,399","49,117,695","40,849,760","29,961,958","36,034,196"
"fast-memoize","39,957,140","78,949,201","965,078","233,789,537","1,585,949","1,472,119","1,158,875","946,388","789,972"
"lodash","14,320,798","27,508,254","1,133,342","32,669,251","24,892,558","24,962,953","1,402,261","1,128,886","868,879"
"memoizee","9,861,157","11,784,109","7,938,205","16,177,336","9,568,376","9,606,616","9,482,240","7,186,371","7,146,006"
"ramda","8,678,762","16,102,353","1,255,172","42,919,616","2,907,167","2,480,276","1,550,152","1,222,321","993,044"
"lru-memoize","7,034,405","7,537,900","6,530,910","8,516,137","7,057,588","7,039,977","6,584,528","6,474,194","6,534,009"
"mem","6,718,548","11,530,426","1,906,669","30,316,899","2,240,383","2,033,998","2,705,018","1,849,057","1,165,934"
"underscore","5,014,181","8,820,887","1,207,475","21,489,781","2,673,530","2,299,352","1,479,025","1,183,156","960,246"
"addy-osmani","4,968,346","7,410,673","2,526,020","17,391,341","2,599,855","2,240,823","5,104,651","1,423,365","1,050,046"
"memoizerific","4,665,606","5,187,389","4,143,824","5,466,050","5,057,754","5,038,363","4,013,486","4,198,578","4,219,410"
const _ = require('lodash');
// const fs = require("fs");
const React = require('react');
const { createSuite } = require('benchee');
const Table = require('cli-table2');
const resolveArguments = function() {
return arguments.length > 1
? JSON.stringify(arguments)
: typeof arguments[0] === 'object'
? JSON.stringify(arguments[0])
: arguments[0];
};
const getResults = results => {
const table = new Table({
head: ['Name', 'Ops / sec'],
});
results.forEach(({ name, stats }) => {
table.push([name, stats.ops.toLocaleString()]);
});
return table.toString();
};
const addyOsmani = require('./addy-osmani');
const fastMemoize = require('fast-memoize');
const lodash = _.memoize;
const lruMemoize = require('lru-memoize').default;
const mem = require('mem');
const memoizee = require('memoizee');
const memoizerific = require('memoizerific');
const memoize =
require('../dist/micro-memoize.cjs').default ||
require('../dist/micro-memoize.cjs');
const ramda = require('ramda').memoizeWith(resolveArguments);
const underscore = require('underscore').memoize;
const deepEqualFastEquals = require('fast-equals').deepEqual;
const deepEqualLodash = _.isEqual;
/************* tests *************/
const fibonacciSinglePrimitive = number =>
number < 2
? number
: fibonacciSinglePrimitive(number - 1) +
fibonacciSinglePrimitive(number - 2);
const fibonacciSingleArray = array =>
array[0] < 2
? array[0]
: fibonacciSingleArray([array[0] - 1]) +
fibonacciSingleArray([array[0] - 2]);
const fibonacciSingleObject = object =>
object.number < 2
? object.number
: fibonacciSingleObject({ number: object.number - 1 }) +
fibonacciSingleObject({ number: object.number - 2 });
const fibonacciMultiplePrimitive = (number, isComplete) => {
if (isComplete) {
return number;
}
const firstValue = number - 1;
const secondValue = number - 2;
return (
fibonacciMultiplePrimitive(firstValue, firstValue < 2) +
fibonacciMultiplePrimitive(secondValue, secondValue < 2)
);
};
const fibonacciMultipleArray = (array, check) => {
if (check[0]) {
return array[0];
}
const firstValue = array[0] - 1;
const secondValue = array[0] - 2;
return (
fibonacciMultipleArray([firstValue], [firstValue < 2]) +
fibonacciMultipleArray([secondValue], [secondValue < 2])
);
};
const fibonacciMultipleObject = (object, check) => {
if (check.isComplete) {
return object.number;
}
const firstValue = object.number - 1;
const secondValue = object.number - 2;
return (
fibonacciMultipleObject(
{ number: firstValue },
{ isComplete: firstValue < 2 },
) +
fibonacciMultipleObject(
{ number: secondValue },
{ isComplete: secondValue < 2 },
)
);
};
/************* benchmarks *************/
const singularPrimitive = {
'addy osmani': addyOsmani(fibonacciSinglePrimitive),
'fast-memoize': fastMemoize(fibonacciSinglePrimitive),
lodash: lodash(fibonacciSinglePrimitive),
'lru-memoize': lruMemoize(1)(fibonacciSinglePrimitive),
mem: mem(fibonacciSinglePrimitive),
memoizee: memoizee(fibonacciSinglePrimitive),
memoizerific: memoizerific(1)(fibonacciSinglePrimitive),
'micro-memoize': memoize(fibonacciSinglePrimitive),
ramda: ramda(fibonacciSinglePrimitive),
underscore: underscore(fibonacciSinglePrimitive),
};
const singularArray = {
'addy osmani': addyOsmani(fibonacciSingleArray),
'fast-memoize': fastMemoize(fibonacciSingleArray),
lodash: lodash(fibonacciSingleArray),
'lru-memoize': lruMemoize(1)(fibonacciSingleArray),
mem: mem(fibonacciSingleArray),
memoizee: memoizee(fibonacciSingleArray),
memoizerific: memoizerific(1)(fibonacciSingleArray),
'micro-memoize': memoize(fibonacciSingleArray),
ramda: ramda(fibonacciSingleArray),
underscore: underscore(fibonacciSingleArray, resolveArguments),
};
const singularObject = {
'addy osmani': addyOsmani(fibonacciSingleObject),
'fast-memoize': fastMemoize(fibonacciSingleObject),
lodash: lodash(fibonacciSingleObject),
'lru-memoize': lruMemoize(1)(fibonacciSingleObject),
mem: mem(fibonacciSingleObject),
memoizee: memoizee(fibonacciSingleObject),
memoizerific: memoizerific(1)(fibonacciSingleObject),
'micro-memoize': memoize(fibonacciSingleObject),
ramda: ramda(fibonacciSingleObject),
underscore: underscore(fibonacciSingleObject, resolveArguments),
};
const multiplePrimitive = {
'addy osmani': addyOsmani(fibonacciMultiplePrimitive),
'fast-memoize': fastMemoize(fibonacciMultiplePrimitive),
lodash: lodash(fibonacciMultiplePrimitive, resolveArguments),
'lru-memoize': lruMemoize(1)(fibonacciMultiplePrimitive),
mem: mem(fibonacciMultiplePrimitive),
memoizee: memoizee(fibonacciMultiplePrimitive),
memoizerific: memoizerific(1)(fibonacciMultiplePrimitive),
'micro-memoize': memoize(fibonacciMultiplePrimitive),
ramda: ramda(fibonacciMultiplePrimitive),
underscore: underscore(fibonacciMultiplePrimitive, resolveArguments),
};
const multipleArray = {
'addy osmani': addyOsmani(fibonacciMultipleArray),
'fast-memoize': fastMemoize(fibonacciMultipleArray),
lodash: lodash(fibonacciMultipleArray, resolveArguments),
'lru-memoize': lruMemoize(1)(fibonacciMultipleArray),
mem: mem(fibonacciMultipleArray),
memoizee: memoizee(fibonacciMultipleArray),
memoizerific: memoizerific(1)(fibonacciMultipleArray),
'micro-memoize': memoize(fibonacciMultipleArray),
ramda: ramda(fibonacciMultipleArray),
underscore: underscore(fibonacciMultipleArray, resolveArguments),
};
const multipleObject = {
'addy osmani': addyOsmani(fibonacciMultipleObject),
'fast-memoize': fastMemoize(fibonacciMultipleObject),
lodash: lodash(fibonacciMultipleObject, resolveArguments),
'lru-memoize': lruMemoize(1)(fibonacciMultipleObject),
mem: mem(fibonacciMultipleObject),
memoizee: memoizee(fibonacciMultipleObject),
memoizerific: memoizerific(1)(fibonacciMultipleObject),
'micro-memoize': memoize(fibonacciMultipleObject),
ramda: ramda(fibonacciMultipleObject),
underscore: underscore(fibonacciMultipleObject, resolveArguments),
};
const number = 25;
const arrayNumber = [number];
const objectNumber = { number };
const isComplete = false;
const arrayIsComplete = [isComplete];
const objectIsComplete = { isComplete };
const suite = createSuite({
onComplete(results) {
const combinedResults = Object.keys(results)
.reduce((combined, group) => {
const groupResults = results[group];
return groupResults.map(({ name, stats }) => {
const existingRowIndex = combined.findIndex(
({ name: rowName }) => name === rowName,
);
return ~existingRowIndex
? {
...combined[existingRowIndex],
stats: {
elapsed: (combined[existingRowIndex].stats.elapsed +=
stats.elapsed),
iterations: (combined[existingRowIndex].stats.iterations +=
stats.iterations),
},
}
: {
name,
stats: {
elapsed: stats.elapsed,
iterations: stats.iterations,
},
};
});
}, [])
.map(({ name, stats }) => ({
name,
stats: {
...stats,
ops: stats.iterations / stats.elapsed,
},
}))
.sort((a, b) => {
if (a.stats.ops > b.stats.ops) {
return -1;
}
if (a.stats.ops < b.stats.ops) {
return 1;
}
return 0;
});
console.log('');
console.log('Benchmark results complete, overall averages:');
console.log('');
console.log(getResults(combinedResults));
console.log('');
},
onGroupComplete({ group, results }) {
console.log('');
console.log(`...finished group ${group}.`);
console.log('');
console.log(getResults(results));
console.log('');
},
onGroupStart(group) {
console.log('');
console.log(`Starting benchmarks for group ${group}...`);
console.log('');
},
minTime: 3000,
onResult({ name, stats }) {
console.log(
`Benchmark completed for ${name}: ${stats.ops.toLocaleString()} ops/sec`,
);
},
});
Object.keys(singularPrimitive).forEach(name => {
const fn = singularPrimitive[name];
suite.add(name, 'singular primitive', () => {
fn(number);
});
});
Object.keys(singularArray).forEach(name => {
const fn = singularArray[name];
suite.add(name, 'singular array', () => {
fn(arrayNumber);
});
});
Object.keys(singularObject).forEach(name => {
const fn = singularObject[name];
suite.add(name, 'singular object', () => {
fn(objectNumber);
});
});
Object.keys(multiplePrimitive).forEach(name => {
const fn = multiplePrimitive[name];
suite.add(name, 'multiple primitive', () => {
fn(number, isComplete);
});
});
Object.keys(multipleArray).forEach(name => {
const fn = multipleArray[name];
suite.add(name, 'multiple array', () => {
fn(arrayNumber, arrayIsComplete);
});
});
Object.keys(multipleObject).forEach(name => {
const fn = multipleObject[name];
suite.add(name, 'multiple object', () => {
fn(objectNumber, objectIsComplete);
});
});
suite.run();
'use strict';
const memoize = require('../lib').default;
const fibonacciSinglePrimitive = (number) => {
return number < 2 ? number : fibonacciSinglePrimitive(number - 1) + fibonacciSinglePrimitive(number - 2);
};
const fibonacciSingleArray = (array) => {
return array[0] < 2 ? array[0] : fibonacciSingleArray([array[0] - 1]) + fibonacciSingleArray([array[0] - 2]);
};
const fibonacciSingleObject = (object) => {
return object.number < 2
? object.number
: fibonacciSingleObject({number: object.number - 1}) + fibonacciSingleObject({number: object.number - 2});
};
const fibonacciMultiplePrimitive = (number, isComplete) => {
if (isComplete) {
return number;
}
const firstValue = number - 1;
const secondValue = number - 2;
return (
fibonacciMultiplePrimitive(firstValue, firstValue < 2) + fibonacciMultiplePrimitive(secondValue, secondValue < 2)
);
};
const fibonacciMultipleArray = (array, check) => {
if (check[0]) {
return array[0];
}
const firstValue = array[0] - 1;
const secondValue = array[0] - 2;
return (
fibonacciMultipleArray([firstValue], [firstValue < 2]) + fibonacciMultipleArray([secondValue], [secondValue < 2])
);
};
const fibonacciMultipleObject = (object, check) => {
if (check.isComplete) {
return object.number;
}
const firstValue = object.number - 1;
const secondValue = object.number - 2;
return (
fibonacciMultipleObject({number: firstValue}, {isComplete: firstValue < 2}) +
fibonacciMultipleObject({number: secondValue}, {isComplete: secondValue < 2})
);
};
const number = 35;
const array = [number];
const object = {number};
const isCompleteBoolean = false;
const isCompleteArray = [false];
const isCompleteObject = {isComplete: false};
fibonacciSinglePrimitive(number);
fibonacciSinglePrimitive(number);
fibonacciSinglePrimitive(number);
fibonacciSingleArray(array);
fibonacciSingleArray(array);
fibonacciSingleArray(array);
fibonacciSingleObject(object);
fibonacciSingleObject(object);
fibonacciSingleObject(object);
fibonacciMultiplePrimitive(number, isCompleteBoolean);
fibonacciMultiplePrimitive(number, isCompleteBoolean);
fibonacciMultiplePrimitive(number, isCompleteBoolean);
fibonacciMultipleArray(array, isCompleteArray);
fibonacciMultipleArray(array, isCompleteArray);
fibonacciMultipleArray(array, isCompleteArray);
fibonacciMultipleObject(object, isCompleteObject);
fibonacciMultipleObject(object, isCompleteObject);
fibonacciMultipleObject(object, isCompleteObject);
'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
function createAreKeysEqual(isEqual) {
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param key1 the keys array to test against
* @param key2 the keys array to test
* @returns are the keys shallowly equal
*/
return function areKeysEqual(key1, key2) {
var length = key1.length;
if (key2.length !== length) {
return false;
}
if (length === 1) {
return isEqual(key1[0], key2[0]);
}
var index = 0;
while (index < length) {
if (!isEqual(key1[index], key2[index])) {
return false;
}
index++;
}
return true;
};
}
function createGetKeyIndex(options) {
var maxSize = options.maxSize;
var areKeysEqual = typeof options.isMatchingKey === 'function'
? options.isMatchingKey
: createAreKeysEqual(options.isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param allKeys the list of all available keys
* @param keyToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function getKeyIndex(allKeys, keyToMatch) {
if (areKeysEqual(allKeys[0], keyToMatch)) {
return 0;
}
if (maxSize > 1) {
var length = maxSize > allKeys.length ? allKeys.length : maxSize;
var index = 1;
while (index < length) {
if (areKeysEqual(allKeys[index], keyToMatch)) {
return index;
}
index++;
}
}
return -1;
};
}
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero equality
*
* @param object1 the first object to compare
* @param object2 the second object to compare
* @returns are the two objects equal
*/
function isSameValueZero(object1, object2) {
return object1 === object2 || (object1 !== object1 && object2 !== object2);
}
/**
* @function mergeOptions
*
* @description
* merge the options into the target
*
* @param extraOptions the extra options passed
* @param providedOptions the defaulted options provided
* @returns the merged options
*/
function mergeOptions(extraOptions, providedOptions) {
var target = {};
for (var key in extraOptions) {
target[key] = extraOptions[key];
}
for (var key in providedOptions) {
target[key] = providedOptions[key];
}
return target;
}
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param keys the keys to order
* @param newKey the new key to move to the front
* @param values the values to order
* @param newValue the new value to move to the front
* @param startingIndex the index of the item to move to the front
*/
function orderByLru(cache, newKey, newValue, startingIndex, maxSize) {
var index = startingIndex;
while (index--) {
cache.keys[index + 1] = cache.keys[index];
cache.values[index + 1] = cache.values[index];
}
cache.keys[0] = newKey;
cache.values[0] = newValue;
if (startingIndex >= maxSize) {
cache.keys.length = maxSize;
cache.values.length = maxSize;
}
}
function createUpdateAsyncCache(options) {
var getKeyIndex = createGetKeyIndex(options);
var onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit;
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
/**
* @function updateAsyncCache
*
* @description
* update the promise method to auto-remove from cache if rejected, and
* if resolved then fire cache hit / changed
*
* @param cache the memoized function's cache
* @param memoized the memoized function
*/
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0]
.then(function (value) {
shouldUpdateOnHit && onCacheHit(cache, options, memoized);
shouldUpdateOnChange && onCacheChange(cache, options, memoized);
return value;
})
.catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
}
var slice = Array.prototype.slice;
function createMemoizedFunction(fn, options) {
if (options === void 0) { options = {}; }
// @ts-ignore
if (fn.isMemoized) {
return fn;
}
var _a = options.isEqual, isEqual = _a === void 0 ? isSameValueZero : _a, isMatchingKey = options.isMatchingKey, _b = options.isPromise, isPromise = _b === void 0 ? false : _b, _c = options.maxSize, maxSize = _c === void 0 ? 1 : _c, onCacheAdd = options.onCacheAdd, onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit, transformKey = options.transformKey, extraOptions = __rest(options, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = mergeOptions(extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey,
});
var getKeyIndex = createGetKeyIndex(normalizedOptions);
var updateAsyncCache = createUpdateAsyncCache(normalizedOptions);
var keys = [];
var values = [];
var cache = {
keys: keys,
get size() {
return cache.keys.length;
},
values: values,
};
var canTransformKey = typeof transformKey === 'function';
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var shouldUpdateOnAdd = typeof onCacheAdd === 'function';
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
function memoized() {
var normalizedArgs = shouldCloneArguments
? slice.call(arguments, 0)
: arguments;
var key = canTransformKey
? transformKey(normalizedArgs)
: normalizedArgs;
var keyIndex = keys.length ? getKeyIndex(keys, key) : -1;
if (~keyIndex) {
shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);
shouldUpdateOnChange &&
onCacheChange(cache, normalizedOptions, memoized);
}
}
else {
var newValue = fn.apply(this, arguments);
var newKey = shouldCloneArguments
? key
: slice.call(normalizedArgs, 0);
orderByLru(cache, newKey, newValue, keys.length, maxSize);
isPromise && updateAsyncCache(cache, memoized);
shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);
shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
value: cache,
},
cacheSnapshot: {
configurable: true,
get: function () {
return {
keys: slice.call(cache.keys, 0),
size: cache.size,
values: slice.call(cache.values, 0),
};
},
},
isMemoized: {
configurable: true,
value: true,
},
options: {
configurable: true,
value: normalizedOptions,
},
});
return memoized;
}
module.exports = createMemoizedFunction;
//# sourceMappingURL=micro-memoize.cjs.js.map
{"version":3,"file":"micro-memoize.cjs.js","sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["export function createAreKeysEqual(\n isEqual: MicroMemoize.EqualityComparator,\n): MicroMemoize.MatchingKeyComparator {\n /**\n * @function areKeysEqual\n *\n * @description\n * are the keys shallowly equal to one another\n *\n * @param key1 the keys array to test against\n * @param key2 the keys array to test\n * @returns are the keys shallowly equal\n */\n return function areKeysEqual(key1: MicroMemoize.Key, key2: MicroMemoize.Key) {\n const length = key1.length;\n\n if (key2.length !== length) {\n return false;\n }\n\n if (length === 1) {\n return isEqual(key1[0], key2[0]);\n }\n\n let index = 0;\n\n while (index < length) {\n if (!isEqual(key1[index], key2[index])) {\n return false;\n }\n\n index++;\n }\n\n return true;\n };\n}\n\nexport function createGetKeyIndex(\n options: MicroMemoize.Options,\n): MicroMemoize.KeyIndexGetter {\n const { maxSize } = options;\n const areKeysEqual: MicroMemoize.MatchingKeyComparator =\n typeof options.isMatchingKey === 'function'\n ? options.isMatchingKey\n : createAreKeysEqual(options.isEqual);\n\n /**\n * @function getKeyIndex\n *\n * @description\n * get the index of the matching key\n *\n * @param allKeys the list of all available keys\n * @param keyToMatch the key to try to match\n *\n * @returns {number} the index of the matching key value, or -1\n */\n return function getKeyIndex(\n allKeys: MicroMemoize.Keys,\n keyToMatch: MicroMemoize.Key,\n ) {\n if (areKeysEqual(allKeys[0], keyToMatch)) {\n return 0;\n }\n\n if (maxSize > 1) {\n const length = maxSize > allKeys.length ? allKeys.length : maxSize;\n\n let index = 1;\n\n while (index < length) {\n if (areKeysEqual(allKeys[index], keyToMatch)) {\n return index;\n }\n\n index++;\n }\n }\n\n return -1;\n };\n}\n\n/**\n * @function isSameValueZero\n *\n * @description\n * are the objects equal based on SameValueZero equality\n *\n * @param object1 the first object to compare\n * @param object2 the second object to compare\n * @returns are the two objects equal\n */\nexport function isSameValueZero(object1: any, object2: any) {\n return object1 === object2 || (object1 !== object1 && object2 !== object2);\n}\n\n/**\n * @function mergeOptions\n *\n * @description\n * merge the options into the target\n *\n * @param extraOptions the extra options passed\n * @param providedOptions the defaulted options provided\n * @returns the merged options\n */\nexport function mergeOptions(\n extraOptions: PlainObject,\n providedOptions: PlainObject,\n) {\n const target: PlainObject = {};\n\n for (const key in extraOptions) {\n target[key] = extraOptions[key];\n }\n\n for (const key in providedOptions) {\n target[key] = providedOptions[key];\n }\n\n return target;\n}\n\n/**\n * @function orderByLru\n *\n * @description\n * order the array based on a Least-Recently-Used basis\n *\n * @param keys the keys to order\n * @param newKey the new key to move to the front\n * @param values the values to order\n * @param newValue the new value to move to the front\n * @param startingIndex the index of the item to move to the front\n */\nexport function orderByLru(\n cache: MicroMemoize.Cache,\n newKey: MicroMemoize.Key,\n newValue: any,\n startingIndex: number,\n maxSize: number,\n) {\n let index = startingIndex;\n\n while (index--) {\n cache.keys[index + 1] = cache.keys[index];\n cache.values[index + 1] = cache.values[index];\n }\n\n cache.keys[0] = newKey;\n cache.values[0] = newValue;\n\n if (startingIndex >= maxSize) {\n cache.keys.length = maxSize;\n cache.values.length = maxSize;\n }\n}\n\nexport function createUpdateAsyncCache(\n options: MicroMemoize.Options,\n): MicroMemoize.AsyncCacheUpdater {\n const getKeyIndex: MicroMemoize.KeyIndexGetter = createGetKeyIndex(options);\n\n const { onCacheChange, onCacheHit } = options;\n\n const shouldUpdateOnChange = typeof onCacheChange === 'function';\n const shouldUpdateOnHit = typeof onCacheHit === 'function';\n\n /**\n * @function updateAsyncCache\n *\n * @description\n * update the promise method to auto-remove from cache if rejected, and\n * if resolved then fire cache hit / changed\n *\n * @param cache the memoized function's cache\n * @param memoized the memoized function\n */\n return (cache: MicroMemoize.Cache, memoized: MicroMemoize.Memoized): void => {\n const key: any = cache.keys[0];\n\n cache.values[0] = cache.values[0]\n .then((value: any) => {\n shouldUpdateOnHit && onCacheHit(cache, options, memoized);\n shouldUpdateOnChange && onCacheChange(cache, options, memoized);\n\n return value;\n })\n .catch((error: Error) => {\n const keyIndex = getKeyIndex(cache.keys, key);\n\n if (~keyIndex) {\n cache.keys.splice(keyIndex, 1);\n cache.values.splice(keyIndex, 1);\n }\n\n throw error;\n });\n };\n}\n","// utils\nimport {\n createGetKeyIndex,\n createUpdateAsyncCache,\n isSameValueZero,\n mergeOptions,\n orderByLru,\n} from './utils';\n\nconst { slice } = Array.prototype;\n\nfunction createMemoizedFunction(\n fn: Function | MicroMemoize.Memoized,\n options: MicroMemoize.Options = {},\n): MicroMemoize.Memoized {\n // @ts-ignore\n if (fn.isMemoized) {\n return fn;\n }\n\n const {\n isEqual = isSameValueZero,\n isMatchingKey,\n isPromise = false,\n maxSize = 1,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n ...extraOptions\n }: MicroMemoize.Options = options;\n\n const normalizedOptions = mergeOptions(extraOptions, {\n isEqual,\n isMatchingKey,\n isPromise,\n maxSize,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n });\n\n const getKeyIndex: MicroMemoize.KeyIndexGetter = createGetKeyIndex(\n normalizedOptions,\n );\n const updateAsyncCache: MicroMemoize.AsyncCacheUpdater = createUpdateAsyncCache(\n normalizedOptions,\n );\n\n const keys: MicroMemoize.Keys = [];\n const values: MicroMemoize.Values = [];\n\n const cache: MicroMemoize.Cache = {\n keys,\n get size() {\n return cache.keys.length;\n },\n values,\n };\n\n const canTransformKey = typeof transformKey === 'function';\n\n const shouldCloneArguments = !!(transformKey || isMatchingKey);\n\n const shouldUpdateOnAdd = typeof onCacheAdd === 'function';\n const shouldUpdateOnChange = typeof onCacheChange === 'function';\n const shouldUpdateOnHit = typeof onCacheHit === 'function';\n\n function memoized(): any {\n const normalizedArgs: MicroMemoize.RawKey = shouldCloneArguments\n ? slice.call(arguments, 0)\n : arguments;\n const key: MicroMemoize.RawKey = canTransformKey\n ? transformKey(normalizedArgs)\n : normalizedArgs;\n const keyIndex: number = keys.length ? getKeyIndex(keys, key) : -1;\n\n if (~keyIndex) {\n shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);\n\n if (keyIndex) {\n orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);\n\n shouldUpdateOnChange &&\n onCacheChange(cache, normalizedOptions, memoized);\n }\n } else {\n const newValue: any = fn.apply(this, arguments);\n const newKey: MicroMemoize.Key = shouldCloneArguments\n ? key\n : slice.call(normalizedArgs, 0);\n\n orderByLru(cache, newKey, newValue, keys.length, maxSize);\n\n isPromise && updateAsyncCache(cache, memoized);\n\n shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);\n shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);\n }\n\n return values[0];\n }\n\n Object.defineProperties(memoized, {\n cache: {\n configurable: true,\n value: cache,\n },\n cacheSnapshot: {\n configurable: true,\n get() {\n return {\n keys: slice.call(cache.keys, 0),\n size: cache.size,\n values: slice.call(cache.values, 0),\n };\n },\n },\n isMemoized: {\n configurable: true,\n value: true,\n },\n options: {\n configurable: true,\n value: normalizedOptions,\n },\n });\n\n return memoized;\n}\n\nexport default createMemoizedFunction;\n"],"names":[],"mappings":"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"}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
function createAreKeysEqual(isEqual) {
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param key1 the keys array to test against
* @param key2 the keys array to test
* @returns are the keys shallowly equal
*/
return function areKeysEqual(key1, key2) {
var length = key1.length;
if (key2.length !== length) {
return false;
}
if (length === 1) {
return isEqual(key1[0], key2[0]);
}
var index = 0;
while (index < length) {
if (!isEqual(key1[index], key2[index])) {
return false;
}
index++;
}
return true;
};
}
function createGetKeyIndex(options) {
var maxSize = options.maxSize;
var areKeysEqual = typeof options.isMatchingKey === 'function'
? options.isMatchingKey
: createAreKeysEqual(options.isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param allKeys the list of all available keys
* @param keyToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function getKeyIndex(allKeys, keyToMatch) {
if (areKeysEqual(allKeys[0], keyToMatch)) {
return 0;
}
if (maxSize > 1) {
var length = maxSize > allKeys.length ? allKeys.length : maxSize;
var index = 1;
while (index < length) {
if (areKeysEqual(allKeys[index], keyToMatch)) {
return index;
}
index++;
}
}
return -1;
};
}
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero equality
*
* @param object1 the first object to compare
* @param object2 the second object to compare
* @returns are the two objects equal
*/
function isSameValueZero(object1, object2) {
return object1 === object2 || (object1 !== object1 && object2 !== object2);
}
/**
* @function mergeOptions
*
* @description
* merge the options into the target
*
* @param extraOptions the extra options passed
* @param providedOptions the defaulted options provided
* @returns the merged options
*/
function mergeOptions(extraOptions, providedOptions) {
var target = {};
for (var key in extraOptions) {
target[key] = extraOptions[key];
}
for (var key in providedOptions) {
target[key] = providedOptions[key];
}
return target;
}
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param keys the keys to order
* @param newKey the new key to move to the front
* @param values the values to order
* @param newValue the new value to move to the front
* @param startingIndex the index of the item to move to the front
*/
function orderByLru(cache, newKey, newValue, startingIndex, maxSize) {
var index = startingIndex;
while (index--) {
cache.keys[index + 1] = cache.keys[index];
cache.values[index + 1] = cache.values[index];
}
cache.keys[0] = newKey;
cache.values[0] = newValue;
if (startingIndex >= maxSize) {
cache.keys.length = maxSize;
cache.values.length = maxSize;
}
}
function createUpdateAsyncCache(options) {
var getKeyIndex = createGetKeyIndex(options);
var onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit;
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
/**
* @function updateAsyncCache
*
* @description
* update the promise method to auto-remove from cache if rejected, and
* if resolved then fire cache hit / changed
*
* @param cache the memoized function's cache
* @param memoized the memoized function
*/
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0]
.then(function (value) {
shouldUpdateOnHit && onCacheHit(cache, options, memoized);
shouldUpdateOnChange && onCacheChange(cache, options, memoized);
return value;
})
.catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
}
var slice = Array.prototype.slice;
function createMemoizedFunction(fn, options) {
if (options === void 0) { options = {}; }
// @ts-ignore
if (fn.isMemoized) {
return fn;
}
var _a = options.isEqual, isEqual = _a === void 0 ? isSameValueZero : _a, isMatchingKey = options.isMatchingKey, _b = options.isPromise, isPromise = _b === void 0 ? false : _b, _c = options.maxSize, maxSize = _c === void 0 ? 1 : _c, onCacheAdd = options.onCacheAdd, onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit, transformKey = options.transformKey, extraOptions = __rest(options, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = mergeOptions(extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey,
});
var getKeyIndex = createGetKeyIndex(normalizedOptions);
var updateAsyncCache = createUpdateAsyncCache(normalizedOptions);
var keys = [];
var values = [];
var cache = {
keys: keys,
get size() {
return cache.keys.length;
},
values: values,
};
var canTransformKey = typeof transformKey === 'function';
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var shouldUpdateOnAdd = typeof onCacheAdd === 'function';
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
function memoized() {
var normalizedArgs = shouldCloneArguments
? slice.call(arguments, 0)
: arguments;
var key = canTransformKey
? transformKey(normalizedArgs)
: normalizedArgs;
var keyIndex = keys.length ? getKeyIndex(keys, key) : -1;
if (~keyIndex) {
shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);
shouldUpdateOnChange &&
onCacheChange(cache, normalizedOptions, memoized);
}
}
else {
var newValue = fn.apply(this, arguments);
var newKey = shouldCloneArguments
? key
: slice.call(normalizedArgs, 0);
orderByLru(cache, newKey, newValue, keys.length, maxSize);
isPromise && updateAsyncCache(cache, memoized);
shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);
shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
value: cache,
},
cacheSnapshot: {
configurable: true,
get: function () {
return {
keys: slice.call(cache.keys, 0),
size: cache.size,
values: slice.call(cache.values, 0),
};
},
},
isMemoized: {
configurable: true,
value: true,
},
options: {
configurable: true,
value: normalizedOptions,
},
});
return memoized;
}
export default createMemoizedFunction;
//# sourceMappingURL=micro-memoize.esm.js.map
{"version":3,"file":"micro-memoize.esm.js","sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["export function createAreKeysEqual(\n isEqual: MicroMemoize.EqualityComparator,\n): MicroMemoize.MatchingKeyComparator {\n /**\n * @function areKeysEqual\n *\n * @description\n * are the keys shallowly equal to one another\n *\n * @param key1 the keys array to test against\n * @param key2 the keys array to test\n * @returns are the keys shallowly equal\n */\n return function areKeysEqual(key1: MicroMemoize.Key, key2: MicroMemoize.Key) {\n const length = key1.length;\n\n if (key2.length !== length) {\n return false;\n }\n\n if (length === 1) {\n return isEqual(key1[0], key2[0]);\n }\n\n let index = 0;\n\n while (index < length) {\n if (!isEqual(key1[index], key2[index])) {\n return false;\n }\n\n index++;\n }\n\n return true;\n };\n}\n\nexport function createGetKeyIndex(\n options: MicroMemoize.Options,\n): MicroMemoize.KeyIndexGetter {\n const { maxSize } = options;\n const areKeysEqual: MicroMemoize.MatchingKeyComparator =\n typeof options.isMatchingKey === 'function'\n ? options.isMatchingKey\n : createAreKeysEqual(options.isEqual);\n\n /**\n * @function getKeyIndex\n *\n * @description\n * get the index of the matching key\n *\n * @param allKeys the list of all available keys\n * @param keyToMatch the key to try to match\n *\n * @returns {number} the index of the matching key value, or -1\n */\n return function getKeyIndex(\n allKeys: MicroMemoize.Keys,\n keyToMatch: MicroMemoize.Key,\n ) {\n if (areKeysEqual(allKeys[0], keyToMatch)) {\n return 0;\n }\n\n if (maxSize > 1) {\n const length = maxSize > allKeys.length ? allKeys.length : maxSize;\n\n let index = 1;\n\n while (index < length) {\n if (areKeysEqual(allKeys[index], keyToMatch)) {\n return index;\n }\n\n index++;\n }\n }\n\n return -1;\n };\n}\n\n/**\n * @function isSameValueZero\n *\n * @description\n * are the objects equal based on SameValueZero equality\n *\n * @param object1 the first object to compare\n * @param object2 the second object to compare\n * @returns are the two objects equal\n */\nexport function isSameValueZero(object1: any, object2: any) {\n return object1 === object2 || (object1 !== object1 && object2 !== object2);\n}\n\n/**\n * @function mergeOptions\n *\n * @description\n * merge the options into the target\n *\n * @param extraOptions the extra options passed\n * @param providedOptions the defaulted options provided\n * @returns the merged options\n */\nexport function mergeOptions(\n extraOptions: PlainObject,\n providedOptions: PlainObject,\n) {\n const target: PlainObject = {};\n\n for (const key in extraOptions) {\n target[key] = extraOptions[key];\n }\n\n for (const key in providedOptions) {\n target[key] = providedOptions[key];\n }\n\n return target;\n}\n\n/**\n * @function orderByLru\n *\n * @description\n * order the array based on a Least-Recently-Used basis\n *\n * @param keys the keys to order\n * @param newKey the new key to move to the front\n * @param values the values to order\n * @param newValue the new value to move to the front\n * @param startingIndex the index of the item to move to the front\n */\nexport function orderByLru(\n cache: MicroMemoize.Cache,\n newKey: MicroMemoize.Key,\n newValue: any,\n startingIndex: number,\n maxSize: number,\n) {\n let index = startingIndex;\n\n while (index--) {\n cache.keys[index + 1] = cache.keys[index];\n cache.values[index + 1] = cache.values[index];\n }\n\n cache.keys[0] = newKey;\n cache.values[0] = newValue;\n\n if (startingIndex >= maxSize) {\n cache.keys.length = maxSize;\n cache.values.length = maxSize;\n }\n}\n\nexport function createUpdateAsyncCache(\n options: MicroMemoize.Options,\n): MicroMemoize.AsyncCacheUpdater {\n const getKeyIndex: MicroMemoize.KeyIndexGetter = createGetKeyIndex(options);\n\n const { onCacheChange, onCacheHit } = options;\n\n const shouldUpdateOnChange = typeof onCacheChange === 'function';\n const shouldUpdateOnHit = typeof onCacheHit === 'function';\n\n /**\n * @function updateAsyncCache\n *\n * @description\n * update the promise method to auto-remove from cache if rejected, and\n * if resolved then fire cache hit / changed\n *\n * @param cache the memoized function's cache\n * @param memoized the memoized function\n */\n return (cache: MicroMemoize.Cache, memoized: MicroMemoize.Memoized): void => {\n const key: any = cache.keys[0];\n\n cache.values[0] = cache.values[0]\n .then((value: any) => {\n shouldUpdateOnHit && onCacheHit(cache, options, memoized);\n shouldUpdateOnChange && onCacheChange(cache, options, memoized);\n\n return value;\n })\n .catch((error: Error) => {\n const keyIndex = getKeyIndex(cache.keys, key);\n\n if (~keyIndex) {\n cache.keys.splice(keyIndex, 1);\n cache.values.splice(keyIndex, 1);\n }\n\n throw error;\n });\n };\n}\n","// utils\nimport {\n createGetKeyIndex,\n createUpdateAsyncCache,\n isSameValueZero,\n mergeOptions,\n orderByLru,\n} from './utils';\n\nconst { slice } = Array.prototype;\n\nfunction createMemoizedFunction(\n fn: Function | MicroMemoize.Memoized,\n options: MicroMemoize.Options = {},\n): MicroMemoize.Memoized {\n // @ts-ignore\n if (fn.isMemoized) {\n return fn;\n }\n\n const {\n isEqual = isSameValueZero,\n isMatchingKey,\n isPromise = false,\n maxSize = 1,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n ...extraOptions\n }: MicroMemoize.Options = options;\n\n const normalizedOptions = mergeOptions(extraOptions, {\n isEqual,\n isMatchingKey,\n isPromise,\n maxSize,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n });\n\n const getKeyIndex: MicroMemoize.KeyIndexGetter = createGetKeyIndex(\n normalizedOptions,\n );\n const updateAsyncCache: MicroMemoize.AsyncCacheUpdater = createUpdateAsyncCache(\n normalizedOptions,\n );\n\n const keys: MicroMemoize.Keys = [];\n const values: MicroMemoize.Values = [];\n\n const cache: MicroMemoize.Cache = {\n keys,\n get size() {\n return cache.keys.length;\n },\n values,\n };\n\n const canTransformKey = typeof transformKey === 'function';\n\n const shouldCloneArguments = !!(transformKey || isMatchingKey);\n\n const shouldUpdateOnAdd = typeof onCacheAdd === 'function';\n const shouldUpdateOnChange = typeof onCacheChange === 'function';\n const shouldUpdateOnHit = typeof onCacheHit === 'function';\n\n function memoized(): any {\n const normalizedArgs: MicroMemoize.RawKey = shouldCloneArguments\n ? slice.call(arguments, 0)\n : arguments;\n const key: MicroMemoize.RawKey = canTransformKey\n ? transformKey(normalizedArgs)\n : normalizedArgs;\n const keyIndex: number = keys.length ? getKeyIndex(keys, key) : -1;\n\n if (~keyIndex) {\n shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);\n\n if (keyIndex) {\n orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);\n\n shouldUpdateOnChange &&\n onCacheChange(cache, normalizedOptions, memoized);\n }\n } else {\n const newValue: any = fn.apply(this, arguments);\n const newKey: MicroMemoize.Key = shouldCloneArguments\n ? key\n : slice.call(normalizedArgs, 0);\n\n orderByLru(cache, newKey, newValue, keys.length, maxSize);\n\n isPromise && updateAsyncCache(cache, memoized);\n\n shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);\n shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);\n }\n\n return values[0];\n }\n\n Object.defineProperties(memoized, {\n cache: {\n configurable: true,\n value: cache,\n },\n cacheSnapshot: {\n configurable: true,\n get() {\n return {\n keys: slice.call(cache.keys, 0),\n size: cache.size,\n values: slice.call(cache.values, 0),\n };\n },\n },\n isMemoized: {\n configurable: true,\n value: true,\n },\n options: {\n configurable: true,\n value: normalizedOptions,\n },\n });\n\n return memoized;\n}\n\nexport default createMemoizedFunction;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;SAAgB,kBAAkB,CAChC,OAAwC;;;;;;;;;;;IAYxC,OAAO,SAAS,YAAY,CAAC,IAAsB,EAAE,IAAsB;QACzE,IAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAE3B,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE;YAC1B,OAAO,KAAK,CAAC;SACd;QAED,IAAI,MAAM,KAAK,CAAC,EAAE;YAChB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SAClC;QAED,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,OAAO,KAAK,GAAG,MAAM,EAAE;YACrB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE;gBACtC,OAAO,KAAK,CAAC;aACd;YAED,KAAK,EAAE,CAAC;SACT;QAED,OAAO,IAAI,CAAC;KACb,CAAC;CACH;AAED,SAAgB,iBAAiB,CAC/B,OAA6B;IAErB,IAAA,yBAAO,CAAa;IAC5B,IAAM,YAAY,GAChB,OAAO,OAAO,CAAC,aAAa,KAAK,UAAU;UACvC,OAAO,CAAC,aAAa;UACrB,kBAAkB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;;;;;;;;;;;;IAa1C,OAAO,SAAS,WAAW,CACzB,OAA0B,EAC1B,UAA4B;QAE5B,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE;YACxC,OAAO,CAAC,CAAC;SACV;QAED,IAAI,OAAO,GAAG,CAAC,EAAE;YACf,IAAM,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC;YAEnE,IAAI,KAAK,GAAG,CAAC,CAAC;YAEd,OAAO,KAAK,GAAG,MAAM,EAAE;gBACrB,IAAI,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,EAAE;oBAC5C,OAAO,KAAK,CAAC;iBACd;gBAED,KAAK,EAAE,CAAC;aACT;SACF;QAED,OAAO,CAAC,CAAC,CAAC;KACX,CAAC;CACH;;;;;;;;;;;AAYD,SAAgB,eAAe,CAAC,OAAY,EAAE,OAAY;IACxD,OAAO,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,OAAO,CAAC,CAAC;CAC5E;;;;;;;;;;;AAYD,SAAgB,YAAY,CAC1B,YAAyB,EACzB,eAA4B;IAE5B,IAAM,MAAM,GAAgB,EAAE,CAAC;IAE/B,KAAK,IAAM,GAAG,IAAI,YAAY,EAAE;QAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;KACjC;IAED,KAAK,IAAM,GAAG,IAAI,eAAe,EAAE;QACjC,MAAM,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;KACpC;IAED,OAAO,MAAM,CAAC;CACf;;;;;;;;;;;;;AAcD,SAAgB,UAAU,CACxB,KAAyB,EACzB,MAAwB,EACxB,QAAa,EACb,aAAqB,EACrB,OAAe;IAEf,IAAI,KAAK,GAAG,aAAa,CAAC;IAE1B,OAAO,KAAK,EAAE,EAAE;QACd,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;KAC/C;IAED,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC;IAE3B,IAAI,aAAa,IAAI,OAAO,EAAE;QAC5B,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;QAC5B,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC;KAC/B;CACF;AAED,SAAgB,sBAAsB,CACpC,OAA6B;IAE7B,IAAM,WAAW,GAAgC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEpE,IAAA,qCAAa,EAAE,+BAAU,CAAa;IAE9C,IAAM,oBAAoB,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC;IACjE,IAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,UAAU,CAAC;;;;;;;;;;;IAY3D,OAAO,UAAC,KAAyB,EAAE,QAA+B;QAChE,IAAM,GAAG,GAAQ,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE/B,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;aAC9B,IAAI,CAAC,UAAC,KAAU;YACf,iBAAiB,IAAI,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC1D,oBAAoB,IAAI,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;YAEhE,OAAO,KAAK,CAAC;SACd,CAAC;aACD,KAAK,CAAC,UAAC,KAAY;YAClB,IAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAE9C,IAAI,CAAC,QAAQ,EAAE;gBACb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;gBAC/B,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;aAClC;YAED,MAAM,KAAK,CAAC;SACb,CAAC,CAAC;KACN,CAAC;CACH;;AChMO,IAAA,6BAAK,CAAqB;AAElC,SAAS,sBAAsB,CAC7B,EAAoC,EACpC,OAAkC;IAAlC,wBAAA,EAAA,YAAkC;;IAGlC,IAAI,EAAE,CAAC,UAAU,EAAE;QACjB,OAAO,EAAE,CAAC;KACX;IAGC,IAAA,oBAAyB,EAAzB,8CAAyB,EACzB,qCAAa,EACb,sBAAiB,EAAjB,sCAAiB,EACjB,oBAAW,EAAX,gCAAW,EACX,+BAAU,EACV,qCAAa,EACb,+BAAU,EACV,mCAAY,EACZ,iJAAe,CACiB;IAElC,IAAM,iBAAiB,GAAG,YAAY,CAAC,YAAY,EAAE;QACnD,OAAO,SAAA;QACP,aAAa,eAAA;QACb,SAAS,WAAA;QACT,OAAO,SAAA;QACP,UAAU,YAAA;QACV,aAAa,eAAA;QACb,UAAU,YAAA;QACV,YAAY,cAAA;KACb,CAAC,CAAC;IAEH,IAAM,WAAW,GAAgC,iBAAiB,CAChE,iBAAiB,CAClB,CAAC;IACF,IAAM,gBAAgB,GAAmC,sBAAsB,CAC7E,iBAAiB,CAClB,CAAC;IAEF,IAAM,IAAI,GAAsB,EAAE,CAAC;IACnC,IAAM,MAAM,GAAwB,EAAE,CAAC;IAEvC,IAAM,KAAK,GAAuB;QAChC,IAAI,MAAA;QACJ,IAAI,IAAI;YACN,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;SAC1B;QACD,MAAM,QAAA;KACP,CAAC;IAEF,IAAM,eAAe,GAAG,OAAO,YAAY,KAAK,UAAU,CAAC;IAE3D,IAAM,oBAAoB,GAAG,CAAC,EAAE,YAAY,IAAI,aAAa,CAAC,CAAC;IAE/D,IAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,UAAU,CAAC;IAC3D,IAAM,oBAAoB,GAAG,OAAO,aAAa,KAAK,UAAU,CAAC;IACjE,IAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,UAAU,CAAC;IAE3D,SAAS,QAAQ;QACf,IAAM,cAAc,GAAwB,oBAAoB;cAC5D,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;cACxB,SAAS,CAAC;QACd,IAAM,GAAG,GAAwB,eAAe;cAC5C,YAAY,CAAC,cAAc,CAAC;cAC5B,cAAc,CAAC;QACnB,IAAM,QAAQ,GAAW,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnE,IAAI,CAAC,QAAQ,EAAE;YACb,iBAAiB,IAAI,UAAU,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;YAEpE,IAAI,QAAQ,EAAE;gBACZ,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAEvE,oBAAoB;oBAClB,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;aACrD;SACF;aAAM;YACL,IAAM,QAAQ,GAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAChD,IAAM,MAAM,GAAqB,oBAAoB;kBACjD,GAAG;kBACH,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;YAElC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE1D,SAAS,IAAI,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAE/C,iBAAiB,IAAI,UAAU,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;YACpE,oBAAoB,IAAI,aAAa,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,CAAC,CAAC;SAC3E;QAED,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;KAClB;IAED,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE;QAChC,KAAK,EAAE;YACL,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,KAAK;SACb;QACD,aAAa,EAAE;YACb,YAAY,EAAE,IAAI;YAClB,GAAG;gBACD,OAAO;oBACL,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC/B,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;iBACpC,CAAC;aACH;SACF;QACD,UAAU,EAAE;YACV,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,IAAI;SACZ;QACD,OAAO,EAAE;YACP,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,iBAAiB;SACzB;KACF,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;CACjB;;;;"}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
function createAreKeysEqual(isEqual) {
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param key1 the keys array to test against
* @param key2 the keys array to test
* @returns are the keys shallowly equal
*/
return function areKeysEqual(key1, key2) {
var length = key1.length;
if (key2.length !== length) {
return false;
}
if (length === 1) {
return isEqual(key1[0], key2[0]);
}
var index = 0;
while (index < length) {
if (!isEqual(key1[index], key2[index])) {
return false;
}
index++;
}
return true;
};
}
function createGetKeyIndex(options) {
var maxSize = options.maxSize;
var areKeysEqual = typeof options.isMatchingKey === 'function'
? options.isMatchingKey
: createAreKeysEqual(options.isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param allKeys the list of all available keys
* @param keyToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function getKeyIndex(allKeys, keyToMatch) {
if (areKeysEqual(allKeys[0], keyToMatch)) {
return 0;
}
if (maxSize > 1) {
var length = maxSize > allKeys.length ? allKeys.length : maxSize;
var index = 1;
while (index < length) {
if (areKeysEqual(allKeys[index], keyToMatch)) {
return index;
}
index++;
}
}
return -1;
};
}
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero equality
*
* @param object1 the first object to compare
* @param object2 the second object to compare
* @returns are the two objects equal
*/
function isSameValueZero(object1, object2) {
return object1 === object2 || (object1 !== object1 && object2 !== object2);
}
/**
* @function mergeOptions
*
* @description
* merge the options into the target
*
* @param extraOptions the extra options passed
* @param providedOptions the defaulted options provided
* @returns the merged options
*/
function mergeOptions(extraOptions, providedOptions) {
var target = {};
for (var key in extraOptions) {
target[key] = extraOptions[key];
}
for (var key in providedOptions) {
target[key] = providedOptions[key];
}
return target;
}
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param keys the keys to order
* @param newKey the new key to move to the front
* @param values the values to order
* @param newValue the new value to move to the front
* @param startingIndex the index of the item to move to the front
*/
function orderByLru(cache, newKey, newValue, startingIndex, maxSize) {
var index = startingIndex;
while (index--) {
cache.keys[index + 1] = cache.keys[index];
cache.values[index + 1] = cache.values[index];
}
cache.keys[0] = newKey;
cache.values[0] = newValue;
if (startingIndex >= maxSize) {
cache.keys.length = maxSize;
cache.values.length = maxSize;
}
}
function createUpdateAsyncCache(options) {
var getKeyIndex = createGetKeyIndex(options);
var onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit;
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
/**
* @function updateAsyncCache
*
* @description
* update the promise method to auto-remove from cache if rejected, and
* if resolved then fire cache hit / changed
*
* @param cache the memoized function's cache
* @param memoized the memoized function
*/
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0]
.then(function (value) {
shouldUpdateOnHit && onCacheHit(cache, options, memoized);
shouldUpdateOnChange && onCacheChange(cache, options, memoized);
return value;
})
.catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
}
var slice = Array.prototype.slice;
function createMemoizedFunction(fn, options) {
if (options === void 0) { options = {}; }
// @ts-ignore
if (fn.isMemoized) {
return fn;
}
var _a = options.isEqual, isEqual = _a === void 0 ? isSameValueZero : _a, isMatchingKey = options.isMatchingKey, _b = options.isPromise, isPromise = _b === void 0 ? false : _b, _c = options.maxSize, maxSize = _c === void 0 ? 1 : _c, onCacheAdd = options.onCacheAdd, onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit, transformKey = options.transformKey, extraOptions = __rest(options, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = mergeOptions(extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey,
});
var getKeyIndex = createGetKeyIndex(normalizedOptions);
var updateAsyncCache = createUpdateAsyncCache(normalizedOptions);
var keys = [];
var values = [];
var cache = {
keys: keys,
get size() {
return cache.keys.length;
},
values: values,
};
var canTransformKey = typeof transformKey === 'function';
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var shouldUpdateOnAdd = typeof onCacheAdd === 'function';
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
function memoized() {
var normalizedArgs = shouldCloneArguments
? slice.call(arguments, 0)
: arguments;
var key = canTransformKey
? transformKey(normalizedArgs)
: normalizedArgs;
var keyIndex = keys.length ? getKeyIndex(keys, key) : -1;
if (~keyIndex) {
shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);
shouldUpdateOnChange &&
onCacheChange(cache, normalizedOptions, memoized);
}
}
else {
var newValue = fn.apply(this, arguments);
var newKey = shouldCloneArguments
? key
: slice.call(normalizedArgs, 0);
orderByLru(cache, newKey, newValue, keys.length, maxSize);
isPromise && updateAsyncCache(cache, memoized);
shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);
shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
value: cache,
},
cacheSnapshot: {
configurable: true,
get: function () {
return {
keys: slice.call(cache.keys, 0),
size: cache.size,
values: slice.call(cache.values, 0),
};
},
},
isMemoized: {
configurable: true,
value: true,
},
options: {
configurable: true,
value: normalizedOptions,
},
});
return memoized;
}
export default createMemoizedFunction;
//# sourceMappingURL=micro-memoize.esm.js.map
module.exports = {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
roots: ['<rootDir>'],
transform: {
'\\.(ts|tsx)$': 'ts-jest',
},
testRegex: '/__tests__/.*\\.(ts|tsx|js)$',
verbose: true,
};
{
"compilerOptions": {
"allowJs": true,
"baseUrl": "src",
"esModuleInterop": true,
"jsx": "react",
"lib": ["dom", "es2015"],
"module": "es2015",
"moduleResolution": "node",
"noImplicitAny": true,
"outDir": "./dist",
"sourceMap": true,
"target": "es5"
},
"exclude": ["node_modules"],
"include": ["src/*", "__tests__/*"]
}
{
"extends": "tslint-config-airbnb",
"rules": {
"import-name": false,
"no-increment-decrement": false,
"prefer-array-literal": false
}
}
+246
-317
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.memoize = {})));
}(this, (function (exports) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, global['micro-memoize'] = factory());
}(this, function () { 'use strict';
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
return target;
}
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
// types
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @function assign
*
* @description
* merge the sources into the target, as you would with Object.assign()
*
* @param {Object} target object to merge into
* @param {...Array<Object>} sources the sources to merge into the target
* @returns {Object} the merged object
*/
var assign = function assign(target) {
var source;
for (var index = 0; index < (arguments.length <= 1 ? 0 : arguments.length - 1); index++) {
source = index + 1 < 1 || arguments.length <= index + 1 ? undefined : arguments[index + 1];
if (source && typeof source === 'object') {
for (var key in source) {
if (hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
}
return target;
};
/**
* @function cloneArray
*
* @description
* clone the array-like object and return the new array
*
* @param {Array<any>|Arguments} arrayLike the array-like object to clone
* @returns {Array<any>} the clone of the array
*/
var cloneArray = function cloneArray(arrayLike) {
var length = arrayLike.length;
if (!length) {
return [];
function createAreKeysEqual(isEqual) {
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param key1 the keys array to test against
* @param key2 the keys array to test
* @returns are the keys shallowly equal
*/
return function areKeysEqual(key1, key2) {
var length = key1.length;
if (key2.length !== length) {
return false;
}
if (length === 1) {
return isEqual(key1[0], key2[0]);
}
var index = 0;
while (index < length) {
if (!isEqual(key1[index], key2[index])) {
return false;
}
index++;
}
return true;
};
}
if (length === 1) {
return [arrayLike[0]];
function createGetKeyIndex(options) {
var maxSize = options.maxSize;
var areKeysEqual = typeof options.isMatchingKey === 'function'
? options.isMatchingKey
: createAreKeysEqual(options.isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param allKeys the list of all available keys
* @param keyToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function getKeyIndex(allKeys, keyToMatch) {
if (areKeysEqual(allKeys[0], keyToMatch)) {
return 0;
}
if (maxSize > 1) {
var length = maxSize > allKeys.length ? allKeys.length : maxSize;
var index = 1;
while (index < length) {
if (areKeysEqual(allKeys[index], keyToMatch)) {
return index;
}
index++;
}
}
return -1;
};
}
if (length === 2) {
return [arrayLike[0], arrayLike[1]];
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero equality
*
* @param object1 the first object to compare
* @param object2 the second object to compare
* @returns are the two objects equal
*/
function isSameValueZero(object1, object2) {
return object1 === object2 || (object1 !== object1 && object2 !== object2);
}
if (length === 3) {
return [arrayLike[0], arrayLike[1], arrayLike[2]];
}
var array = new Array(length);
for (var index = 0; index < length; index++) {
array[index] = arrayLike[index];
}
return array;
};
var createAreKeysEqual = function createAreKeysEqual(isEqual
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param {Array<any>} keys1 the keys array to test against
* @param {Array<any>} keys2 the keys array to test
* @returns {boolean} are the keys shallowly equal
*/
) {
return function (keys1, keys2) {
if (keys1.length !== keys2.length) {
return false;
}
for (var index = 0, length = keys1.length; index < length; index++) {
if (!isEqual(keys1[index], keys2[index])) {
return false;
}
}
return true;
};
};
var createGetKeyIndex = function createGetKeyIndex(isEqual, isMatchingKey) {
var areKeysEqual = typeof isMatchingKey === 'function' ? isMatchingKey : createAreKeysEqual(isEqual);
/**
* @function getKeyIndex
* @function mergeOptions
*
* @description
* get the index of the matching key
* merge the options into the target
*
* @param {Array<Array<any>>} allKeys the list of all available keys
* @param {Array<any>} keysToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
* @param extraOptions the extra options passed
* @param providedOptions the defaulted options provided
* @returns the merged options
*/
return function (allKeys, keysToMatch) {
for (var index = 0; index < allKeys.length; index++) {
if (areKeysEqual(allKeys[index], keysToMatch)) {
return index;
function mergeOptions(extraOptions, providedOptions) {
var target = {};
for (var key in extraOptions) {
target[key] = extraOptions[key];
}
}
return -1;
};
};
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero
*
* @param {any} object1 the first object to compare
* @param {any} object2 the second object to compare
* @returns {boolean} are the two objects equal
*/
var isSameValueZero = function isSameValueZero(object1, object2) {
return object1 === object2 || object1 !== object1 && object2 !== object2;
};
var onCacheOperation = function onCacheOperation(cacheIgnored, optionsIgnored, memoizedIgnored) {};
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param {Array<any>} array the array to order
* @param {any} value the value to assign at the beginning of the array
* @param {number} startingIndex the index of the item to move to the front
*/
var orderByLru = function orderByLru(array, value, startingIndex) {
var index = startingIndex;
while (index--) {
array[index + 1] = array[index];
}
array[0] = value;
};
/**
* @function createSetPromiseHandler
*
* @description
* update the promise method to auto-remove from cache if rejected, and if resolved then fire cache hit / changed
*
* @param {Options} options the options for the memoized function
* @param {function(Cache, function): function} memoized the memoized function
*/
var createSetPromiseHandler = function createSetPromiseHandler(options) {
var getKeyIndex = createGetKeyIndex(options.isEqual, options.isMatchingKey);
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0].then(function (value) {
options.onCacheHit(cache, options, memoized);
options.onCacheChange(cache, options, memoized);
return value;
}).catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
for (var key in providedOptions) {
target[key] = providedOptions[key];
}
throw error;
});
};
};
/**
* @function memoize
*
* @description
* get the memoized version of the method passed
*
* @param {function} fn the method to memoize
* @param {Object} [options={}] the options to build the memoizer with
* @param {boolean} [options.isEqual=isSameValueZero] the method to compare equality of keys with
* @param {number} [options.maxSize=1] the number of items to store in cache
* @returns {function} the memoized method
*/
function memoize(fn, options) {
// if it is a memoized method, don't re-memoize it
if (fn.isMemoized) {
return fn;
return target;
}
var _ref = options || {},
_ref$isEqual = _ref.isEqual,
isEqual = _ref$isEqual === void 0 ? isSameValueZero : _ref$isEqual,
isMatchingKey = _ref.isMatchingKey,
_ref$isPromise = _ref.isPromise,
isPromise = _ref$isPromise === void 0 ? false : _ref$isPromise,
_ref$maxSize = _ref.maxSize,
maxSize = _ref$maxSize === void 0 ? 1 : _ref$maxSize,
_ref$onCacheAdd = _ref.onCacheAdd,
onCacheAdd = _ref$onCacheAdd === void 0 ? onCacheOperation : _ref$onCacheAdd,
_ref$onCacheChange = _ref.onCacheChange,
onCacheChange = _ref$onCacheChange === void 0 ? onCacheOperation : _ref$onCacheChange,
_ref$onCacheHit = _ref.onCacheHit,
onCacheHit = _ref$onCacheHit === void 0 ? onCacheOperation : _ref$onCacheHit,
transformKey = _ref.transformKey,
extraOptions = _objectWithoutPropertiesLoose(_ref, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = assign({}, extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey
});
var getKeyIndex = createGetKeyIndex(isEqual, isMatchingKey);
var setPromiseHandler = createSetPromiseHandler(normalizedOptions);
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var cache = {
keys: [],
get size() {
return cache.keys.length;
},
values: []
};
var keys = cache.keys,
values = cache.values;
/**
* @function memoized
* @function orderByLru
*
* @description
* the memoized version of the method passed
* order the array based on a Least-Recently-Used basis
*
* @param {...Array<any>} key the arguments passed, which create a unique cache key
* @returns {any} the value of the method called with the arguments
* @param keys the keys to order
* @param newKey the new key to move to the front
* @param values the values to order
* @param newValue the new value to move to the front
* @param startingIndex the index of the item to move to the front
*/
function memoized() {
var args = arguments;
var normalizedArgs = shouldCloneArguments ? cloneArray(args) : args;
var key = transformKey ? transformKey(normalizedArgs) : normalizedArgs;
var keyIndex = getKeyIndex(keys, key);
if (~keyIndex) {
onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(keys, keys[keyIndex], keyIndex);
orderByLru(values, values[keyIndex], keyIndex);
onCacheChange(cache, normalizedOptions, memoized);
function orderByLru(cache, newKey, newValue, startingIndex, maxSize) {
var index = startingIndex;
while (index--) {
cache.keys[index + 1] = cache.keys[index];
cache.values[index + 1] = cache.values[index];
}
} else {
if (keys.length >= maxSize) {
keys.pop();
values.pop();
cache.keys[0] = newKey;
cache.values[0] = newValue;
if (startingIndex >= maxSize) {
cache.keys.length = maxSize;
cache.values.length = maxSize;
}
var newKey = shouldCloneArguments ? key : cloneArray(normalizedArgs);
var newValue = fn.apply(this, args);
orderByLru(keys, newKey, keys.length);
orderByLru(values, newValue, values.length);
if (isPromise) {
setPromiseHandler(cache, memoized);
}
onCacheAdd(cache, normalizedOptions, memoized);
onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
function createUpdateAsyncCache(options) {
var getKeyIndex = createGetKeyIndex(options);
var onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit;
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
/**
* @function updateAsyncCache
*
* @description
* update the promise method to auto-remove from cache if rejected, and
* if resolved then fire cache hit / changed
*
* @param cache the memoized function's cache
* @param memoized the memoized function
*/
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0]
.then(function (value) {
shouldUpdateOnHit && onCacheHit(cache, options, memoized);
shouldUpdateOnChange && onCacheChange(cache, options, memoized);
return value;
})
.catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
get: function get() {
return cache;
var slice = Array.prototype.slice;
function createMemoizedFunction(fn, options) {
if (options === void 0) { options = {}; }
// @ts-ignore
if (fn.isMemoized) {
return fn;
}
},
cacheSnapshot: {
configurable: true,
get: function get() {
return {
keys: cloneArray(cache.keys),
size: cache.size,
values: cloneArray(cache.values)
};
var _a = options.isEqual, isEqual = _a === void 0 ? isSameValueZero : _a, isMatchingKey = options.isMatchingKey, _b = options.isPromise, isPromise = _b === void 0 ? false : _b, _c = options.maxSize, maxSize = _c === void 0 ? 1 : _c, onCacheAdd = options.onCacheAdd, onCacheChange = options.onCacheChange, onCacheHit = options.onCacheHit, transformKey = options.transformKey, extraOptions = __rest(options, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = mergeOptions(extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey,
});
var getKeyIndex = createGetKeyIndex(normalizedOptions);
var updateAsyncCache = createUpdateAsyncCache(normalizedOptions);
var keys = [];
var values = [];
var cache = {
keys: keys,
get size() {
return cache.keys.length;
},
values: values,
};
var canTransformKey = typeof transformKey === 'function';
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var shouldUpdateOnAdd = typeof onCacheAdd === 'function';
var shouldUpdateOnChange = typeof onCacheChange === 'function';
var shouldUpdateOnHit = typeof onCacheHit === 'function';
function memoized() {
var normalizedArgs = shouldCloneArguments
? slice.call(arguments, 0)
: arguments;
var key = canTransformKey
? transformKey(normalizedArgs)
: normalizedArgs;
var keyIndex = keys.length ? getKeyIndex(keys, key) : -1;
if (~keyIndex) {
shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);
shouldUpdateOnChange &&
onCacheChange(cache, normalizedOptions, memoized);
}
}
else {
var newValue = fn.apply(this, arguments);
var newKey = shouldCloneArguments
? key
: slice.call(normalizedArgs, 0);
orderByLru(cache, newKey, newValue, keys.length, maxSize);
isPromise && updateAsyncCache(cache, memoized);
shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);
shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
},
isMemoized: {
configurable: true,
get: function get() {
return true;
}
},
options: {
configurable: true,
get: function get() {
return normalizedOptions;
}
}
});
return memoized;
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
value: cache,
},
cacheSnapshot: {
configurable: true,
get: function () {
return {
keys: slice.call(cache.keys, 0),
size: cache.size,
values: slice.call(cache.values, 0),
};
},
},
isMemoized: {
configurable: true,
value: true,
},
options: {
configurable: true,
value: normalizedOptions,
},
});
return memoized;
}
exports.default = memoize;
return createMemoizedFunction;
Object.defineProperty(exports, '__esModule', { value: true });
})));
}));
//# sourceMappingURL=micro-memoize.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"micro-memoize.js","sources":["../src/utils.js","../src/index.js"],"sourcesContent":["// @flow\n\n// types\nimport type {\n Cache,\n Options,\n} from './types';\n\nconst hasOwnProperty: Function = Object.prototype.hasOwnProperty;\n\n/**\n * @function assign\n *\n * @description\n * merge the sources into the target, as you would with Object.assign()\n *\n * @param {Object} target object to merge into\n * @param {...Array<Object>} sources the sources to merge into the target\n * @returns {Object} the merged object\n */\nexport const assign = (target: Object, ...sources: Array<Object>): Object => {\n let source;\n\n for (let index = 0; index < sources.length; index++) {\n source = sources[index];\n\n if (source && typeof source === 'object') {\n for (let key in source) {\n if (hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n }\n\n return target;\n};\n\n/**\n * @function cloneArray\n *\n * @description\n * clone the array-like object and return the new array\n *\n * @param {Array<any>|Arguments} arrayLike the array-like object to clone\n * @returns {Array<any>} the clone of the array\n */\nexport const cloneArray = (arrayLike: Array<any> | Object): Array<any> => {\n const length: number = arrayLike.length;\n\n if (!length) {\n return [];\n }\n\n if (length === 1) {\n return [arrayLike[0]];\n }\n\n if (length === 2) {\n return [arrayLike[0], arrayLike[1]];\n }\n\n if (length === 3) {\n return [arrayLike[0], arrayLike[1], arrayLike[2]];\n }\n\n const array: Array<any> = new Array(length);\n\n for (let index: number = 0; index < length; index++) {\n array[index] = arrayLike[index];\n }\n\n return array;\n};\n\nexport const createAreKeysEqual = (isEqual: Function): Function =>\n /**\n * @function areKeysEqual\n *\n * @description\n * are the keys shallowly equal to one another\n *\n * @param {Array<any>} keys1 the keys array to test against\n * @param {Array<any>} keys2 the keys array to test\n * @returns {boolean} are the keys shallowly equal\n */\n (keys1: Array<any>, keys2: Array<any>): boolean => {\n if (keys1.length !== keys2.length) {\n return false;\n }\n\n for (let index: number = 0, length: number = keys1.length; index < length; index++) {\n if (!isEqual(keys1[index], keys2[index])) {\n return false;\n }\n }\n\n return true;\n };\n\nexport const createGetKeyIndex = (isEqual: Function, isMatchingKey: ?Function): Function => {\n const areKeysEqual: Function = typeof isMatchingKey === 'function' ? isMatchingKey : createAreKeysEqual(isEqual);\n\n /**\n * @function getKeyIndex\n *\n * @description\n * get the index of the matching key\n *\n * @param {Array<Array<any>>} allKeys the list of all available keys\n * @param {Array<any>} keysToMatch the key to try to match\n *\n * @returns {number} the index of the matching key value, or -1\n */\n return (allKeys: Array<Array<any>>, keysToMatch: Array<any>): number => {\n for (let index: number = 0; index < allKeys.length; index++) {\n if (areKeysEqual(allKeys[index], keysToMatch)) {\n return index;\n }\n }\n\n return -1;\n };\n};\n\n/**\n * @function isSameValueZero\n *\n * @description\n * are the objects equal based on SameValueZero\n *\n * @param {any} object1 the first object to compare\n * @param {any} object2 the second object to compare\n * @returns {boolean} are the two objects equal\n */\nexport const isSameValueZero = (object1: any, object2: any): boolean =>\n object1 === object2 || (object1 !== object1 && object2 !== object2);\n\nexport const onCacheOperation = (cacheIgnored: Cache, optionsIgnored: Options, memoizedIgnored: Function): void => {};\n\n/**\n * @function orderByLru\n *\n * @description\n * order the array based on a Least-Recently-Used basis\n *\n * @param {Array<any>} array the array to order\n * @param {any} value the value to assign at the beginning of the array\n * @param {number} startingIndex the index of the item to move to the front\n */\nexport const orderByLru = (array: Array<any>, value: any, startingIndex: number) => {\n let index: number = startingIndex;\n\n while (index--) {\n array[index + 1] = array[index];\n }\n\n array[0] = value;\n};\n\n/**\n * @function createSetPromiseHandler\n *\n * @description\n * update the promise method to auto-remove from cache if rejected, and if resolved then fire cache hit / changed\n *\n * @param {Options} options the options for the memoized function\n * @param {function(Cache, function): function} memoized the memoized function\n */\nexport const createSetPromiseHandler = (options: Options): Function => {\n const getKeyIndex = createGetKeyIndex(options.isEqual, options.isMatchingKey);\n\n return (cache: Cache, memoized: Function): void => {\n const key: any = cache.keys[0];\n\n cache.values[0] = cache.values[0]\n .then(\n (value: any): any => {\n options.onCacheHit(cache, options, memoized);\n options.onCacheChange(cache, options, memoized);\n\n return value;\n }\n )\n .catch((error: Error) => {\n const keyIndex: number = getKeyIndex(cache.keys, key);\n\n if (~keyIndex) {\n cache.keys.splice(keyIndex, 1);\n cache.values.splice(keyIndex, 1);\n }\n\n throw error;\n });\n };\n};\n","// @flow\n\n// types\nimport type {\n Cache,\n Options,\n} from './types';\n\n// utils\nimport {\n assign,\n cloneArray,\n createGetKeyIndex,\n createSetPromiseHandler,\n isSameValueZero,\n onCacheOperation,\n orderByLru,\n} from './utils';\n\n/**\n * @function memoize\n *\n * @description\n * get the memoized version of the method passed\n *\n * @param {function} fn the method to memoize\n * @param {Object} [options={}] the options to build the memoizer with\n * @param {boolean} [options.isEqual=isSameValueZero] the method to compare equality of keys with\n * @param {number} [options.maxSize=1] the number of items to store in cache\n * @returns {function} the memoized method\n */\nexport default function memoize(fn: Function, options: Options) {\n // if it is a memoized method, don't re-memoize it\n if (fn.isMemoized) {\n return fn;\n }\n\n const {\n isEqual = isSameValueZero,\n isMatchingKey,\n isPromise = false,\n maxSize = 1,\n onCacheAdd = onCacheOperation,\n onCacheChange = onCacheOperation,\n onCacheHit = onCacheOperation,\n transformKey,\n ...extraOptions\n } = options || {};\n\n const normalizedOptions = assign({}, extraOptions, {\n isEqual,\n isMatchingKey,\n isPromise,\n maxSize,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n });\n\n const getKeyIndex: Function = createGetKeyIndex(isEqual, isMatchingKey);\n const setPromiseHandler: Function = createSetPromiseHandler(normalizedOptions);\n const shouldCloneArguments: boolean = !!(transformKey || isMatchingKey);\n\n const cache: Cache = {\n keys: [],\n get size() {\n return cache.keys.length;\n },\n values: [],\n };\n const {keys, values} = cache;\n\n /**\n * @function memoized\n *\n * @description\n * the memoized version of the method passed\n *\n * @param {...Array<any>} key the arguments passed, which create a unique cache key\n * @returns {any} the value of the method called with the arguments\n */\n function memoized(): any {\n const args: Object = arguments;\n const normalizedArgs: Array<any> | Object = shouldCloneArguments ? cloneArray(args) : args;\n const key: Array<any> | Object = transformKey ? transformKey(normalizedArgs) : normalizedArgs;\n const keyIndex: number = getKeyIndex(keys, key);\n\n if (~keyIndex) {\n onCacheHit(cache, normalizedOptions, memoized);\n\n if (keyIndex) {\n orderByLru(keys, keys[keyIndex], keyIndex);\n orderByLru(values, values[keyIndex], keyIndex);\n\n onCacheChange(cache, normalizedOptions, memoized);\n }\n } else {\n if (keys.length >= maxSize) {\n keys.pop();\n values.pop();\n }\n\n const newKey = shouldCloneArguments ? key : cloneArray(normalizedArgs);\n const newValue = fn.apply(this, args);\n\n orderByLru(keys, newKey, keys.length);\n orderByLru(values, newValue, values.length);\n\n if (isPromise) {\n setPromiseHandler(cache, memoized);\n }\n\n onCacheAdd(cache, normalizedOptions, memoized);\n onCacheChange(cache, normalizedOptions, memoized);\n }\n\n return values[0];\n }\n\n Object.defineProperties(\n memoized,\n ({\n cache: {\n configurable: true,\n get() {\n return cache;\n },\n },\n cacheSnapshot: {\n configurable: true,\n get() {\n return {\n keys: cloneArray(cache.keys),\n size: cache.size,\n values: cloneArray(cache.values),\n };\n },\n },\n isMemoized: {\n configurable: true,\n get() {\n return true;\n },\n },\n options: {\n configurable: true,\n get() {\n return normalizedOptions;\n },\n },\n }: Object)\n );\n\n return memoized;\n}\n"],"names":["hasOwnProperty","Object","prototype","assign","target","source","index","key","call","cloneArray","arrayLike","length","array","Array","createAreKeysEqual","isEqual","keys1","keys2","createGetKeyIndex","isMatchingKey","areKeysEqual","allKeys","keysToMatch","isSameValueZero","object1","object2","onCacheOperation","cacheIgnored","optionsIgnored","memoizedIgnored","orderByLru","value","startingIndex","createSetPromiseHandler","options","getKeyIndex","cache","memoized","keys","values","then","onCacheHit","onCacheChange","catch","error","keyIndex","splice","memoize","fn","isMemoized","isPromise","maxSize","onCacheAdd","transformKey","extraOptions","normalizedOptions","setPromiseHandler","shouldCloneArguments","size","args","arguments","normalizedArgs","pop","newKey","newValue","apply","defineProperties","configurable","get","cacheSnapshot"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAEA;EAMA,IAAMA,cAAwB,GAAGC,MAAM,CAACC,SAAP,CAAiBF,cAAlD;EAEA;;;;;;;;;;;AAUA,EAAO,IAAMG,MAAM,GAAG,SAATA,MAAS,CAACC,MAAD,EAAuD;EAC3E,MAAIC,MAAJ;;EAEA,OAAK,IAAIC,KAAK,GAAG,CAAjB,EAAoBA,KAAK,qDAAzB,EAA4CA,KAAK,EAAjD,EAAqD;EACnDD,IAAAA,MAAM,GAAWC,KAAX,gCAAWA,KAAX,6BAAWA,KAAX,KAAN;;EAEA,QAAID,MAAM,IAAI,OAAOA,MAAP,KAAkB,QAAhC,EAA0C;EACxC,WAAK,IAAIE,GAAT,IAAgBF,MAAhB,EAAwB;EACtB,YAAIL,cAAc,CAACQ,IAAf,CAAoBH,MAApB,EAA4BE,GAA5B,CAAJ,EAAsC;EACpCH,UAAAA,MAAM,CAACG,GAAD,CAAN,GAAcF,MAAM,CAACE,GAAD,CAApB;EACD;EACF;EACF;EACF;;EAED,SAAOH,MAAP;EACD,CAhBM;EAkBP;;;;;;;;;;AASA,EAAO,IAAMK,UAAU,GAAG,SAAbA,UAAa,CAACC,SAAD,EAAgD;EACxE,MAAMC,MAAc,GAAGD,SAAS,CAACC,MAAjC;;EAEA,MAAI,CAACA,MAAL,EAAa;EACX,WAAO,EAAP;EACD;;EAED,MAAIA,MAAM,KAAK,CAAf,EAAkB;EAChB,WAAO,CAACD,SAAS,CAAC,CAAD,CAAV,CAAP;EACD;;EAED,MAAIC,MAAM,KAAK,CAAf,EAAkB;EAChB,WAAO,CAACD,SAAS,CAAC,CAAD,CAAV,EAAeA,SAAS,CAAC,CAAD,CAAxB,CAAP;EACD;;EAED,MAAIC,MAAM,KAAK,CAAf,EAAkB;EAChB,WAAO,CAACD,SAAS,CAAC,CAAD,CAAV,EAAeA,SAAS,CAAC,CAAD,CAAxB,EAA6BA,SAAS,CAAC,CAAD,CAAtC,CAAP;EACD;;EAED,MAAME,KAAiB,GAAG,IAAIC,KAAJ,CAAUF,MAAV,CAA1B;;EAEA,OAAK,IAAIL,KAAa,GAAG,CAAzB,EAA4BA,KAAK,GAAGK,MAApC,EAA4CL,KAAK,EAAjD,EAAqD;EACnDM,IAAAA,KAAK,CAACN,KAAD,CAAL,GAAeI,SAAS,CAACJ,KAAD,CAAxB;EACD;;EAED,SAAOM,KAAP;EACD,CA1BM;AA4BP,EAAO,IAAME,kBAAkB,GAAG,SAArBA,kBAAqB,CAACC;EACjC;;;;;;;;;;EADgC;EAAA,SAWhC,UAACC,KAAD,EAAoBC,KAApB,EAAmD;EACjD,QAAID,KAAK,CAACL,MAAN,KAAiBM,KAAK,CAACN,MAA3B,EAAmC;EACjC,aAAO,KAAP;EACD;;EAED,SAAK,IAAIL,KAAa,GAAG,CAApB,EAAuBK,MAAc,GAAGK,KAAK,CAACL,MAAnD,EAA2DL,KAAK,GAAGK,MAAnE,EAA2EL,KAAK,EAAhF,EAAoF;EAClF,UAAI,CAACS,OAAO,CAACC,KAAK,CAACV,KAAD,CAAN,EAAeW,KAAK,CAACX,KAAD,CAApB,CAAZ,EAA0C;EACxC,eAAO,KAAP;EACD;EACF;;EAED,WAAO,IAAP;EACD,GAvB+B;EAAA,CAA3B;AAyBP,EAAO,IAAMY,iBAAiB,GAAG,SAApBA,iBAAoB,CAACH,OAAD,EAAoBI,aAApB,EAA2D;EAC1F,MAAMC,YAAsB,GAAG,OAAOD,aAAP,KAAyB,UAAzB,GAAsCA,aAAtC,GAAsDL,kBAAkB,CAACC,OAAD,CAAvG;EAEA;;;;;;;;;;;;EAWA,SAAO,UAACM,OAAD,EAA6BC,WAA7B,EAAiE;EACtE,SAAK,IAAIhB,KAAa,GAAG,CAAzB,EAA4BA,KAAK,GAAGe,OAAO,CAACV,MAA5C,EAAoDL,KAAK,EAAzD,EAA6D;EAC3D,UAAIc,YAAY,CAACC,OAAO,CAACf,KAAD,CAAR,EAAiBgB,WAAjB,CAAhB,EAA+C;EAC7C,eAAOhB,KAAP;EACD;EACF;;EAED,WAAO,CAAC,CAAR;EACD,GARD;EASD,CAvBM;EAyBP;;;;;;;;;;;AAUA,EAAO,IAAMiB,eAAe,GAAG,SAAlBA,eAAkB,CAACC,OAAD,EAAeC,OAAf;EAAA,SAC7BD,OAAO,KAAKC,OAAZ,IAAwBD,OAAO,KAAKA,OAAZ,IAAuBC,OAAO,KAAKA,OAD9B;EAAA,CAAxB;AAGP,EAAO,IAAMC,gBAAgB,GAAG,SAAnBA,gBAAmB,CAACC,YAAD,EAAsBC,cAAtB,EAA+CC,eAA/C,EAAmF,EAA5G;EAEP;;;;;;;;;;;AAUA,EAAO,IAAMC,UAAU,GAAG,SAAbA,UAAa,CAAClB,KAAD,EAAoBmB,KAApB,EAAgCC,aAAhC,EAA0D;EAClF,MAAI1B,KAAa,GAAG0B,aAApB;;EAEA,SAAO1B,KAAK,EAAZ,EAAgB;EACdM,IAAAA,KAAK,CAACN,KAAK,GAAG,CAAT,CAAL,GAAmBM,KAAK,CAACN,KAAD,CAAxB;EACD;;EAEDM,EAAAA,KAAK,CAAC,CAAD,CAAL,GAAWmB,KAAX;EACD,CARM;EAUP;;;;;;;;;;AASA,EAAO,IAAME,uBAAuB,GAAG,SAA1BA,uBAA0B,CAACC,OAAD,EAAgC;EACrE,MAAMC,WAAW,GAAGjB,iBAAiB,CAACgB,OAAO,CAACnB,OAAT,EAAkBmB,OAAO,CAACf,aAA1B,CAArC;EAEA,SAAO,UAACiB,KAAD,EAAeC,QAAf,EAA4C;EACjD,QAAM9B,GAAQ,GAAG6B,KAAK,CAACE,IAAN,CAAW,CAAX,CAAjB;EAEAF,IAAAA,KAAK,CAACG,MAAN,CAAa,CAAb,IAAkBH,KAAK,CAACG,MAAN,CAAa,CAAb,EACfC,IADe,CAEd,UAACT,KAAD,EAAqB;EACnBG,MAAAA,OAAO,CAACO,UAAR,CAAmBL,KAAnB,EAA0BF,OAA1B,EAAmCG,QAAnC;EACAH,MAAAA,OAAO,CAACQ,aAAR,CAAsBN,KAAtB,EAA6BF,OAA7B,EAAsCG,QAAtC;EAEA,aAAON,KAAP;EACD,KAPa,EASfY,KATe,CAST,UAACC,KAAD,EAAkB;EACvB,UAAMC,QAAgB,GAAGV,WAAW,CAACC,KAAK,CAACE,IAAP,EAAa/B,GAAb,CAApC;;EAEA,UAAI,CAACsC,QAAL,EAAe;EACbT,QAAAA,KAAK,CAACE,IAAN,CAAWQ,MAAX,CAAkBD,QAAlB,EAA4B,CAA5B;EACAT,QAAAA,KAAK,CAACG,MAAN,CAAaO,MAAb,CAAoBD,QAApB,EAA8B,CAA9B;EACD;;EAED,YAAMD,KAAN;EACD,KAlBe,CAAlB;EAmBD,GAtBD;EAuBD,CA1BM;;ECtJP;;;;;;;;;;;;;AAYA,EAAe,SAASG,OAAT,CAAiBC,EAAjB,EAA+Bd,OAA/B,EAAiD;EAC9D;EACA,MAAIc,EAAE,CAACC,UAAP,EAAmB;EACjB,WAAOD,EAAP;EACD;;EAJ6D,aAgB1Dd,OAAO,IAAI,EAhB+C;EAAA,0BAO5DnB,OAP4D;EAAA,MAO5DA,OAP4D,6BAOlDQ,eAPkD;EAAA,MAQ5DJ,aAR4D,QAQ5DA,aAR4D;EAAA,4BAS5D+B,SAT4D;EAAA,MAS5DA,SAT4D,+BAShD,KATgD;EAAA,0BAU5DC,OAV4D;EAAA,MAU5DA,OAV4D,6BAUlD,CAVkD;EAAA,6BAW5DC,UAX4D;EAAA,MAW5DA,UAX4D,gCAW/C1B,gBAX+C;EAAA,gCAY5DgB,aAZ4D;EAAA,MAY5DA,aAZ4D,mCAY5ChB,gBAZ4C;EAAA,6BAa5De,UAb4D;EAAA,MAa5DA,UAb4D,gCAa/Cf,gBAb+C;EAAA,MAc5D2B,YAd4D,QAc5DA,YAd4D;EAAA,MAezDC,YAfyD;;EAkB9D,MAAMC,iBAAiB,GAAGpD,MAAM,CAAC,EAAD,EAAKmD,YAAL,EAAmB;EACjDvC,IAAAA,OAAO,EAAPA,OADiD;EAEjDI,IAAAA,aAAa,EAAbA,aAFiD;EAGjD+B,IAAAA,SAAS,EAATA,SAHiD;EAIjDC,IAAAA,OAAO,EAAPA,OAJiD;EAKjDC,IAAAA,UAAU,EAAVA,UALiD;EAMjDV,IAAAA,aAAa,EAAbA,aANiD;EAOjDD,IAAAA,UAAU,EAAVA,UAPiD;EAQjDY,IAAAA,YAAY,EAAZA;EARiD,GAAnB,CAAhC;EAWA,MAAMlB,WAAqB,GAAGjB,iBAAiB,CAACH,OAAD,EAAUI,aAAV,CAA/C;EACA,MAAMqC,iBAA2B,GAAGvB,uBAAuB,CAACsB,iBAAD,CAA3D;EACA,MAAME,oBAA6B,GAAG,CAAC,EAAEJ,YAAY,IAAIlC,aAAlB,CAAvC;EAEA,MAAMiB,KAAY,GAAG;EACnBE,IAAAA,IAAI,EAAE,EADa;;EAEnB,QAAIoB,IAAJ,GAAW;EACT,aAAOtB,KAAK,CAACE,IAAN,CAAW3B,MAAlB;EACD,KAJkB;;EAKnB4B,IAAAA,MAAM,EAAE;EALW,GAArB;EAjC8D,MAwCvDD,IAxCuD,GAwCvCF,KAxCuC,CAwCvDE,IAxCuD;EAAA,MAwCjDC,MAxCiD,GAwCvCH,KAxCuC,CAwCjDG,MAxCiD;EA0C9D;;;;;;;;;;EASA,WAASF,QAAT,GAAyB;EACvB,QAAMsB,IAAY,GAAGC,SAArB;EACA,QAAMC,cAAmC,GAAGJ,oBAAoB,GAAGhD,UAAU,CAACkD,IAAD,CAAb,GAAsBA,IAAtF;EACA,QAAMpD,GAAwB,GAAG8C,YAAY,GAAGA,YAAY,CAACQ,cAAD,CAAf,GAAkCA,cAA/E;EACA,QAAMhB,QAAgB,GAAGV,WAAW,CAACG,IAAD,EAAO/B,GAAP,CAApC;;EAEA,QAAI,CAACsC,QAAL,EAAe;EACbJ,MAAAA,UAAU,CAACL,KAAD,EAAQmB,iBAAR,EAA2BlB,QAA3B,CAAV;;EAEA,UAAIQ,QAAJ,EAAc;EACZf,QAAAA,UAAU,CAACQ,IAAD,EAAOA,IAAI,CAACO,QAAD,CAAX,EAAuBA,QAAvB,CAAV;EACAf,QAAAA,UAAU,CAACS,MAAD,EAASA,MAAM,CAACM,QAAD,CAAf,EAA2BA,QAA3B,CAAV;EAEAH,QAAAA,aAAa,CAACN,KAAD,EAAQmB,iBAAR,EAA2BlB,QAA3B,CAAb;EACD;EACF,KATD,MASO;EACL,UAAIC,IAAI,CAAC3B,MAAL,IAAewC,OAAnB,EAA4B;EAC1Bb,QAAAA,IAAI,CAACwB,GAAL;EACAvB,QAAAA,MAAM,CAACuB,GAAP;EACD;;EAED,UAAMC,MAAM,GAAGN,oBAAoB,GAAGlD,GAAH,GAASE,UAAU,CAACoD,cAAD,CAAtD;EACA,UAAMG,QAAQ,GAAGhB,EAAE,CAACiB,KAAH,CAAS,IAAT,EAAeN,IAAf,CAAjB;EAEA7B,MAAAA,UAAU,CAACQ,IAAD,EAAOyB,MAAP,EAAezB,IAAI,CAAC3B,MAApB,CAAV;EACAmB,MAAAA,UAAU,CAACS,MAAD,EAASyB,QAAT,EAAmBzB,MAAM,CAAC5B,MAA1B,CAAV;;EAEA,UAAIuC,SAAJ,EAAe;EACbM,QAAAA,iBAAiB,CAACpB,KAAD,EAAQC,QAAR,CAAjB;EACD;;EAEDe,MAAAA,UAAU,CAAChB,KAAD,EAAQmB,iBAAR,EAA2BlB,QAA3B,CAAV;EACAK,MAAAA,aAAa,CAACN,KAAD,EAAQmB,iBAAR,EAA2BlB,QAA3B,CAAb;EACD;;EAED,WAAOE,MAAM,CAAC,CAAD,CAAb;EACD;;EAEDtC,EAAAA,MAAM,CAACiE,gBAAP,CACE7B,QADF,EAEG;EACCD,IAAAA,KAAK,EAAE;EACL+B,MAAAA,YAAY,EAAE,IADT;EAELC,MAAAA,GAFK,iBAEC;EACJ,eAAOhC,KAAP;EACD;EAJI,KADR;EAOCiC,IAAAA,aAAa,EAAE;EACbF,MAAAA,YAAY,EAAE,IADD;EAEbC,MAAAA,GAFa,iBAEP;EACJ,eAAO;EACL9B,UAAAA,IAAI,EAAE7B,UAAU,CAAC2B,KAAK,CAACE,IAAP,CADX;EAELoB,UAAAA,IAAI,EAAEtB,KAAK,CAACsB,IAFP;EAGLnB,UAAAA,MAAM,EAAE9B,UAAU,CAAC2B,KAAK,CAACG,MAAP;EAHb,SAAP;EAKD;EARY,KAPhB;EAiBCU,IAAAA,UAAU,EAAE;EACVkB,MAAAA,YAAY,EAAE,IADJ;EAEVC,MAAAA,GAFU,iBAEJ;EACJ,eAAO,IAAP;EACD;EAJS,KAjBb;EAuBClC,IAAAA,OAAO,EAAE;EACPiC,MAAAA,YAAY,EAAE,IADP;EAEPC,MAAAA,GAFO,iBAED;EACJ,eAAOb,iBAAP;EACD;EAJM;EAvBV,GAFH;EAkCA,SAAOlB,QAAP;EACD;;;;;;;;;;;;"}
{"version":3,"file":"micro-memoize.js","sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["export function createAreKeysEqual(\n isEqual: MicroMemoize.EqualityComparator,\n): MicroMemoize.MatchingKeyComparator {\n /**\n * @function areKeysEqual\n *\n * @description\n * are the keys shallowly equal to one another\n *\n * @param key1 the keys array to test against\n * @param key2 the keys array to test\n * @returns are the keys shallowly equal\n */\n return function areKeysEqual(key1: MicroMemoize.Key, key2: MicroMemoize.Key) {\n const length = key1.length;\n\n if (key2.length !== length) {\n return false;\n }\n\n if (length === 1) {\n return isEqual(key1[0], key2[0]);\n }\n\n let index = 0;\n\n while (index < length) {\n if (!isEqual(key1[index], key2[index])) {\n return false;\n }\n\n index++;\n }\n\n return true;\n };\n}\n\nexport function createGetKeyIndex(\n options: MicroMemoize.Options,\n): MicroMemoize.KeyIndexGetter {\n const { maxSize } = options;\n const areKeysEqual: MicroMemoize.MatchingKeyComparator =\n typeof options.isMatchingKey === 'function'\n ? options.isMatchingKey\n : createAreKeysEqual(options.isEqual);\n\n /**\n * @function getKeyIndex\n *\n * @description\n * get the index of the matching key\n *\n * @param allKeys the list of all available keys\n * @param keyToMatch the key to try to match\n *\n * @returns {number} the index of the matching key value, or -1\n */\n return function getKeyIndex(\n allKeys: MicroMemoize.Keys,\n keyToMatch: MicroMemoize.Key,\n ) {\n if (areKeysEqual(allKeys[0], keyToMatch)) {\n return 0;\n }\n\n if (maxSize > 1) {\n const length = maxSize > allKeys.length ? allKeys.length : maxSize;\n\n let index = 1;\n\n while (index < length) {\n if (areKeysEqual(allKeys[index], keyToMatch)) {\n return index;\n }\n\n index++;\n }\n }\n\n return -1;\n };\n}\n\n/**\n * @function isSameValueZero\n *\n * @description\n * are the objects equal based on SameValueZero equality\n *\n * @param object1 the first object to compare\n * @param object2 the second object to compare\n * @returns are the two objects equal\n */\nexport function isSameValueZero(object1: any, object2: any) {\n return object1 === object2 || (object1 !== object1 && object2 !== object2);\n}\n\n/**\n * @function mergeOptions\n *\n * @description\n * merge the options into the target\n *\n * @param extraOptions the extra options passed\n * @param providedOptions the defaulted options provided\n * @returns the merged options\n */\nexport function mergeOptions(\n extraOptions: PlainObject,\n providedOptions: PlainObject,\n) {\n const target: PlainObject = {};\n\n for (const key in extraOptions) {\n target[key] = extraOptions[key];\n }\n\n for (const key in providedOptions) {\n target[key] = providedOptions[key];\n }\n\n return target;\n}\n\n/**\n * @function orderByLru\n *\n * @description\n * order the array based on a Least-Recently-Used basis\n *\n * @param keys the keys to order\n * @param newKey the new key to move to the front\n * @param values the values to order\n * @param newValue the new value to move to the front\n * @param startingIndex the index of the item to move to the front\n */\nexport function orderByLru(\n cache: MicroMemoize.Cache,\n newKey: MicroMemoize.Key,\n newValue: any,\n startingIndex: number,\n maxSize: number,\n) {\n let index = startingIndex;\n\n while (index--) {\n cache.keys[index + 1] = cache.keys[index];\n cache.values[index + 1] = cache.values[index];\n }\n\n cache.keys[0] = newKey;\n cache.values[0] = newValue;\n\n if (startingIndex >= maxSize) {\n cache.keys.length = maxSize;\n cache.values.length = maxSize;\n }\n}\n\nexport function createUpdateAsyncCache(\n options: MicroMemoize.Options,\n): MicroMemoize.AsyncCacheUpdater {\n const getKeyIndex: MicroMemoize.KeyIndexGetter = createGetKeyIndex(options);\n\n const { onCacheChange, onCacheHit } = options;\n\n const shouldUpdateOnChange = typeof onCacheChange === 'function';\n const shouldUpdateOnHit = typeof onCacheHit === 'function';\n\n /**\n * @function updateAsyncCache\n *\n * @description\n * update the promise method to auto-remove from cache if rejected, and\n * if resolved then fire cache hit / changed\n *\n * @param cache the memoized function's cache\n * @param memoized the memoized function\n */\n return (cache: MicroMemoize.Cache, memoized: MicroMemoize.Memoized): void => {\n const key: any = cache.keys[0];\n\n cache.values[0] = cache.values[0]\n .then((value: any) => {\n shouldUpdateOnHit && onCacheHit(cache, options, memoized);\n shouldUpdateOnChange && onCacheChange(cache, options, memoized);\n\n return value;\n })\n .catch((error: Error) => {\n const keyIndex = getKeyIndex(cache.keys, key);\n\n if (~keyIndex) {\n cache.keys.splice(keyIndex, 1);\n cache.values.splice(keyIndex, 1);\n }\n\n throw error;\n });\n };\n}\n","// utils\nimport {\n createGetKeyIndex,\n createUpdateAsyncCache,\n isSameValueZero,\n mergeOptions,\n orderByLru,\n} from './utils';\n\nconst { slice } = Array.prototype;\n\nfunction createMemoizedFunction(\n fn: Function | MicroMemoize.Memoized,\n options: MicroMemoize.Options = {},\n): MicroMemoize.Memoized {\n // @ts-ignore\n if (fn.isMemoized) {\n return fn;\n }\n\n const {\n isEqual = isSameValueZero,\n isMatchingKey,\n isPromise = false,\n maxSize = 1,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n ...extraOptions\n }: MicroMemoize.Options = options;\n\n const normalizedOptions = mergeOptions(extraOptions, {\n isEqual,\n isMatchingKey,\n isPromise,\n maxSize,\n onCacheAdd,\n onCacheChange,\n onCacheHit,\n transformKey,\n });\n\n const getKeyIndex: MicroMemoize.KeyIndexGetter = createGetKeyIndex(\n normalizedOptions,\n );\n const updateAsyncCache: MicroMemoize.AsyncCacheUpdater = createUpdateAsyncCache(\n normalizedOptions,\n );\n\n const keys: MicroMemoize.Keys = [];\n const values: MicroMemoize.Values = [];\n\n const cache: MicroMemoize.Cache = {\n keys,\n get size() {\n return cache.keys.length;\n },\n values,\n };\n\n const canTransformKey = typeof transformKey === 'function';\n\n const shouldCloneArguments = !!(transformKey || isMatchingKey);\n\n const shouldUpdateOnAdd = typeof onCacheAdd === 'function';\n const shouldUpdateOnChange = typeof onCacheChange === 'function';\n const shouldUpdateOnHit = typeof onCacheHit === 'function';\n\n function memoized(): any {\n const normalizedArgs: MicroMemoize.RawKey = shouldCloneArguments\n ? slice.call(arguments, 0)\n : arguments;\n const key: MicroMemoize.RawKey = canTransformKey\n ? transformKey(normalizedArgs)\n : normalizedArgs;\n const keyIndex: number = keys.length ? getKeyIndex(keys, key) : -1;\n\n if (~keyIndex) {\n shouldUpdateOnHit && onCacheHit(cache, normalizedOptions, memoized);\n\n if (keyIndex) {\n orderByLru(cache, keys[keyIndex], values[keyIndex], keyIndex, maxSize);\n\n shouldUpdateOnChange &&\n onCacheChange(cache, normalizedOptions, memoized);\n }\n } else {\n const newValue: any = fn.apply(this, arguments);\n const newKey: MicroMemoize.Key = shouldCloneArguments\n ? key\n : slice.call(normalizedArgs, 0);\n\n orderByLru(cache, newKey, newValue, keys.length, maxSize);\n\n isPromise && updateAsyncCache(cache, memoized);\n\n shouldUpdateOnAdd && onCacheAdd(cache, normalizedOptions, memoized);\n shouldUpdateOnChange && onCacheChange(cache, normalizedOptions, memoized);\n }\n\n return values[0];\n }\n\n Object.defineProperties(memoized, {\n cache: {\n configurable: true,\n value: cache,\n },\n cacheSnapshot: {\n configurable: true,\n get() {\n return {\n keys: slice.call(cache.keys, 0),\n size: cache.size,\n values: slice.call(cache.values, 0),\n };\n },\n },\n isMemoized: {\n configurable: true,\n value: true,\n },\n options: {\n configurable: true,\n value: normalizedOptions,\n },\n });\n\n return memoized;\n}\n\nexport default createMemoizedFunction;\n"],"names":[],"mappings":"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"}

@@ -1,1 +0,1 @@

!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(e.memoize={})}(this,function(e){"use strict";var O=Object.prototype.hasOwnProperty,P=function(e){var n=e.length;if(!n)return[];if(1===n)return[e[0]];if(2===n)return[e[0],e[1]];if(3===n)return[e[0],e[1],e[2]];for(var t=new Array(n),r=0;r<n;r++)t[r]=e[r];return t},q=function(e,n){var i,r="function"==typeof n?n:(i=e,function(e,n){if(e.length!==n.length)return!1;for(var t=0,r=e.length;t<r;t++)if(!i(e[t],n[t]))return!1;return!0});return function(e,n){for(var t=0;t<e.length;t++)if(r(e[t],n))return t;return-1}},A=function(e,n){return e===n||e!=e&&n!=n},E=function(e,n,t){},H=function(e,n,t){for(var r=t;r--;)e[r+1]=e[r];e[0]=n};e.default=function(u,e){if(u.isMemoized)return u;var i,o,n=e||{},t=n.isEqual,r=void 0===t?A:t,a=n.isMatchingKey,f=n.isPromise,c=void 0!==f&&f,s=n.maxSize,h=void 0===s?1:s,l=n.onCacheAdd,g=void 0===l?E:l,v=n.onCacheChange,d=void 0===v?E:v,y=n.onCacheHit,p=void 0===y?E:y,m=n.transformKey,C=function(e){for(var n,t=0;t<(arguments.length<=1?0:arguments.length-1);t++)if((n=t+1<1||arguments.length<=t+1?void 0:arguments[t+1])&&"object"==typeof n)for(var r in n)O.call(n,r)&&(e[r]=n[r]);return e}({},function(e,n){if(null==e)return{};var t,r,i={},o=Object.keys(e);for(r=0;r<o.length;r++)t=o[r],0<=n.indexOf(t)||(i[t]=e[t]);return i}(n,["isEqual","isMatchingKey","isPromise","maxSize","onCacheAdd","onCacheChange","onCacheHit","transformKey"]),{isEqual:r,isMatchingKey:a,isPromise:c,maxSize:h,onCacheAdd:g,onCacheChange:d,onCacheHit:p,transformKey:m}),b=q(r,a),k=(o=q((i=C).isEqual,i.isMatchingKey),function(t,n){var r=t.keys[0];t.values[0]=t.values[0].then(function(e){return i.onCacheHit(t,i,n),i.onCacheChange(t,i,n),e}).catch(function(e){var n=o(t.keys,r);throw~n&&(t.keys.splice(n,1),t.values.splice(n,1)),e})}),z=!(!m&&!a),x={keys:[],get size(){return x.keys.length},values:[]},K=x.keys,M=x.values;function j(){var e=arguments,n=z?P(e):e,t=m?m(n):n,r=b(K,t);if(~r)p(x,C,j),r&&(H(K,K[r],r),H(M,M[r],r),d(x,C,j));else{K.length>=h&&(K.pop(),M.pop());var i=z?t:P(n),o=u.apply(this,e);H(K,i,K.length),H(M,o,M.length),c&&k(x,j),g(x,C,j),d(x,C,j)}return M[0]}return Object.defineProperties(j,{cache:{configurable:!0,get:function(){return x}},cacheSnapshot:{configurable:!0,get:function(){return{keys:P(x.keys),size:x.size,values:P(x.values)}}},isMemoized:{configurable:!0,get:function(){return!0}},options:{configurable:!0,get:function(){return C}}}),j},Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self)["micro-memoize"]=n()}(this,function(){"use strict";function w(e){var o,r=e.maxSize,a="function"==typeof e.isMatchingKey?e.isMatchingKey:(o=e.isEqual,function(e,n){var t=e.length;if(n.length!==t)return!1;if(1===t)return o(e[0],n[0]);for(var i=0;i<t;){if(!o(e[i],n[i]))return!1;i++}return!0});return function(e,n){if(a(e[0],n))return 0;if(1<r)for(var t=r>e.length?e.length:r,i=1;i<t;){if(a(e[i],n))return i;i++}return-1}}function A(e,n){return e===n||e!=e&&n!=n}function E(e,n,t,i,o){for(var r=i;r--;)e.keys[r+1]=e.keys[r],e.values[r+1]=e.values[r];e.keys[0]=n,e.values[0]=t,o<=i&&(e.keys.length=o,e.values.length=o)}var H=Array.prototype.slice;return function(r,e){if(void 0===e&&(e={}),r.isMemoized)return r;var o,a,u,f,c,s,n=e.isEqual,t=void 0===n?A:n,i=e.isMatchingKey,l=e.isPromise,h=void 0!==l&&l,y=e.maxSize,v=void 0===y?1:y,g=e.onCacheAdd,p=e.onCacheChange,d=e.onCacheHit,m=e.transformKey,C=function(e,n){var t={};for(var i in e)t[i]=e[i];for(var i in n)t[i]=n[i];return t}(function(e,n){var t={};for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&n.indexOf(i)<0&&(t[i]=e[i]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(i=Object.getOwnPropertySymbols(e);o<i.length;o++)n.indexOf(i[o])<0&&(t[i[o]]=e[i[o]])}return t}(e,["isEqual","isMatchingKey","isPromise","maxSize","onCacheAdd","onCacheChange","onCacheHit","transformKey"]),{isEqual:t,isMatchingKey:i,isPromise:h,maxSize:v,onCacheAdd:g,onCacheChange:p,onCacheHit:d,transformKey:m}),b=w(C),k=(a=w(o=C),u=o.onCacheChange,f=o.onCacheHit,c="function"==typeof u,s="function"==typeof f,function(t,n){var i=t.keys[0];t.values[0]=t.values[0].then(function(e){return s&&f(t,o,n),c&&u(t,o,n),e}).catch(function(e){var n=a(t.keys,i);throw~n&&(t.keys.splice(n,1),t.values.splice(n,1)),e})}),z=[],O=[],x={keys:z,get size(){return x.keys.length},values:O},K="function"==typeof m,M=!(!m&&!i),P="function"==typeof g,S="function"==typeof p,j="function"==typeof d;function q(){var e=M?H.call(arguments,0):arguments,n=K?m(e):e,t=z.length?b(z,n):-1;if(~t)j&&d(x,C,q),t&&(E(x,z[t],O[t],t,v),S&&p(x,C,q));else{var i=r.apply(this,arguments),o=M?n:H.call(e,0);E(x,o,i,z.length,v),h&&k(x,q),P&&g(x,C,q),S&&p(x,C,q)}return O[0]}return Object.defineProperties(q,{cache:{configurable:!0,value:x},cacheSnapshot:{configurable:!0,get:function(){return{keys:H.call(x.keys,0),size:x.size,values:H.call(x.values,0)}}},isMemoized:{configurable:!0,value:!0},options:{configurable:!0,value:C}}),q}});

@@ -1,14 +0,21 @@

const fs = require('fs-extra');
const fs = require('fs');
const path = require('path');
const ES_DIRECTORY = path.join(__dirname, 'es');
const MJS_DIRECTORY = path.join(__dirname, 'mjs');
const pkg = require('./package.json');
fs.readdirSync(ES_DIRECTORY).forEach((file) => {
const fullPathJsFilename = path.resolve(ES_DIRECTORY, file);
const fullPathMjsFilename = path.resolve(MJS_DIRECTORY, `${file.slice(0, -3)}.mjs`);
const SOURCE = path.join(__dirname, pkg.module);
const DESTINATION = path.join(__dirname, pkg.module.replace('esm.js', 'mjs'));
fs.copySync(fullPathJsFilename, fullPathMjsFilename);
const getFileName = filename => {
const split = filename.split('/');
console.log(`es/${file} -> mjs/${file.slice(0, -3)}.mjs`);
return split[split.length - 1];
};
fs.copyFile(SOURCE, DESTINATION, error => {
if (error) {
throw error;
}
console.log(`Copied ${getFileName(SOURCE)} to ${getFileName(DESTINATION)}`);
});

@@ -1,20 +0,60 @@

interface Cache {
keys: Array<any>;
size: number;
values: Array<any>;
}
type PlainObject = {
[key: string]: any;
[index: number]: any;
};
interface Options {
isEqual?: (firstValue: any, secondValue: any) => boolean;
isMatchingKey?: (cacheKey: Array<any>, key: Array<any>) => boolean;
isPromise?: boolean;
maxSize?: number;
onCacheAdd?: (cache: Cache, options: Options, memoized: Function) => void;
onCacheChange?: (cache: Cache, options: Options, memoized: Function) => void;
onCacheHit?: (cache: Cache, options: Options, memoized: Function) => void;
transformKey?: (args: any[]) => any;
declare namespace MicroMemoize {
export type Key = any[];
export type RawKey = Key | IArguments;
export type Keys = Key[];
export type Values = any[];
export type Cache = {
keys: Keys;
size: number;
values: Values;
};
export type EqualityComparator = (object1: any, object2: any) => boolean;
export type MatchingKeyComparator = (key1: Key, key2: RawKey) => boolean;
export type CacheModifiedHandler = (
cache: Cache,
options: Options,
memoized: Function,
) => void;
export type KeyTransformer = (args: RawKey) => Key;
export type KeyIndexGetter = (allKeys: Keys, keyToMatch: RawKey) => number;
export type AsyncCacheUpdater = (cache: Cache, memoized: Memoized) => void;
export type Options = {
isEqual?: EqualityComparator;
isMatchingKey?: MatchingKeyComparator;
isPromise?: boolean;
maxSize?: number;
onCacheAdd?: CacheModifiedHandler;
onCacheChange?: CacheModifiedHandler;
onCacheHit?: CacheModifiedHandler;
transformKey?: KeyTransformer;
};
export interface Memoized extends Function {
[key: string]: any;
cache?: Cache;
cacheSnapshot?: Cache;
isMemoized?: boolean;
options?: Options;
}
}
type Fn = (...args: any[]) => any;
export default function memoize<T extends Fn>(fn: T, options?: Options): T;
export default function memoize<T extends Function>(
fn: T,
options?: MicroMemoize.Options,
): MicroMemoize.Memoized;
{
"author": "tony.quetano@planttheidea.com",
"ava": {
"failFast": true,
"files": [
"test/*.js"
],
"require": [
"@babel/register"
],
"sources": [
"src/*.js"
],
"verbose": true
},
"browser": "dist/micro-memoize.js",
"browserslist": [

@@ -29,48 +17,35 @@ "defaults",

"devDependencies": {
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/plugin-syntax-flow": "^7.0.0",
"@babel/plugin-transform-flow-strip-types": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@babel/register": "^7.0.0",
"@babel/runtime": "^7.1.2",
"ava": "^1.0.0-rc.1",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"@types/bluebird": "^3.5.25",
"@types/jest": "^24.0.0",
"@types/react": "^16.7.20",
"benchee": "^1.0.0",
"benchmark": "^2.1.4",
"case-sensitive-paths-webpack-plugin": "^2.1.2",
"bluebird": "^3.5.2",
"cli-table2": "^0.2.0",
"eslint": "^5.7.0",
"eslint-config-rapid7": "^3.0.4",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.1.1",
"fast-equals": "^1.6.1",
"fast-memoize": "^2.5.1",
"flow-babel-webpack-plugin": "^1.1.1",
"fs-extra": "^7.0.0",
"hash-it": "^4.0.3",
"html-webpack-plugin": "^3.2.0",
"in-publish": "^2.0.0",
"lodash": "^4.17.10",
"jest": "^24.1.0",
"lodash": "^4.17.11",
"lru-memoize": "^1.0.2",
"mem": "^4.0.0",
"memoizee": "^0.4.13",
"memoizee": "^0.4.14",
"memoizerific": "^1.11.3",
"nyc": "^13.1.0",
"optimize-js-plugin": "^0.0.4",
"mini-bench": "^1.0.0",
"ora": "^3.0.0",
"prop-types": "^15.6.2",
"ramda": "^0.25.0",
"react": "^16.4.2",
"react-dev-utils": "^6.0.5",
"react-dom": "^16.4.2",
"react-hot-loader": "^4.3.11",
"rimraf": "^2.6.2",
"rollup": "^0.66.6",
"rollup-plugin-babel": "^4.0.1",
"performance-now": "^2.1.0",
"ramda": "^0.26.1",
"react": "^16.7.0",
"rollup": "^1.1.2",
"rollup-plugin-typescript": "^1.0.0",
"rollup-plugin-uglify": "^6.0.0",
"sinon": "^7.0.0",
"rsvp": "^4.8.4",
"simple-statistics": "^7.0.0",
"ts-jest": "^23.10.4",
"ts-loader": "^5.2.2",
"tslint": "^5.11.0",
"tslint-config-airbnb": "^5.11.0",
"tslint-loader": "^3.5.4",
"typescript": "^3.1.3",
"underscore": "^1.9.1",

@@ -100,4 +75,4 @@ "webpack": "^4.20.2",

"license": "MIT",
"main": "lib/index.js",
"module": "es/index.js",
"main": "dist/micro-memoize.cjs.js",
"module": "dist/micro-memoize.esm.js",
"name": "micro-memoize",

@@ -109,23 +84,20 @@ "repository": {

"scripts": {
"benchmark": "npm run transpile:lib -- --no-comments && node benchmark/index.js",
"benchmark:trace": "npm run transpile:lib -- --no-comments && node --trace-deopt --trace-opt benchmark/trace-test.js",
"benchmark:alternative": "npm run transpile:lib -- --no-comments && ALTERNATIVE=true node benchmark/index.js",
"benchmark": "npm run dist && NODE_ENV=production node ./benchmarks/index.js",
"build": "NODE_ENV=production rollup -c",
"clean": "rimraf lib && rimraf es && rimraf mjs && rimraf dist",
"copy:mjs": "node ./es-to-mjs.js",
"dev": "NODE_ENV=development webpack-dev-server --progress --colors --config=webpack/webpack.config.js",
"flow": "flow check src",
"lint": "eslint --max-warnings 0 src",
"build:mjs": "node ./es-to-mjs.js",
"clean": "rimraf dist",
"dev": "NODE_ENV=development webpack-dev-server --colors --progress --config=webpack/webpack.config.js",
"dist": "npm run clean && npm run build && npm run build:mjs",
"lint": "NODE_ENV=test tslint 'src/*.ts'",
"lint:fix": "npm run lint -- --fix",
"prepublish": "if in-publish; then npm run prepublish:compile; fi",
"prepublish:compile": "npm run lint && npm run flow && npm run test:coverage && npm run clean && npm run transpile:lib && npm run transpile:es && npm run copy:mjs && npm run build",
"prepublish:compile": "npm run lint && npm run test:coverage && npm run dist",
"start": "npm run dev",
"test": "NODE_PATH=. NODE_ENV=test ava",
"test:coverage": "nyc --cache npm test",
"test:watch": "npm run test -- --watch",
"transpile:es": "BABEL_ENV=es babel src --out-dir es",
"transpile:lib": "BABEL_ENV=lib babel src --out-dir lib"
"test": "NODE_PATH=. jest",
"test:coverage": "npm run test -- --coverage",
"test:watch": "npm run test -- --watch"
},
"sideEffects": false,
"types": "./index.d.ts",
"version": "2.1.2"
"version": "3.0.0-beta.0"
}
+87
-87

@@ -35,3 +35,3 @@ # micro-memoize

As the author of [`moize`](https://github.com/planttheidea/moize), I created a consistently fast memoization library, but `moize` has a lot of features to satisfy a large number of edge cases. `micro-memoize` is a simpler approach, focusing on the core feature set with a much smaller footprint (~1.1kB minified+gzipped). Stripping out these edge cases also allows `micro-memoize` to be faster across the board than `moize`.
As the author of [`moize`](https://github.com/planttheidea/moize), I created a consistently fast memoization library, but `moize` has a lot of features to satisfy a large number of edge cases. `micro-memoize` is a simpler approach, focusing on the core feature set with a much smaller footprint (~1.2kB minified+gzipped). Stripping out these edge cases also allows `micro-memoize` to be faster across the board than `moize`.

@@ -43,3 +43,3 @@ ## Importing

```javascript
import memoize from "micro-memoize";
import memoize from 'micro-memoize';
```

@@ -50,3 +50,3 @@

```javascript
import memoize from "micro-memoize/mjs";
import memoize from 'micro-memoize/mjs';
```

@@ -57,3 +57,3 @@

```javascript
const memoize = require("micro-memoize").default;
const memoize = require('micro-memoize').default;
```

@@ -65,6 +65,6 @@

// ES2015+
import memoize from "micro-memoize";
import memoize from 'micro-memoize';
// CommonJS
const memoize = require("micro-memoize").default;
const memoize = require('micro-memoize').default;

@@ -80,4 +80,4 @@ // old-school

console.log(memoized("one", "two")); // {one: 'one', two: 'two'}
console.log(memoized("one", "two")); // pulled from cache, {one: 'one', two: 'two'}
console.log(memoized('one', 'two')); // {one: 'one', two: 'two'}
console.log(memoized('one', 'two')); // pulled from cache, {one: 'one', two: 'two'}
```

@@ -99,3 +99,3 @@

```javascript
import { deepEqual } from "fast-equals";
import { deepEqual } from 'fast-equals';

@@ -105,3 +105,3 @@ const deepObject = object => {

foo: object.foo,
bar: object.bar
bar: object.bar,
};

@@ -115,11 +115,11 @@ };

foo: {
deep: "foo"
deep: 'foo',
},
bar: {
deep: "bar"
deep: 'bar',
},
baz: {
deep: "baz"
}
})
deep: 'baz',
},
}),
); // {foo: {deep: 'foo'}, bar: {deep: 'bar'}}

@@ -130,11 +130,11 @@

foo: {
deep: "foo"
deep: 'foo',
},
bar: {
deep: "bar"
deep: 'bar',
},
baz: {
deep: "baz"
}
})
deep: 'baz',
},
}),
); // pulled from cache

@@ -158,3 +158,3 @@ ```

```javascript
import { deepEqual } from "fast-equals";
import { deepEqual } from 'fast-equals';

@@ -164,3 +164,3 @@ const deepObject = object => {

foo: object.foo,
bar: object.bar
bar: object.bar,
};

@@ -172,7 +172,7 @@ };

return (
object1.hasOwnProperty("foo") &&
object2.hasOwnProperty("foo") &&
object1.hasOwnProperty('foo') &&
object2.hasOwnProperty('foo') &&
object1.bar === object2.bar
);
}
},
});

@@ -182,6 +182,6 @@

memoizedShape({
foo: "foo",
bar: "bar",
baz: "baz"
})
foo: 'foo',
bar: 'bar',
baz: 'baz',
}),
); // {foo: {deep: 'foo'}, bar: {deep: 'bar'}}

@@ -191,6 +191,6 @@

memoizedShape({
foo: "not foo",
bar: "bar",
baz: "baz"
})
foo: 'not foo',
bar: 'bar',
baz: 'baz',
}),
); // pulled from cache

@@ -219,3 +219,3 @@ ```

memoized("one", "two");
memoized('one', 'two');

@@ -246,11 +246,11 @@ console.log(memoized.cacheSnapshot.keys); // [['one', 'two']]

console.log(memoized("one", "two")); // ['one', 'two']
console.log(memoized("two", "three")); // ['two', 'three']
console.log(memoized("three", "four")); // ['three', 'four']
console.log(memoized('one', 'two')); // ['one', 'two']
console.log(memoized('two', 'three')); // ['two', 'three']
console.log(memoized('three', 'four')); // ['three', 'four']
console.log(memoized("one", "two")); // pulled from cache
console.log(memoized("two", "three")); // pulled from cache
console.log(memoized("three", "four")); // pulled from cache
console.log(memoized('one', 'two')); // pulled from cache
console.log(memoized('two', 'three')); // pulled from cache
console.log(memoized('three', 'four')); // pulled from cache
console.log(memoized("four", "five")); // ['four', 'five'], drops ['one', 'two'] from cache
console.log(memoized('four', 'five')); // ['four', 'five'], drops ['one', 'two'] from cache
```

@@ -273,18 +273,18 @@

onCacheAdd(cache, options) {
console.log("cache has been added to: ", cache);
console.log("memoized method has the following options applied: ", options);
}
console.log('cache has been added to: ', cache);
console.log('memoized method has the following options applied: ', options);
},
});
memoized("foo", "bar"); // cache has been added to
memoized("foo", "bar");
memoized("foo", "bar");
memoized('foo', 'bar'); // cache has been added to
memoized('foo', 'bar');
memoized('foo', 'bar');
memoized("bar", "foo"); // cache has been added to
memoized("bar", "foo");
memoized("bar", "foo");
memoized('bar', 'foo'); // cache has been added to
memoized('bar', 'foo');
memoized('bar', 'foo');
memoized("foo", "bar");
memoized("foo", "bar");
memoized("foo", "bar");
memoized('foo', 'bar');
memoized('foo', 'bar');
memoized('foo', 'bar');
```

@@ -307,18 +307,18 @@

onCacheChange(cache, options) {
console.log("cache has changed: ", cache);
console.log("memoized method has the following options applied: ", options);
}
console.log('cache has changed: ', cache);
console.log('memoized method has the following options applied: ', options);
},
});
memoized("foo", "bar"); // cache has changed
memoized("foo", "bar");
memoized("foo", "bar");
memoized('foo', 'bar'); // cache has changed
memoized('foo', 'bar');
memoized('foo', 'bar');
memoized("bar", "foo"); // cache has changed
memoized("bar", "foo");
memoized("bar", "foo");
memoized('bar', 'foo'); // cache has changed
memoized('bar', 'foo');
memoized('bar', 'foo');
memoized("foo", "bar"); // cache has changed
memoized("foo", "bar");
memoized("foo", "bar");
memoized('foo', 'bar'); // cache has changed
memoized('foo', 'bar');
memoized('foo', 'bar');
```

@@ -342,18 +342,18 @@

onCacheHit(cache, options) {
console.log("cache was hit: ", cache);
console.log("memoized method has the following options applied: ", options);
}
console.log('cache was hit: ', cache);
console.log('memoized method has the following options applied: ', options);
},
});
memoized("foo", "bar");
memoized("foo", "bar"); // cache was hit
memoized("foo", "bar"); // cache was hit
memoized('foo', 'bar');
memoized('foo', 'bar'); // cache was hit
memoized('foo', 'bar'); // cache was hit
memoized("bar", "foo");
memoized("bar", "foo"); // cache was hit
memoized("bar", "foo"); // cache was hit
memoized('bar', 'foo');
memoized('bar', 'foo'); // cache was hit
memoized('bar', 'foo'); // cache was hit
memoized("foo", "bar"); // cache was hit
memoized("foo", "bar"); // cache was hit
memoized("foo", "bar"); // cache was hit
memoized('foo', 'bar'); // cache was hit
memoized('foo', 'bar'); // cache was hit
memoized('foo', 'bar'); // cache was hit
```

@@ -375,7 +375,7 @@

const memoized = memoize(ignoreFunctionArgs, {
transformKey: JSON.stringify
transformKey: JSON.stringify,
});
console.log(memoized("one", () => {})); // ['one', () => {}]
console.log(memoized("one", () => {})); // pulled from cache, ['one', () => {}]
console.log(memoized('one', () => {})); // ['one', () => {}]
console.log(memoized('one', () => {})); // pulled from cache, ['one', () => {}]
```

@@ -396,9 +396,9 @@

return {
args: JSON.stringify(args)
args: JSON.stringify(args),
};
}
},
});
console.log(memoized("one", () => {})); // ['one', () => {}]
console.log(memoized("one", () => {})); // pulled from cache, ['one', () => {}]
console.log(memoized('one', () => {})); // ['one', () => {}]
console.log(memoized('one', () => {})); // pulled from cache, ['one', () => {}]
```

@@ -430,6 +430,6 @@

memoized.cache.keys.push(["one", "two"]);
memoized.cache.values.push("cached");
memoized.cache.keys.push(['one', 'two']);
memoized.cache.values.push('cached');
console.log(memoized("one", "two")); // 'cached'
console.log(memoized('one', 'two')); // 'cached'
```

@@ -436,0 +436,0 @@

@@ -1,35 +0,43 @@

import babel from 'rollup-plugin-babel';
import {uglify} from 'rollup-plugin-uglify';
import typescript from 'rollup-plugin-typescript';
import { uglify } from 'rollup-plugin-uglify';
export default [
{
input: 'src/index.js',
output: {
exports: 'named',
file: 'dist/micro-memoize.js',
format: 'umd',
name: 'memoize',
sourcemap: true,
},
plugins: [
babel({
exclude: 'node_modules/**',
}),
],
import pkg from './package.json';
const UMD_CONFIG = {
input: 'src/index.ts',
output: {
exports: 'default',
file: pkg.browser,
format: 'umd',
name: pkg.name,
sourcemap: true,
},
{
input: 'src/index.js',
output: {
exports: 'named',
file: 'dist/micro-memoize.min.js',
format: 'umd',
name: 'memoize',
},
plugins: [
babel({
exclude: 'node_modules/**',
}),
uglify(),
],
},
];
plugins: [
typescript({
typescript: require('typescript'),
}),
],
};
const FORMATTED_CONFIG = Object.assign({}, UMD_CONFIG, {
output: [
Object.assign({}, UMD_CONFIG.output, {
file: pkg.main,
format: 'cjs',
}),
Object.assign({}, UMD_CONFIG.output, {
file: pkg.module,
format: 'es',
}),
],
});
const MINIFIED_CONFIG = Object.assign({}, UMD_CONFIG, {
output: Object.assign({}, UMD_CONFIG.output, {
file: pkg.browser.replace('.js', '.min.js'),
sourcemap: false,
}),
plugins: UMD_CONFIG.plugins.concat([uglify()]),
});
export default [UMD_CONFIG, FORMATTED_CONFIG, MINIFIED_CONFIG];

Sorry, the diff of this file is not supported yet

/*
* memoize.js
* by @philogb and @addyosmani
* with further optimizations by @mathias
* and @DmitryBaranovsk
* perf tests: http://bit.ly/q3zpG3
* Released under an MIT license.
*/
module.exports = function memoize(fn) {
return function(...args) {
let index = args.length,
hash = '',
currentArg = null;
currentArg = null;
while (index--) {
currentArg = args[index];
hash += currentArg === Object(currentArg) ? JSON.stringify(currentArg) : currentArg;
fn.memoize || (fn.memoize = {});
}
return hash in fn.memoize ? fn.memoize[hash] : (fn.memoize[hash] = fn.apply(this, args));
};
};
"Name","Overall (average)","Single (average)","Multiple (average)","single primitive","single array","single object","multiple primitive","multiple array","multiple object"
"micro-memoize","43,702,165","51,789,026","35,615,304","57,637,984","48,611,399","49,117,695","40,849,760","29,961,958","36,034,196"
"fast-memoize","39,957,140","78,949,201","965,078","233,789,537","1,585,949","1,472,119","1,158,875","946,388","789,972"
"lodash","14,320,798","27,508,254","1,133,342","32,669,251","24,892,558","24,962,953","1,402,261","1,128,886","868,879"
"memoizee","9,861,157","11,784,109","7,938,205","16,177,336","9,568,376","9,606,616","9,482,240","7,186,371","7,146,006"
"ramda","8,678,762","16,102,353","1,255,172","42,919,616","2,907,167","2,480,276","1,550,152","1,222,321","993,044"
"lru-memoize","7,034,405","7,537,900","6,530,910","8,516,137","7,057,588","7,039,977","6,584,528","6,474,194","6,534,009"
"mem","6,718,548","11,530,426","1,906,669","30,316,899","2,240,383","2,033,998","2,705,018","1,849,057","1,165,934"
"underscore","5,014,181","8,820,887","1,207,475","21,489,781","2,673,530","2,299,352","1,479,025","1,183,156","960,246"
"addy-osmani","4,968,346","7,410,673","2,526,020","17,391,341","2,599,855","2,240,823","5,104,651","1,423,365","1,050,046"
"memoizerific","4,665,606","5,187,389","4,143,824","5,466,050","5,057,754","5,038,363","4,013,486","4,198,578","4,219,410"
'use strict';
const _ = require('lodash');
const fs = require('fs');
const React = require('react');
const Benchmark = require('benchmark');
const Table = require('cli-table2');
const ora = require('ora');
const addyOsmani = require('./addy-osmani');
const fastMemoize = require('fast-memoize');
const lodash = _.memoize;
const lruMemoize = require('lru-memoize').default;
const mem = require('mem');
const memoizee = require('memoizee');
const memoizerific = require('memoizerific');
const memoize = require('../lib').default;
const ramda = require('ramda').memoizeWith;
const underscore = require('underscore').memoize;
const deepEqualFastEquals = require('fast-equals').deepEqual;
const deepEqualLodash = _.isEqual;
const resolveArguments = function() {
return arguments.length > 1
? JSON.stringify(arguments)
: typeof arguments[0] === 'object' ? JSON.stringify(arguments[0]) : arguments[0];
};
const showResults = (benchmarkResults) => {
const table = new Table({
head: ['Name', 'Ops / sec', 'Relative margin of error', 'Sample size']
});
benchmarkResults.forEach((result) => {
const name = result.target.name;
const opsPerSecond = result.target.hz.toLocaleString('en-US', {
maximumFractionDigits: 0
});
const relativeMarginOferror = `± ${result.target.stats.rme.toFixed(2)}%`;
const sampleSize = result.target.stats.sample.length;
table.push([name, opsPerSecond, relativeMarginOferror, sampleSize]);
});
console.log(table.toString()); // eslint-disable-line no-console
};
const sortDescResults = (benchmarkResults) => {
return benchmarkResults.sort((a, b) => {
return a.target.hz < b.target.hz ? 1 : -1;
});
};
const spinner = ora('Running benchmark');
let cliResults = [],
csvResults = {};
const onCycle = (event) => {
cliResults.push(event);
const {currentTarget, target} = event;
if (!csvResults[currentTarget.name]) {
csvResults[currentTarget.name] = {};
}
csvResults[currentTarget.name][target.name] = ~~event.target.hz;
ora(target.name).succeed();
};
const onComplete = () => {
spinner.stop();
const orderedBenchmarkResults = sortDescResults(cliResults);
showResults(orderedBenchmarkResults);
};
const fibonacciSinglePrimitive = (number) => {
return number < 2 ? number : fibonacciSinglePrimitive(number - 1) + fibonacciSinglePrimitive(number - 2);
};
const fibonacciSingleArray = (array) => {
return array[0] < 2 ? array[0] : fibonacciSingleArray([array[0] - 1]) + fibonacciSingleArray([array[0] - 2]);
};
const fibonacciSingleObject = (object) => {
return object.number < 2
? object.number
: fibonacciSingleObject({number: object.number - 1}) + fibonacciSingleObject({number: object.number - 2});
};
const fibonacciMultiplePrimitive = (number, isComplete) => {
if (isComplete) {
return number;
}
const firstValue = number - 1;
const secondValue = number - 2;
return (
fibonacciMultiplePrimitive(firstValue, firstValue < 2) + fibonacciMultiplePrimitive(secondValue, secondValue < 2)
);
};
const fibonacciMultipleArray = (array, check) => {
if (check[0]) {
return array[0];
}
const firstValue = array[0] - 1;
const secondValue = array[0] - 2;
return (
fibonacciMultipleArray([firstValue], [firstValue < 2]) + fibonacciMultipleArray([secondValue], [secondValue < 2])
);
};
const fibonacciMultipleObject = (object, check) => {
if (check.isComplete) {
return object.number;
}
const firstValue = object.number - 1;
const secondValue = object.number - 2;
return (
fibonacciMultipleObject({number: firstValue}, {isComplete: firstValue < 2}) +
fibonacciMultipleObject({number: secondValue}, {isComplete: secondValue < 2})
);
};
const fibonacciMultipleDeepEqual = ({number}) => {
return number < 2
? number
: fibonacciMultipleDeepEqual({number: number - 1}) + fibonacciMultipleDeepEqual({number: number - 2});
};
const getSuiteOptions = (name, resolve) => {
return {
name,
onComplete() {
onComplete();
resolve();
},
onCycle,
onStart() {
console.log(''); // eslint-disable-line no-console
console.log(`Starting cycles for ${name}...`); // eslint-disable-line no-console
cliResults = [];
spinner.start();
},
queued: true
};
};
const runSinglePrimitiveSuite = () => {
// const fibonacciSuite = new Benchmark.Suite('Single parameter (primitive)');
const fibonacciNumber = 35;
const mAddyOsmani = addyOsmani(fibonacciSinglePrimitive);
const mFastMemoize = fastMemoize(fibonacciSinglePrimitive);
const mLodash = lodash(fibonacciSinglePrimitive);
const mLruMemoize = lruMemoize(Infinity)(fibonacciSinglePrimitive);
const mMem = mem(fibonacciSinglePrimitive);
const mMemoizee = memoizee(fibonacciSinglePrimitive);
const mMemoizerific = memoizerific(Infinity)(fibonacciSinglePrimitive);
const mMicroMemoize = memoize(fibonacciSinglePrimitive);
const mRamda = ramda(resolveArguments, fibonacciSinglePrimitive);
const mUnderscore = underscore(fibonacciSinglePrimitive);
return new Promise((resolve) => {
new Benchmark.Suite(getSuiteOptions('single primitive parameter', resolve))
.add('addy-osmani', () => {
mAddyOsmani(fibonacciNumber);
})
.add('fast-memoize', () => {
mFastMemoize(fibonacciNumber);
})
.add('lodash', () => {
mLodash(fibonacciNumber);
})
.add('lru-memoize', () => {
mLruMemoize(fibonacciNumber);
})
.add('mem', () => {
mMem(fibonacciNumber);
})
.add('memoizee', () => {
mMemoizee(fibonacciNumber);
})
.add('memoizerific', () => {
mMemoizerific(fibonacciNumber);
})
.add('micro-memoize', () => {
mMicroMemoize(fibonacciNumber);
})
.add('ramda', () => {
mRamda(fibonacciNumber);
})
.add('underscore', () => {
mUnderscore(fibonacciNumber);
})
.run({async: true});
});
};
const runSingleArraySuite = () => {
const fibonacciNumber = [35];
const mAddyOsmani = addyOsmani(fibonacciSingleArray);
const mFastMemoize = fastMemoize(fibonacciSingleArray);
const mLodash = lodash(fibonacciSingleArray);
const mLruMemoize = lruMemoize(Infinity)(fibonacciSingleArray);
const mMem = mem(fibonacciSingleArray);
const mMemoizee = memoizee(fibonacciSingleArray);
const mMemoizerific = memoizerific(Infinity)(fibonacciSingleArray);
const mMicroMemoize = memoize(fibonacciSingleArray);
const mRamda = ramda(resolveArguments, fibonacciSingleArray);
const mUnderscore = underscore(fibonacciSingleArray, resolveArguments);
return new Promise((resolve) => {
new Benchmark.Suite(getSuiteOptions('single array parameter', resolve))
.add('addy-osmani', () => {
mAddyOsmani(fibonacciNumber);
})
.add('fast-memoize', () => {
mFastMemoize(fibonacciNumber);
})
.add('lodash', () => {
mLodash(fibonacciNumber);
})
.add('lru-memoize', () => {
mLruMemoize(fibonacciNumber);
})
.add('mem', () => {
mMem(fibonacciNumber);
})
.add('memoizee', () => {
mMemoizee(fibonacciNumber);
})
.add('memoizerific', () => {
mMemoizerific(fibonacciNumber);
})
.add('micro-memoize', () => {
mMicroMemoize(fibonacciNumber);
})
.add('ramda', () => {
mRamda(fibonacciNumber);
})
.add('underscore', () => {
mUnderscore(fibonacciNumber);
})
.run({
async: true,
queued: true
});
});
};
const runSingleObjectSuite = () => {
const fibonacciNumber = {
number: 35
};
const mAddyOsmani = addyOsmani(fibonacciSingleObject);
const mFastMemoize = fastMemoize(fibonacciSingleObject);
const mLodash = lodash(fibonacciSingleObject);
const mLruMemoize = lruMemoize(Infinity)(fibonacciSingleObject);
const mMem = mem(fibonacciSingleObject);
const mMemoizee = memoizee(fibonacciSingleObject);
const mMemoizerific = memoizerific(Infinity)(fibonacciSingleObject);
const mMicroMemoize = memoize(fibonacciSingleObject);
const mRamda = ramda(resolveArguments, fibonacciSingleObject);
const mUnderscore = underscore(fibonacciSingleObject, resolveArguments);
return new Promise((resolve) => {
new Benchmark.Suite(getSuiteOptions('single object parameter', resolve))
.add('addy-osmani', () => {
mAddyOsmani(fibonacciNumber);
})
.add('fast-memoize', () => {
mFastMemoize(fibonacciNumber);
})
.add('lodash', () => {
mLodash(fibonacciNumber);
})
.add('lru-memoize', () => {
mLruMemoize(fibonacciNumber);
})
.add('mem', () => {
mMem(fibonacciNumber);
})
.add('memoizee', () => {
mMemoizee(fibonacciNumber);
})
.add('memoizerific', () => {
mMemoizerific(fibonacciNumber);
})
.add('micro-memoize', () => {
mMicroMemoize(fibonacciNumber);
})
.add('ramda', () => {
mRamda(fibonacciNumber);
})
.add('underscore', () => {
mUnderscore(fibonacciNumber);
})
.run({
async: true,
queued: true
});
});
};
const runMultiplePrimitiveSuite = () => {
const fibonacciNumber = 35;
const isComplete = false;
const mAddyOsmani = addyOsmani(fibonacciMultiplePrimitive);
const mFastMemoize = fastMemoize(fibonacciMultiplePrimitive);
const mLodash = lodash(fibonacciMultiplePrimitive, resolveArguments);
const mLruMemoize = lruMemoize(Infinity)(fibonacciMultiplePrimitive);
const mMem = mem(fibonacciMultiplePrimitive);
const mMemoizee = memoizee(fibonacciMultiplePrimitive);
const mMemoizerific = memoizerific(Infinity)(fibonacciMultiplePrimitive);
const mMicroMemoize = memoize(fibonacciMultiplePrimitive);
const mRamda = ramda(resolveArguments, fibonacciMultiplePrimitive);
const mUnderscore = underscore(fibonacciMultiplePrimitive, resolveArguments);
return new Promise((resolve) => {
new Benchmark.Suite(getSuiteOptions('multiple primitive parameters', resolve))
.add('addy-osmani', () => {
mAddyOsmani(fibonacciNumber, isComplete);
})
.add('fast-memoize', () => {
mFastMemoize(fibonacciNumber, isComplete);
})
.add('lodash', () => {
mLodash(fibonacciNumber, isComplete);
})
.add('lru-memoize', () => {
mLruMemoize(fibonacciNumber, isComplete);
})
.add('mem', () => {
mMem(fibonacciNumber, isComplete);
})
.add('memoizee', () => {
mMemoizee(fibonacciNumber, isComplete);
})
.add('memoizerific', () => {
mMemoizerific(fibonacciNumber, isComplete);
})
.add('micro-memoize', () => {
mMicroMemoize(fibonacciNumber, isComplete);
})
.add('ramda', () => {
mRamda(fibonacciNumber, isComplete);
})
.add('underscore', () => {
mUnderscore(fibonacciNumber, isComplete);
})
.run({
async: true,
queued: true
});
});
};
const runMultipleArraySuite = () => {
const fibonacciNumber = [35];
const isComplete = [false];
const mAddyOsmani = addyOsmani(fibonacciMultipleArray);
const mFastMemoize = fastMemoize(fibonacciMultipleArray);
const mLodash = lodash(fibonacciMultipleArray, resolveArguments);
const mLruMemoize = lruMemoize(Infinity)(fibonacciMultipleArray);
const mMem = mem(fibonacciMultipleArray);
const mMemoizee = memoizee(fibonacciMultipleArray);
const mMemoizerific = memoizerific(Infinity)(fibonacciMultipleArray);
const mMicroMemoize = memoize(fibonacciMultipleArray);
const mRamda = ramda(resolveArguments, fibonacciMultipleArray);
const mUnderscore = underscore(fibonacciMultipleArray, resolveArguments);
return new Promise((resolve) => {
new Benchmark.Suite(getSuiteOptions('multiple array parameters', resolve))
.add('addy-osmani', () => {
mAddyOsmani(fibonacciNumber, isComplete);
})
.add('fast-memoize', () => {
mFastMemoize(fibonacciNumber, isComplete);
})
.add('lodash', () => {
mLodash(fibonacciNumber, isComplete);
})
.add('lru-memoize', () => {
mLruMemoize(fibonacciNumber, isComplete);
})
.add('mem', () => {
mMem(fibonacciNumber, isComplete);
})
.add('memoizee', () => {
mMemoizee(fibonacciNumber, isComplete);
})
.add('memoizerific', () => {
mMemoizerific(fibonacciNumber, isComplete);
})
.add('micro-memoize', () => {
mMicroMemoize(fibonacciNumber, isComplete);
})
.add('ramda', () => {
mRamda(fibonacciNumber, isComplete);
})
.add('underscore', () => {
mUnderscore(fibonacciNumber, isComplete);
})
.run({
async: true,
queued: true
});
});
};
const runMultipleObjectSuite = () => {
const fibonacciNumber = {number: 35};
const isComplete = {isComplete: false};
const mAddyOsmani = addyOsmani(fibonacciMultipleObject);
const mFastMemoize = fastMemoize(fibonacciMultipleObject);
const mLodash = lodash(fibonacciMultipleObject, resolveArguments);
const mLruMemoize = lruMemoize(Infinity)(fibonacciMultipleObject);
const mMem = mem(fibonacciMultipleObject);
const mMemoizee = memoizee(fibonacciMultipleObject);
const mMemoizerific = memoizerific(Infinity)(fibonacciMultipleObject);
const mMicroMemoize = memoize(fibonacciMultipleObject);
const mRamda = ramda(resolveArguments, fibonacciMultipleObject);
const mUnderscore = underscore(fibonacciMultipleObject, resolveArguments);
return new Promise((resolve) => {
new Benchmark.Suite(getSuiteOptions('multiple object parameters', resolve))
.add('addy-osmani', () => {
mAddyOsmani(fibonacciNumber, isComplete);
})
.add('fast-memoize', () => {
mFastMemoize(fibonacciNumber, isComplete);
})
.add('lodash', () => {
mLodash(fibonacciNumber, isComplete);
})
.add('lru-memoize', () => {
mLruMemoize(fibonacciNumber, isComplete);
})
.add('mem', () => {
mMem(fibonacciNumber, isComplete);
})
.add('memoizee', () => {
mMemoizee(fibonacciNumber, isComplete);
})
.add('memoizerific', () => {
mMemoizerific(fibonacciNumber, isComplete);
})
.add('micro-memoize', () => {
mMicroMemoize(fibonacciNumber, isComplete);
})
.add('ramda', () => {
mRamda(fibonacciNumber, isComplete);
})
.add('underscore', () => {
mUnderscore(fibonacciNumber, isComplete);
})
.run({
async: true,
queued: true
});
});
};
const runAlternativeOptionsSuite = () => {
const mMoizeDeep = memoize(fibonacciMultipleDeepEqual, {
isMatchingKey: deepEqualFastEquals
});
const mMoizeLodashDeep = memoize(fibonacciMultipleDeepEqual, {
isMatchingKey: deepEqualLodash
});
const mMoizeSerialize = memoize(fibonacciMultipleDeepEqual, {
transformKey: JSON.stringify
});
const chooseSpecificArgs = (foo, bar, baz) => {
return [foo, baz];
};
const mMoizeSpecificArgs = memoize(chooseSpecificArgs, {
transformKey(args) {
let index = args.length,
newKey = [];
while (--index) {
newKey[index - 1] = args[index];
}
return newKey;
}
});
const mMoizeMaxArgs = memoize(
(one, two, three) => {
return [one, two, three];
},
{
transformKey(args) {
return [args[0], args[1]];
}
}
);
const object1 = {foo: 'bar'};
const object2 = ['foo'];
return new Promise((resolve) => {
new Benchmark.Suite('Alternative options', getSuiteOptions('alternative options', resolve))
.add('moize serialized', () => {
mMoizeSerialize({number: 35});
})
.add('moize deep equals', () => {
mMoizeDeep({number: 35});
})
.add('moize deep equals (lodash isEqual)', () => {
mMoizeLodashDeep({number: 35});
})
.add('moize (transform args)', () => {
mMoizeSpecificArgs('foo', object1, object2);
})
.add('moize (maximum args)', () => {
mMoizeMaxArgs('foo', object1, object2);
})
.run({
async: true,
queued: true
});
});
};
const writeCsv = () => {
let invidualResultsHeaders = ['Name', 'Overall (average)', 'Single (average)', 'Multiple (average)'];
const individualTableMap = Object.keys(csvResults).reduce((rows, key) => {
const header = key.replace(/ (parameters|parameter)/, '');
if (!~invidualResultsHeaders.indexOf(header)) {
invidualResultsHeaders.push(header);
}
return Object.keys(csvResults[key]).reduce((values, library) => {
if (!rows[library]) {
rows[library] = {};
}
rows[library][header] = csvResults[key][library];
return rows;
}, rows);
}, {});
const averages = Object.keys(individualTableMap).reduce((rows, library) => {
if (!rows[library]) {
rows[library] = {};
}
const libraryAverages = Object.keys(individualTableMap[library]).reduce(
({multiple, single}, header) => {
if (~header.indexOf('multiple')) {
multiple.length++;
multiple.total += ~~individualTableMap[library][header];
} else {
single.length++;
single.total += ~~individualTableMap[library][header];
}
return {
multiple,
single
};
},
{
multiple: {
length: 0,
total: 0
},
single: {
length: 0,
total: 0
}
}
);
rows[library] = {
multiple: libraryAverages.multiple.length
? ~~(libraryAverages.multiple.total / libraryAverages.multiple.length)
: 0,
overall: libraryAverages.multiple.length
? ~~(
(libraryAverages.multiple.total + libraryAverages.single.total) /
(libraryAverages.multiple.length + libraryAverages.single.length)
)
: 0,
single: libraryAverages.single.length ? ~~(libraryAverages.single.total / libraryAverages.single.length) : 0
};
return rows;
}, {});
const individualRows = _.orderBy(
Object.keys(individualTableMap).map((key) => {
const values = invidualResultsHeaders.slice(4).map((header) => {
return individualTableMap[key][header];
});
return [key, averages[key].overall, averages[key].single, averages[key].multiple].concat(values);
}),
[1, 2],
['desc', 'desc']
);
const individualCsvText = `${invidualResultsHeaders
.map((header) => {
return `"${header}"`;
})
.join(',')}\n${individualRows
.map((row) => {
return row
.map((value) => {
return value ? `"${value.toLocaleString()}"` : '"N/A"';
})
.join(',');
})
.join('\n')}`;
// write to file
if (fs && fs.writeFileSync) {
fs.writeFileSync('benchmark/benchmark_results.csv', individualCsvText, 'utf8');
console.log('Benchmarks done! Results saved to benchmark_results.csv');
} else {
console.log('Benchmarks done!');
}
};
if (process.env.ALTERNATIVE) {
Promise.resolve().then(runAlternativeOptionsSuite);
} else {
Promise.resolve()
.then(runSinglePrimitiveSuite)
.then(runSingleArraySuite)
.then(runSingleObjectSuite)
.then(runMultiplePrimitiveSuite)
.then(runMultipleArraySuite)
.then(runMultipleObjectSuite)
.then(writeCsv);
}
'use strict';
const memoize = require('../lib').default;
const fibonacciSinglePrimitive = (number) => {
return number < 2 ? number : fibonacciSinglePrimitive(number - 1) + fibonacciSinglePrimitive(number - 2);
};
const fibonacciSingleArray = (array) => {
return array[0] < 2 ? array[0] : fibonacciSingleArray([array[0] - 1]) + fibonacciSingleArray([array[0] - 2]);
};
const fibonacciSingleObject = (object) => {
return object.number < 2
? object.number
: fibonacciSingleObject({number: object.number - 1}) + fibonacciSingleObject({number: object.number - 2});
};
const fibonacciMultiplePrimitive = (number, isComplete) => {
if (isComplete) {
return number;
}
const firstValue = number - 1;
const secondValue = number - 2;
return (
fibonacciMultiplePrimitive(firstValue, firstValue < 2) + fibonacciMultiplePrimitive(secondValue, secondValue < 2)
);
};
const fibonacciMultipleArray = (array, check) => {
if (check[0]) {
return array[0];
}
const firstValue = array[0] - 1;
const secondValue = array[0] - 2;
return (
fibonacciMultipleArray([firstValue], [firstValue < 2]) + fibonacciMultipleArray([secondValue], [secondValue < 2])
);
};
const fibonacciMultipleObject = (object, check) => {
if (check.isComplete) {
return object.number;
}
const firstValue = object.number - 1;
const secondValue = object.number - 2;
return (
fibonacciMultipleObject({number: firstValue}, {isComplete: firstValue < 2}) +
fibonacciMultipleObject({number: secondValue}, {isComplete: secondValue < 2})
);
};
const number = 35;
const array = [number];
const object = {number};
const isCompleteBoolean = false;
const isCompleteArray = [false];
const isCompleteObject = {isComplete: false};
fibonacciSinglePrimitive(number);
fibonacciSinglePrimitive(number);
fibonacciSinglePrimitive(number);
fibonacciSingleArray(array);
fibonacciSingleArray(array);
fibonacciSingleArray(array);
fibonacciSingleObject(object);
fibonacciSingleObject(object);
fibonacciSingleObject(object);
fibonacciMultiplePrimitive(number, isCompleteBoolean);
fibonacciMultiplePrimitive(number, isCompleteBoolean);
fibonacciMultiplePrimitive(number, isCompleteBoolean);
fibonacciMultipleArray(array, isCompleteArray);
fibonacciMultipleArray(array, isCompleteArray);
fibonacciMultipleArray(array, isCompleteArray);
fibonacciMultipleObject(object, isCompleteObject);
fibonacciMultipleObject(object, isCompleteObject);
fibonacciMultipleObject(object, isCompleteObject);
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
// types
// utils
import { assign, cloneArray, createGetKeyIndex, createSetPromiseHandler, isSameValueZero, onCacheOperation, orderByLru } from './utils';
/**
* @function memoize
*
* @description
* get the memoized version of the method passed
*
* @param {function} fn the method to memoize
* @param {Object} [options={}] the options to build the memoizer with
* @param {boolean} [options.isEqual=isSameValueZero] the method to compare equality of keys with
* @param {number} [options.maxSize=1] the number of items to store in cache
* @returns {function} the memoized method
*/
export default function memoize(fn, options) {
// if it is a memoized method, don't re-memoize it
if (fn.isMemoized) {
return fn;
}
var _ref = options || {},
_ref$isEqual = _ref.isEqual,
isEqual = _ref$isEqual === void 0 ? isSameValueZero : _ref$isEqual,
isMatchingKey = _ref.isMatchingKey,
_ref$isPromise = _ref.isPromise,
isPromise = _ref$isPromise === void 0 ? false : _ref$isPromise,
_ref$maxSize = _ref.maxSize,
maxSize = _ref$maxSize === void 0 ? 1 : _ref$maxSize,
_ref$onCacheAdd = _ref.onCacheAdd,
onCacheAdd = _ref$onCacheAdd === void 0 ? onCacheOperation : _ref$onCacheAdd,
_ref$onCacheChange = _ref.onCacheChange,
onCacheChange = _ref$onCacheChange === void 0 ? onCacheOperation : _ref$onCacheChange,
_ref$onCacheHit = _ref.onCacheHit,
onCacheHit = _ref$onCacheHit === void 0 ? onCacheOperation : _ref$onCacheHit,
transformKey = _ref.transformKey,
extraOptions = _objectWithoutPropertiesLoose(_ref, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = assign({}, extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey
});
var getKeyIndex = createGetKeyIndex(isEqual, isMatchingKey);
var setPromiseHandler = createSetPromiseHandler(normalizedOptions);
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var cache = {
keys: [],
get size() {
return cache.keys.length;
},
values: []
};
var keys = cache.keys,
values = cache.values;
/**
* @function memoized
*
* @description
* the memoized version of the method passed
*
* @param {...Array<any>} key the arguments passed, which create a unique cache key
* @returns {any} the value of the method called with the arguments
*/
function memoized() {
var args = arguments;
var normalizedArgs = shouldCloneArguments ? cloneArray(args) : args;
var key = transformKey ? transformKey(normalizedArgs) : normalizedArgs;
var keyIndex = getKeyIndex(keys, key);
if (~keyIndex) {
onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(keys, keys[keyIndex], keyIndex);
orderByLru(values, values[keyIndex], keyIndex);
onCacheChange(cache, normalizedOptions, memoized);
}
} else {
if (keys.length >= maxSize) {
keys.pop();
values.pop();
}
var newKey = shouldCloneArguments ? key : cloneArray(normalizedArgs);
var newValue = fn.apply(this, args);
orderByLru(keys, newKey, keys.length);
orderByLru(values, newValue, values.length);
if (isPromise) {
setPromiseHandler(cache, memoized);
}
onCacheAdd(cache, normalizedOptions, memoized);
onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
get: function get() {
return cache;
}
},
cacheSnapshot: {
configurable: true,
get: function get() {
return {
keys: cloneArray(cache.keys),
size: cache.size,
values: cloneArray(cache.values)
};
}
},
isMemoized: {
configurable: true,
get: function get() {
return true;
}
},
options: {
configurable: true,
get: function get() {
return normalizedOptions;
}
}
});
return memoized;
}
// types
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @function assign
*
* @description
* merge the sources into the target, as you would with Object.assign()
*
* @param {Object} target object to merge into
* @param {...Array<Object>} sources the sources to merge into the target
* @returns {Object} the merged object
*/
export var assign = function assign(target) {
var source;
for (var index = 0; index < (arguments.length <= 1 ? 0 : arguments.length - 1); index++) {
source = index + 1 < 1 || arguments.length <= index + 1 ? undefined : arguments[index + 1];
if (source && typeof source === 'object') {
for (var key in source) {
if (hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
/**
* @function cloneArray
*
* @description
* clone the array-like object and return the new array
*
* @param {Array<any>|Arguments} arrayLike the array-like object to clone
* @returns {Array<any>} the clone of the array
*/
export var cloneArray = function cloneArray(arrayLike) {
var length = arrayLike.length;
if (!length) {
return [];
}
if (length === 1) {
return [arrayLike[0]];
}
if (length === 2) {
return [arrayLike[0], arrayLike[1]];
}
if (length === 3) {
return [arrayLike[0], arrayLike[1], arrayLike[2]];
}
var array = new Array(length);
for (var index = 0; index < length; index++) {
array[index] = arrayLike[index];
}
return array;
};
export var createAreKeysEqual = function createAreKeysEqual(isEqual
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param {Array<any>} keys1 the keys array to test against
* @param {Array<any>} keys2 the keys array to test
* @returns {boolean} are the keys shallowly equal
*/
) {
return function (keys1, keys2) {
if (keys1.length !== keys2.length) {
return false;
}
for (var index = 0, length = keys1.length; index < length; index++) {
if (!isEqual(keys1[index], keys2[index])) {
return false;
}
}
return true;
};
};
export var createGetKeyIndex = function createGetKeyIndex(isEqual, isMatchingKey) {
var areKeysEqual = typeof isMatchingKey === 'function' ? isMatchingKey : createAreKeysEqual(isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param {Array<Array<any>>} allKeys the list of all available keys
* @param {Array<any>} keysToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function (allKeys, keysToMatch) {
for (var index = 0; index < allKeys.length; index++) {
if (areKeysEqual(allKeys[index], keysToMatch)) {
return index;
}
}
return -1;
};
};
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero
*
* @param {any} object1 the first object to compare
* @param {any} object2 the second object to compare
* @returns {boolean} are the two objects equal
*/
export var isSameValueZero = function isSameValueZero(object1, object2) {
return object1 === object2 || object1 !== object1 && object2 !== object2;
};
export var onCacheOperation = function onCacheOperation(cacheIgnored, optionsIgnored, memoizedIgnored) {};
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param {Array<any>} array the array to order
* @param {any} value the value to assign at the beginning of the array
* @param {number} startingIndex the index of the item to move to the front
*/
export var orderByLru = function orderByLru(array, value, startingIndex) {
var index = startingIndex;
while (index--) {
array[index + 1] = array[index];
}
array[0] = value;
};
/**
* @function createSetPromiseHandler
*
* @description
* update the promise method to auto-remove from cache if rejected, and if resolved then fire cache hit / changed
*
* @param {Options} options the options for the memoized function
* @param {function(Cache, function): function} memoized the memoized function
*/
export var createSetPromiseHandler = function createSetPromiseHandler(options) {
var getKeyIndex = createGetKeyIndex(options.isEqual, options.isMatchingKey);
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0].then(function (value) {
options.onCacheHit(cache, options, memoized);
options.onCacheChange(cache, options, memoized);
return value;
}).catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
};
declare module 'micro-memoize' {
declare type Cache = {
keys: Array<any>,
size: number,
values: Array<any>
};
declare type Options = {
isEqual?: (firstValue: any, secondValue: any) => boolean,
isMatchingKey?: (cacheKey: Array<any>, key: Array<any>) => boolean,
isPromise?: boolean,
maxSize?: number,
onCacheAdd?: (cache: Cache, options: Options) => void,
onCacheChange?: (cache: Cache, options: Options) => void,
onCacheHit?: (cache: Cache, options: Options) => void,
transformKey?: (args: any[]) => any
};
declare type Fn = (...args: any[]) => any;
declare module.exports: {
(fn: Fn, options?: Options): Fn
};
}
"use strict";
exports.__esModule = true;
exports.default = memoize;
var _utils = require("./utils");
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
/**
* @function memoize
*
* @description
* get the memoized version of the method passed
*
* @param {function} fn the method to memoize
* @param {Object} [options={}] the options to build the memoizer with
* @param {boolean} [options.isEqual=isSameValueZero] the method to compare equality of keys with
* @param {number} [options.maxSize=1] the number of items to store in cache
* @returns {function} the memoized method
*/
function memoize(fn, options) {
// if it is a memoized method, don't re-memoize it
if (fn.isMemoized) {
return fn;
}
var _ref = options || {},
_ref$isEqual = _ref.isEqual,
isEqual = _ref$isEqual === void 0 ? _utils.isSameValueZero : _ref$isEqual,
isMatchingKey = _ref.isMatchingKey,
_ref$isPromise = _ref.isPromise,
isPromise = _ref$isPromise === void 0 ? false : _ref$isPromise,
_ref$maxSize = _ref.maxSize,
maxSize = _ref$maxSize === void 0 ? 1 : _ref$maxSize,
_ref$onCacheAdd = _ref.onCacheAdd,
onCacheAdd = _ref$onCacheAdd === void 0 ? _utils.onCacheOperation : _ref$onCacheAdd,
_ref$onCacheChange = _ref.onCacheChange,
onCacheChange = _ref$onCacheChange === void 0 ? _utils.onCacheOperation : _ref$onCacheChange,
_ref$onCacheHit = _ref.onCacheHit,
onCacheHit = _ref$onCacheHit === void 0 ? _utils.onCacheOperation : _ref$onCacheHit,
transformKey = _ref.transformKey,
extraOptions = _objectWithoutPropertiesLoose(_ref, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = (0, _utils.assign)({}, extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey
});
var getKeyIndex = (0, _utils.createGetKeyIndex)(isEqual, isMatchingKey);
var setPromiseHandler = (0, _utils.createSetPromiseHandler)(normalizedOptions);
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var cache = {
keys: [],
get size() {
return cache.keys.length;
},
values: []
};
var keys = cache.keys,
values = cache.values;
/**
* @function memoized
*
* @description
* the memoized version of the method passed
*
* @param {...Array<any>} key the arguments passed, which create a unique cache key
* @returns {any} the value of the method called with the arguments
*/
function memoized() {
var args = arguments;
var normalizedArgs = shouldCloneArguments ? (0, _utils.cloneArray)(args) : args;
var key = transformKey ? transformKey(normalizedArgs) : normalizedArgs;
var keyIndex = getKeyIndex(keys, key);
if (~keyIndex) {
onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
(0, _utils.orderByLru)(keys, keys[keyIndex], keyIndex);
(0, _utils.orderByLru)(values, values[keyIndex], keyIndex);
onCacheChange(cache, normalizedOptions, memoized);
}
} else {
if (keys.length >= maxSize) {
keys.pop();
values.pop();
}
var newKey = shouldCloneArguments ? key : (0, _utils.cloneArray)(normalizedArgs);
var newValue = fn.apply(this, args);
(0, _utils.orderByLru)(keys, newKey, keys.length);
(0, _utils.orderByLru)(values, newValue, values.length);
if (isPromise) {
setPromiseHandler(cache, memoized);
}
onCacheAdd(cache, normalizedOptions, memoized);
onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
get: function get() {
return cache;
}
},
cacheSnapshot: {
configurable: true,
get: function get() {
return {
keys: (0, _utils.cloneArray)(cache.keys),
size: cache.size,
values: (0, _utils.cloneArray)(cache.values)
};
}
},
isMemoized: {
configurable: true,
get: function get() {
return true;
}
},
options: {
configurable: true,
get: function get() {
return normalizedOptions;
}
}
});
return memoized;
}
"use strict";
"use strict";
exports.__esModule = true;
exports.createSetPromiseHandler = exports.orderByLru = exports.onCacheOperation = exports.isSameValueZero = exports.createGetKeyIndex = exports.createAreKeysEqual = exports.cloneArray = exports.assign = void 0;
// types
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @function assign
*
* @description
* merge the sources into the target, as you would with Object.assign()
*
* @param {Object} target object to merge into
* @param {...Array<Object>} sources the sources to merge into the target
* @returns {Object} the merged object
*/
var assign = function assign(target) {
var source;
for (var index = 0; index < (arguments.length <= 1 ? 0 : arguments.length - 1); index++) {
source = index + 1 < 1 || arguments.length <= index + 1 ? undefined : arguments[index + 1];
if (source && typeof source === 'object') {
for (var key in source) {
if (hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
/**
* @function cloneArray
*
* @description
* clone the array-like object and return the new array
*
* @param {Array<any>|Arguments} arrayLike the array-like object to clone
* @returns {Array<any>} the clone of the array
*/
exports.assign = assign;
var cloneArray = function cloneArray(arrayLike) {
var length = arrayLike.length;
if (!length) {
return [];
}
if (length === 1) {
return [arrayLike[0]];
}
if (length === 2) {
return [arrayLike[0], arrayLike[1]];
}
if (length === 3) {
return [arrayLike[0], arrayLike[1], arrayLike[2]];
}
var array = new Array(length);
for (var index = 0; index < length; index++) {
array[index] = arrayLike[index];
}
return array;
};
exports.cloneArray = cloneArray;
var createAreKeysEqual = function createAreKeysEqual(isEqual
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param {Array<any>} keys1 the keys array to test against
* @param {Array<any>} keys2 the keys array to test
* @returns {boolean} are the keys shallowly equal
*/
) {
return function (keys1, keys2) {
if (keys1.length !== keys2.length) {
return false;
}
for (var index = 0, length = keys1.length; index < length; index++) {
if (!isEqual(keys1[index], keys2[index])) {
return false;
}
}
return true;
};
};
exports.createAreKeysEqual = createAreKeysEqual;
var createGetKeyIndex = function createGetKeyIndex(isEqual, isMatchingKey) {
var areKeysEqual = typeof isMatchingKey === 'function' ? isMatchingKey : createAreKeysEqual(isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param {Array<Array<any>>} allKeys the list of all available keys
* @param {Array<any>} keysToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function (allKeys, keysToMatch) {
for (var index = 0; index < allKeys.length; index++) {
if (areKeysEqual(allKeys[index], keysToMatch)) {
return index;
}
}
return -1;
};
};
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero
*
* @param {any} object1 the first object to compare
* @param {any} object2 the second object to compare
* @returns {boolean} are the two objects equal
*/
exports.createGetKeyIndex = createGetKeyIndex;
var isSameValueZero = function isSameValueZero(object1, object2) {
return object1 === object2 || object1 !== object1 && object2 !== object2;
};
exports.isSameValueZero = isSameValueZero;
var onCacheOperation = function onCacheOperation(cacheIgnored, optionsIgnored, memoizedIgnored) {};
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param {Array<any>} array the array to order
* @param {any} value the value to assign at the beginning of the array
* @param {number} startingIndex the index of the item to move to the front
*/
exports.onCacheOperation = onCacheOperation;
var orderByLru = function orderByLru(array, value, startingIndex) {
var index = startingIndex;
while (index--) {
array[index + 1] = array[index];
}
array[0] = value;
};
/**
* @function createSetPromiseHandler
*
* @description
* update the promise method to auto-remove from cache if rejected, and if resolved then fire cache hit / changed
*
* @param {Options} options the options for the memoized function
* @param {function(Cache, function): function} memoized the memoized function
*/
exports.orderByLru = orderByLru;
var createSetPromiseHandler = function createSetPromiseHandler(options) {
var getKeyIndex = createGetKeyIndex(options.isEqual, options.isMatchingKey);
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0].then(function (value) {
options.onCacheHit(cache, options, memoized);
options.onCacheChange(cache, options, memoized);
return value;
}).catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
};
exports.createSetPromiseHandler = createSetPromiseHandler;
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
// types
// utils
import { assign, cloneArray, createGetKeyIndex, createSetPromiseHandler, isSameValueZero, onCacheOperation, orderByLru } from './utils';
/**
* @function memoize
*
* @description
* get the memoized version of the method passed
*
* @param {function} fn the method to memoize
* @param {Object} [options={}] the options to build the memoizer with
* @param {boolean} [options.isEqual=isSameValueZero] the method to compare equality of keys with
* @param {number} [options.maxSize=1] the number of items to store in cache
* @returns {function} the memoized method
*/
export default function memoize(fn, options) {
// if it is a memoized method, don't re-memoize it
if (fn.isMemoized) {
return fn;
}
var _ref = options || {},
_ref$isEqual = _ref.isEqual,
isEqual = _ref$isEqual === void 0 ? isSameValueZero : _ref$isEqual,
isMatchingKey = _ref.isMatchingKey,
_ref$isPromise = _ref.isPromise,
isPromise = _ref$isPromise === void 0 ? false : _ref$isPromise,
_ref$maxSize = _ref.maxSize,
maxSize = _ref$maxSize === void 0 ? 1 : _ref$maxSize,
_ref$onCacheAdd = _ref.onCacheAdd,
onCacheAdd = _ref$onCacheAdd === void 0 ? onCacheOperation : _ref$onCacheAdd,
_ref$onCacheChange = _ref.onCacheChange,
onCacheChange = _ref$onCacheChange === void 0 ? onCacheOperation : _ref$onCacheChange,
_ref$onCacheHit = _ref.onCacheHit,
onCacheHit = _ref$onCacheHit === void 0 ? onCacheOperation : _ref$onCacheHit,
transformKey = _ref.transformKey,
extraOptions = _objectWithoutPropertiesLoose(_ref, ["isEqual", "isMatchingKey", "isPromise", "maxSize", "onCacheAdd", "onCacheChange", "onCacheHit", "transformKey"]);
var normalizedOptions = assign({}, extraOptions, {
isEqual: isEqual,
isMatchingKey: isMatchingKey,
isPromise: isPromise,
maxSize: maxSize,
onCacheAdd: onCacheAdd,
onCacheChange: onCacheChange,
onCacheHit: onCacheHit,
transformKey: transformKey
});
var getKeyIndex = createGetKeyIndex(isEqual, isMatchingKey);
var setPromiseHandler = createSetPromiseHandler(normalizedOptions);
var shouldCloneArguments = !!(transformKey || isMatchingKey);
var cache = {
keys: [],
get size() {
return cache.keys.length;
},
values: []
};
var keys = cache.keys,
values = cache.values;
/**
* @function memoized
*
* @description
* the memoized version of the method passed
*
* @param {...Array<any>} key the arguments passed, which create a unique cache key
* @returns {any} the value of the method called with the arguments
*/
function memoized() {
var args = arguments;
var normalizedArgs = shouldCloneArguments ? cloneArray(args) : args;
var key = transformKey ? transformKey(normalizedArgs) : normalizedArgs;
var keyIndex = getKeyIndex(keys, key);
if (~keyIndex) {
onCacheHit(cache, normalizedOptions, memoized);
if (keyIndex) {
orderByLru(keys, keys[keyIndex], keyIndex);
orderByLru(values, values[keyIndex], keyIndex);
onCacheChange(cache, normalizedOptions, memoized);
}
} else {
if (keys.length >= maxSize) {
keys.pop();
values.pop();
}
var newKey = shouldCloneArguments ? key : cloneArray(normalizedArgs);
var newValue = fn.apply(this, args);
orderByLru(keys, newKey, keys.length);
orderByLru(values, newValue, values.length);
if (isPromise) {
setPromiseHandler(cache, memoized);
}
onCacheAdd(cache, normalizedOptions, memoized);
onCacheChange(cache, normalizedOptions, memoized);
}
return values[0];
}
Object.defineProperties(memoized, {
cache: {
configurable: true,
get: function get() {
return cache;
}
},
cacheSnapshot: {
configurable: true,
get: function get() {
return {
keys: cloneArray(cache.keys),
size: cache.size,
values: cloneArray(cache.values)
};
}
},
isMemoized: {
configurable: true,
get: function get() {
return true;
}
},
options: {
configurable: true,
get: function get() {
return normalizedOptions;
}
}
});
return memoized;
}
// types
var hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* @function assign
*
* @description
* merge the sources into the target, as you would with Object.assign()
*
* @param {Object} target object to merge into
* @param {...Array<Object>} sources the sources to merge into the target
* @returns {Object} the merged object
*/
export var assign = function assign(target) {
var source;
for (var index = 0; index < (arguments.length <= 1 ? 0 : arguments.length - 1); index++) {
source = index + 1 < 1 || arguments.length <= index + 1 ? undefined : arguments[index + 1];
if (source && typeof source === 'object') {
for (var key in source) {
if (hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
}
return target;
};
/**
* @function cloneArray
*
* @description
* clone the array-like object and return the new array
*
* @param {Array<any>|Arguments} arrayLike the array-like object to clone
* @returns {Array<any>} the clone of the array
*/
export var cloneArray = function cloneArray(arrayLike) {
var length = arrayLike.length;
if (!length) {
return [];
}
if (length === 1) {
return [arrayLike[0]];
}
if (length === 2) {
return [arrayLike[0], arrayLike[1]];
}
if (length === 3) {
return [arrayLike[0], arrayLike[1], arrayLike[2]];
}
var array = new Array(length);
for (var index = 0; index < length; index++) {
array[index] = arrayLike[index];
}
return array;
};
export var createAreKeysEqual = function createAreKeysEqual(isEqual
/**
* @function areKeysEqual
*
* @description
* are the keys shallowly equal to one another
*
* @param {Array<any>} keys1 the keys array to test against
* @param {Array<any>} keys2 the keys array to test
* @returns {boolean} are the keys shallowly equal
*/
) {
return function (keys1, keys2) {
if (keys1.length !== keys2.length) {
return false;
}
for (var index = 0, length = keys1.length; index < length; index++) {
if (!isEqual(keys1[index], keys2[index])) {
return false;
}
}
return true;
};
};
export var createGetKeyIndex = function createGetKeyIndex(isEqual, isMatchingKey) {
var areKeysEqual = typeof isMatchingKey === 'function' ? isMatchingKey : createAreKeysEqual(isEqual);
/**
* @function getKeyIndex
*
* @description
* get the index of the matching key
*
* @param {Array<Array<any>>} allKeys the list of all available keys
* @param {Array<any>} keysToMatch the key to try to match
*
* @returns {number} the index of the matching key value, or -1
*/
return function (allKeys, keysToMatch) {
for (var index = 0; index < allKeys.length; index++) {
if (areKeysEqual(allKeys[index], keysToMatch)) {
return index;
}
}
return -1;
};
};
/**
* @function isSameValueZero
*
* @description
* are the objects equal based on SameValueZero
*
* @param {any} object1 the first object to compare
* @param {any} object2 the second object to compare
* @returns {boolean} are the two objects equal
*/
export var isSameValueZero = function isSameValueZero(object1, object2) {
return object1 === object2 || object1 !== object1 && object2 !== object2;
};
export var onCacheOperation = function onCacheOperation(cacheIgnored, optionsIgnored, memoizedIgnored) {};
/**
* @function orderByLru
*
* @description
* order the array based on a Least-Recently-Used basis
*
* @param {Array<any>} array the array to order
* @param {any} value the value to assign at the beginning of the array
* @param {number} startingIndex the index of the item to move to the front
*/
export var orderByLru = function orderByLru(array, value, startingIndex) {
var index = startingIndex;
while (index--) {
array[index + 1] = array[index];
}
array[0] = value;
};
/**
* @function createSetPromiseHandler
*
* @description
* update the promise method to auto-remove from cache if rejected, and if resolved then fire cache hit / changed
*
* @param {Options} options the options for the memoized function
* @param {function(Cache, function): function} memoized the memoized function
*/
export var createSetPromiseHandler = function createSetPromiseHandler(options) {
var getKeyIndex = createGetKeyIndex(options.isEqual, options.isMatchingKey);
return function (cache, memoized) {
var key = cache.keys[0];
cache.values[0] = cache.values[0].then(function (value) {
options.onCacheHit(cache, options, memoized);
options.onCacheChange(cache, options, memoized);
return value;
}).catch(function (error) {
var keyIndex = getKeyIndex(cache.keys, key);
if (~keyIndex) {
cache.keys.splice(keyIndex, 1);
cache.values.splice(keyIndex, 1);
}
throw error;
});
};
};

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display