UNPKG

4.4 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _MapStorage = require('./MapStorage');
8
9var _MapStorage2 = _interopRequireDefault(_MapStorage);
10
11function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13/**
14 * A specialization of the {@codelink MapStorage} storage mimicking the native
15 * {@code WeakMap} using its internal garbage collector used once the size of
16 * the storage reaches the configured threshold.
17 */
18class WeakMapStorage extends _MapStorage2.default {
19 /**
20 * Initializes the storage.
21 *
22 * @param {{entryTtl: number}} config Weak map storage configuration. The
23 * fields have the following meaning:
24 * - entryTtl The time-to-live of a storage entry in milliseconds.
25 */
26 constructor(config) {
27 super();
28
29 /**
30 * The time-to-live of a storage entry in milliseconds.
31 *
32 * @type {number}
33 */
34 this._entryTtl = config.entryTtl;
35 }
36
37 /**
38 * @inheritdoc
39 */
40 has(key) {
41 this._discardExpiredEntries();
42
43 return super.has(key);
44 }
45
46 /**
47 * @inheritdoc
48 */
49 get(key) {
50 this._discardExpiredEntries();
51
52 if (!super.has(key)) {
53 return undefined;
54 }
55
56 return super.get(key).target;
57 }
58
59 /**
60 * @inheritdoc
61 */
62 set(key, value) {
63 this._discardExpiredEntries();
64
65 return super.set(key, new WeakRef(value, this._entryTtl));
66 }
67
68 /**
69 * @inheritdoc
70 */
71 delete(key) {
72 this._discardExpiredEntries();
73
74 return super.delete(key);
75 }
76
77 /**
78 * @inheritdoc
79 */
80 keys() {
81 this._discardExpiredEntries();
82
83 return super.keys();
84 }
85
86 /**
87 * @inheritdoc
88 */
89 size() {
90 this._discardExpiredEntries();
91
92 return super.size();
93 }
94
95 /**
96 * Deletes all expired entries from this storage.
97 */
98 _discardExpiredEntries() {
99 for (let key of super.keys()) {
100 let targetReference = super.get(key);
101 if (!targetReference.target) {
102 // the reference has died
103 super.delete(key);
104 }
105 }
106 }
107}
108
109exports.default = WeakMapStorage; /**
110 * A simple reference wrapper that emulates a weak reference. We seem to have
111 * no other option, since WeakMap and WeakSet are not enumerable (so what is
112 * the point of WeakMap and WeakSet if you still need to manage the keys?!) and
113 * there is no native way to create a weak reference.
114 */
115
116class WeakRef {
117 /**
118 * Initializes the weak reference to the target reference.
119 *
120 * @param {Object} target The target reference that should be referenced by
121 * this weak reference.
122 * @param {number} ttl The maximum number of milliseconds the weak
123 * reference should be kept. The reference will be discarded once
124 * ACCESSED after the specified timeout.
125 */
126 constructor(target, ttl) {
127 if ($Debug) {
128 if (!(target instanceof Object)) {
129 throw new TypeError('The target reference must point to an object, ' + 'primitive values are not allowed');
130 }
131 if (ttl <= 0) {
132 throw new Error('The time-to-live must be positive');
133 }
134 }
135
136 /**
137 * The actual target reference, or {@code null} if the reference has
138 * been already discarded.
139 *
140 * @type {?Object}
141 */
142 this._reference = target;
143
144 /**
145 * The UNIX timestamp with millisecond precision marking the moment at
146 * or after which the reference will be discarded.
147 *
148 * @type {number}
149 */
150 this._expiration = Date.now() + ttl;
151 }
152
153 /**
154 * Returns the target reference, provided that the target reference is
155 * still alive. Returns {@code null} if the reference has been discarded.
156 *
157 * @return {?Object} The target reference, or {@code null} if the reference
158 * has been discarded by the garbage collector.
159 */
160 get target() {
161 if (this._reference && Date.now() >= this._expiration) {
162 this._reference = null; // let the GC do its job
163 }
164
165 return this._reference;
166 }
167}
168
169typeof $IMA !== 'undefined' && $IMA !== null && $IMA.Loader && $IMA.Loader.register('ima/storage/WeakMapStorage', [], function (_export, _context) {
170 'use strict';
171 return {
172 setters: [],
173 execute: function () {
174 _export('default', exports.default);
175 }
176 };
177});