UNPKG

2.28 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8/**
9 * @template K
10 * @template V
11 */
12class StackedCacheMap {
13 constructor() {
14 /** @type {Map<K, V>} */
15 this.map = new Map();
16 /** @type {ReadonlyMap<K, V>[]} */
17 this.stack = [];
18 }
19
20 /**
21 * @param {ReadonlyMap<K, V>} map map to add
22 * @param {boolean} immutable if 'map' is immutable and StackedCacheMap can keep referencing it
23 */
24 addAll(map, immutable) {
25 if (immutable) {
26 this.stack.push(map);
27
28 // largest map should go first
29 for (let i = this.stack.length - 1; i > 0; i--) {
30 const beforeLast = this.stack[i - 1];
31 if (beforeLast.size >= map.size) break;
32 this.stack[i] = beforeLast;
33 this.stack[i - 1] = map;
34 }
35 } else {
36 for (const [key, value] of map) {
37 this.map.set(key, value);
38 }
39 }
40 }
41
42 /**
43 * @param {K} item the key of the element to add
44 * @param {V} value the value of the element to add
45 * @returns {void}
46 */
47 set(item, value) {
48 this.map.set(item, value);
49 }
50
51 /**
52 * @param {K} item the item to delete
53 * @returns {void}
54 */
55 delete(item) {
56 throw new Error("Items can't be deleted from a StackedCacheMap");
57 }
58
59 /**
60 * @param {K} item the item to test
61 * @returns {boolean} true if the item exists in this set
62 */
63 has(item) {
64 throw new Error(
65 "Checking StackedCacheMap.has before reading is inefficient, use StackedCacheMap.get and check for undefined"
66 );
67 }
68
69 /**
70 * @param {K} item the key of the element to return
71 * @returns {V} the value of the element
72 */
73 get(item) {
74 for (const map of this.stack) {
75 const value = map.get(item);
76 if (value !== undefined) return value;
77 }
78 return this.map.get(item);
79 }
80
81 clear() {
82 this.stack.length = 0;
83 this.map.clear();
84 }
85
86 get size() {
87 let size = this.map.size;
88 for (const map of this.stack) {
89 size += map.size;
90 }
91 return size;
92 }
93
94 [Symbol.iterator]() {
95 const iterators = this.stack.map(map => map[Symbol.iterator]());
96 let current = this.map[Symbol.iterator]();
97 return {
98 next() {
99 let result = current.next();
100 while (result.done && iterators.length > 0) {
101 current = iterators.pop();
102 result = current.next();
103 }
104 return result;
105 }
106 };
107 }
108}
109
110module.exports = StackedCacheMap;