| /** | ||
| * Memize options object. | ||
| * | ||
| * @typedef MemizeOptions | ||
| * | ||
| * @property {number} [maxSize] Maximum size of the cache. | ||
| */ | ||
| /** | ||
| * Internal cache entry. | ||
| * | ||
| * @typedef MemizeCacheNode | ||
| * | ||
| * @property {?MemizeCacheNode|undefined} [prev] Previous node. | ||
| * @property {?MemizeCacheNode|undefined} [next] Next node. | ||
| * @property {Array<*>} args Function arguments for cache | ||
| * entry. | ||
| * @property {*} val Function result. | ||
| */ | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| * | ||
| * @typedef MemizeMemoizedFunction | ||
| * | ||
| * @property {()=>void} clear Clear the cache. | ||
| */ | ||
| /** | ||
| * Accepts a function to be memoized, and returns a new memoized function, with | ||
| * optional options. | ||
| * | ||
| * @template {(...args: any[]) => any} F | ||
| * | ||
| * @param {F} fn Function to memoize. | ||
| * @param {MemizeOptions} [options] Options object. | ||
| * | ||
| * @return {((...args: Parameters<F>) => ReturnType<F>) & MemizeMemoizedFunction} Memoized function. | ||
| */ | ||
| export default function memize<F extends (...args: any[]) => any>(fn: F, options?: MemizeOptions | undefined): ((...args: Parameters<F>) => ReturnType<F>) & MemizeMemoizedFunction; | ||
| /** | ||
| * Memize options object. | ||
| */ | ||
| export type MemizeOptions = { | ||
| /** | ||
| * Maximum size of the cache. | ||
| */ | ||
| maxSize?: number | undefined; | ||
| }; | ||
| /** | ||
| * Internal cache entry. | ||
| */ | ||
| export type MemizeCacheNode = { | ||
| /** | ||
| * Previous node. | ||
| */ | ||
| prev?: (MemizeCacheNode | undefined) | null; | ||
| /** | ||
| * Next node. | ||
| */ | ||
| next?: (MemizeCacheNode | undefined) | null; | ||
| /** | ||
| * Function arguments for cache | ||
| * entry. | ||
| */ | ||
| args: Array<any>; | ||
| /** | ||
| * Function result. | ||
| */ | ||
| val: any; | ||
| }; | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| */ | ||
| export type MemizeMemoizedFunction = { | ||
| /** | ||
| * Clear the cache. | ||
| */ | ||
| clear: () => void; | ||
| }; |
+160
| /** | ||
| * Memize options object. | ||
| * | ||
| * @typedef MemizeOptions | ||
| * | ||
| * @property {number} [maxSize] Maximum size of the cache. | ||
| */ | ||
| /** | ||
| * Internal cache entry. | ||
| * | ||
| * @typedef MemizeCacheNode | ||
| * | ||
| * @property {?MemizeCacheNode|undefined} [prev] Previous node. | ||
| * @property {?MemizeCacheNode|undefined} [next] Next node. | ||
| * @property {Array<*>} args Function arguments for cache | ||
| * entry. | ||
| * @property {*} val Function result. | ||
| */ | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| * | ||
| * @typedef MemizeMemoizedFunction | ||
| * | ||
| * @property {()=>void} clear Clear the cache. | ||
| */ | ||
| /** | ||
| * Accepts a function to be memoized, and returns a new memoized function, with | ||
| * optional options. | ||
| * | ||
| * @template {(...args: any[]) => any} F | ||
| * | ||
| * @param {F} fn Function to memoize. | ||
| * @param {MemizeOptions} [options] Options object. | ||
| * | ||
| * @return {((...args: Parameters<F>) => ReturnType<F>) & MemizeMemoizedFunction} Memoized function. | ||
| */ | ||
| function memize(fn, options) { | ||
| var size = 0; | ||
| /** @type {?MemizeCacheNode|undefined} */ | ||
| var head; | ||
| /** @type {?MemizeCacheNode|undefined} */ | ||
| var tail; | ||
| options = options || {}; | ||
| function memoized(/* ...args */) { | ||
| var node = head, | ||
| len = arguments.length, | ||
| args, | ||
| i; | ||
| searchCache: while (node) { | ||
| // Perform a shallow equality test to confirm that whether the node | ||
| // under test is a candidate for the arguments passed. Two arrays | ||
| // are shallowly equal if their length matches and each entry is | ||
| // strictly equal between the two sets. Avoid abstracting to a | ||
| // function which could incur an arguments leaking deoptimization. | ||
| // Check whether node arguments match arguments length | ||
| if (node.args.length !== arguments.length) { | ||
| node = node.next; | ||
| continue; | ||
| } | ||
| // Check whether node arguments match arguments values | ||
| for (i = 0; i < len; i++) { | ||
| if (node.args[i] !== arguments[i]) { | ||
| node = node.next; | ||
| continue searchCache; | ||
| } | ||
| } | ||
| // At this point we can assume we've found a match | ||
| // Surface matched node to head if not already | ||
| if (node !== head) { | ||
| // As tail, shift to previous. Must only shift if not also | ||
| // head, since if both head and tail, there is no previous. | ||
| if (node === tail) { | ||
| tail = node.prev; | ||
| } | ||
| // Adjust siblings to point to each other. If node was tail, | ||
| // this also handles new tail's empty `next` assignment. | ||
| /** @type {MemizeCacheNode} */ (node.prev).next = node.next; | ||
| if (node.next) { | ||
| node.next.prev = node.prev; | ||
| } | ||
| node.next = head; | ||
| node.prev = null; | ||
| /** @type {MemizeCacheNode} */ (head).prev = node; | ||
| head = node; | ||
| } | ||
| // Return immediately | ||
| return node.val; | ||
| } | ||
| // No cached value found. Continue to insertion phase: | ||
| // Create a copy of arguments (avoid leaking deoptimization) | ||
| args = new Array(len); | ||
| for (i = 0; i < len; i++) { | ||
| args[i] = arguments[i]; | ||
| } | ||
| node = { | ||
| args: args, | ||
| // Generate the result from original function | ||
| val: fn.apply(null, args), | ||
| }; | ||
| // Don't need to check whether node is already head, since it would | ||
| // have been returned above already if it was | ||
| // Shift existing head down list | ||
| if (head) { | ||
| head.prev = node; | ||
| node.next = head; | ||
| } else { | ||
| // If no head, follows that there's no tail (at initial or reset) | ||
| tail = node; | ||
| } | ||
| // Trim tail if we're reached max size and are pending cache insertion | ||
| if (size === /** @type {MemizeOptions} */ (options).maxSize) { | ||
| tail = /** @type {MemizeCacheNode} */ (tail).prev; | ||
| /** @type {MemizeCacheNode} */ (tail).next = null; | ||
| } else { | ||
| size++; | ||
| } | ||
| head = node; | ||
| return node.val; | ||
| } | ||
| memoized.clear = function () { | ||
| head = null; | ||
| tail = null; | ||
| size = 0; | ||
| }; | ||
| // Ignore reason: There's not a clear solution to create an intersection of | ||
| // the function with additional properties, where the goal is to retain the | ||
| // function signature of the incoming argument and add control properties | ||
| // on the return value. | ||
| // @ts-ignore | ||
| return memoized; | ||
| } | ||
| export { memize as default }; |
+56
-67
| { | ||
| "name": "memize", | ||
| "version": "1.1.0", | ||
| "description": "Unabashedly-barebones memoization library with an aim toward speed", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "build": "npm run build:bundle && npm run build:types", | ||
| "build:bundle": "NODE_ENV=production rollup -c rollup.config.js", | ||
| "postbuild:bundle": "npm run minify", | ||
| "build:types": "tsc -p tsconfig.decl.json", | ||
| "minify": "uglifyjs dist/memize.js -c -m --mangle-props domprops --mangle-props regex=\"/^next|prev|val|args|maxSize$/\" > dist/memize.min.js", | ||
| "test:unit": "NODE_ENV=test mocha", | ||
| "test:lint": "eslint .", | ||
| "test:types": "tsc", | ||
| "test": "npm run test:unit && npm run test:lint && npm run test:types", | ||
| "benchmark": "node benchmark", | ||
| "prepublishOnly": "npm test && npm run build" | ||
| }, | ||
| "files": [ | ||
| "dist", | ||
| "index.js", | ||
| "index.d.ts" | ||
| ], | ||
| "keywords": [ | ||
| "memoize", | ||
| "memoization", | ||
| "memoisation", | ||
| "cache" | ||
| ], | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/aduth/memize.git" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/aduth/memize/issues" | ||
| }, | ||
| "author": { | ||
| "name": "Andrew Duthie", | ||
| "email": "andrew@andrewduthie.com", | ||
| "url": "https://andrewduthie.com" | ||
| }, | ||
| "license": "MIT", | ||
| "devDependencies": { | ||
| "@aduth/eslint-config": "^3.0.0", | ||
| "@types/node": "^13.9.0", | ||
| "benchmark": "^2.1.4", | ||
| "chai": "^4.2.0", | ||
| "cli-table2": "^0.2.0", | ||
| "eslint": "^6.8.0", | ||
| "eslint-plugin-jsdoc": "^22.0.0", | ||
| "fast-memoize": "^2.5.2", | ||
| "lodash": "^4.17.15", | ||
| "lru-memoize": "^1.1.0", | ||
| "memoizee": "^0.4.14", | ||
| "memoizejs": "^0.1.1", | ||
| "memoizerific": "^1.11.3", | ||
| "mocha": "^7.1.0", | ||
| "moize": "^5.4.5", | ||
| "ora": "^4.0.3", | ||
| "ramda": "^0.27.0", | ||
| "rollup": "^2.0.2", | ||
| "rollup-plugin-commonjs": "^10.1.0", | ||
| "rollup-plugin-replace": "^2.2.0", | ||
| "sinon": "^9.0.0", | ||
| "typescript": "^3.8.3", | ||
| "uglify-js": "^3.8.0", | ||
| "underscore": "^1.9.2" | ||
| } | ||
| "name": "memize", | ||
| "version": "2.0.0", | ||
| "description": "Unabashedly-barebones memoization library with an aim toward speed", | ||
| "type": "module", | ||
| "main": "dist/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "scripts": { | ||
| "build": "npm run build:bundle && npm run build:types", | ||
| "build:bundle": "rollup -c rollup.config.js", | ||
| "build:types": "tsc -b tsconfig.decl.json", | ||
| "test:unit": "NODE_ENV=test mocha", | ||
| "test:lint": "eslint .", | ||
| "test:types": "tsc -b", | ||
| "test": "npm run test:unit && npm run test:lint && npm run test:types", | ||
| "prebenchmark": "npm install --no-save benchmark memoizee moize ramda underscore lodash fast-memoize lru-memoize memoizejs memoizerific cli-table2 ora", | ||
| "benchmark": "node benchmark", | ||
| "prepublishOnly": "npm test && npm run build" | ||
| }, | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "keywords": [ | ||
| "memoize", | ||
| "memoization", | ||
| "memoisation", | ||
| "cache" | ||
| ], | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/aduth/memize.git" | ||
| }, | ||
| "bugs": { | ||
| "url": "https://github.com/aduth/memize/issues" | ||
| }, | ||
| "author": { | ||
| "name": "Andrew Duthie", | ||
| "email": "andrew@andrewduthie.com", | ||
| "url": "https://andrewduthie.com" | ||
| }, | ||
| "license": "MIT", | ||
| "devDependencies": { | ||
| "@aduth/eslint-config": "^4.4.1", | ||
| "@rollup/plugin-replace": "^5.0.2", | ||
| "@types/chai": "^4.3.4", | ||
| "@types/mocha": "^10.0.1", | ||
| "@types/node": "^18.16.1", | ||
| "chai": "^4.3.7", | ||
| "eslint": "^8.39.0", | ||
| "eslint-config-prettier": "^8.8.0", | ||
| "eslint-plugin-prettier": "^4.2.1", | ||
| "mocha": "^10.2.0", | ||
| "prettier": "^2.8.8", | ||
| "rollup": "^3.21.0", | ||
| "sinon": "^15.0.4", | ||
| "typescript": "^5.0.4" | ||
| } | ||
| } |
+0
-4
@@ -35,6 +35,2 @@ Memize | ||
| Otherwise, download a pre-built copy from unpkg: | ||
| [https://unpkg.com/memize/dist/memize.min.js](https://unpkg.com/memize/dist/memize.min.js) | ||
| ## Usage | ||
@@ -41,0 +37,0 @@ |
-28
| #### v1.1.0 (2020-03-07) | ||
| - New Feature: Add TypeScript type definition. | ||
| #### v1.0.5 (2018-01-25) | ||
| - Fix: Correctly skips incorrect cached value return on mismatched argument length | ||
| #### v1.0.4 (2017-09-06) | ||
| - Fix: Resolve infinite loop which can occur due to lingering references in recalling from previous cache | ||
| - Internal: Include more thorough test cases for expected cache list progression | ||
| #### v1.0.3 (2017-08-30) | ||
| - Fix: Resolve error which can occur in certain conditions with `maxSize` | ||
| #### v1.0.2 (2017-08-24) | ||
| - Fix: Resolve infinite loop which can occur due to lingering references in recalling from previous cache | ||
| #### v1.0.1 (2017-08-09) | ||
| - Internal: Include repository details in `package.json` | ||
| #### v1.0.0 (2017-08-08) | ||
| - Initial release |
-166
| var memize = (function () { | ||
| 'use strict'; | ||
| /** | ||
| * Memize options object. | ||
| * | ||
| * @typedef MemizeOptions | ||
| * | ||
| * @property {number} [maxSize] Maximum size of the cache. | ||
| */ | ||
| /** | ||
| * Internal cache entry. | ||
| * | ||
| * @typedef MemizeCacheNode | ||
| * | ||
| * @property {?MemizeCacheNode|undefined} [prev] Previous node. | ||
| * @property {?MemizeCacheNode|undefined} [next] Next node. | ||
| * @property {Array<*>} args Function arguments for cache | ||
| * entry. | ||
| * @property {*} val Function result. | ||
| */ | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| * | ||
| * @typedef MemizeMemoizedFunction | ||
| * | ||
| * @property {()=>void} clear Clear the cache. | ||
| */ | ||
| /** | ||
| * Accepts a function to be memoized, and returns a new memoized function, with | ||
| * optional options. | ||
| * | ||
| * @template {Function} F | ||
| * | ||
| * @param {F} fn Function to memoize. | ||
| * @param {MemizeOptions} [options] Options object. | ||
| * | ||
| * @return {F & MemizeMemoizedFunction} Memoized function. | ||
| */ | ||
| function memize( fn, options ) { | ||
| var size = 0; | ||
| /** @type {?MemizeCacheNode|undefined} */ | ||
| var head; | ||
| /** @type {?MemizeCacheNode|undefined} */ | ||
| var tail; | ||
| options = options || {}; | ||
| function memoized( /* ...args */ ) { | ||
| var node = head, | ||
| len = arguments.length, | ||
| args, i; | ||
| searchCache: while ( node ) { | ||
| // Perform a shallow equality test to confirm that whether the node | ||
| // under test is a candidate for the arguments passed. Two arrays | ||
| // are shallowly equal if their length matches and each entry is | ||
| // strictly equal between the two sets. Avoid abstracting to a | ||
| // function which could incur an arguments leaking deoptimization. | ||
| // Check whether node arguments match arguments length | ||
| if ( node.args.length !== arguments.length ) { | ||
| node = node.next; | ||
| continue; | ||
| } | ||
| // Check whether node arguments match arguments values | ||
| for ( i = 0; i < len; i++ ) { | ||
| if ( node.args[ i ] !== arguments[ i ] ) { | ||
| node = node.next; | ||
| continue searchCache; | ||
| } | ||
| } | ||
| // At this point we can assume we've found a match | ||
| // Surface matched node to head if not already | ||
| if ( node !== head ) { | ||
| // As tail, shift to previous. Must only shift if not also | ||
| // head, since if both head and tail, there is no previous. | ||
| if ( node === tail ) { | ||
| tail = node.prev; | ||
| } | ||
| // Adjust siblings to point to each other. If node was tail, | ||
| // this also handles new tail's empty `next` assignment. | ||
| /** @type {MemizeCacheNode} */ ( node.prev ).next = node.next; | ||
| if ( node.next ) { | ||
| node.next.prev = node.prev; | ||
| } | ||
| node.next = head; | ||
| node.prev = null; | ||
| /** @type {MemizeCacheNode} */ ( head ).prev = node; | ||
| head = node; | ||
| } | ||
| // Return immediately | ||
| return node.val; | ||
| } | ||
| // No cached value found. Continue to insertion phase: | ||
| // Create a copy of arguments (avoid leaking deoptimization) | ||
| args = new Array( len ); | ||
| for ( i = 0; i < len; i++ ) { | ||
| args[ i ] = arguments[ i ]; | ||
| } | ||
| node = { | ||
| args: args, | ||
| // Generate the result from original function | ||
| val: fn.apply( null, args ), | ||
| }; | ||
| // Don't need to check whether node is already head, since it would | ||
| // have been returned above already if it was | ||
| // Shift existing head down list | ||
| if ( head ) { | ||
| head.prev = node; | ||
| node.next = head; | ||
| } else { | ||
| // If no head, follows that there's no tail (at initial or reset) | ||
| tail = node; | ||
| } | ||
| // Trim tail if we're reached max size and are pending cache insertion | ||
| if ( size === /** @type {MemizeOptions} */ ( options ).maxSize ) { | ||
| tail = /** @type {MemizeCacheNode} */ ( tail ).prev; | ||
| /** @type {MemizeCacheNode} */ ( tail ).next = null; | ||
| } else { | ||
| size++; | ||
| } | ||
| head = node; | ||
| return node.val; | ||
| } | ||
| memoized.clear = function() { | ||
| head = null; | ||
| tail = null; | ||
| size = 0; | ||
| }; | ||
| // Ignore reason: There's not a clear solution to create an intersection of | ||
| // the function with additional properties, where the goal is to retain the | ||
| // function signature of the incoming argument and add control properties | ||
| // on the return value. | ||
| // @ts-ignore | ||
| return memoized; | ||
| } | ||
| var memize_1 = memize; | ||
| return memize_1; | ||
| }()); |
| var memize=function(){"use strict";return function(e,f){var i,l,o=0;function n(){var n,r,u=i,t=arguments.length;n:for(;u;){if(u.n.length===arguments.length){for(r=0;r<t;r++)if(u.n[r]!==arguments[r]){u=u.r;continue n}return u!==i&&(u===l&&(l=u.u),u.u.r=u.r,u.r&&(u.r.u=u.u),u.r=i,u.u=null,i.u=u,i=u),u.t}u=u.r}for(n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return u={n:n,t:e.apply(null,n)},i?(i.u=u).r=i:l=u,o===f.e?(l=l.u).r=null:o++,(i=u).t}return f=f||{},n.clear=function(){l=i=null,o=0},n}}(); |
-81
| export = memize; | ||
| /** | ||
| * Memize options object. | ||
| * | ||
| * @typedef MemizeOptions | ||
| * | ||
| * @property {number} [maxSize] Maximum size of the cache. | ||
| */ | ||
| /** | ||
| * Internal cache entry. | ||
| * | ||
| * @typedef MemizeCacheNode | ||
| * | ||
| * @property {?MemizeCacheNode|undefined} [prev] Previous node. | ||
| * @property {?MemizeCacheNode|undefined} [next] Next node. | ||
| * @property {Array<*>} args Function arguments for cache | ||
| * entry. | ||
| * @property {*} val Function result. | ||
| */ | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| * | ||
| * @typedef MemizeMemoizedFunction | ||
| * | ||
| * @property {()=>void} clear Clear the cache. | ||
| */ | ||
| /** | ||
| * Accepts a function to be memoized, and returns a new memoized function, with | ||
| * optional options. | ||
| * | ||
| * @template {Function} F | ||
| * | ||
| * @param {F} fn Function to memoize. | ||
| * @param {MemizeOptions} [options] Options object. | ||
| * | ||
| * @return {F & MemizeMemoizedFunction} Memoized function. | ||
| */ | ||
| declare function memize<F extends Function>(fn: F, options?: MemizeOptions | undefined): F & MemizeMemoizedFunction; | ||
| declare namespace memize { | ||
| export { MemizeOptions, MemizeCacheNode, MemizeMemoizedFunction }; | ||
| } | ||
| /** | ||
| * Memize options object. | ||
| */ | ||
| type MemizeOptions = { | ||
| /** | ||
| * Maximum size of the cache. | ||
| */ | ||
| maxSize?: number; | ||
| }; | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| */ | ||
| type MemizeMemoizedFunction = { | ||
| /** | ||
| * Clear the cache. | ||
| */ | ||
| clear: () => void; | ||
| }; | ||
| /** | ||
| * Internal cache entry. | ||
| */ | ||
| type MemizeCacheNode = { | ||
| /** | ||
| * Previous node. | ||
| */ | ||
| prev?: MemizeCacheNode | null | undefined; | ||
| /** | ||
| * Next node. | ||
| */ | ||
| next?: MemizeCacheNode | null | undefined; | ||
| /** | ||
| * Function arguments for cache | ||
| * entry. | ||
| */ | ||
| args: any[]; | ||
| /** | ||
| * Function result. | ||
| */ | ||
| val: any; | ||
| }; |
-167
| /** | ||
| * Memize options object. | ||
| * | ||
| * @typedef MemizeOptions | ||
| * | ||
| * @property {number} [maxSize] Maximum size of the cache. | ||
| */ | ||
| /** | ||
| * Internal cache entry. | ||
| * | ||
| * @typedef MemizeCacheNode | ||
| * | ||
| * @property {?MemizeCacheNode|undefined} [prev] Previous node. | ||
| * @property {?MemizeCacheNode|undefined} [next] Next node. | ||
| * @property {Array<*>} args Function arguments for cache | ||
| * entry. | ||
| * @property {*} val Function result. | ||
| */ | ||
| /** | ||
| * Properties of the enhanced function for controlling cache. | ||
| * | ||
| * @typedef MemizeMemoizedFunction | ||
| * | ||
| * @property {()=>void} clear Clear the cache. | ||
| */ | ||
| /** | ||
| * Accepts a function to be memoized, and returns a new memoized function, with | ||
| * optional options. | ||
| * | ||
| * @template {Function} F | ||
| * | ||
| * @param {F} fn Function to memoize. | ||
| * @param {MemizeOptions} [options] Options object. | ||
| * | ||
| * @return {F & MemizeMemoizedFunction} Memoized function. | ||
| */ | ||
| function memize( fn, options ) { | ||
| var size = 0; | ||
| /** @type {?MemizeCacheNode|undefined} */ | ||
| var head; | ||
| /** @type {?MemizeCacheNode|undefined} */ | ||
| var tail; | ||
| options = options || {}; | ||
| function memoized( /* ...args */ ) { | ||
| var node = head, | ||
| len = arguments.length, | ||
| args, i; | ||
| searchCache: while ( node ) { | ||
| // Perform a shallow equality test to confirm that whether the node | ||
| // under test is a candidate for the arguments passed. Two arrays | ||
| // are shallowly equal if their length matches and each entry is | ||
| // strictly equal between the two sets. Avoid abstracting to a | ||
| // function which could incur an arguments leaking deoptimization. | ||
| // Check whether node arguments match arguments length | ||
| if ( node.args.length !== arguments.length ) { | ||
| node = node.next; | ||
| continue; | ||
| } | ||
| // Check whether node arguments match arguments values | ||
| for ( i = 0; i < len; i++ ) { | ||
| if ( node.args[ i ] !== arguments[ i ] ) { | ||
| node = node.next; | ||
| continue searchCache; | ||
| } | ||
| } | ||
| // At this point we can assume we've found a match | ||
| // Surface matched node to head if not already | ||
| if ( node !== head ) { | ||
| // As tail, shift to previous. Must only shift if not also | ||
| // head, since if both head and tail, there is no previous. | ||
| if ( node === tail ) { | ||
| tail = node.prev; | ||
| } | ||
| // Adjust siblings to point to each other. If node was tail, | ||
| // this also handles new tail's empty `next` assignment. | ||
| /** @type {MemizeCacheNode} */ ( node.prev ).next = node.next; | ||
| if ( node.next ) { | ||
| node.next.prev = node.prev; | ||
| } | ||
| node.next = head; | ||
| node.prev = null; | ||
| /** @type {MemizeCacheNode} */ ( head ).prev = node; | ||
| head = node; | ||
| } | ||
| // Return immediately | ||
| return node.val; | ||
| } | ||
| // No cached value found. Continue to insertion phase: | ||
| // Create a copy of arguments (avoid leaking deoptimization) | ||
| args = new Array( len ); | ||
| for ( i = 0; i < len; i++ ) { | ||
| args[ i ] = arguments[ i ]; | ||
| } | ||
| node = { | ||
| args: args, | ||
| // Generate the result from original function | ||
| val: fn.apply( null, args ), | ||
| }; | ||
| // Don't need to check whether node is already head, since it would | ||
| // have been returned above already if it was | ||
| // Shift existing head down list | ||
| if ( head ) { | ||
| head.prev = node; | ||
| node.next = head; | ||
| } else { | ||
| // If no head, follows that there's no tail (at initial or reset) | ||
| tail = node; | ||
| } | ||
| // Trim tail if we're reached max size and are pending cache insertion | ||
| if ( size === /** @type {MemizeOptions} */ ( options ).maxSize ) { | ||
| tail = /** @type {MemizeCacheNode} */ ( tail ).prev; | ||
| /** @type {MemizeCacheNode} */ ( tail ).next = null; | ||
| } else { | ||
| size++; | ||
| } | ||
| head = node; | ||
| return node.val; | ||
| } | ||
| memoized.clear = function() { | ||
| head = null; | ||
| tail = null; | ||
| size = 0; | ||
| }; | ||
| if ( process.env.NODE_ENV === 'test' ) { | ||
| // Cache is not exposed in the public API, but used in tests to ensure | ||
| // expected list progression | ||
| memoized.getCache = function() { | ||
| return [ head, tail, size ]; | ||
| }; | ||
| } | ||
| // Ignore reason: There's not a clear solution to create an intersection of | ||
| // the function with additional properties, where the goal is to retain the | ||
| // function signature of the incoming argument and add control properties | ||
| // on the return value. | ||
| // @ts-ignore | ||
| return memoized; | ||
| } | ||
| module.exports = memize; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
14
-41.67%1
-50%0
-100%Yes
NaN15734
-28.37%5
-37.5%209
-41.29%116
-3.33%