
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
💾 Memoize a function the way you want.
⚡ Keep your JS/TS/React code running lightning fast and smooth!
🌍 Avoid wasting precious computation and worsen global warming.
⚠️ Not to be confused with the Spanish word "memo": https://m.interglot.com/es/en/Memo
npm install @swyg/memo
yarn install @swyg/memo
useMemo
vs. @swyg/memo
With @swyg/memo
you'll be able to enjoy a less verbose syntax and get more control over your memoization strategy.
For example, your component might re-render often and always call the same function with only a few combinations of params (e.g. filter or sort functionality). In that case, you could use memoCacheKey(...)
.
With React's useMemo
:
const memoFunction = memoRef(myFunction);
const ReactComponent = ({ a, b, c }) => {
const myResult = useMemo(() => myFunction(a, b, c), [a, b, c]);
...
}
With @swyg/memo
:
const memoFunction = memoCacheKey(myFunction); // or memoLastKey or memoLastRef
const ReactComponent = ({ a, b, c }) => {
const myResult = memoFunction(a, b, c);
...
}
However, keep in mind abusing memoization, especially when using memoCacheKey
, can also have detrimental effects in your app's performance, as memory usage will increase.
Also, it's worth pointing out React's useMemo
might eventually manage memory usage differently, as stated in the docs:
You may rely on
useMemo
as a performance optimization, not as a semantic guarantee. In the future, React may choose to “forget” some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works withoutuseMemo
— and then add it to optimize performance.
Functions:
memoLastKey(func[, { resolver }]): MemoizedLastKeyFunction
memoLastRef(func): MemoizedLastRefFunction
memoCacheKey(func[, { resolver }]): MemoizedCacheFunction
Classes:
memoLastKey(func[, { resolver }]): MemoizedLastKeyFunction
Memoizes the result from the last call of the function func
using the serialized arguments as the string key:
examples/last/key/basic.ts
const func = (value1: any, value2?: any) => {
console.log('run');
return { value1, value2 };
};
const memoFunc = memoLastKey(func);
const objA = { value: 'a' };
const objB = { value: 'b' };
const objC = { value: 'c' };
const a = func('foo'); // run
const b = memoFunc('foo'); // run
const c = memoFunc('foo');
const d = memoFunc('bar'); // run
const e = memoFunc('foo'); // run
const f = memoFunc(objA, objB); // run
const g = memoFunc(objA, objB); // NO run (incorrect)
const h = memoFunc(objA, objC); // NO run (incorrect)
console.log(a === b); // false
console.log(a === c); // false
console.log(b === c); // true
console.log(a === e); // false
console.log(b === e); // false
console.log(c === e); // false
console.log(f === g); // true
console.log(f === h); // true (incorrect)
A custom resolver
function can be provided with the options param to use a custom cache identifier, which can be of any type:
examples/last/key/basic-resolver-str.ts
const func = (value: string | number) => {
console.log('run');
return { value };
};
const memoFunc = memoLastKey(func, {
resolver: (...args) => args.map(arg => `${ arg }`).join('')
});
const a = memoFunc('1'); // run
const b = memoFunc(1);
console.log(a === b); // true
examples/last/key/basic-resolver-obj.ts
const func = (value: any) => {
console.log('run');
return { value };
};
const memoFunc = memoLastKey(func, {
resolver: (arg: any) => arg.keyObj,
});
const keyObj = {};
const a = memoFunc({ keyObj }); // run
const b = memoFunc({ keyObj });
console.log(a === b); // true
By default, the following resolver function is used:
(...args) => `[${ args.map(arg => `${ typeof arg === 'string' ? `'${ arg }'` : arg }`).join(', ') }]`
Two additional properties, lastKey
and lastValue
, are attached to the memoized function:
examples/last/key/internals.ts
const func = (value: string) => ({ value });
const memoFunc = memoLastKey(func);
memoFunc('foo');
console.log(memoFunc.lastKey); // ['foo', 2, true, [object Object]]
console.log(memoFunc.lastValue); // foo
memoLastRef(func): MemoizedLastRefFunction
Memoizes the result from the last call of the function func
until the arguments change:
examples/last/ref/basic.ts
const func = (value1: any, value2?: any) => {
console.log('run');
return { value1, value2 };
};
const memoFunc = memoLastRef(func);
const objA = { value: 'a' };
const objB = { value: 'b' };
const objC = { value: 'c' };
const a = func('foo'); // run
const b = memoFunc('foo'); // run
const c = memoFunc('foo');
const d = memoFunc('bar'); // run
const e = memoFunc('foo'); // run
const f = memoFunc(objA, objB); // run
const g = memoFunc(objA, objB);
const h = memoFunc(objA, objC); // run
console.log(a === b); // false
console.log(a === c); // false
console.log(b === c); // true
console.log(a === e); // false
console.log(b === e); // false
console.log(c === e); // false
console.log(f === g); // true
console.log(f === h); // false
Two additional properties, lastArgs
and lastValue
, are attached to the memoized function:
examples/last/ref/internals.ts
const func = (...args: any) => 'foo';
const memoFunc = memoLastRef(func);
memoFunc('foo', 2, true, { a: 1 });
console.log(memoFunc.lastArgs); // [ 'foo', 2, true, { a: 1 } ]
console.log(memoFunc.lastValue); // foo
memoCacheKey(func[, { resolver }]): MemoizedCacheFunction
Memoizes the result from the N most recent calls of the function func
using the serialized arguments as the string key:
examples/cache/basic.ts
const func = (value1: any, value2?: any) => {
console.log('run');
return { value1, value2 };
};
const memoFunc = memoCacheKey(func, { slots: 2 });
const a = func('foo'); // run
const b = memoFunc('foo'); // run
const c = memoFunc('foo');
const d = memoFunc('bar'); // run
const e = memoFunc('foo');
const f = memoFunc('bar');
const g = memoFunc('baz'); // run
const h = memoFunc('foo'); // run
console.log(a === b); // false
console.log(a === c); // false
console.log(b === c); // true
console.log(b === e); // true
console.log(c === e); // true
console.log(e === h); // false
An additional property, cache
, is attached to the memoized function:
examples/cache/internals.ts
const func = (value1: any, value2?: any) => {
console.log('run');
return { value1, value2 };
};
const memoFunc = memoCacheKey(func, { slots: 2 });
memoFunc('foo');
memoFunc('bar');
memoFunc('baz');
console.log(memoFunc.cache); // CacheSet [Map] { ... }
CacheSet(iterableOrObject?: Iterable<[K, V]> | CacheSetOptions, options?: CacheSetOptions)
Create an instance of a set with a maximum number of elements (options.slots
), limited time-to-live (options.ttl
) or the ability to update the stored value when Promises are resolved (options.keepPromises
):
const cacheSet = new CacheSet<number, string>([[1, 'one'], [2, 'two']], { slots: 2});
console.log(cacheSet.size); // 2
cacheSet.set(3, 'three');
console.log(cacheSet.size); // 2
console.log(cacheSet.get(1)); // undefined
Types are already included in this package.
You can check if a variable is referencing a memoized function with the following type guards:
isMemoLastKeyFunction(func)
isMemoLastRefFunction(func)
isMemoCacheFunction(func)
isMemoFunction(func)
undefined
for the cache key or attach an withoutMemo()
function to the memoized function).FAQs
💾 Memoize a function the way you want.
We found that @swyg/memo demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.