Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 3x 3x 2x 2x 2x 5x 1x 3x 1x 1x 5x 42x 17x 17x 17x 11x 11x 11x 3x 3x 3x 3x 8x 4x 4x 4x 4x 11x 17x 6x 3x 3x 3x 3x 6x 17x 5x 17x | import { CacheKeyFn } from './fn'
import { exactEqual } from './utils'
// import { exactEqual } from './utils'
let memoizeId = 0
export function memoize(cacheKeyFn?: CacheKeyFn<any>) {
return function(target: any, key: string, descriptor: any): any {
const memoizePrefix = `memoize:${memoizeId++}`
let fnKey: string
let fn: any
let hasRun = false
let newParams: any[] = []
const cachedLastValue = new Map<string, ReturnType<any>>()
const cachedLastParams = new Map<string, Parameters<any>>()
// memoize on methods
if (typeof descriptor.value === 'function') {
fnKey = 'value'
fn = descriptor.value
} else Eif (typeof descriptor.get === 'function') {
// memoize on getters
fnKey = 'get'
fn = descriptor.get
} else {
throw new Error(
'decorated memoize on un supported property or method'
)
}
if (typeof descriptor.set === 'function') {
const rawSetter = descriptor.set
descriptor.set = function(...args: any[]) {
hasRun = false // intercept setter to mark getter as refreshed
rawSetter!.apply(this, args)
}
}
const memoizeKey = `${memoizePrefix}:${key}`
// override original method or getter
descriptor[fnKey] = function(...args: any[]) {
const _self = this // the instance
newParams = args;
const methodUpdater = function() {
const key = cacheKeyFn?.(...args) || 'only'
const lastParams = cachedLastParams.get(key) || []
let lastValue
if (!hasRun) {
hasRun = true
lastValue = fn.apply(_self, newParams)
cachedLastValue.set(key, lastValue!)
cachedLastParams.set(key, newParams)
} else if (!exactEqual(newParams, lastParams)) {
lastValue = fn.apply(_self, newParams)
cachedLastValue.set(key, lastValue!)
cachedLastParams.set(key, newParams)
} else {
lastValue = cachedLastValue.get(key)!
}
return lastValue
}
const getterUpdater = function() {
let lastValue
if (!hasRun) {
lastValue = fn.apply(_self)
hasRun = true
cachedLastValue.set(key, lastValue!)
} else {
lastValue = cachedLastValue.get(key)!
}
return lastValue
}
if (!this.hasOwnProperty(memoizeKey)) {
Object.defineProperty(this, memoizeKey, {
configurable: false,
enumerable: false,
get: fnKey === 'value' ? methodUpdater : getterUpdater
})
}
return this[memoizeKey]
}
}
}
|