@btc-vision/transaction 1.7.5 → 1.7.7
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/browser/index.js +1 -1
- package/browser/src/_version.d.ts +1 -1
- package/browser/src/deterministic/DeterministicMap.d.ts +3 -3
- package/browser/src/deterministic/FastMap.d.ts +24 -0
- package/browser/src/opnet.d.ts +1 -1
- package/browser/test/fastmap-setall.test.d.ts +1 -0
- package/browser/test/fastmap.test.d.ts +1 -0
- package/browser/test/old/FastBigIntMap.d.ts +18 -0
- package/browser/test/oldfastmap.test.d.ts +1 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/deterministic/AddressMap.js +2 -2
- package/build/deterministic/DeterministicMap.d.ts +3 -3
- package/build/deterministic/DeterministicMap.js +2 -2
- package/build/deterministic/FastMap.d.ts +24 -0
- package/build/deterministic/FastMap.js +88 -0
- package/build/opnet.d.ts +1 -1
- package/build/opnet.js +1 -1
- package/package.json +1 -1
- package/src/_version.ts +1 -1
- package/src/deterministic/AddressMap.ts +3 -3
- package/src/deterministic/DeterministicMap.ts +9 -6
- package/src/deterministic/FastMap.ts +124 -0
- package/src/opnet.ts +1 -1
- package/test/fastmap-setall.test.ts +143 -0
- package/test/fastmap.test.ts +917 -0
- package/test/old/FastBigIntMap.ts +132 -0
- package/test/oldfastmap.test.ts +917 -0
- package/browser/src/deterministic/Map.d.ts +0 -16
- package/build/deterministic/Map.d.ts +0 -16
- package/build/deterministic/Map.js +0 -74
- package/src/deterministic/Map.ts +0 -87
|
@@ -0,0 +1,917 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { FastMap } from '../src';
|
|
3
|
+
|
|
4
|
+
describe('FastMap<bigint, bigint> - Comprehensive Tests', () => {
|
|
5
|
+
describe('Constructor', () => {
|
|
6
|
+
it('should create an empty map with no parameters', () => {
|
|
7
|
+
const map = new FastMap<bigint, bigint>();
|
|
8
|
+
expect(map.size).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should create an empty map with null parameter', () => {
|
|
12
|
+
const map = new FastMap<bigint, bigint>(null);
|
|
13
|
+
expect(map.size).toBe(0);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should create an empty map with undefined parameter', () => {
|
|
17
|
+
const map = new FastMap<bigint, bigint>(undefined);
|
|
18
|
+
expect(map.size).toBe(0);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should create a map from an array of tuples', () => {
|
|
22
|
+
const entries: ReadonlyArray<readonly [bigint, bigint]> = [
|
|
23
|
+
[1n, 100n],
|
|
24
|
+
[2n, 200n],
|
|
25
|
+
[3n, 300n],
|
|
26
|
+
];
|
|
27
|
+
const map = new FastMap<bigint, bigint>(entries);
|
|
28
|
+
|
|
29
|
+
expect(map.size).toBe(3);
|
|
30
|
+
expect(map.get(1n)).toBe(100n);
|
|
31
|
+
expect(map.get(2n)).toBe(200n);
|
|
32
|
+
expect(map.get(3n)).toBe(300n);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should create a map from an empty array', () => {
|
|
36
|
+
const map = new FastMap<bigint, bigint>([]);
|
|
37
|
+
expect(map.size).toBe(0);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should create a map from another FastMap<bigint, bigint> instance', () => {
|
|
41
|
+
const original = new FastMap<bigint, bigint>([
|
|
42
|
+
[10n, 1000n],
|
|
43
|
+
[20n, 2000n],
|
|
44
|
+
]);
|
|
45
|
+
const copy = new FastMap<bigint, bigint>(original);
|
|
46
|
+
|
|
47
|
+
expect(copy.size).toBe(2);
|
|
48
|
+
expect(copy.get(10n)).toBe(1000n);
|
|
49
|
+
expect(copy.get(20n)).toBe(2000n);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should create an independent copy when constructed from another FastMap<bigint, bigint>', () => {
|
|
53
|
+
const original = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
54
|
+
const copy = new FastMap<bigint, bigint>(original);
|
|
55
|
+
|
|
56
|
+
// Modify original
|
|
57
|
+
original.set(1n, 999n);
|
|
58
|
+
original.set(2n, 200n);
|
|
59
|
+
|
|
60
|
+
// Copy should remain unchanged
|
|
61
|
+
expect(copy.get(1n)).toBe(100n);
|
|
62
|
+
expect(copy.has(2n)).toBe(false);
|
|
63
|
+
expect(copy.size).toBe(1);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should handle duplicate keys in initial array (last value wins)', () => {
|
|
67
|
+
const entries: ReadonlyArray<readonly [bigint, bigint]> = [
|
|
68
|
+
[1n, 100n],
|
|
69
|
+
[1n, 200n],
|
|
70
|
+
[1n, 300n],
|
|
71
|
+
];
|
|
72
|
+
const map = new FastMap<bigint, bigint>(entries);
|
|
73
|
+
|
|
74
|
+
expect(map.size).toBe(1);
|
|
75
|
+
expect(map.get(1n)).toBe(300n);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('size property', () => {
|
|
80
|
+
it('should return 0 for empty map', () => {
|
|
81
|
+
const map = new FastMap<bigint, bigint>();
|
|
82
|
+
expect(map.size).toBe(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should return correct size after adding elements', () => {
|
|
86
|
+
const map = new FastMap<bigint, bigint>();
|
|
87
|
+
map.set(1n, 100n);
|
|
88
|
+
expect(map.size).toBe(1);
|
|
89
|
+
|
|
90
|
+
map.set(2n, 200n);
|
|
91
|
+
expect(map.size).toBe(2);
|
|
92
|
+
|
|
93
|
+
map.set(3n, 300n);
|
|
94
|
+
expect(map.size).toBe(3);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should not increase size when updating existing key', () => {
|
|
98
|
+
const map = new FastMap<bigint, bigint>();
|
|
99
|
+
map.set(1n, 100n);
|
|
100
|
+
expect(map.size).toBe(1);
|
|
101
|
+
|
|
102
|
+
map.set(1n, 200n);
|
|
103
|
+
expect(map.size).toBe(1);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should decrease size after deletion', () => {
|
|
107
|
+
const map = new FastMap<bigint, bigint>([
|
|
108
|
+
[1n, 100n],
|
|
109
|
+
[2n, 200n],
|
|
110
|
+
]);
|
|
111
|
+
expect(map.size).toBe(2);
|
|
112
|
+
|
|
113
|
+
map.delete(1n);
|
|
114
|
+
expect(map.size).toBe(1);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should be 0 after clear', () => {
|
|
118
|
+
const map = new FastMap<bigint, bigint>([
|
|
119
|
+
[1n, 100n],
|
|
120
|
+
[2n, 200n],
|
|
121
|
+
]);
|
|
122
|
+
map.clear();
|
|
123
|
+
expect(map.size).toBe(0);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('set method', () => {
|
|
128
|
+
it('should add a new key-value pair', () => {
|
|
129
|
+
const map = new FastMap<bigint, bigint>();
|
|
130
|
+
map.set(1n, 100n);
|
|
131
|
+
|
|
132
|
+
expect(map.has(1n)).toBe(true);
|
|
133
|
+
expect(map.get(1n)).toBe(100n);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('should update an existing key', () => {
|
|
137
|
+
const map = new FastMap<bigint, bigint>();
|
|
138
|
+
map.set(1n, 100n);
|
|
139
|
+
map.set(1n, 200n);
|
|
140
|
+
|
|
141
|
+
expect(map.size).toBe(1);
|
|
142
|
+
expect(map.get(1n)).toBe(200n);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('should return this for chaining', () => {
|
|
146
|
+
const map = new FastMap<bigint, bigint>();
|
|
147
|
+
const result = map.set(1n, 100n);
|
|
148
|
+
|
|
149
|
+
expect(result).toBe(map);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should allow method chaining', () => {
|
|
153
|
+
const map = new FastMap<bigint, bigint>();
|
|
154
|
+
map.set(1n, 100n).set(2n, 200n).set(3n, 300n);
|
|
155
|
+
|
|
156
|
+
expect(map.size).toBe(3);
|
|
157
|
+
expect(map.get(1n)).toBe(100n);
|
|
158
|
+
expect(map.get(2n)).toBe(200n);
|
|
159
|
+
expect(map.get(3n)).toBe(300n);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should handle negative bigint keys', () => {
|
|
163
|
+
const map = new FastMap<bigint, bigint>();
|
|
164
|
+
map.set(-1n, 100n);
|
|
165
|
+
map.set(-999999999999999999n, 200n);
|
|
166
|
+
|
|
167
|
+
expect(map.get(-1n)).toBe(100n);
|
|
168
|
+
expect(map.get(-999999999999999999n)).toBe(200n);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should handle very large bigint keys', () => {
|
|
172
|
+
const map = new FastMap<bigint, bigint>();
|
|
173
|
+
const largeKey = 12345678901234567890123456789012345678901234567890n;
|
|
174
|
+
map.set(largeKey, 100n);
|
|
175
|
+
|
|
176
|
+
expect(map.has(largeKey)).toBe(true);
|
|
177
|
+
expect(map.get(largeKey)).toBe(100n);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should handle zero as key', () => {
|
|
181
|
+
const map = new FastMap<bigint, bigint>();
|
|
182
|
+
map.set(0n, 100n);
|
|
183
|
+
|
|
184
|
+
expect(map.has(0n)).toBe(true);
|
|
185
|
+
expect(map.get(0n)).toBe(100n);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should handle negative values', () => {
|
|
189
|
+
const map = new FastMap<bigint, bigint>();
|
|
190
|
+
map.set(1n, -100n);
|
|
191
|
+
|
|
192
|
+
expect(map.get(1n)).toBe(-100n);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should handle zero as value', () => {
|
|
196
|
+
const map = new FastMap<bigint, bigint>();
|
|
197
|
+
map.set(1n, 0n);
|
|
198
|
+
|
|
199
|
+
expect(map.get(1n)).toBe(0n);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('get method', () => {
|
|
204
|
+
it('should return the value for an existing key', () => {
|
|
205
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
206
|
+
expect(map.get(1n)).toBe(100n);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should return undefined for a non-existing key', () => {
|
|
210
|
+
const map = new FastMap<bigint, bigint>();
|
|
211
|
+
expect(map.get(1n)).toBeUndefined();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('should return undefined for key in empty map', () => {
|
|
215
|
+
const map = new FastMap<bigint, bigint>();
|
|
216
|
+
expect(map.get(999n)).toBeUndefined();
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('should return correct value after update', () => {
|
|
220
|
+
const map = new FastMap<bigint, bigint>();
|
|
221
|
+
map.set(1n, 100n);
|
|
222
|
+
map.set(1n, 200n);
|
|
223
|
+
|
|
224
|
+
expect(map.get(1n)).toBe(200n);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should return undefined for deleted key', () => {
|
|
228
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
229
|
+
map.delete(1n);
|
|
230
|
+
|
|
231
|
+
expect(map.get(1n)).toBeUndefined();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe('has method', () => {
|
|
236
|
+
it('should return true for existing key', () => {
|
|
237
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
238
|
+
expect(map.has(1n)).toBe(true);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it('should return false for non-existing key', () => {
|
|
242
|
+
const map = new FastMap<bigint, bigint>();
|
|
243
|
+
expect(map.has(1n)).toBe(false);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should return false after key is deleted', () => {
|
|
247
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
248
|
+
map.delete(1n);
|
|
249
|
+
|
|
250
|
+
expect(map.has(1n)).toBe(false);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('should return false after clear', () => {
|
|
254
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
255
|
+
map.clear();
|
|
256
|
+
|
|
257
|
+
expect(map.has(1n)).toBe(false);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('should distinguish between different keys', () => {
|
|
261
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
262
|
+
|
|
263
|
+
expect(map.has(1n)).toBe(true);
|
|
264
|
+
expect(map.has(2n)).toBe(false);
|
|
265
|
+
expect(map.has(-1n)).toBe(false);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
describe('delete method', () => {
|
|
270
|
+
it('should delete an existing key and return true', () => {
|
|
271
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
272
|
+
const result = map.delete(1n);
|
|
273
|
+
|
|
274
|
+
expect(result).toBe(true);
|
|
275
|
+
expect(map.has(1n)).toBe(false);
|
|
276
|
+
expect(map.size).toBe(0);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should return false for non-existing key', () => {
|
|
280
|
+
const map = new FastMap<bigint, bigint>();
|
|
281
|
+
const result = map.delete(1n);
|
|
282
|
+
|
|
283
|
+
expect(result).toBe(false);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('should return false when deleting from empty map', () => {
|
|
287
|
+
const map = new FastMap<bigint, bigint>();
|
|
288
|
+
expect(map.delete(999n)).toBe(false);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it('should only delete the specified key', () => {
|
|
292
|
+
const map = new FastMap<bigint, bigint>([
|
|
293
|
+
[1n, 100n],
|
|
294
|
+
[2n, 200n],
|
|
295
|
+
[3n, 300n],
|
|
296
|
+
]);
|
|
297
|
+
map.delete(2n);
|
|
298
|
+
|
|
299
|
+
expect(map.has(1n)).toBe(true);
|
|
300
|
+
expect(map.has(2n)).toBe(false);
|
|
301
|
+
expect(map.has(3n)).toBe(true);
|
|
302
|
+
expect(map.size).toBe(2);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
it('should maintain insertion order after deletion', () => {
|
|
306
|
+
const map = new FastMap<bigint, bigint>([
|
|
307
|
+
[1n, 100n],
|
|
308
|
+
[2n, 200n],
|
|
309
|
+
[3n, 300n],
|
|
310
|
+
]);
|
|
311
|
+
map.delete(2n);
|
|
312
|
+
|
|
313
|
+
const keys = [...map.keys()];
|
|
314
|
+
expect(keys).toEqual([1n, 3n]);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
it('should return false when deleting already deleted key', () => {
|
|
318
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
319
|
+
map.delete(1n);
|
|
320
|
+
|
|
321
|
+
expect(map.delete(1n)).toBe(false);
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('clear method', () => {
|
|
326
|
+
it('should remove all entries', () => {
|
|
327
|
+
const map = new FastMap<bigint, bigint>([
|
|
328
|
+
[1n, 100n],
|
|
329
|
+
[2n, 200n],
|
|
330
|
+
[3n, 300n],
|
|
331
|
+
]);
|
|
332
|
+
map.clear();
|
|
333
|
+
|
|
334
|
+
expect(map.size).toBe(0);
|
|
335
|
+
expect(map.has(1n)).toBe(false);
|
|
336
|
+
expect(map.has(2n)).toBe(false);
|
|
337
|
+
expect(map.has(3n)).toBe(false);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should work on empty map', () => {
|
|
341
|
+
const map = new FastMap<bigint, bigint>();
|
|
342
|
+
map.clear();
|
|
343
|
+
|
|
344
|
+
expect(map.size).toBe(0);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should allow adding entries after clear', () => {
|
|
348
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
349
|
+
map.clear();
|
|
350
|
+
map.set(2n, 200n);
|
|
351
|
+
|
|
352
|
+
expect(map.size).toBe(1);
|
|
353
|
+
expect(map.get(2n)).toBe(200n);
|
|
354
|
+
});
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
describe('setAll method', () => {
|
|
358
|
+
it('should copy all entries from another map', () => {
|
|
359
|
+
const source = new FastMap<bigint, bigint>([
|
|
360
|
+
[1n, 100n],
|
|
361
|
+
[2n, 200n],
|
|
362
|
+
]);
|
|
363
|
+
const target = new FastMap<bigint, bigint>();
|
|
364
|
+
target.setAll(source);
|
|
365
|
+
|
|
366
|
+
expect(target.size).toBe(2);
|
|
367
|
+
expect(target.get(1n)).toBe(100n);
|
|
368
|
+
expect(target.get(2n)).toBe(200n);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it('should replace all existing entries', () => {
|
|
372
|
+
const source = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
373
|
+
const target = new FastMap<bigint, bigint>([
|
|
374
|
+
[2n, 200n],
|
|
375
|
+
[3n, 300n],
|
|
376
|
+
]);
|
|
377
|
+
target.setAll(source);
|
|
378
|
+
|
|
379
|
+
expect(target.size).toBe(1);
|
|
380
|
+
expect(target.get(1n)).toBe(100n);
|
|
381
|
+
expect(target.has(2n)).toBe(false);
|
|
382
|
+
expect(target.has(3n)).toBe(false);
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
it('should create independent copy (modifications to source do not affect target)', () => {
|
|
386
|
+
const source = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
387
|
+
const target = new FastMap<bigint, bigint>();
|
|
388
|
+
target.setAll(source);
|
|
389
|
+
|
|
390
|
+
source.set(1n, 999n);
|
|
391
|
+
source.set(2n, 200n);
|
|
392
|
+
|
|
393
|
+
expect(target.get(1n)).toBe(100n);
|
|
394
|
+
expect(target.has(2n)).toBe(false);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('should handle empty source map', () => {
|
|
398
|
+
const source = new FastMap<bigint, bigint>();
|
|
399
|
+
const target = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
400
|
+
target.setAll(source);
|
|
401
|
+
|
|
402
|
+
expect(target.size).toBe(0);
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
describe('addAll method', () => {
|
|
407
|
+
it('should add all entries from another map', () => {
|
|
408
|
+
const source = new FastMap<bigint, bigint>([
|
|
409
|
+
[1n, 100n],
|
|
410
|
+
[2n, 200n],
|
|
411
|
+
]);
|
|
412
|
+
const target = new FastMap<bigint, bigint>();
|
|
413
|
+
target.addAll(source);
|
|
414
|
+
|
|
415
|
+
expect(target.size).toBe(2);
|
|
416
|
+
expect(target.get(1n)).toBe(100n);
|
|
417
|
+
expect(target.get(2n)).toBe(200n);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('should merge with existing entries', () => {
|
|
421
|
+
const source = new FastMap<bigint, bigint>([
|
|
422
|
+
[2n, 200n],
|
|
423
|
+
[3n, 300n],
|
|
424
|
+
]);
|
|
425
|
+
const target = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
426
|
+
target.addAll(source);
|
|
427
|
+
|
|
428
|
+
expect(target.size).toBe(3);
|
|
429
|
+
expect(target.get(1n)).toBe(100n);
|
|
430
|
+
expect(target.get(2n)).toBe(200n);
|
|
431
|
+
expect(target.get(3n)).toBe(300n);
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
it('should overwrite existing keys with values from source', () => {
|
|
435
|
+
const source = new FastMap<bigint, bigint>([[1n, 999n]]);
|
|
436
|
+
const target = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
437
|
+
target.addAll(source);
|
|
438
|
+
|
|
439
|
+
expect(target.size).toBe(1);
|
|
440
|
+
expect(target.get(1n)).toBe(999n);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('should handle empty source map', () => {
|
|
444
|
+
const source = new FastMap<bigint, bigint>();
|
|
445
|
+
const target = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
446
|
+
target.addAll(source);
|
|
447
|
+
|
|
448
|
+
expect(target.size).toBe(1);
|
|
449
|
+
expect(target.get(1n)).toBe(100n);
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('should preserve insertion order (existing keys first, then new keys)', () => {
|
|
453
|
+
const source = new FastMap<bigint, bigint>([
|
|
454
|
+
[2n, 200n],
|
|
455
|
+
[3n, 300n],
|
|
456
|
+
]);
|
|
457
|
+
const target = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
458
|
+
target.addAll(source);
|
|
459
|
+
|
|
460
|
+
const keys = [...target.keys()];
|
|
461
|
+
expect(keys).toEqual([1n, 2n, 3n]);
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
describe('entries method', () => {
|
|
466
|
+
it('should return an iterator of [key, value] pairs', () => {
|
|
467
|
+
const map = new FastMap<bigint, bigint>([
|
|
468
|
+
[1n, 100n],
|
|
469
|
+
[2n, 200n],
|
|
470
|
+
]);
|
|
471
|
+
const entries = [...map.entries()];
|
|
472
|
+
|
|
473
|
+
expect(entries).toEqual([
|
|
474
|
+
[1n, 100n],
|
|
475
|
+
[2n, 200n],
|
|
476
|
+
]);
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it('should return empty iterator for empty map', () => {
|
|
480
|
+
const map = new FastMap<bigint, bigint>();
|
|
481
|
+
const entries = [...map.entries()];
|
|
482
|
+
|
|
483
|
+
expect(entries).toEqual([]);
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
it('should iterate in insertion order', () => {
|
|
487
|
+
const map = new FastMap<bigint, bigint>();
|
|
488
|
+
map.set(3n, 300n);
|
|
489
|
+
map.set(1n, 100n);
|
|
490
|
+
map.set(2n, 200n);
|
|
491
|
+
|
|
492
|
+
const entries = [...map.entries()];
|
|
493
|
+
expect(entries).toEqual([
|
|
494
|
+
[3n, 300n],
|
|
495
|
+
[1n, 100n],
|
|
496
|
+
[2n, 200n],
|
|
497
|
+
]);
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it('should be usable with for...of loop', () => {
|
|
501
|
+
const map = new FastMap<bigint, bigint>([
|
|
502
|
+
[1n, 100n],
|
|
503
|
+
[2n, 200n],
|
|
504
|
+
]);
|
|
505
|
+
const collected: [bigint, bigint][] = [];
|
|
506
|
+
|
|
507
|
+
for (const entry of map.entries()) {
|
|
508
|
+
collected.push(entry);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
expect(collected).toEqual([
|
|
512
|
+
[1n, 100n],
|
|
513
|
+
[2n, 200n],
|
|
514
|
+
]);
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
describe('keys method', () => {
|
|
519
|
+
it('should return an iterator of keys', () => {
|
|
520
|
+
const map = new FastMap<bigint, bigint>([
|
|
521
|
+
[1n, 100n],
|
|
522
|
+
[2n, 200n],
|
|
523
|
+
[3n, 300n],
|
|
524
|
+
]);
|
|
525
|
+
const keys = [...map.keys()];
|
|
526
|
+
|
|
527
|
+
expect(keys).toEqual([1n, 2n, 3n]);
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
it('should return empty iterator for empty map', () => {
|
|
531
|
+
const map = new FastMap<bigint, bigint>();
|
|
532
|
+
const keys = [...map.keys()];
|
|
533
|
+
|
|
534
|
+
expect(keys).toEqual([]);
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('should iterate in insertion order', () => {
|
|
538
|
+
const map = new FastMap<bigint, bigint>();
|
|
539
|
+
map.set(5n, 500n);
|
|
540
|
+
map.set(1n, 100n);
|
|
541
|
+
map.set(3n, 300n);
|
|
542
|
+
|
|
543
|
+
const keys = [...map.keys()];
|
|
544
|
+
expect(keys).toEqual([5n, 1n, 3n]);
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
it('should be usable with for...of loop', () => {
|
|
548
|
+
const map = new FastMap<bigint, bigint>([
|
|
549
|
+
[1n, 100n],
|
|
550
|
+
[2n, 200n],
|
|
551
|
+
]);
|
|
552
|
+
const collected: bigint[] = [];
|
|
553
|
+
|
|
554
|
+
for (const key of map.keys()) {
|
|
555
|
+
collected.push(key);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
expect(collected).toEqual([1n, 2n]);
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
describe('values method', () => {
|
|
563
|
+
it('should return an iterator of values', () => {
|
|
564
|
+
const map = new FastMap<bigint, bigint>([
|
|
565
|
+
[1n, 100n],
|
|
566
|
+
[2n, 200n],
|
|
567
|
+
[3n, 300n],
|
|
568
|
+
]);
|
|
569
|
+
const values = [...map.values()];
|
|
570
|
+
|
|
571
|
+
expect(values).toEqual([100n, 200n, 300n]);
|
|
572
|
+
});
|
|
573
|
+
|
|
574
|
+
it('should return empty iterator for empty map', () => {
|
|
575
|
+
const map = new FastMap<bigint, bigint>();
|
|
576
|
+
const values = [...map.values()];
|
|
577
|
+
|
|
578
|
+
expect(values).toEqual([]);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
it('should iterate in insertion order', () => {
|
|
582
|
+
const map = new FastMap<bigint, bigint>();
|
|
583
|
+
map.set(3n, 300n);
|
|
584
|
+
map.set(1n, 100n);
|
|
585
|
+
map.set(2n, 200n);
|
|
586
|
+
|
|
587
|
+
const values = [...map.values()];
|
|
588
|
+
expect(values).toEqual([300n, 100n, 200n]);
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
it('should be usable with for...of loop', () => {
|
|
592
|
+
const map = new FastMap<bigint, bigint>([
|
|
593
|
+
[1n, 100n],
|
|
594
|
+
[2n, 200n],
|
|
595
|
+
]);
|
|
596
|
+
const collected: bigint[] = [];
|
|
597
|
+
|
|
598
|
+
for (const value of map.values()) {
|
|
599
|
+
collected.push(value);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
expect(collected).toEqual([100n, 200n]);
|
|
603
|
+
});
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
describe('forEach method', () => {
|
|
607
|
+
it('should call callback for each entry', () => {
|
|
608
|
+
const map = new FastMap<bigint, bigint>([
|
|
609
|
+
[1n, 100n],
|
|
610
|
+
[2n, 200n],
|
|
611
|
+
]);
|
|
612
|
+
const callback = vi.fn();
|
|
613
|
+
|
|
614
|
+
map.forEach(callback);
|
|
615
|
+
|
|
616
|
+
expect(callback).toHaveBeenCalledTimes(2);
|
|
617
|
+
expect(callback).toHaveBeenNthCalledWith(1, 100n, 1n, map);
|
|
618
|
+
expect(callback).toHaveBeenNthCalledWith(2, 200n, 2n, map);
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
it('should not call callback for empty map', () => {
|
|
622
|
+
const map = new FastMap<bigint, bigint>();
|
|
623
|
+
const callback = vi.fn();
|
|
624
|
+
|
|
625
|
+
map.forEach(callback);
|
|
626
|
+
|
|
627
|
+
expect(callback).not.toHaveBeenCalled();
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
it('should iterate in insertion order', () => {
|
|
631
|
+
const map = new FastMap<bigint, bigint>();
|
|
632
|
+
map.set(3n, 300n);
|
|
633
|
+
map.set(1n, 100n);
|
|
634
|
+
map.set(2n, 200n);
|
|
635
|
+
|
|
636
|
+
const order: bigint[] = [];
|
|
637
|
+
map.forEach((value, key) => {
|
|
638
|
+
order.push(key);
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
expect(order).toEqual([3n, 1n, 2n]);
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
it('should use thisArg when provided', () => {
|
|
645
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
646
|
+
const context = { multiplier: 2n };
|
|
647
|
+
|
|
648
|
+
let result: bigint = 0n;
|
|
649
|
+
map.forEach(function (this: { multiplier: bigint }, value) {
|
|
650
|
+
result = value * this.multiplier;
|
|
651
|
+
}, context);
|
|
652
|
+
|
|
653
|
+
expect(result).toBe(200n);
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
it('should work without thisArg', () => {
|
|
657
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
658
|
+
let sum = 0n;
|
|
659
|
+
|
|
660
|
+
map.forEach((value) => {
|
|
661
|
+
sum += value;
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
expect(sum).toBe(100n);
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
it('should pass map as third argument', () => {
|
|
668
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
669
|
+
let receivedMap: FastMap<bigint, bigint> | null = null;
|
|
670
|
+
|
|
671
|
+
map.forEach((value, key, m) => {
|
|
672
|
+
receivedMap = m;
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
expect(receivedMap).toBe(map);
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
describe('Symbol.iterator', () => {
|
|
680
|
+
it('should make map iterable with for...of', () => {
|
|
681
|
+
const map = new FastMap<bigint, bigint>([
|
|
682
|
+
[1n, 100n],
|
|
683
|
+
[2n, 200n],
|
|
684
|
+
]);
|
|
685
|
+
const collected: [bigint, bigint][] = [];
|
|
686
|
+
|
|
687
|
+
for (const entry of map) {
|
|
688
|
+
collected.push(entry);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
expect(collected).toEqual([
|
|
692
|
+
[1n, 100n],
|
|
693
|
+
[2n, 200n],
|
|
694
|
+
]);
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
it('should return same iterator as entries()', () => {
|
|
698
|
+
const map = new FastMap<bigint, bigint>([
|
|
699
|
+
[1n, 100n],
|
|
700
|
+
[2n, 200n],
|
|
701
|
+
]);
|
|
702
|
+
|
|
703
|
+
const fromIterator = [...map];
|
|
704
|
+
const fromEntries = [...map.entries()];
|
|
705
|
+
|
|
706
|
+
expect(fromIterator).toEqual(fromEntries);
|
|
707
|
+
});
|
|
708
|
+
|
|
709
|
+
it('should work with spread operator', () => {
|
|
710
|
+
const map = new FastMap<bigint, bigint>([
|
|
711
|
+
[1n, 100n],
|
|
712
|
+
[2n, 200n],
|
|
713
|
+
]);
|
|
714
|
+
const entries = [...map];
|
|
715
|
+
|
|
716
|
+
expect(entries).toEqual([
|
|
717
|
+
[1n, 100n],
|
|
718
|
+
[2n, 200n],
|
|
719
|
+
]);
|
|
720
|
+
});
|
|
721
|
+
|
|
722
|
+
it('should work with Array.from', () => {
|
|
723
|
+
const map = new FastMap<bigint, bigint>([
|
|
724
|
+
[1n, 100n],
|
|
725
|
+
[2n, 200n],
|
|
726
|
+
]);
|
|
727
|
+
const entries = Array.from(map);
|
|
728
|
+
|
|
729
|
+
expect(entries).toEqual([
|
|
730
|
+
[1n, 100n],
|
|
731
|
+
[2n, 200n],
|
|
732
|
+
]);
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
it('should work with destructuring', () => {
|
|
736
|
+
const map = new FastMap<bigint, bigint>([
|
|
737
|
+
[1n, 100n],
|
|
738
|
+
[2n, 200n],
|
|
739
|
+
]);
|
|
740
|
+
const [first, second] = map;
|
|
741
|
+
|
|
742
|
+
expect(first).toEqual([1n, 100n]);
|
|
743
|
+
expect(second).toEqual([2n, 200n]);
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
it('should return empty iterator for empty map', () => {
|
|
747
|
+
const map = new FastMap<bigint, bigint>();
|
|
748
|
+
const entries = [...map];
|
|
749
|
+
|
|
750
|
+
expect(entries).toEqual([]);
|
|
751
|
+
});
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
describe('Insertion order preservation', () => {
|
|
755
|
+
it('should maintain insertion order across all iteration methods', () => {
|
|
756
|
+
const map = new FastMap<bigint, bigint>();
|
|
757
|
+
map.set(5n, 500n);
|
|
758
|
+
map.set(1n, 100n);
|
|
759
|
+
map.set(3n, 300n);
|
|
760
|
+
map.set(2n, 200n);
|
|
761
|
+
map.set(4n, 400n);
|
|
762
|
+
|
|
763
|
+
const keysFromKeys = [...map.keys()];
|
|
764
|
+
const keysFromEntries = [...map.entries()].map(([k]) => k);
|
|
765
|
+
const keysFromForEach: bigint[] = [];
|
|
766
|
+
map.forEach((_, key) => keysFromForEach.push(key));
|
|
767
|
+
const keysFromIterator = [...map].map(([k]) => k);
|
|
768
|
+
|
|
769
|
+
const expectedOrder = [5n, 1n, 3n, 2n, 4n];
|
|
770
|
+
|
|
771
|
+
expect(keysFromKeys).toEqual(expectedOrder);
|
|
772
|
+
expect(keysFromEntries).toEqual(expectedOrder);
|
|
773
|
+
expect(keysFromForEach).toEqual(expectedOrder);
|
|
774
|
+
expect(keysFromIterator).toEqual(expectedOrder);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
it('should not change order when updating existing key', () => {
|
|
778
|
+
const map = new FastMap<bigint, bigint>();
|
|
779
|
+
map.set(1n, 100n);
|
|
780
|
+
map.set(2n, 200n);
|
|
781
|
+
map.set(3n, 300n);
|
|
782
|
+
|
|
783
|
+
// Update middle key
|
|
784
|
+
map.set(2n, 999n);
|
|
785
|
+
|
|
786
|
+
const keys = [...map.keys()];
|
|
787
|
+
expect(keys).toEqual([1n, 2n, 3n]);
|
|
788
|
+
expect(map.get(2n)).toBe(999n);
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
describe('Edge cases', () => {
|
|
793
|
+
it('should handle maximum safe bigint values', () => {
|
|
794
|
+
const map = new FastMap<bigint, bigint>();
|
|
795
|
+
const maxSafe = BigInt(Number.MAX_SAFE_INTEGER);
|
|
796
|
+
const minSafe = BigInt(Number.MIN_SAFE_INTEGER);
|
|
797
|
+
|
|
798
|
+
map.set(maxSafe, 1n);
|
|
799
|
+
map.set(minSafe, 2n);
|
|
800
|
+
|
|
801
|
+
expect(map.get(maxSafe)).toBe(1n);
|
|
802
|
+
expect(map.get(minSafe)).toBe(2n);
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
it('should handle extremely large bigints', () => {
|
|
806
|
+
const map = new FastMap<bigint, bigint>();
|
|
807
|
+
const hugeKey = 10n ** 100n;
|
|
808
|
+
const hugeValue = 10n ** 200n;
|
|
809
|
+
|
|
810
|
+
map.set(hugeKey, hugeValue);
|
|
811
|
+
|
|
812
|
+
expect(map.get(hugeKey)).toBe(hugeValue);
|
|
813
|
+
});
|
|
814
|
+
|
|
815
|
+
it('should handle many entries', () => {
|
|
816
|
+
const map = new FastMap<bigint, bigint>();
|
|
817
|
+
const count = 10000;
|
|
818
|
+
|
|
819
|
+
for (let i = 0; i < count; i++) {
|
|
820
|
+
map.set(BigInt(i), BigInt(i * 10));
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
expect(map.size).toBe(count);
|
|
824
|
+
expect(map.get(0n)).toBe(0n);
|
|
825
|
+
expect(map.get(5000n)).toBe(50000n);
|
|
826
|
+
expect(map.get(9999n)).toBe(99990n);
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
it('should correctly handle 0n as both key and value', () => {
|
|
830
|
+
const map = new FastMap<bigint, bigint>();
|
|
831
|
+
map.set(0n, 0n);
|
|
832
|
+
|
|
833
|
+
expect(map.has(0n)).toBe(true);
|
|
834
|
+
expect(map.get(0n)).toBe(0n);
|
|
835
|
+
expect(map.size).toBe(1);
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
it('should handle negative zero (-0n is same as 0n in bigint)', () => {
|
|
839
|
+
const map = new FastMap<bigint, bigint>();
|
|
840
|
+
map.set(-0n, 100n);
|
|
841
|
+
|
|
842
|
+
expect(map.get(0n)).toBe(100n);
|
|
843
|
+
expect(map.has(-0n)).toBe(true);
|
|
844
|
+
});
|
|
845
|
+
|
|
846
|
+
it('should handle operations in sequence', () => {
|
|
847
|
+
const map = new FastMap<bigint, bigint>();
|
|
848
|
+
|
|
849
|
+
// Add
|
|
850
|
+
map.set(1n, 100n);
|
|
851
|
+
map.set(2n, 200n);
|
|
852
|
+
expect(map.size).toBe(2);
|
|
853
|
+
|
|
854
|
+
// Update
|
|
855
|
+
map.set(1n, 150n);
|
|
856
|
+
expect(map.get(1n)).toBe(150n);
|
|
857
|
+
expect(map.size).toBe(2);
|
|
858
|
+
|
|
859
|
+
// Delete
|
|
860
|
+
map.delete(1n);
|
|
861
|
+
expect(map.size).toBe(1);
|
|
862
|
+
expect(map.has(1n)).toBe(false);
|
|
863
|
+
|
|
864
|
+
// Add back
|
|
865
|
+
map.set(1n, 100n);
|
|
866
|
+
expect(map.size).toBe(2);
|
|
867
|
+
|
|
868
|
+
// Clear
|
|
869
|
+
map.clear();
|
|
870
|
+
expect(map.size).toBe(0);
|
|
871
|
+
|
|
872
|
+
// Add after clear
|
|
873
|
+
map.set(3n, 300n);
|
|
874
|
+
expect(map.size).toBe(1);
|
|
875
|
+
expect(map.get(3n)).toBe(300n);
|
|
876
|
+
});
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
describe('Type safety and method signatures', () => {
|
|
880
|
+
it('set should accept bigint key and bigint value', () => {
|
|
881
|
+
const map = new FastMap<bigint, bigint>();
|
|
882
|
+
const result = map.set(1n, 100n);
|
|
883
|
+
|
|
884
|
+
expect(result).toBeInstanceOf(FastMap<bigint, bigint>);
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
it('get should return bigint or undefined', () => {
|
|
888
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
889
|
+
|
|
890
|
+
const existing: bigint | undefined = map.get(1n);
|
|
891
|
+
const nonExisting: bigint | undefined = map.get(999n);
|
|
892
|
+
|
|
893
|
+
expect(typeof existing).toBe('bigint');
|
|
894
|
+
expect(nonExisting).toBeUndefined();
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
it('has should return boolean', () => {
|
|
898
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
899
|
+
|
|
900
|
+
expect(typeof map.has(1n)).toBe('boolean');
|
|
901
|
+
expect(typeof map.has(999n)).toBe('boolean');
|
|
902
|
+
});
|
|
903
|
+
|
|
904
|
+
it('delete should return boolean', () => {
|
|
905
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
906
|
+
|
|
907
|
+
expect(typeof map.delete(1n)).toBe('boolean');
|
|
908
|
+
expect(typeof map.delete(999n)).toBe('boolean');
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
it('size should return number', () => {
|
|
912
|
+
const map = new FastMap<bigint, bigint>([[1n, 100n]]);
|
|
913
|
+
|
|
914
|
+
expect(typeof map.size).toBe('number');
|
|
915
|
+
});
|
|
916
|
+
});
|
|
917
|
+
});
|