mutts 1.0.0 → 1.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/chunks/{decorator-BXsign4Z.js → decorator-8qjFb7dw.js} +2 -2
- package/dist/chunks/decorator-8qjFb7dw.js.map +1 -0
- package/dist/chunks/{decorator-CPbZNnsX.esm.js → decorator-AbRkXM5O.esm.js} +2 -2
- package/dist/chunks/decorator-AbRkXM5O.esm.js.map +1 -0
- package/dist/decorator.d.ts +1 -1
- package/dist/decorator.esm.js +1 -1
- package/dist/decorator.js +1 -1
- package/dist/destroyable.esm.js +1 -1
- package/dist/destroyable.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +2 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mutts.umd.js +1 -1
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/reactive.d.ts +4 -3
- package/dist/reactive.esm.js +61 -57
- package/dist/reactive.esm.js.map +1 -1
- package/dist/reactive.js +61 -56
- package/dist/reactive.js.map +1 -1
- package/dist/std-decorators.esm.js +1 -1
- package/dist/std-decorators.js +1 -1
- package/docs/reactive.md +616 -0
- package/package.json +1 -2
- package/dist/chunks/decorator-BXsign4Z.js.map +0 -1
- package/dist/chunks/decorator-CPbZNnsX.esm.js.map +0 -1
- package/src/decorator.test.ts +0 -495
- package/src/decorator.ts +0 -205
- package/src/destroyable.test.ts +0 -155
- package/src/destroyable.ts +0 -158
- package/src/eventful.test.ts +0 -380
- package/src/eventful.ts +0 -69
- package/src/index.ts +0 -7
- package/src/indexable.test.ts +0 -388
- package/src/indexable.ts +0 -124
- package/src/promiseChain.test.ts +0 -201
- package/src/promiseChain.ts +0 -99
- package/src/reactive/array.test.ts +0 -923
- package/src/reactive/array.ts +0 -352
- package/src/reactive/core.test.ts +0 -1663
- package/src/reactive/core.ts +0 -866
- package/src/reactive/index.ts +0 -28
- package/src/reactive/interface.test.ts +0 -1477
- package/src/reactive/interface.ts +0 -231
- package/src/reactive/map.test.ts +0 -866
- package/src/reactive/map.ts +0 -162
- package/src/reactive/set.test.ts +0 -289
- package/src/reactive/set.ts +0 -142
- package/src/std-decorators.test.ts +0 -679
- package/src/std-decorators.ts +0 -182
- package/src/utils.ts +0 -52
package/src/reactive/map.test.ts
DELETED
|
@@ -1,866 +0,0 @@
|
|
|
1
|
-
import { effect, reactive } from './index'
|
|
2
|
-
|
|
3
|
-
describe('ReactiveWeakMap', () => {
|
|
4
|
-
describe('basic functionality', () => {
|
|
5
|
-
it('should create a reactive WeakMap wrapper', () => {
|
|
6
|
-
const weakMap = new WeakMap<object, string>()
|
|
7
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
8
|
-
expect(reactiveWeakMap).toBeInstanceOf(Object)
|
|
9
|
-
// ReactiveWeakMap is a wrapper, not a native WeakMap instance
|
|
10
|
-
expect(reactiveWeakMap).toBeInstanceOf(WeakMap)
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it('should work with reactive() function', () => {
|
|
14
|
-
const weakMap = new WeakMap<object, string>()
|
|
15
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
16
|
-
|
|
17
|
-
// The reactive wrapper should behave like a WeakMap
|
|
18
|
-
expect(reactiveWeakMap).toBeInstanceOf(WeakMap)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('should wrap existing WeakMap with entries', () => {
|
|
22
|
-
const key1 = { id: 1 }
|
|
23
|
-
const key2 = { id: 2 }
|
|
24
|
-
const originalWeakMap = new WeakMap<object, string>([
|
|
25
|
-
[key1, 'value1'],
|
|
26
|
-
[key2, 'value2'],
|
|
27
|
-
])
|
|
28
|
-
const reactiveWeakMap = reactive(originalWeakMap)
|
|
29
|
-
|
|
30
|
-
expect(reactiveWeakMap.get(key1)).toBe('value1')
|
|
31
|
-
expect(reactiveWeakMap.get(key2)).toBe('value2')
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
describe('reactive operations', () => {
|
|
36
|
-
it('should track dependencies when getting values', () => {
|
|
37
|
-
const weakMap = new WeakMap<object, string>()
|
|
38
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
39
|
-
const key = { id: 1 }
|
|
40
|
-
reactiveWeakMap.set(key, 'test')
|
|
41
|
-
|
|
42
|
-
let effectCount = 0
|
|
43
|
-
effect(() => {
|
|
44
|
-
effectCount++
|
|
45
|
-
reactiveWeakMap.get(key)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
expect(effectCount).toBe(1)
|
|
49
|
-
|
|
50
|
-
// Changing the value should trigger the effect
|
|
51
|
-
reactiveWeakMap.set(key, 'new value')
|
|
52
|
-
expect(effectCount).toBe(2)
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it('should track dependencies when checking existence', () => {
|
|
56
|
-
const weakMap = new WeakMap<object, string>()
|
|
57
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
58
|
-
const key = { id: 1 }
|
|
59
|
-
reactiveWeakMap.set(key, 'test')
|
|
60
|
-
|
|
61
|
-
let effectCount = 0
|
|
62
|
-
effect(() => {
|
|
63
|
-
effectCount++
|
|
64
|
-
reactiveWeakMap.has(key)
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
expect(effectCount).toBe(1)
|
|
68
|
-
|
|
69
|
-
// Deleting the key should trigger the effect
|
|
70
|
-
reactiveWeakMap.delete(key)
|
|
71
|
-
expect(effectCount).toBe(2)
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('should trigger effects when setting new values', () => {
|
|
75
|
-
const weakMap = new WeakMap<object, string>()
|
|
76
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
77
|
-
const key = { id: 1 }
|
|
78
|
-
|
|
79
|
-
let effectCount = 0
|
|
80
|
-
effect(() => {
|
|
81
|
-
effectCount++
|
|
82
|
-
reactiveWeakMap.get(key)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
expect(effectCount).toBe(1)
|
|
86
|
-
|
|
87
|
-
// Setting a new value should trigger the effect
|
|
88
|
-
reactiveWeakMap.set(key, 'new value')
|
|
89
|
-
expect(effectCount).toBe(2)
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
it('should trigger effects when updating existing values', () => {
|
|
93
|
-
const weakMap = new WeakMap<object, string>()
|
|
94
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
95
|
-
const key = { id: 1 }
|
|
96
|
-
reactiveWeakMap.set(key, 'old value')
|
|
97
|
-
|
|
98
|
-
let effectCount = 0
|
|
99
|
-
effect(() => {
|
|
100
|
-
effectCount++
|
|
101
|
-
reactiveWeakMap.get(key)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
expect(effectCount).toBe(1)
|
|
105
|
-
|
|
106
|
-
// Updating the value should trigger the effect
|
|
107
|
-
reactiveWeakMap.set(key, 'new value')
|
|
108
|
-
expect(effectCount).toBe(2)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('should trigger effects when deleting keys', () => {
|
|
112
|
-
const weakMap = new WeakMap<object, string>()
|
|
113
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
114
|
-
const key = { id: 1 }
|
|
115
|
-
reactiveWeakMap.set(key, 'test')
|
|
116
|
-
|
|
117
|
-
let effectCount = 0
|
|
118
|
-
effect(() => {
|
|
119
|
-
effectCount++
|
|
120
|
-
reactiveWeakMap.has(key)
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
expect(effectCount).toBe(1)
|
|
124
|
-
|
|
125
|
-
// Deleting the key should trigger the effect
|
|
126
|
-
reactiveWeakMap.delete(key)
|
|
127
|
-
expect(effectCount).toBe(2)
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
it('should not trigger effects when deleting non-existent keys', () => {
|
|
131
|
-
const weakMap = new WeakMap<object, string>()
|
|
132
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
133
|
-
const key = { id: 1 }
|
|
134
|
-
|
|
135
|
-
let effectCount = 0
|
|
136
|
-
effect(() => {
|
|
137
|
-
effectCount++
|
|
138
|
-
reactiveWeakMap.has(key)
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
expect(effectCount).toBe(1)
|
|
142
|
-
|
|
143
|
-
// Deleting a non-existent key should not trigger the effect
|
|
144
|
-
reactiveWeakMap.delete(key)
|
|
145
|
-
expect(effectCount).toBe(1)
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
describe('allProps reactivity', () => {
|
|
150
|
-
it('should trigger allProps effects when setting values', () => {
|
|
151
|
-
const weakMap = new WeakMap<object, string>()
|
|
152
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
153
|
-
const key1 = { id: 1 }
|
|
154
|
-
const key2 = { id: 2 }
|
|
155
|
-
|
|
156
|
-
let allPropsEffectCount = 0
|
|
157
|
-
effect(() => {
|
|
158
|
-
allPropsEffectCount++
|
|
159
|
-
// Access allProps by using a method that iterates
|
|
160
|
-
reactiveWeakMap.has(key1)
|
|
161
|
-
reactiveWeakMap.has(key2)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
expect(allPropsEffectCount).toBe(1)
|
|
165
|
-
|
|
166
|
-
// Setting a new value should trigger allProps effects
|
|
167
|
-
reactiveWeakMap.set(key1, 'value1')
|
|
168
|
-
expect(allPropsEffectCount).toBe(2)
|
|
169
|
-
|
|
170
|
-
// Setting another value should trigger allProps effects
|
|
171
|
-
reactiveWeakMap.set(key2, 'value2')
|
|
172
|
-
expect(allPropsEffectCount).toBe(3)
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
it('should trigger allProps effects when deleting values', () => {
|
|
176
|
-
const weakMap = new WeakMap<object, string>()
|
|
177
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
178
|
-
const key1 = { id: 1 }
|
|
179
|
-
const key2 = { id: 2 }
|
|
180
|
-
|
|
181
|
-
reactiveWeakMap.set(key1, 'value1')
|
|
182
|
-
reactiveWeakMap.set(key2, 'value2')
|
|
183
|
-
|
|
184
|
-
let allPropsEffectCount = 0
|
|
185
|
-
effect(() => {
|
|
186
|
-
allPropsEffectCount++
|
|
187
|
-
// Access allProps by using a method that iterates
|
|
188
|
-
reactiveWeakMap.has(key1)
|
|
189
|
-
reactiveWeakMap.has(key2)
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
expect(allPropsEffectCount).toBe(1)
|
|
193
|
-
|
|
194
|
-
// Deleting a value should trigger allProps effects
|
|
195
|
-
reactiveWeakMap.delete(key1)
|
|
196
|
-
expect(allPropsEffectCount).toBe(2)
|
|
197
|
-
|
|
198
|
-
// Deleting another value should trigger allProps effects
|
|
199
|
-
reactiveWeakMap.delete(key2)
|
|
200
|
-
expect(allPropsEffectCount).toBe(3)
|
|
201
|
-
})
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
describe('WeakMap constraints', () => {
|
|
205
|
-
it('should only accept objects as keys', () => {
|
|
206
|
-
const weakMap = new WeakMap<object, string>()
|
|
207
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
208
|
-
|
|
209
|
-
// These should work
|
|
210
|
-
const objKey = { id: 1 }
|
|
211
|
-
const arrKey = [1, 2, 3]
|
|
212
|
-
const funcKey = () => {}
|
|
213
|
-
|
|
214
|
-
reactiveWeakMap.set(objKey, 'obj value')
|
|
215
|
-
reactiveWeakMap.set(arrKey, 'arr value')
|
|
216
|
-
reactiveWeakMap.set(funcKey, 'func value')
|
|
217
|
-
|
|
218
|
-
expect(reactiveWeakMap.get(objKey)).toBe('obj value')
|
|
219
|
-
expect(reactiveWeakMap.get(arrKey)).toBe('arr value')
|
|
220
|
-
expect(reactiveWeakMap.get(funcKey)).toBe('func value')
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
it('should not have size property', () => {
|
|
224
|
-
const weakMap = new WeakMap<object, string>()
|
|
225
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
226
|
-
|
|
227
|
-
// WeakMap should not have a size property
|
|
228
|
-
expect('size' in reactiveWeakMap).toBe(false)
|
|
229
|
-
expect((reactiveWeakMap as any).size).toBeUndefined()
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
it('should not have clear method', () => {
|
|
233
|
-
const weakMap = new WeakMap<object, string>()
|
|
234
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
235
|
-
|
|
236
|
-
// WeakMap should not have a clear method
|
|
237
|
-
expect(typeof (reactiveWeakMap as any).clear).toBe('undefined')
|
|
238
|
-
})
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
describe('toStringTag', () => {
|
|
242
|
-
it('should have correct toStringTag', () => {
|
|
243
|
-
const weakMap = new WeakMap<object, string>()
|
|
244
|
-
const reactiveWeakMap = reactive(weakMap)
|
|
245
|
-
expect(reactiveWeakMap[Symbol.toStringTag]).toBe('ReactiveWeakMap')
|
|
246
|
-
})
|
|
247
|
-
})
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
describe('ReactiveMap', () => {
|
|
251
|
-
describe('basic functionality', () => {
|
|
252
|
-
it('should create a reactive Map wrapper', () => {
|
|
253
|
-
const map = new Map<string, number>()
|
|
254
|
-
const reactiveMap = reactive(map)
|
|
255
|
-
expect(reactiveMap).toBeInstanceOf(Object)
|
|
256
|
-
// ReactiveMap is a wrapper, not a native Map instance
|
|
257
|
-
expect(reactiveMap).toBeInstanceOf(Map)
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
it('should work with reactive() function', () => {
|
|
261
|
-
const map = new Map<string, number>()
|
|
262
|
-
const reactiveMap = reactive(map)
|
|
263
|
-
|
|
264
|
-
// The reactive wrapper should behave like a Map
|
|
265
|
-
expect(reactiveMap).toBeInstanceOf(Map)
|
|
266
|
-
})
|
|
267
|
-
|
|
268
|
-
it('should wrap existing Map with entries', () => {
|
|
269
|
-
const originalMap = new Map<string, number>([
|
|
270
|
-
['key1', 1],
|
|
271
|
-
['key2', 2],
|
|
272
|
-
])
|
|
273
|
-
const reactiveMap = reactive(originalMap)
|
|
274
|
-
|
|
275
|
-
expect(reactiveMap.get('key1')).toBe(1)
|
|
276
|
-
expect(reactiveMap.get('key2')).toBe(2)
|
|
277
|
-
expect(reactiveMap.size).toBe(2)
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
it('should accept Map instance', () => {
|
|
281
|
-
const originalMap = new Map([
|
|
282
|
-
['key1', 1],
|
|
283
|
-
['key2', 2],
|
|
284
|
-
])
|
|
285
|
-
const reactiveMap = reactive(originalMap)
|
|
286
|
-
|
|
287
|
-
expect(reactiveMap.get('key1')).toBe(1)
|
|
288
|
-
expect(reactiveMap.get('key2')).toBe(2)
|
|
289
|
-
expect(reactiveMap.size).toBe(2)
|
|
290
|
-
})
|
|
291
|
-
})
|
|
292
|
-
|
|
293
|
-
describe('reactive operations', () => {
|
|
294
|
-
it('should track size dependencies', () => {
|
|
295
|
-
const map = new Map<string, number>()
|
|
296
|
-
const reactiveMap = reactive(map)
|
|
297
|
-
|
|
298
|
-
let effectCount = 0
|
|
299
|
-
effect(() => {
|
|
300
|
-
effectCount++
|
|
301
|
-
reactiveMap.size
|
|
302
|
-
})
|
|
303
|
-
|
|
304
|
-
expect(effectCount).toBe(1)
|
|
305
|
-
|
|
306
|
-
// Adding a key should trigger the effect
|
|
307
|
-
reactiveMap.set('test', 42)
|
|
308
|
-
expect(effectCount).toBe(2)
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
it('should track dependencies when getting values', () => {
|
|
312
|
-
const map = new Map<string, number>()
|
|
313
|
-
const reactiveMap = reactive(map)
|
|
314
|
-
reactiveMap.set('test', 42)
|
|
315
|
-
|
|
316
|
-
let effectCount = 0
|
|
317
|
-
effect(() => {
|
|
318
|
-
effectCount++
|
|
319
|
-
reactiveMap.get('test')
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
expect(effectCount).toBe(1)
|
|
323
|
-
|
|
324
|
-
// Changing the value should trigger the effect
|
|
325
|
-
reactiveMap.set('test', 100)
|
|
326
|
-
expect(effectCount).toBe(2)
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
it('should track dependencies when checking existence', () => {
|
|
330
|
-
const map = new Map<string, number>()
|
|
331
|
-
const reactiveMap = reactive(map)
|
|
332
|
-
reactiveMap.set('test', 42)
|
|
333
|
-
|
|
334
|
-
let effectCount = 0
|
|
335
|
-
effect(() => {
|
|
336
|
-
effectCount++
|
|
337
|
-
reactiveMap.has('test')
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
expect(effectCount).toBe(1)
|
|
341
|
-
|
|
342
|
-
// Deleting the key should trigger the effect
|
|
343
|
-
reactiveMap.delete('test')
|
|
344
|
-
expect(effectCount).toBe(2)
|
|
345
|
-
})
|
|
346
|
-
|
|
347
|
-
it('should trigger effects when setting new values', () => {
|
|
348
|
-
const map = new Map<string, number>()
|
|
349
|
-
const reactiveMap = reactive(map)
|
|
350
|
-
|
|
351
|
-
let effectCount = 0
|
|
352
|
-
effect(() => {
|
|
353
|
-
effectCount++
|
|
354
|
-
reactiveMap.get('test')
|
|
355
|
-
})
|
|
356
|
-
|
|
357
|
-
expect(effectCount).toBe(1)
|
|
358
|
-
|
|
359
|
-
// Setting a new value should trigger the effect
|
|
360
|
-
reactiveMap.set('test', 42)
|
|
361
|
-
expect(effectCount).toBe(2)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
it('should trigger effects when updating existing values', () => {
|
|
365
|
-
const map = new Map<string, number>()
|
|
366
|
-
const reactiveMap = reactive(map)
|
|
367
|
-
reactiveMap.set('test', 42)
|
|
368
|
-
|
|
369
|
-
let effectCount = 0
|
|
370
|
-
effect(() => {
|
|
371
|
-
effectCount++
|
|
372
|
-
reactiveMap.get('test')
|
|
373
|
-
})
|
|
374
|
-
|
|
375
|
-
expect(effectCount).toBe(1)
|
|
376
|
-
|
|
377
|
-
// Updating the value should trigger the effect
|
|
378
|
-
reactiveMap.set('test', 100)
|
|
379
|
-
expect(effectCount).toBe(2)
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
it('should trigger effects when deleting keys', () => {
|
|
383
|
-
const map = new Map<string, number>()
|
|
384
|
-
const reactiveMap = reactive(map)
|
|
385
|
-
reactiveMap.set('test', 42)
|
|
386
|
-
|
|
387
|
-
let effectCount = 0
|
|
388
|
-
effect(() => {
|
|
389
|
-
effectCount++
|
|
390
|
-
reactiveMap.has('test')
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
expect(effectCount).toBe(1)
|
|
394
|
-
|
|
395
|
-
// Deleting the key should trigger the effect
|
|
396
|
-
reactiveMap.delete('test')
|
|
397
|
-
expect(effectCount).toBe(2)
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
it('should not trigger effects when deleting non-existent keys', () => {
|
|
401
|
-
const map = new Map<string, number>()
|
|
402
|
-
const reactiveMap = reactive(map)
|
|
403
|
-
|
|
404
|
-
let effectCount = 0
|
|
405
|
-
effect(() => {
|
|
406
|
-
effectCount++
|
|
407
|
-
reactiveMap.has('test')
|
|
408
|
-
})
|
|
409
|
-
|
|
410
|
-
expect(effectCount).toBe(1)
|
|
411
|
-
|
|
412
|
-
// Deleting a non-existent key should not trigger the effect
|
|
413
|
-
reactiveMap.delete('test')
|
|
414
|
-
expect(effectCount).toBe(1)
|
|
415
|
-
})
|
|
416
|
-
})
|
|
417
|
-
|
|
418
|
-
describe('allProps reactivity', () => {
|
|
419
|
-
it('should trigger allProps effects when setting values', () => {
|
|
420
|
-
const map = new Map<string, number>()
|
|
421
|
-
const reactiveMap = reactive(map)
|
|
422
|
-
|
|
423
|
-
let allPropsEffectCount = 0
|
|
424
|
-
effect(() => {
|
|
425
|
-
allPropsEffectCount++
|
|
426
|
-
// Access allProps by using iteration methods
|
|
427
|
-
reactiveMap.entries()
|
|
428
|
-
})
|
|
429
|
-
|
|
430
|
-
expect(allPropsEffectCount).toBe(1)
|
|
431
|
-
|
|
432
|
-
// Setting a new value should trigger allProps effects
|
|
433
|
-
reactiveMap.set('key1', 1)
|
|
434
|
-
expect(allPropsEffectCount).toBe(2)
|
|
435
|
-
|
|
436
|
-
// Setting another value should trigger allProps effects
|
|
437
|
-
reactiveMap.set('key2', 2)
|
|
438
|
-
expect(allPropsEffectCount).toBe(3)
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
it('should trigger allProps effects when deleting values', () => {
|
|
442
|
-
const map = new Map<string, number>()
|
|
443
|
-
const reactiveMap = reactive(map)
|
|
444
|
-
reactiveMap.set('key1', 1)
|
|
445
|
-
reactiveMap.set('key2', 2)
|
|
446
|
-
|
|
447
|
-
let allPropsEffectCount = 0
|
|
448
|
-
effect(() => {
|
|
449
|
-
allPropsEffectCount++
|
|
450
|
-
// Access allProps by using iteration methods
|
|
451
|
-
reactiveMap.keys()
|
|
452
|
-
})
|
|
453
|
-
|
|
454
|
-
expect(allPropsEffectCount).toBe(1)
|
|
455
|
-
|
|
456
|
-
// Deleting a value should trigger allProps effects
|
|
457
|
-
reactiveMap.delete('key1')
|
|
458
|
-
expect(allPropsEffectCount).toBe(2)
|
|
459
|
-
|
|
460
|
-
// Deleting another value should trigger allProps effects
|
|
461
|
-
reactiveMap.delete('key2')
|
|
462
|
-
expect(allPropsEffectCount).toBe(3)
|
|
463
|
-
})
|
|
464
|
-
|
|
465
|
-
it('should trigger allProps effects when clearing', () => {
|
|
466
|
-
const map = new Map<string, number>()
|
|
467
|
-
const reactiveMap = reactive(map)
|
|
468
|
-
reactiveMap.set('key1', 1)
|
|
469
|
-
reactiveMap.set('key2', 2)
|
|
470
|
-
|
|
471
|
-
let allPropsEffectCount = 0
|
|
472
|
-
effect(() => {
|
|
473
|
-
allPropsEffectCount++
|
|
474
|
-
// Access allProps by using iteration methods
|
|
475
|
-
reactiveMap.values()
|
|
476
|
-
})
|
|
477
|
-
|
|
478
|
-
expect(allPropsEffectCount).toBe(1)
|
|
479
|
-
|
|
480
|
-
// Clearing should trigger allProps effects
|
|
481
|
-
reactiveMap.clear()
|
|
482
|
-
expect(allPropsEffectCount).toBe(2)
|
|
483
|
-
})
|
|
484
|
-
})
|
|
485
|
-
|
|
486
|
-
describe('iteration methods', () => {
|
|
487
|
-
it('should track allProps for entries()', () => {
|
|
488
|
-
const map = new Map<string, number>()
|
|
489
|
-
const reactiveMap = reactive(map)
|
|
490
|
-
|
|
491
|
-
let effectCount = 0
|
|
492
|
-
effect(() => {
|
|
493
|
-
effectCount++
|
|
494
|
-
reactiveMap.entries()
|
|
495
|
-
})
|
|
496
|
-
|
|
497
|
-
expect(effectCount).toBe(1)
|
|
498
|
-
|
|
499
|
-
// Any map change should trigger the effect
|
|
500
|
-
reactiveMap.set('test', 42)
|
|
501
|
-
expect(effectCount).toBe(2)
|
|
502
|
-
})
|
|
503
|
-
|
|
504
|
-
it('should track allProps for forEach()', () => {
|
|
505
|
-
const map = new Map<string, number>()
|
|
506
|
-
const reactiveMap = reactive(map)
|
|
507
|
-
|
|
508
|
-
let effectCount = 0
|
|
509
|
-
effect(() => {
|
|
510
|
-
effectCount++
|
|
511
|
-
reactiveMap.forEach(() => {})
|
|
512
|
-
})
|
|
513
|
-
|
|
514
|
-
expect(effectCount).toBe(1)
|
|
515
|
-
|
|
516
|
-
// Any map change should trigger the effect
|
|
517
|
-
reactiveMap.set('test', 42)
|
|
518
|
-
expect(effectCount).toBe(2)
|
|
519
|
-
})
|
|
520
|
-
|
|
521
|
-
it('should track allProps for keys()', () => {
|
|
522
|
-
const map = new Map<string, number>()
|
|
523
|
-
const reactiveMap = reactive(map)
|
|
524
|
-
|
|
525
|
-
let effectCount = 0
|
|
526
|
-
effect(() => {
|
|
527
|
-
effectCount++
|
|
528
|
-
reactiveMap.keys()
|
|
529
|
-
})
|
|
530
|
-
|
|
531
|
-
expect(effectCount).toBe(1)
|
|
532
|
-
|
|
533
|
-
// Any map change should trigger the effect
|
|
534
|
-
reactiveMap.set('test', 42)
|
|
535
|
-
expect(effectCount).toBe(2)
|
|
536
|
-
})
|
|
537
|
-
|
|
538
|
-
it('should track allProps for values()', () => {
|
|
539
|
-
const map = new Map<string, number>()
|
|
540
|
-
const reactiveMap = reactive(map)
|
|
541
|
-
|
|
542
|
-
let effectCount = 0
|
|
543
|
-
effect(() => {
|
|
544
|
-
effectCount++
|
|
545
|
-
reactiveMap.values()
|
|
546
|
-
})
|
|
547
|
-
|
|
548
|
-
expect(effectCount).toBe(1)
|
|
549
|
-
|
|
550
|
-
// Any map change should trigger the effect
|
|
551
|
-
reactiveMap.set('test', 42)
|
|
552
|
-
expect(effectCount).toBe(2)
|
|
553
|
-
})
|
|
554
|
-
|
|
555
|
-
it('should track allProps for Symbol.iterator', () => {
|
|
556
|
-
const map = new Map<string, number>()
|
|
557
|
-
const reactiveMap = reactive(map)
|
|
558
|
-
|
|
559
|
-
let effectCount = 0
|
|
560
|
-
effect(() => {
|
|
561
|
-
effectCount++
|
|
562
|
-
for (const [_key, _value] of reactiveMap) {
|
|
563
|
-
// Just iterate to trigger allProps dependency
|
|
564
|
-
}
|
|
565
|
-
})
|
|
566
|
-
|
|
567
|
-
expect(effectCount).toBe(1)
|
|
568
|
-
|
|
569
|
-
// Any map change should trigger the effect
|
|
570
|
-
reactiveMap.set('test', 42)
|
|
571
|
-
expect(effectCount).toBe(2)
|
|
572
|
-
})
|
|
573
|
-
})
|
|
574
|
-
|
|
575
|
-
describe('clear method', () => {
|
|
576
|
-
it('should trigger size and allProps effects when clearing', () => {
|
|
577
|
-
const map = new Map<string, number>()
|
|
578
|
-
const reactiveMap = reactive(map)
|
|
579
|
-
reactiveMap.set('key1', 1)
|
|
580
|
-
reactiveMap.set('key2', 2)
|
|
581
|
-
|
|
582
|
-
let sizeEffectCount = 0
|
|
583
|
-
let allPropsEffectCount = 0
|
|
584
|
-
|
|
585
|
-
effect(() => {
|
|
586
|
-
sizeEffectCount++
|
|
587
|
-
reactiveMap.size
|
|
588
|
-
})
|
|
589
|
-
|
|
590
|
-
effect(() => {
|
|
591
|
-
allPropsEffectCount++
|
|
592
|
-
reactiveMap.entries()
|
|
593
|
-
})
|
|
594
|
-
|
|
595
|
-
expect(sizeEffectCount).toBe(1)
|
|
596
|
-
expect(allPropsEffectCount).toBe(1)
|
|
597
|
-
|
|
598
|
-
// Clearing should trigger both effects
|
|
599
|
-
reactiveMap.clear()
|
|
600
|
-
expect(sizeEffectCount).toBe(2)
|
|
601
|
-
expect(allPropsEffectCount).toBe(2)
|
|
602
|
-
})
|
|
603
|
-
|
|
604
|
-
it('should not trigger effects when clearing empty map', () => {
|
|
605
|
-
const map = new Map<string, number>()
|
|
606
|
-
const reactiveMap = reactive(map)
|
|
607
|
-
|
|
608
|
-
let sizeEffectCount = 0
|
|
609
|
-
let allPropsEffectCount = 0
|
|
610
|
-
|
|
611
|
-
effect(() => {
|
|
612
|
-
sizeEffectCount++
|
|
613
|
-
reactiveMap.size
|
|
614
|
-
})
|
|
615
|
-
|
|
616
|
-
effect(() => {
|
|
617
|
-
allPropsEffectCount++
|
|
618
|
-
reactiveMap.entries()
|
|
619
|
-
})
|
|
620
|
-
|
|
621
|
-
expect(sizeEffectCount).toBe(1)
|
|
622
|
-
expect(allPropsEffectCount).toBe(1)
|
|
623
|
-
|
|
624
|
-
// Clearing empty map should not trigger effects
|
|
625
|
-
reactiveMap.clear()
|
|
626
|
-
expect(sizeEffectCount).toBe(1)
|
|
627
|
-
expect(allPropsEffectCount).toBe(1)
|
|
628
|
-
})
|
|
629
|
-
})
|
|
630
|
-
|
|
631
|
-
describe('static methods', () => {
|
|
632
|
-
it('should create ReactiveMap from existing Map', () => {
|
|
633
|
-
const originalMap = new Map([
|
|
634
|
-
['key1', 1],
|
|
635
|
-
['key2', 2],
|
|
636
|
-
])
|
|
637
|
-
const reactiveMap = reactive(originalMap)
|
|
638
|
-
expect(reactiveMap.size).toBe(2)
|
|
639
|
-
expect(reactiveMap.get('key1')).toBe(1)
|
|
640
|
-
expect(reactiveMap.get('key2')).toBe(2)
|
|
641
|
-
})
|
|
642
|
-
|
|
643
|
-
it('should work with reactive() function on existing Map', () => {
|
|
644
|
-
const originalMap = new Map([
|
|
645
|
-
['key1', 1],
|
|
646
|
-
['key2', 2],
|
|
647
|
-
])
|
|
648
|
-
const reactiveMap = reactive(originalMap)
|
|
649
|
-
expect(reactiveMap.size).toBe(2)
|
|
650
|
-
expect(reactiveMap.get('key1')).toBe(1)
|
|
651
|
-
expect(reactiveMap.get('key2')).toBe(2)
|
|
652
|
-
})
|
|
653
|
-
})
|
|
654
|
-
|
|
655
|
-
describe('toStringTag', () => {
|
|
656
|
-
it('should have correct toStringTag', () => {
|
|
657
|
-
const map = new Map<string, number>()
|
|
658
|
-
const reactiveMap = reactive(map)
|
|
659
|
-
expect(reactiveMap[Symbol.toStringTag]).toBe('ReactiveMap')
|
|
660
|
-
})
|
|
661
|
-
})
|
|
662
|
-
|
|
663
|
-
describe('seamless reactive integration', () => {
|
|
664
|
-
describe('native Map integration', () => {
|
|
665
|
-
it('should automatically create ReactiveMap when using reactive() on native Map', () => {
|
|
666
|
-
const nativeMap = new Map([
|
|
667
|
-
['key1', 1],
|
|
668
|
-
['key2', 2],
|
|
669
|
-
])
|
|
670
|
-
const reactiveMap = reactive(nativeMap)
|
|
671
|
-
|
|
672
|
-
// Should still behave like a Map
|
|
673
|
-
expect(reactiveMap.get('key1')).toBe(1)
|
|
674
|
-
expect(reactiveMap.get('key2')).toBe(2)
|
|
675
|
-
expect(reactiveMap.size).toBe(2)
|
|
676
|
-
})
|
|
677
|
-
|
|
678
|
-
it('should track dependencies when accessing reactive native Map', () => {
|
|
679
|
-
const nativeMap = new Map([['key1', 1]])
|
|
680
|
-
const reactiveMap = reactive(nativeMap)
|
|
681
|
-
|
|
682
|
-
let effectCount = 0
|
|
683
|
-
effect(() => {
|
|
684
|
-
effectCount++
|
|
685
|
-
reactiveMap.get('key1')
|
|
686
|
-
})
|
|
687
|
-
|
|
688
|
-
expect(effectCount).toBe(1)
|
|
689
|
-
|
|
690
|
-
// Modifying the reactive map should trigger effects
|
|
691
|
-
reactiveMap.set('key1', 100)
|
|
692
|
-
expect(effectCount).toBe(2)
|
|
693
|
-
})
|
|
694
|
-
|
|
695
|
-
it('should track size dependencies on reactive native Map', () => {
|
|
696
|
-
const nativeMap = new Map([['key1', 1]])
|
|
697
|
-
const reactiveMap = reactive(nativeMap)
|
|
698
|
-
|
|
699
|
-
let effectCount = 0
|
|
700
|
-
effect(() => {
|
|
701
|
-
effectCount++
|
|
702
|
-
reactiveMap.size
|
|
703
|
-
})
|
|
704
|
-
|
|
705
|
-
expect(effectCount).toBe(1)
|
|
706
|
-
|
|
707
|
-
// Adding a key should trigger size effect
|
|
708
|
-
reactiveMap.set('key2', 2)
|
|
709
|
-
expect(effectCount).toBe(2)
|
|
710
|
-
})
|
|
711
|
-
|
|
712
|
-
it('should track allProps dependencies on reactive native Map', () => {
|
|
713
|
-
const nativeMap = new Map([['key1', 1]])
|
|
714
|
-
const reactiveMap = reactive(nativeMap)
|
|
715
|
-
|
|
716
|
-
let effectCount = 0
|
|
717
|
-
effect(() => {
|
|
718
|
-
effectCount++
|
|
719
|
-
reactiveMap.entries()
|
|
720
|
-
})
|
|
721
|
-
|
|
722
|
-
expect(effectCount).toBe(1)
|
|
723
|
-
|
|
724
|
-
// Any map change should trigger allProps effect
|
|
725
|
-
reactiveMap.set('key2', 2)
|
|
726
|
-
expect(effectCount).toBe(2)
|
|
727
|
-
})
|
|
728
|
-
|
|
729
|
-
it('should handle clear operations on reactive native Map', () => {
|
|
730
|
-
const nativeMap = new Map([
|
|
731
|
-
['key1', 1],
|
|
732
|
-
['key2', 2],
|
|
733
|
-
])
|
|
734
|
-
const reactiveMap = reactive(nativeMap)
|
|
735
|
-
|
|
736
|
-
let sizeEffectCount = 0
|
|
737
|
-
let allPropsEffectCount = 0
|
|
738
|
-
|
|
739
|
-
effect(() => {
|
|
740
|
-
sizeEffectCount++
|
|
741
|
-
reactiveMap.size
|
|
742
|
-
})
|
|
743
|
-
|
|
744
|
-
effect(() => {
|
|
745
|
-
allPropsEffectCount++
|
|
746
|
-
reactiveMap.keys()
|
|
747
|
-
})
|
|
748
|
-
|
|
749
|
-
expect(sizeEffectCount).toBe(1)
|
|
750
|
-
expect(allPropsEffectCount).toBe(1)
|
|
751
|
-
|
|
752
|
-
// Clearing should trigger both effects
|
|
753
|
-
reactiveMap.clear()
|
|
754
|
-
expect(sizeEffectCount).toBe(2)
|
|
755
|
-
expect(allPropsEffectCount).toBe(2)
|
|
756
|
-
})
|
|
757
|
-
})
|
|
758
|
-
|
|
759
|
-
describe('native WeakMap integration', () => {
|
|
760
|
-
it('should automatically create ReactiveWeakMap when using reactive() on native WeakMap', () => {
|
|
761
|
-
const key1 = { id: 1 }
|
|
762
|
-
const key2 = { id: 2 }
|
|
763
|
-
const nativeWeakMap = new WeakMap([
|
|
764
|
-
[key1, 'value1'],
|
|
765
|
-
[key2, 'value2'],
|
|
766
|
-
])
|
|
767
|
-
const reactiveWeakMap = reactive(nativeWeakMap)
|
|
768
|
-
// Should still behave like a WeakMap
|
|
769
|
-
expect(reactiveWeakMap.get(key1)).toBe('value1')
|
|
770
|
-
expect(reactiveWeakMap.get(key2)).toBe('value2')
|
|
771
|
-
})
|
|
772
|
-
|
|
773
|
-
it('should track dependencies when accessing reactive native WeakMap', () => {
|
|
774
|
-
const key = { id: 1 }
|
|
775
|
-
const nativeWeakMap = new WeakMap([[key, 'value']])
|
|
776
|
-
const reactiveWeakMap = reactive(nativeWeakMap)
|
|
777
|
-
|
|
778
|
-
let effectCount = 0
|
|
779
|
-
effect(() => {
|
|
780
|
-
effectCount++
|
|
781
|
-
reactiveWeakMap.get(key)
|
|
782
|
-
})
|
|
783
|
-
|
|
784
|
-
expect(effectCount).toBe(1)
|
|
785
|
-
|
|
786
|
-
// Modifying the reactive weak map should trigger effects
|
|
787
|
-
reactiveWeakMap.set(key, 'new value')
|
|
788
|
-
expect(effectCount).toBe(2)
|
|
789
|
-
})
|
|
790
|
-
|
|
791
|
-
it('should handle delete operations on reactive native WeakMap', () => {
|
|
792
|
-
const key = { id: 1 }
|
|
793
|
-
const nativeWeakMap = new WeakMap([[key, 'value']])
|
|
794
|
-
const reactiveWeakMap = reactive(nativeWeakMap)
|
|
795
|
-
|
|
796
|
-
let effectCount = 0
|
|
797
|
-
effect(() => {
|
|
798
|
-
effectCount++
|
|
799
|
-
reactiveWeakMap.has(key)
|
|
800
|
-
})
|
|
801
|
-
|
|
802
|
-
expect(effectCount).toBe(1)
|
|
803
|
-
|
|
804
|
-
// Deleting the key should trigger effects
|
|
805
|
-
reactiveWeakMap.delete(key)
|
|
806
|
-
expect(effectCount).toBe(2)
|
|
807
|
-
})
|
|
808
|
-
})
|
|
809
|
-
|
|
810
|
-
describe('mixed usage scenarios', () => {
|
|
811
|
-
it('should work with both reactive Map and WeakMap in same effect', () => {
|
|
812
|
-
const nativeMap = new Map([['key1', 1]])
|
|
813
|
-
const key = { id: 1 }
|
|
814
|
-
const nativeWeakMap = new WeakMap([[key, 'value']])
|
|
815
|
-
|
|
816
|
-
const reactiveMap = reactive(nativeMap)
|
|
817
|
-
const reactiveWeakMap = reactive(nativeWeakMap)
|
|
818
|
-
|
|
819
|
-
let effectCount = 0
|
|
820
|
-
effect(() => {
|
|
821
|
-
effectCount++
|
|
822
|
-
reactiveMap.get('key1')
|
|
823
|
-
reactiveWeakMap.get(key)
|
|
824
|
-
})
|
|
825
|
-
|
|
826
|
-
expect(effectCount).toBe(1)
|
|
827
|
-
|
|
828
|
-
// Modifying either should trigger the effect
|
|
829
|
-
reactiveMap.set('key1', 100)
|
|
830
|
-
expect(effectCount).toBe(2)
|
|
831
|
-
|
|
832
|
-
reactiveWeakMap.set(key, 'new value')
|
|
833
|
-
expect(effectCount).toBe(3)
|
|
834
|
-
})
|
|
835
|
-
|
|
836
|
-
it('should handle nested reactive structures', () => {
|
|
837
|
-
const nativeMap = new Map([['config', { enabled: true }]])
|
|
838
|
-
const reactiveMap = reactive(nativeMap)
|
|
839
|
-
|
|
840
|
-
let effectCount = 0
|
|
841
|
-
effect(() => {
|
|
842
|
-
effectCount++
|
|
843
|
-
const config = reactiveMap.get('config')
|
|
844
|
-
if (config?.enabled) {
|
|
845
|
-
// Access nested property
|
|
846
|
-
}
|
|
847
|
-
})
|
|
848
|
-
|
|
849
|
-
expect(effectCount).toBe(1)
|
|
850
|
-
|
|
851
|
-
// Modifying the map should trigger effects
|
|
852
|
-
reactiveMap.set('config', { enabled: false })
|
|
853
|
-
expect(effectCount).toBe(2)
|
|
854
|
-
})
|
|
855
|
-
|
|
856
|
-
it('should work with reactive() called multiple times', () => {
|
|
857
|
-
const nativeMap = new Map([['key1', 1]])
|
|
858
|
-
const reactiveMap1 = reactive(nativeMap)
|
|
859
|
-
const reactiveMap2 = reactive(nativeMap)
|
|
860
|
-
|
|
861
|
-
// Should return the same reactive instance
|
|
862
|
-
expect(reactiveMap1).toBe(reactiveMap2)
|
|
863
|
-
})
|
|
864
|
-
})
|
|
865
|
-
})
|
|
866
|
-
})
|