index.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. module.exports = (function() {
  2. var __MODS__ = {};
  3. var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
  4. var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
  5. var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
  6. var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
  7. __DEFINE__(1682324647501, function(require, module, exports) {
  8. // A linked list to keep track of recently-used-ness
  9. const Yallist = require('yallist')
  10. const MAX = Symbol('max')
  11. const LENGTH = Symbol('length')
  12. const LENGTH_CALCULATOR = Symbol('lengthCalculator')
  13. const ALLOW_STALE = Symbol('allowStale')
  14. const MAX_AGE = Symbol('maxAge')
  15. const DISPOSE = Symbol('dispose')
  16. const NO_DISPOSE_ON_SET = Symbol('noDisposeOnSet')
  17. const LRU_LIST = Symbol('lruList')
  18. const CACHE = Symbol('cache')
  19. const UPDATE_AGE_ON_GET = Symbol('updateAgeOnGet')
  20. const naiveLength = () => 1
  21. // lruList is a yallist where the head is the youngest
  22. // item, and the tail is the oldest. the list contains the Hit
  23. // objects as the entries.
  24. // Each Hit object has a reference to its Yallist.Node. This
  25. // never changes.
  26. //
  27. // cache is a Map (or PseudoMap) that matches the keys to
  28. // the Yallist.Node object.
  29. class LRUCache {
  30. constructor (options) {
  31. if (typeof options === 'number')
  32. options = { max: options }
  33. if (!options)
  34. options = {}
  35. if (options.max && (typeof options.max !== 'number' || options.max < 0))
  36. throw new TypeError('max must be a non-negative number')
  37. // Kind of weird to have a default max of Infinity, but oh well.
  38. const max = this[MAX] = options.max || Infinity
  39. const lc = options.length || naiveLength
  40. this[LENGTH_CALCULATOR] = (typeof lc !== 'function') ? naiveLength : lc
  41. this[ALLOW_STALE] = options.stale || false
  42. if (options.maxAge && typeof options.maxAge !== 'number')
  43. throw new TypeError('maxAge must be a number')
  44. this[MAX_AGE] = options.maxAge || 0
  45. this[DISPOSE] = options.dispose
  46. this[NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false
  47. this[UPDATE_AGE_ON_GET] = options.updateAgeOnGet || false
  48. this.reset()
  49. }
  50. // resize the cache when the max changes.
  51. set max (mL) {
  52. if (typeof mL !== 'number' || mL < 0)
  53. throw new TypeError('max must be a non-negative number')
  54. this[MAX] = mL || Infinity
  55. trim(this)
  56. }
  57. get max () {
  58. return this[MAX]
  59. }
  60. set allowStale (allowStale) {
  61. this[ALLOW_STALE] = !!allowStale
  62. }
  63. get allowStale () {
  64. return this[ALLOW_STALE]
  65. }
  66. set maxAge (mA) {
  67. if (typeof mA !== 'number')
  68. throw new TypeError('maxAge must be a non-negative number')
  69. this[MAX_AGE] = mA
  70. trim(this)
  71. }
  72. get maxAge () {
  73. return this[MAX_AGE]
  74. }
  75. // resize the cache when the lengthCalculator changes.
  76. set lengthCalculator (lC) {
  77. if (typeof lC !== 'function')
  78. lC = naiveLength
  79. if (lC !== this[LENGTH_CALCULATOR]) {
  80. this[LENGTH_CALCULATOR] = lC
  81. this[LENGTH] = 0
  82. this[LRU_LIST].forEach(hit => {
  83. hit.length = this[LENGTH_CALCULATOR](hit.value, hit.key)
  84. this[LENGTH] += hit.length
  85. })
  86. }
  87. trim(this)
  88. }
  89. get lengthCalculator () { return this[LENGTH_CALCULATOR] }
  90. get length () { return this[LENGTH] }
  91. get itemCount () { return this[LRU_LIST].length }
  92. rforEach (fn, thisp) {
  93. thisp = thisp || this
  94. for (let walker = this[LRU_LIST].tail; walker !== null;) {
  95. const prev = walker.prev
  96. forEachStep(this, fn, walker, thisp)
  97. walker = prev
  98. }
  99. }
  100. forEach (fn, thisp) {
  101. thisp = thisp || this
  102. for (let walker = this[LRU_LIST].head; walker !== null;) {
  103. const next = walker.next
  104. forEachStep(this, fn, walker, thisp)
  105. walker = next
  106. }
  107. }
  108. keys () {
  109. return this[LRU_LIST].toArray().map(k => k.key)
  110. }
  111. values () {
  112. return this[LRU_LIST].toArray().map(k => k.value)
  113. }
  114. reset () {
  115. if (this[DISPOSE] &&
  116. this[LRU_LIST] &&
  117. this[LRU_LIST].length) {
  118. this[LRU_LIST].forEach(hit => this[DISPOSE](hit.key, hit.value))
  119. }
  120. this[CACHE] = new Map() // hash of items by key
  121. this[LRU_LIST] = new Yallist() // list of items in order of use recency
  122. this[LENGTH] = 0 // length of items in the list
  123. }
  124. dump () {
  125. return this[LRU_LIST].map(hit =>
  126. isStale(this, hit) ? false : {
  127. k: hit.key,
  128. v: hit.value,
  129. e: hit.now + (hit.maxAge || 0)
  130. }).toArray().filter(h => h)
  131. }
  132. dumpLru () {
  133. return this[LRU_LIST]
  134. }
  135. set (key, value, maxAge) {
  136. maxAge = maxAge || this[MAX_AGE]
  137. if (maxAge && typeof maxAge !== 'number')
  138. throw new TypeError('maxAge must be a number')
  139. const now = maxAge ? Date.now() : 0
  140. const len = this[LENGTH_CALCULATOR](value, key)
  141. if (this[CACHE].has(key)) {
  142. if (len > this[MAX]) {
  143. del(this, this[CACHE].get(key))
  144. return false
  145. }
  146. const node = this[CACHE].get(key)
  147. const item = node.value
  148. // dispose of the old one before overwriting
  149. // split out into 2 ifs for better coverage tracking
  150. if (this[DISPOSE]) {
  151. if (!this[NO_DISPOSE_ON_SET])
  152. this[DISPOSE](key, item.value)
  153. }
  154. item.now = now
  155. item.maxAge = maxAge
  156. item.value = value
  157. this[LENGTH] += len - item.length
  158. item.length = len
  159. this.get(key)
  160. trim(this)
  161. return true
  162. }
  163. const hit = new Entry(key, value, len, now, maxAge)
  164. // oversized objects fall out of cache automatically.
  165. if (hit.length > this[MAX]) {
  166. if (this[DISPOSE])
  167. this[DISPOSE](key, value)
  168. return false
  169. }
  170. this[LENGTH] += hit.length
  171. this[LRU_LIST].unshift(hit)
  172. this[CACHE].set(key, this[LRU_LIST].head)
  173. trim(this)
  174. return true
  175. }
  176. has (key) {
  177. if (!this[CACHE].has(key)) return false
  178. const hit = this[CACHE].get(key).value
  179. return !isStale(this, hit)
  180. }
  181. get (key) {
  182. return get(this, key, true)
  183. }
  184. peek (key) {
  185. return get(this, key, false)
  186. }
  187. pop () {
  188. const node = this[LRU_LIST].tail
  189. if (!node)
  190. return null
  191. del(this, node)
  192. return node.value
  193. }
  194. del (key) {
  195. del(this, this[CACHE].get(key))
  196. }
  197. load (arr) {
  198. // reset the cache
  199. this.reset()
  200. const now = Date.now()
  201. // A previous serialized cache has the most recent items first
  202. for (let l = arr.length - 1; l >= 0; l--) {
  203. const hit = arr[l]
  204. const expiresAt = hit.e || 0
  205. if (expiresAt === 0)
  206. // the item was created without expiration in a non aged cache
  207. this.set(hit.k, hit.v)
  208. else {
  209. const maxAge = expiresAt - now
  210. // dont add already expired items
  211. if (maxAge > 0) {
  212. this.set(hit.k, hit.v, maxAge)
  213. }
  214. }
  215. }
  216. }
  217. prune () {
  218. this[CACHE].forEach((value, key) => get(this, key, false))
  219. }
  220. }
  221. const get = (self, key, doUse) => {
  222. const node = self[CACHE].get(key)
  223. if (node) {
  224. const hit = node.value
  225. if (isStale(self, hit)) {
  226. del(self, node)
  227. if (!self[ALLOW_STALE])
  228. return undefined
  229. } else {
  230. if (doUse) {
  231. if (self[UPDATE_AGE_ON_GET])
  232. node.value.now = Date.now()
  233. self[LRU_LIST].unshiftNode(node)
  234. }
  235. }
  236. return hit.value
  237. }
  238. }
  239. const isStale = (self, hit) => {
  240. if (!hit || (!hit.maxAge && !self[MAX_AGE]))
  241. return false
  242. const diff = Date.now() - hit.now
  243. return hit.maxAge ? diff > hit.maxAge
  244. : self[MAX_AGE] && (diff > self[MAX_AGE])
  245. }
  246. const trim = self => {
  247. if (self[LENGTH] > self[MAX]) {
  248. for (let walker = self[LRU_LIST].tail;
  249. self[LENGTH] > self[MAX] && walker !== null;) {
  250. // We know that we're about to delete this one, and also
  251. // what the next least recently used key will be, so just
  252. // go ahead and set it now.
  253. const prev = walker.prev
  254. del(self, walker)
  255. walker = prev
  256. }
  257. }
  258. }
  259. const del = (self, node) => {
  260. if (node) {
  261. const hit = node.value
  262. if (self[DISPOSE])
  263. self[DISPOSE](hit.key, hit.value)
  264. self[LENGTH] -= hit.length
  265. self[CACHE].delete(hit.key)
  266. self[LRU_LIST].removeNode(node)
  267. }
  268. }
  269. class Entry {
  270. constructor (key, value, length, now, maxAge) {
  271. this.key = key
  272. this.value = value
  273. this.length = length
  274. this.now = now
  275. this.maxAge = maxAge || 0
  276. }
  277. }
  278. const forEachStep = (self, fn, node, thisp) => {
  279. let hit = node.value
  280. if (isStale(self, hit)) {
  281. del(self, node)
  282. if (!self[ALLOW_STALE])
  283. hit = undefined
  284. }
  285. if (hit)
  286. fn.call(thisp, hit.value, hit.key, self)
  287. }
  288. module.exports = LRUCache
  289. }, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
  290. return __REQUIRE__(1682324647501);
  291. })()
  292. //miniprogram-npm-outsideDeps=["yallist"]
  293. //# sourceMappingURL=index.js.map