Skip to content

Commit

Permalink
Meta tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Mar 12, 2019
1 parent 6887496 commit 003c2ef
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 45 deletions.
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface Options<
*
* You could for example change it to only cache on the first argument `x => JSON.stringify(x)`.
*/
readonly cacheKey?: (...args: ArgumentsType) => CacheKeyType;
readonly cacheKey?: (...arguments: ArgumentsType) => CacheKeyType;

/**
* Use a different cache storage. Must implement the following methods: `.has(key)`, `.get(key)`, `.set(key, value)`, `.delete(key)`, and optionally `.clear()`. You could for example use a `WeakMap` instead or [`quick-lru`](https://github.com/sindresorhus/quick-lru) for a LRU cache.
Expand Down
28 changes: 13 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ const mapAgeCleaner = require('map-age-cleaner');

const cacheStore = new WeakMap();

const defaultCacheKey = (...args) => {
if (args.length === 0) {
const defaultCacheKey = (...arguments_) => {
if (arguments_.length === 0) {
return '__defaultKey';
}

if (args.length === 1) {
const [firstArgument] = args;
if (arguments_.length === 1) {
const [firstArgument] = arguments_;
if (
firstArgument === null ||
firstArgument === undefined ||
Expand All @@ -21,7 +21,7 @@ const defaultCacheKey = (...args) => {
}
}

return JSON.stringify(args);
return JSON.stringify(arguments_);
};

const mem = (fn, options) => {
Expand All @@ -45,25 +45,23 @@ const mem = (fn, options) => {
});
};

const memoized = function (...args) {
const key = options.cacheKey(...args);
const memoized = function (...arguments_) {
const key = options.cacheKey(...arguments_);

if (cache.has(key)) {
const c = cache.get(key);

return c.data;
return cache.get(key).data;
}

const ret = fn.call(this, ...args);
const cacheItem = fn.call(this, ...arguments_);

setData(key, ret);
setData(key, cacheItem);

if (isPromise(ret) && options.cachePromiseRejection === false) {
if (isPromise(cacheItem) && options.cachePromiseRejection === false) {
// Remove rejected promises from cache unless `cachePromiseRejection` is set to `true`
ret.catch(() => cache.delete(key));
cacheItem.catch(() => cache.delete(key));
}

return ret;
return cacheItem;
};

try {
Expand Down
4 changes: 2 additions & 2 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ const fn = (string: string) => true;

expectType<(string: string) => boolean>(mem(fn));
expectType<(string: string) => boolean>(mem(fn, {maxAge: 1}));
expectType<(string: string) => boolean>(mem(fn, {cacheKey: (...args) => args}));
expectType<(string: string) => boolean>(mem(fn, {cacheKey: (...arguments_) => arguments_}));
expectType<(string: string) => boolean>(
mem(fn, {cacheKey: (...args) => args, cache: new Map<[string], boolean>()})
mem(fn, {cacheKey: (...arguments_) => arguments_, cache: new Map<[string], boolean>()})
);
expectType<(string: string) => boolean>(
mem(fn, {cache: new Map<[string], boolean>()})
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
],
"dependencies": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^1.0.0",
"mimic-fn": "^2.0.0",
"p-is-promise": "^2.0.0"
},
"devDependencies": {
Expand Down
52 changes: 26 additions & 26 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import mem from '.';

test('memoize', t => {
let i = 0;
const f = () => i++;
const memoized = mem(f);
const fixture = () => i++;
const memoized = mem(fixture);
t.is(memoized(), 0);
t.is(memoized(), 0);
t.is(memoized(), 0);
Expand Down Expand Up @@ -41,25 +41,25 @@ test.failing('memoize with regexp arguments', t => {

test.failing('memoize with Symbol arguments', t => {
let i = 0;
const arg1 = Symbol('fixture1');
const arg2 = Symbol('fixture2');
const argument1 = Symbol('fixture1');
const argument2 = Symbol('fixture2');
const memoized = mem(() => i++);
t.is(memoized(), 0);
t.is(memoized(), 0);
t.is(memoized(arg1), 1);
t.is(memoized(arg1), 1);
t.is(memoized(arg2), 2);
t.is(memoized(arg2), 2);
t.is(memoized({foo: arg1}), 3);
t.is(memoized({foo: arg1}), 3);
t.is(memoized({foo: arg2}), 4);
t.is(memoized({foo: arg2}), 4);
t.is(memoized(argument1), 1);
t.is(memoized(argument1), 1);
t.is(memoized(argument2), 2);
t.is(memoized(argument2), 2);
t.is(memoized({foo: argument1}), 3);
t.is(memoized({foo: argument1}), 3);
t.is(memoized({foo: argument2}), 4);
t.is(memoized({foo: argument2}), 4);
});

test('maxAge option', async t => {
let i = 0;
const f = () => i++;
const memoized = mem(f, {maxAge: 100});
const fixture = () => i++;
const memoized = mem(fixture, {maxAge: 100});
t.is(memoized(1), 0);
t.is(memoized(1), 0);
await delay(50);
Expand All @@ -70,7 +70,7 @@ test('maxAge option', async t => {

test('maxAge option deletes old items', async t => {
let i = 0;
const f = () => i++;
const fixture = () => i++;
const cache = new Map();
const deleted = [];
const remove = cache.delete.bind(cache);
Expand All @@ -79,7 +79,7 @@ test('maxAge option deletes old items', async t => {
return remove(item);
};

const memoized = mem(f, {maxAge: 100, cache});
const memoized = mem(fixture, {maxAge: 100, cache});
t.is(memoized(1), 0);
t.is(memoized(1), 0);
t.is(cache.has(1), true);
Expand All @@ -94,7 +94,7 @@ test('maxAge option deletes old items', async t => {

test('maxAge items are deleted even if function throws', async t => {
let i = 0;
const f = () => {
const fixture = () => {
if (i === 1) {
throw new Error('failure');
}
Expand All @@ -103,7 +103,7 @@ test('maxAge items are deleted even if function throws', async t => {
};

const cache = new Map();
const memoized = mem(f, {maxAge: 100, cache});
const memoized = mem(fixture, {maxAge: 100, cache});
t.is(memoized(1), 0);
t.is(memoized(1), 0);
t.is(cache.size, 1);
Expand All @@ -116,8 +116,8 @@ test('maxAge items are deleted even if function throws', async t => {

test('cacheKey option', t => {
let i = 0;
const f = () => i++;
const memoized = mem(f, {cacheKey: x => x});
const fixture = () => i++;
const memoized = mem(fixture, {cacheKey: x => x});
t.is(memoized(1), 0);
t.is(memoized(1), 0);
t.is(memoized(1, 2), 0);
Expand All @@ -127,8 +127,8 @@ test('cacheKey option', t => {

test('cache option', t => {
let i = 0;
const f = () => i++;
const memoized = mem(f, {
const fixture = () => i++;
const memoized = mem(fixture, {
cache: new WeakMap(),
cacheKey: x => x
});
Expand Down Expand Up @@ -196,8 +196,8 @@ test('preserves the original function name', t => {

test('.clear()', t => {
let i = 0;
const f = () => i++;
const memoized = mem(f);
const fixture = () => i++;
const memoized = mem(fixture);
t.is(memoized(), 0);
t.is(memoized(), 0);
mem.clear(memoized);
Expand All @@ -206,15 +206,15 @@ test('.clear()', t => {
});

test('prototype support', t => {
const f = function () {
const fixture = function () {
return this.i++;
};

const Unicorn = function () {
this.i = 0;
};

Unicorn.prototype.foo = mem(f);
Unicorn.prototype.foo = mem(fixture);

const unicorn = new Unicorn();

Expand Down

0 comments on commit 003c2ef

Please sign in to comment.