forked from aduth/memize
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
103 lines (82 loc) · 2.08 KB
/
index.js
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
94
95
96
97
98
99
100
101
102
103
module.exports = function memize( fn, options ) {
var size = 0,
maxSize, head, tail;
if ( options && options.maxSize ) {
maxSize = options.maxSize;
}
function memoized( /* ...args */ ) {
var node = head,
len = arguments.length,
args, i;
searchCache: while ( node ) {
// Check whether node arguments match arguments
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 ) {
const beforeNode = node.prev;
const afterNode = node.next;
beforeNode.next = afterNode;
if ( ! afterNode ) {
tail = beforeNode;
} else {
afterNode.prev = beforeNode;
}
node.next = head;
node.prev = null;
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 === maxSize ) {
tail = tail.prev;
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 ];
};
}
return memoized;
};