@simplysm/core-common 13.0.99 → 14.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/common.types.d.ts +14 -14
- package/dist/common.types.js +2 -1
- package/dist/common.types.js.map +1 -6
- package/dist/env.d.ts +5 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +12 -8
- package/dist/env.js.map +1 -6
- package/dist/errors/argument-error.d.ts +10 -10
- package/dist/errors/argument-error.d.ts.map +1 -1
- package/dist/errors/argument-error.js +31 -14
- package/dist/errors/argument-error.js.map +1 -6
- package/dist/errors/not-implemented-error.d.ts +8 -8
- package/dist/errors/not-implemented-error.js +30 -12
- package/dist/errors/not-implemented-error.js.map +1 -6
- package/dist/errors/sd-error.d.ts +10 -10
- package/dist/errors/sd-error.d.ts.map +1 -1
- package/dist/errors/sd-error.js +45 -24
- package/dist/errors/sd-error.js.map +1 -6
- package/dist/errors/timeout-error.d.ts +10 -10
- package/dist/errors/timeout-error.js +34 -15
- package/dist/errors/timeout-error.js.map +1 -6
- package/dist/extensions/arr-ext.d.ts +2 -2
- package/dist/extensions/arr-ext.helpers.d.ts +10 -10
- package/dist/extensions/arr-ext.helpers.js +112 -89
- package/dist/extensions/arr-ext.helpers.js.map +1 -6
- package/dist/extensions/arr-ext.js +458 -422
- package/dist/extensions/arr-ext.js.map +1 -6
- package/dist/extensions/arr-ext.types.d.ts +57 -57
- package/dist/extensions/arr-ext.types.d.ts.map +1 -1
- package/dist/extensions/arr-ext.types.js +6 -1
- package/dist/extensions/arr-ext.types.js.map +1 -6
- package/dist/extensions/map-ext.d.ts +16 -16
- package/dist/extensions/map-ext.js +27 -22
- package/dist/extensions/map-ext.js.map +1 -6
- package/dist/extensions/set-ext.d.ts +11 -11
- package/dist/extensions/set-ext.js +32 -25
- package/dist/extensions/set-ext.js.map +1 -6
- package/dist/features/debounce-queue.d.ts +17 -17
- package/dist/features/debounce-queue.js +98 -70
- package/dist/features/debounce-queue.js.map +1 -6
- package/dist/features/event-emitter.d.ts +20 -20
- package/dist/features/event-emitter.js +101 -78
- package/dist/features/event-emitter.js.map +1 -6
- package/dist/features/serial-queue.d.ts +11 -11
- package/dist/features/serial-queue.js +78 -57
- package/dist/features/serial-queue.js.map +1 -6
- package/dist/globals.d.ts +4 -4
- package/dist/globals.js +9 -1
- package/dist/globals.js.map +1 -6
- package/dist/index.js +28 -27
- package/dist/index.js.map +1 -6
- package/dist/types/date-only.d.ts +64 -64
- package/dist/types/date-only.d.ts.map +1 -1
- package/dist/types/date-only.js +263 -252
- package/dist/types/date-only.js.map +1 -6
- package/dist/types/date-time.d.ts +36 -36
- package/dist/types/date-time.d.ts.map +1 -1
- package/dist/types/date-time.js +196 -288
- package/dist/types/date-time.js.map +1 -6
- package/dist/types/lazy-gc-map.d.ts +26 -26
- package/dist/types/lazy-gc-map.d.ts.map +1 -1
- package/dist/types/lazy-gc-map.js +202 -159
- package/dist/types/lazy-gc-map.js.map +1 -6
- package/dist/types/time.d.ts +23 -23
- package/dist/types/time.d.ts.map +1 -1
- package/dist/types/time.js +169 -158
- package/dist/types/time.js.map +1 -6
- package/dist/types/uuid.d.ts +11 -11
- package/dist/types/uuid.d.ts.map +1 -1
- package/dist/types/uuid.js +95 -70
- package/dist/types/uuid.js.map +1 -6
- package/dist/utils/bytes.d.ts +17 -17
- package/dist/utils/bytes.js +137 -81
- package/dist/utils/bytes.js.map +1 -6
- package/dist/utils/date-format.d.ts +40 -40
- package/dist/utils/date-format.js +187 -101
- package/dist/utils/date-format.js.map +1 -6
- package/dist/utils/error.d.ts +4 -4
- package/dist/utils/error.js +11 -6
- package/dist/utils/error.js.map +1 -6
- package/dist/utils/json.d.ts +19 -19
- package/dist/utils/json.js +187 -135
- package/dist/utils/json.js.map +1 -6
- package/dist/utils/num.d.ts +20 -20
- package/dist/utils/num.js +76 -34
- package/dist/utils/num.js.map +1 -6
- package/dist/utils/obj.d.ts +111 -111
- package/dist/utils/obj.d.ts.map +1 -1
- package/dist/utils/obj.js +706 -496
- package/dist/utils/obj.js.map +1 -6
- package/dist/utils/path.d.ts +10 -10
- package/dist/utils/path.js +35 -18
- package/dist/utils/path.js.map +1 -6
- package/dist/utils/primitive.d.ts +5 -5
- package/dist/utils/primitive.js +34 -14
- package/dist/utils/primitive.js.map +1 -6
- package/dist/utils/str.d.ts +38 -38
- package/dist/utils/str.js +217 -113
- package/dist/utils/str.js.map +1 -6
- package/dist/utils/template-strings.d.ts +26 -26
- package/dist/utils/template-strings.js +113 -40
- package/dist/utils/template-strings.js.map +1 -6
- package/dist/utils/transferable.d.ts +18 -18
- package/dist/utils/transferable.js +218 -151
- package/dist/utils/transferable.js.map +1 -6
- package/dist/utils/wait.d.ts +9 -9
- package/dist/utils/wait.js +30 -15
- package/dist/utils/wait.js.map +1 -6
- package/dist/utils/xml.d.ts +13 -13
- package/dist/utils/xml.js +84 -46
- package/dist/utils/xml.js.map +1 -6
- package/dist/utils/zip.d.ts +22 -22
- package/dist/utils/zip.js +172 -148
- package/dist/utils/zip.js.map +1 -6
- package/package.json +5 -7
- package/src/common.types.ts +14 -14
- package/src/env.ts +9 -1
- package/src/errors/argument-error.ts +15 -15
- package/src/errors/not-implemented-error.ts +9 -9
- package/src/errors/sd-error.ts +12 -12
- package/src/errors/timeout-error.ts +12 -12
- package/src/extensions/arr-ext.helpers.ts +16 -16
- package/src/extensions/arr-ext.ts +35 -35
- package/src/extensions/arr-ext.types.ts +57 -57
- package/src/extensions/map-ext.ts +16 -16
- package/src/extensions/set-ext.ts +11 -11
- package/src/features/debounce-queue.ts +23 -23
- package/src/features/event-emitter.ts +25 -25
- package/src/features/serial-queue.ts +13 -13
- package/src/globals.ts +4 -4
- package/src/index.ts +5 -5
- package/src/types/date-only.ts +84 -83
- package/src/types/date-time.ts +43 -42
- package/src/types/lazy-gc-map.ts +44 -44
- package/src/types/time.ts +29 -29
- package/src/types/uuid.ts +15 -15
- package/src/utils/bytes.ts +35 -35
- package/src/utils/date-format.ts +59 -59
- package/src/utils/error.ts +4 -4
- package/src/utils/json.ts +41 -41
- package/src/utils/num.ts +20 -20
- package/src/utils/obj.ts +138 -138
- package/src/utils/path.ts +10 -10
- package/src/utils/primitive.ts +6 -6
- package/src/utils/str.ts +48 -48
- package/src/utils/template-strings.ts +29 -29
- package/src/utils/transferable.ts +38 -38
- package/src/utils/wait.ts +10 -10
- package/src/utils/xml.ts +19 -19
- package/src/utils/zip.ts +25 -25
- package/README.md +0 -160
- package/docs/errors.md +0 -119
- package/docs/extensions.md +0 -387
- package/docs/features.md +0 -143
- package/docs/types.md +0 -287
- package/docs/utils.md +0 -757
- package/tests/errors/errors.spec.ts +0 -80
- package/tests/extensions/array-extension.spec.ts +0 -654
- package/tests/extensions/map-extension.spec.ts +0 -117
- package/tests/extensions/set-extension.spec.ts +0 -67
- package/tests/types/date-only.spec.ts +0 -533
- package/tests/types/date-time.spec.ts +0 -246
- package/tests/types/lazy-gc-map.spec.ts +0 -606
- package/tests/types/time.spec.ts +0 -428
- package/tests/types/uuid.spec.ts +0 -74
- package/tests/utils/bytes-utils.spec.ts +0 -197
- package/tests/utils/date-format.spec.ts +0 -350
- package/tests/utils/debounce-queue.spec.ts +0 -226
- package/tests/utils/json.spec.ts +0 -400
- package/tests/utils/number.spec.ts +0 -136
- package/tests/utils/object.spec.ts +0 -810
- package/tests/utils/path.spec.ts +0 -70
- package/tests/utils/primitive.spec.ts +0 -43
- package/tests/utils/sd-event-emitter.spec.ts +0 -189
- package/tests/utils/serial-queue.spec.ts +0 -305
- package/tests/utils/string.spec.ts +0 -265
- package/tests/utils/template-strings.spec.ts +0 -48
- package/tests/utils/transferable.spec.ts +0 -639
- package/tests/utils/wait.spec.ts +0 -123
- package/tests/utils/xml.spec.ts +0 -146
- package/tests/utils/zip.spec.ts +0 -221
|
@@ -1,606 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { LazyGcMap } from "@simplysm/core-common";
|
|
3
|
-
|
|
4
|
-
describe("LazyGcMap", () => {
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
vi.useFakeTimers();
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
vi.useRealTimers();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
//#region Basic Map operations
|
|
14
|
-
|
|
15
|
-
describe("Basic Map operations", () => {
|
|
16
|
-
it("Deletes values with delete", () => {
|
|
17
|
-
const map = new LazyGcMap<string, number>({
|
|
18
|
-
gcInterval: 1000,
|
|
19
|
-
expireTime: 5000,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
map.set("key1", 100);
|
|
23
|
-
expect(map.delete("key1")).toBe(true);
|
|
24
|
-
expect(map.has("key1")).toBe(false);
|
|
25
|
-
expect(map.delete("key1")).toBe(false); // Already deleted
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("Deletes all values with dispose", () => {
|
|
29
|
-
const map = new LazyGcMap<string, number>({
|
|
30
|
-
gcInterval: 1000,
|
|
31
|
-
expireTime: 5000,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
map.set("key1", 100);
|
|
35
|
-
map.set("key2", 200);
|
|
36
|
-
expect(map.size).toBe(2);
|
|
37
|
-
|
|
38
|
-
map.dispose();
|
|
39
|
-
expect(map.size).toBe(0);
|
|
40
|
-
expect(map.has("key1")).toBe(false);
|
|
41
|
-
expect(map.has("key2")).toBe(false);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
//#endregion
|
|
46
|
-
|
|
47
|
-
//#region getOrCreate
|
|
48
|
-
|
|
49
|
-
describe("getOrCreate()", () => {
|
|
50
|
-
it("Creates new value with factory for non-existent keys", () => {
|
|
51
|
-
const map = new LazyGcMap<string, number>({
|
|
52
|
-
gcInterval: 1000,
|
|
53
|
-
expireTime: 5000,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const value = map.getOrCreate("key1", () => 100);
|
|
57
|
-
expect(value).toBe(100);
|
|
58
|
-
expect(map.get("key1")).toBe(100);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it("Returns existing value without calling factory", () => {
|
|
62
|
-
const map = new LazyGcMap<string, number>({
|
|
63
|
-
gcInterval: 1000,
|
|
64
|
-
expireTime: 5000,
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
map.set("key1", 100);
|
|
68
|
-
const factoryCalls: number[] = [];
|
|
69
|
-
const value = map.getOrCreate("key1", () => {
|
|
70
|
-
factoryCalls.push(1);
|
|
71
|
-
return 200;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(value).toBe(100); // Existing value
|
|
75
|
-
expect(factoryCalls).toHaveLength(0); // Factory not called
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it("Factory creates new value each time for different keys", () => {
|
|
79
|
-
const map = new LazyGcMap<string, { id: number }>({
|
|
80
|
-
gcInterval: 1000,
|
|
81
|
-
expireTime: 5000,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const value1 = map.getOrCreate("key1", () => ({ id: 1 }));
|
|
85
|
-
const value2 = map.getOrCreate("key2", () => ({ id: 2 }));
|
|
86
|
-
|
|
87
|
-
expect(value1).toEqual({ id: 1 });
|
|
88
|
-
expect(value2).toEqual({ id: 2 });
|
|
89
|
-
expect(value1).not.toBe(value2);
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
//#endregion
|
|
94
|
-
|
|
95
|
-
//#region Automatic expiration (GC)
|
|
96
|
-
|
|
97
|
-
describe("Automatic expiration (GC)", () => {
|
|
98
|
-
it("Automatically deletes values after expireTime without access", async () => {
|
|
99
|
-
const map = new LazyGcMap<string, number>({
|
|
100
|
-
gcInterval: 100, // GC every 100ms
|
|
101
|
-
expireTime: 200, // Expire after 200ms
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
map.set("key1", 100);
|
|
105
|
-
expect(map.has("key1")).toBe(true);
|
|
106
|
-
|
|
107
|
-
// GC runs after expireTime(200) + gcInterval(100) = 300ms
|
|
108
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
109
|
-
|
|
110
|
-
expect(map.has("key1")).toBe(false);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("Refreshes expiration time on access (LRU)", async () => {
|
|
114
|
-
const map = new LazyGcMap<string, number>({
|
|
115
|
-
gcInterval: 100,
|
|
116
|
-
expireTime: 200,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
map.set("key1", 100);
|
|
120
|
-
|
|
121
|
-
// Access every 150ms (less than expireTime 200ms)
|
|
122
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
123
|
-
map.get("key1"); // Access refreshes time
|
|
124
|
-
|
|
125
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
126
|
-
map.get("key1"); // Access refreshes time
|
|
127
|
-
|
|
128
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
129
|
-
|
|
130
|
-
// Continuous access prevents expiration
|
|
131
|
-
expect(map.has("key1")).toBe(true);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it("has() does not refresh access time", async () => {
|
|
135
|
-
const map = new LazyGcMap<string, number>({
|
|
136
|
-
gcInterval: 100,
|
|
137
|
-
expireTime: 200,
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
map.set("key1", 100);
|
|
141
|
-
|
|
142
|
-
// Call has() every 150ms (not get())
|
|
143
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
144
|
-
map.has("key1"); // has() does not refresh access time
|
|
145
|
-
|
|
146
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
147
|
-
map.has("key1"); // has() does not refresh access time
|
|
148
|
-
|
|
149
|
-
await vi.advanceTimersByTimeAsync(100);
|
|
150
|
-
|
|
151
|
-
// has() does not refresh, so expires
|
|
152
|
-
expect(map.has("key1")).toBe(false);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it("getOrCreate also refreshes access time", async () => {
|
|
156
|
-
const map = new LazyGcMap<string, number>({
|
|
157
|
-
gcInterval: 100,
|
|
158
|
-
expireTime: 200,
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
map.set("key1", 100);
|
|
162
|
-
|
|
163
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
164
|
-
map.getOrCreate("key1", () => 200); // Access refreshes time
|
|
165
|
-
|
|
166
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
167
|
-
|
|
168
|
-
expect(map.has("key1")).toBe(true);
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it("Deletes only expired items among multiple items", async () => {
|
|
172
|
-
const map = new LazyGcMap<string, number>({
|
|
173
|
-
gcInterval: 100,
|
|
174
|
-
expireTime: 200,
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
map.set("key1", 100);
|
|
178
|
-
await vi.advanceTimersByTimeAsync(150);
|
|
179
|
-
map.set("key2", 200); // Added 150ms after key1
|
|
180
|
-
|
|
181
|
-
await vi.advanceTimersByTimeAsync(200);
|
|
182
|
-
|
|
183
|
-
// key1 expires, key2 still alive
|
|
184
|
-
expect(map.has("key1")).toBe(false);
|
|
185
|
-
expect(map.has("key2")).toBe(true);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it("GC timer stops when all items expire", async () => {
|
|
189
|
-
const map = new LazyGcMap<string, number>({
|
|
190
|
-
gcInterval: 100,
|
|
191
|
-
expireTime: 200,
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
map.set("key1", 100);
|
|
195
|
-
|
|
196
|
-
// Wait for expiration
|
|
197
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
198
|
-
|
|
199
|
-
expect(map.size).toBe(0);
|
|
200
|
-
// Verify GC timer stopped (waiting more is safe)
|
|
201
|
-
await vi.advanceTimersByTimeAsync(200);
|
|
202
|
-
expect(map.size).toBe(0);
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
//#endregion
|
|
207
|
-
|
|
208
|
-
//#region onExpire callback
|
|
209
|
-
|
|
210
|
-
describe("onExpire callback", () => {
|
|
211
|
-
it("Calls onExpire callback when item expires", async () => {
|
|
212
|
-
const expired: Array<[string, number]> = [];
|
|
213
|
-
const map = new LazyGcMap<string, number>({
|
|
214
|
-
gcInterval: 100,
|
|
215
|
-
expireTime: 200,
|
|
216
|
-
onExpire: (key, value) => {
|
|
217
|
-
expired.push([key, value]);
|
|
218
|
-
},
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
map.set("key1", 100);
|
|
222
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
223
|
-
|
|
224
|
-
expect(expired).toEqual([["key1", 100]]);
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it("Supports async onExpire callback", async () => {
|
|
228
|
-
const expired: Array<[string, number]> = [];
|
|
229
|
-
const map = new LazyGcMap<string, number>({
|
|
230
|
-
gcInterval: 100,
|
|
231
|
-
expireTime: 200,
|
|
232
|
-
onExpire: async (key, value) => {
|
|
233
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
234
|
-
expired.push([key, value]);
|
|
235
|
-
},
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
map.set("key1", 100);
|
|
239
|
-
// expireTime(200) + gcInterval(100) + callback(10) = 310ms
|
|
240
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
241
|
-
|
|
242
|
-
expect(expired).toEqual([["key1", 100]]);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it("Calls onExpire for each expired item", async () => {
|
|
246
|
-
const expired: Array<[string, number]> = [];
|
|
247
|
-
const map = new LazyGcMap<string, number>({
|
|
248
|
-
gcInterval: 100,
|
|
249
|
-
expireTime: 200,
|
|
250
|
-
onExpire: (key, value) => {
|
|
251
|
-
expired.push([key, value]);
|
|
252
|
-
},
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
map.set("key1", 100);
|
|
256
|
-
map.set("key2", 200);
|
|
257
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
258
|
-
|
|
259
|
-
expect(expired).toHaveLength(2);
|
|
260
|
-
expect(expired).toContainEqual(["key1", 100]);
|
|
261
|
-
expect(expired).toContainEqual(["key2", 200]);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it("Ignores onExpire errors", async () => {
|
|
265
|
-
const expired: Array<[string, number]> = [];
|
|
266
|
-
const map = new LazyGcMap<string, number>({
|
|
267
|
-
gcInterval: 100,
|
|
268
|
-
expireTime: 200,
|
|
269
|
-
onExpire: (key, value) => {
|
|
270
|
-
expired.push([key, value]);
|
|
271
|
-
throw new Error("callback error");
|
|
272
|
-
},
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
map.set("key1", 100);
|
|
276
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
277
|
-
|
|
278
|
-
// Expiration handled normally despite error
|
|
279
|
-
expect(expired).toEqual([["key1", 100]]);
|
|
280
|
-
expect(map.has("key1")).toBe(false);
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
it("Maintains new value if set is called during onExpire for same key", async () => {
|
|
284
|
-
let map: LazyGcMap<string, number>;
|
|
285
|
-
const expired: Array<[string, number]> = [];
|
|
286
|
-
|
|
287
|
-
map = new LazyGcMap<string, number>({
|
|
288
|
-
gcInterval: 100,
|
|
289
|
-
expireTime: 200,
|
|
290
|
-
onExpire: (key, value) => {
|
|
291
|
-
expired.push([key, value]);
|
|
292
|
-
// Register new value for same key during onExpire
|
|
293
|
-
map.set(key, value + 1000);
|
|
294
|
-
},
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
map.set("key1", 100);
|
|
298
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
299
|
-
|
|
300
|
-
// onExpire called, but new value not deleted
|
|
301
|
-
expect(expired).toEqual([["key1", 100]]);
|
|
302
|
-
expect(map.has("key1")).toBe(true);
|
|
303
|
-
expect(map.get("key1")).toBe(1100);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it("Unaffected by set during onExpire for different key", async () => {
|
|
307
|
-
let map: LazyGcMap<string, number>;
|
|
308
|
-
const expired: Array<[string, number]> = [];
|
|
309
|
-
|
|
310
|
-
map = new LazyGcMap<string, number>({
|
|
311
|
-
gcInterval: 100,
|
|
312
|
-
expireTime: 200,
|
|
313
|
-
onExpire: (key, value) => {
|
|
314
|
-
expired.push([key, value]);
|
|
315
|
-
// Register new value for different key during onExpire (only for key1)
|
|
316
|
-
if (key === "key1") {
|
|
317
|
-
map.set("key2", 200);
|
|
318
|
-
}
|
|
319
|
-
},
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
map.set("key1", 100);
|
|
323
|
-
// GC runs after expireTime(200) + gcInterval(100) = 300ms
|
|
324
|
-
// key2 not expired yet after being registered
|
|
325
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
326
|
-
|
|
327
|
-
// key1 deleted after expiration
|
|
328
|
-
expect(expired).toEqual([["key1", 100]]);
|
|
329
|
-
expect(map.has("key1")).toBe(false);
|
|
330
|
-
// key2 newly registered (not yet expired)
|
|
331
|
-
expect(map.has("key2")).toBe(true);
|
|
332
|
-
expect(map.get("key2")).toBe(200);
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
//#endregion
|
|
337
|
-
|
|
338
|
-
//#region dispose (Timer and resource cleanup)
|
|
339
|
-
|
|
340
|
-
describe("dispose() - Timer cleanup", () => {
|
|
341
|
-
it("GC callback not called after dispose when timer is cleaned up", async () => {
|
|
342
|
-
const expired: Array<[string, number]> = [];
|
|
343
|
-
const map = new LazyGcMap<string, number>({
|
|
344
|
-
gcInterval: 100,
|
|
345
|
-
expireTime: 200,
|
|
346
|
-
onExpire: (key, value) => {
|
|
347
|
-
expired.push([key, value]);
|
|
348
|
-
},
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
map.set("key1", 100);
|
|
352
|
-
expect(map.has("key1")).toBe(true);
|
|
353
|
-
|
|
354
|
-
// Clean up timer with dispose
|
|
355
|
-
map.dispose();
|
|
356
|
-
expect(map.size).toBe(0);
|
|
357
|
-
|
|
358
|
-
// Wait expireTime + gcInterval or more
|
|
359
|
-
await vi.advanceTimersByTimeAsync(400);
|
|
360
|
-
|
|
361
|
-
// GC callback should not be called (already cleaned by dispose)
|
|
362
|
-
expect(expired).toHaveLength(0);
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
it("set is ignored after dispose", () => {
|
|
366
|
-
const map = new LazyGcMap<string, number>({
|
|
367
|
-
gcInterval: 100,
|
|
368
|
-
expireTime: 200,
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
map.set("key1", 100);
|
|
372
|
-
map.dispose();
|
|
373
|
-
|
|
374
|
-
// set ignored after dispose
|
|
375
|
-
map.set("key2", 200);
|
|
376
|
-
expect(map.has("key2")).toBe(false);
|
|
377
|
-
expect(map.get("key2")).toBeUndefined();
|
|
378
|
-
expect(map.size).toBe(0);
|
|
379
|
-
});
|
|
380
|
-
|
|
381
|
-
it("dispose is safe to call multiple times", () => {
|
|
382
|
-
const map = new LazyGcMap<string, number>({
|
|
383
|
-
gcInterval: 1000,
|
|
384
|
-
expireTime: 5000,
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
map.set("key1", 100);
|
|
388
|
-
|
|
389
|
-
// Safe to call multiple times
|
|
390
|
-
map.dispose();
|
|
391
|
-
map.dispose();
|
|
392
|
-
map.dispose();
|
|
393
|
-
|
|
394
|
-
expect(map.size).toBe(0);
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
it("Automatically disposed with using statement", async () => {
|
|
398
|
-
const expired: Array<[string, number]> = [];
|
|
399
|
-
{
|
|
400
|
-
using map = new LazyGcMap<string, number>({
|
|
401
|
-
gcInterval: 100,
|
|
402
|
-
expireTime: 200,
|
|
403
|
-
onExpire: (key, value) => {
|
|
404
|
-
expired.push([key, value]);
|
|
405
|
-
},
|
|
406
|
-
});
|
|
407
|
-
map.set("key1", 100);
|
|
408
|
-
expect(map.has("key1")).toBe(true);
|
|
409
|
-
} // dispose auto-called at end of using block
|
|
410
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
411
|
-
// Cleaned up by dispose (onExpire not called)
|
|
412
|
-
expect(expired).toHaveLength(0);
|
|
413
|
-
});
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
//#endregion
|
|
417
|
-
|
|
418
|
-
//#region clear
|
|
419
|
-
|
|
420
|
-
describe("clear()", () => {
|
|
421
|
-
it("Deletes all items", () => {
|
|
422
|
-
const map = new LazyGcMap<string, number>({
|
|
423
|
-
gcInterval: 1000,
|
|
424
|
-
expireTime: 5000,
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
map.set("key1", 100);
|
|
428
|
-
map.set("key2", 200);
|
|
429
|
-
expect(map.size).toBe(2);
|
|
430
|
-
|
|
431
|
-
map.clear();
|
|
432
|
-
expect(map.size).toBe(0);
|
|
433
|
-
expect(map.has("key1")).toBe(false);
|
|
434
|
-
expect(map.has("key2")).toBe(false);
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
it("Can add new items after clear", () => {
|
|
438
|
-
const map = new LazyGcMap<string, number>({
|
|
439
|
-
gcInterval: 1000,
|
|
440
|
-
expireTime: 5000,
|
|
441
|
-
});
|
|
442
|
-
|
|
443
|
-
map.set("key1", 100);
|
|
444
|
-
map.clear();
|
|
445
|
-
|
|
446
|
-
map.set("key2", 200);
|
|
447
|
-
expect(map.has("key2")).toBe(true);
|
|
448
|
-
expect(map.get("key2")).toBe(200);
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
it("GC works normally after clear", async () => {
|
|
452
|
-
const map = new LazyGcMap<string, number>({
|
|
453
|
-
gcInterval: 100,
|
|
454
|
-
expireTime: 200,
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
map.set("key1", 100);
|
|
458
|
-
map.clear();
|
|
459
|
-
|
|
460
|
-
// Add new item after clear
|
|
461
|
-
map.set("key2", 200);
|
|
462
|
-
|
|
463
|
-
// Verify GC works normally
|
|
464
|
-
await vi.advanceTimersByTimeAsync(350);
|
|
465
|
-
expect(map.has("key2")).toBe(false);
|
|
466
|
-
});
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
//#endregion
|
|
470
|
-
|
|
471
|
-
//#region Iterator
|
|
472
|
-
|
|
473
|
-
describe("Iterator", () => {
|
|
474
|
-
it("Iterates values with values()", () => {
|
|
475
|
-
const map = new LazyGcMap<string, number>({
|
|
476
|
-
gcInterval: 1000,
|
|
477
|
-
expireTime: 5000,
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
map.set("key1", 100);
|
|
481
|
-
map.set("key2", 200);
|
|
482
|
-
map.set("key3", 300);
|
|
483
|
-
|
|
484
|
-
const values = Array.from(map.values());
|
|
485
|
-
expect(values).toHaveLength(3);
|
|
486
|
-
expect(values).toContain(100);
|
|
487
|
-
expect(values).toContain(200);
|
|
488
|
-
expect(values).toContain(300);
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
it("Iterates keys with keys()", () => {
|
|
492
|
-
const map = new LazyGcMap<string, number>({
|
|
493
|
-
gcInterval: 1000,
|
|
494
|
-
expireTime: 5000,
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
map.set("key1", 100);
|
|
498
|
-
map.set("key2", 200);
|
|
499
|
-
|
|
500
|
-
const keys = Array.from(map.keys());
|
|
501
|
-
expect(keys).toEqual(["key1", "key2"]);
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
it("Iterates entries with entries()", () => {
|
|
505
|
-
const map = new LazyGcMap<string, number>({
|
|
506
|
-
gcInterval: 1000,
|
|
507
|
-
expireTime: 5000,
|
|
508
|
-
});
|
|
509
|
-
|
|
510
|
-
map.set("key1", 100);
|
|
511
|
-
map.set("key2", 200);
|
|
512
|
-
|
|
513
|
-
const entries = Array.from(map.entries());
|
|
514
|
-
expect(entries).toEqual([
|
|
515
|
-
["key1", 100],
|
|
516
|
-
["key2", 200],
|
|
517
|
-
]);
|
|
518
|
-
});
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
//#endregion
|
|
522
|
-
|
|
523
|
-
//#region Safety after dispose
|
|
524
|
-
|
|
525
|
-
describe("Safety after dispose", () => {
|
|
526
|
-
it("Returns undefined on get after dispose", () => {
|
|
527
|
-
const map = new LazyGcMap<string, number>({
|
|
528
|
-
gcInterval: 10000,
|
|
529
|
-
expireTime: 60000,
|
|
530
|
-
});
|
|
531
|
-
map.set("a", 1);
|
|
532
|
-
map.dispose();
|
|
533
|
-
expect(map.get("a")).toBeUndefined();
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
it("Returns false on has after dispose", () => {
|
|
537
|
-
const map = new LazyGcMap<string, number>({
|
|
538
|
-
gcInterval: 10000,
|
|
539
|
-
expireTime: 60000,
|
|
540
|
-
});
|
|
541
|
-
map.set("a", 1);
|
|
542
|
-
map.dispose();
|
|
543
|
-
expect(map.has("a")).toBe(false);
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
it("Returns false on delete after dispose", () => {
|
|
547
|
-
const map = new LazyGcMap<string, number>({
|
|
548
|
-
gcInterval: 10000,
|
|
549
|
-
expireTime: 60000,
|
|
550
|
-
});
|
|
551
|
-
map.set("a", 1);
|
|
552
|
-
map.dispose();
|
|
553
|
-
expect(map.delete("a")).toBe(false);
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
it("Throws error on getOrCreate after dispose", () => {
|
|
557
|
-
const map = new LazyGcMap<string, number>({
|
|
558
|
-
gcInterval: 10000,
|
|
559
|
-
expireTime: 60000,
|
|
560
|
-
});
|
|
561
|
-
map.dispose();
|
|
562
|
-
expect(() => map.getOrCreate("a", () => 1)).toThrow();
|
|
563
|
-
});
|
|
564
|
-
|
|
565
|
-
it("clear is safely ignored after dispose without error", () => {
|
|
566
|
-
const map = new LazyGcMap<string, number>({
|
|
567
|
-
gcInterval: 10000,
|
|
568
|
-
expireTime: 60000,
|
|
569
|
-
});
|
|
570
|
-
map.dispose();
|
|
571
|
-
expect(() => map.clear()).not.toThrow();
|
|
572
|
-
});
|
|
573
|
-
|
|
574
|
-
it("Returns empty iterator on values after dispose", () => {
|
|
575
|
-
const map = new LazyGcMap<string, number>({
|
|
576
|
-
gcInterval: 10000,
|
|
577
|
-
expireTime: 60000,
|
|
578
|
-
});
|
|
579
|
-
map.set("a", 1);
|
|
580
|
-
map.dispose();
|
|
581
|
-
expect([...map.values()]).toEqual([]);
|
|
582
|
-
});
|
|
583
|
-
|
|
584
|
-
it("Returns empty iterator on keys after dispose", () => {
|
|
585
|
-
const map = new LazyGcMap<string, number>({
|
|
586
|
-
gcInterval: 10000,
|
|
587
|
-
expireTime: 60000,
|
|
588
|
-
});
|
|
589
|
-
map.set("a", 1);
|
|
590
|
-
map.dispose();
|
|
591
|
-
expect([...map.keys()]).toEqual([]);
|
|
592
|
-
});
|
|
593
|
-
|
|
594
|
-
it("Returns empty iterator on entries after dispose", () => {
|
|
595
|
-
const map = new LazyGcMap<string, number>({
|
|
596
|
-
gcInterval: 10000,
|
|
597
|
-
expireTime: 60000,
|
|
598
|
-
});
|
|
599
|
-
map.set("a", 1);
|
|
600
|
-
map.dispose();
|
|
601
|
-
expect([...map.entries()]).toEqual([]);
|
|
602
|
-
});
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
//#endregion
|
|
606
|
-
});
|