muya 1.1.0 → 2.0.0-beta.2
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/README.md +202 -139
- package/cjs/index.js +1 -1
- package/esm/__tests__/create-async.test.js +1 -0
- package/esm/__tests__/test-utils.js +1 -0
- package/esm/create.js +1 -1
- package/esm/debug/development-tools.js +1 -0
- package/esm/index.js +1 -1
- package/esm/subscriber.js +1 -0
- package/esm/types.js +1 -1
- package/esm/use.js +1 -0
- package/esm/utils/__tests__/context.test.js +1 -0
- package/esm/utils/__tests__/is.test.js +1 -0
- package/esm/utils/__tests__/shallow.test.js +1 -0
- package/esm/utils/__tests__/sub-memo.test.js +1 -0
- package/esm/utils/common.js +1 -0
- package/esm/utils/create-context.js +1 -0
- package/esm/utils/create-emitter.js +1 -0
- package/esm/utils/global-scheduler.js +1 -0
- package/esm/utils/is.js +1 -0
- package/esm/utils/scheduler.js +1 -0
- package/esm/utils/shallow.js +1 -0
- package/esm/utils/sub-memo.js +1 -0
- package/package.json +1 -1
- package/packages/core/__tests__/bench.test.tsx +266 -0
- package/packages/core/__tests__/create-async.test.ts +88 -0
- package/packages/core/__tests__/create.test.tsx +107 -0
- package/packages/core/__tests__/subscriber.test.tsx +89 -0
- package/packages/core/__tests__/test-utils.ts +40 -0
- package/packages/core/__tests__/use-async.test.tsx +45 -0
- package/packages/core/__tests__/use.test.tsx +125 -0
- package/packages/core/create.ts +98 -0
- package/packages/core/debug/development-tools.ts +37 -0
- package/packages/core/index.ts +4 -0
- package/packages/core/subscriber.ts +165 -0
- package/packages/core/types.ts +15 -0
- package/packages/core/use.ts +57 -0
- package/packages/core/utils/__tests__/context.test.ts +198 -0
- package/packages/core/utils/__tests__/is.test.ts +74 -0
- package/packages/core/utils/__tests__/shallow.test.ts +418 -0
- package/packages/core/utils/__tests__/sub-memo.test.ts +13 -0
- package/packages/core/utils/common.ts +48 -0
- package/packages/core/utils/create-context.ts +60 -0
- package/packages/core/utils/create-emitter.ts +55 -0
- package/packages/core/utils/global-scheduler.ts +75 -0
- package/packages/core/utils/is.ts +50 -0
- package/packages/core/utils/scheduler.ts +59 -0
- package/{src → packages/core/utils}/shallow.ts +3 -6
- package/packages/core/utils/sub-memo.ts +49 -0
- package/types/__tests__/test-utils.d.ts +20 -0
- package/types/create.d.ts +21 -21
- package/types/debug/development-tools.d.ts +10 -0
- package/types/index.d.ts +2 -4
- package/types/subscriber.d.ts +25 -0
- package/types/types.d.ts +9 -65
- package/types/use.d.ts +2 -0
- package/types/utils/common.d.ts +15 -0
- package/types/utils/create-context.d.ts +5 -0
- package/types/utils/create-emitter.d.ts +20 -0
- package/types/utils/global-scheduler.d.ts +5 -0
- package/types/utils/is.d.ts +13 -0
- package/types/utils/scheduler.d.ts +8 -0
- package/types/utils/sub-memo.d.ts +7 -0
- package/esm/common.js +0 -1
- package/esm/create-base-state.js +0 -1
- package/esm/create-emitter.js +0 -1
- package/esm/create-getter-state.js +0 -1
- package/esm/is.js +0 -1
- package/esm/merge.js +0 -1
- package/esm/select.js +0 -1
- package/esm/shallow.js +0 -1
- package/esm/use-state-value.js +0 -1
- package/src/common.ts +0 -28
- package/src/create-base-state.ts +0 -35
- package/src/create-emitter.ts +0 -24
- package/src/create-getter-state.ts +0 -19
- package/src/create.ts +0 -102
- package/src/index.ts +0 -6
- package/src/is.ts +0 -36
- package/src/merge.ts +0 -41
- package/src/select.ts +0 -33
- package/src/state.test.tsx +0 -647
- package/src/types.ts +0 -94
- package/src/use-state-value.ts +0 -29
- package/types/common.d.ts +0 -7
- package/types/create-base-state.d.ts +0 -10
- package/types/create-emitter.d.ts +0 -7
- package/types/create-getter-state.d.ts +0 -6
- package/types/is.d.ts +0 -10
- package/types/merge.d.ts +0 -2
- package/types/select.d.ts +0 -2
- package/types/use-state-value.d.ts +0 -10
- /package/types/{shallow.d.ts → utils/shallow.d.ts} +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Abort } from '../common'
|
|
2
|
+
import { isPromise, isFunction, isSetValueFunction, isMap, isSet, isArray, isEqualBase, isAbortError } from '../is'
|
|
3
|
+
|
|
4
|
+
describe('isPromise', () => {
|
|
5
|
+
it('should return true for a Promise', () => {
|
|
6
|
+
expect(isPromise(Promise.resolve())).toBe(true)
|
|
7
|
+
})
|
|
8
|
+
it('should return false for a non-Promise', () => {
|
|
9
|
+
expect(isPromise(123)).toBe(false)
|
|
10
|
+
})
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
describe('isFunction', () => {
|
|
14
|
+
it('should return true for a function', () => {
|
|
15
|
+
expect(isFunction(() => {})).toBe(true)
|
|
16
|
+
})
|
|
17
|
+
it('should return false for a non-function', () => {
|
|
18
|
+
expect(isFunction(123)).toBe(false)
|
|
19
|
+
})
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
describe('isSetValueFunction', () => {
|
|
23
|
+
it('should return true for a function', () => {
|
|
24
|
+
expect(isSetValueFunction(() => {})).toBe(true)
|
|
25
|
+
})
|
|
26
|
+
it('should return false for a non-function', () => {
|
|
27
|
+
expect(isSetValueFunction(123)).toBe(false)
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
describe('isMap', () => {
|
|
32
|
+
it('should return true for a Map', () => {
|
|
33
|
+
expect(isMap(new Map())).toBe(true)
|
|
34
|
+
})
|
|
35
|
+
it('should return false for a non-Map', () => {
|
|
36
|
+
expect(isMap(123)).toBe(false)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
describe('isSet', () => {
|
|
41
|
+
it('should return true for a Set', () => {
|
|
42
|
+
expect(isSet(new Set())).toBe(true)
|
|
43
|
+
})
|
|
44
|
+
it('should return false for a non-Set', () => {
|
|
45
|
+
expect(isSet(123)).toBe(false)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe('isArray', () => {
|
|
50
|
+
it('should return true for an array', () => {
|
|
51
|
+
expect(isArray([])).toBe(true)
|
|
52
|
+
})
|
|
53
|
+
it('should return false for a non-array', () => {
|
|
54
|
+
expect(isArray(123)).toBe(false)
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
describe('isEqualBase', () => {
|
|
59
|
+
it('should return true for equal values', () => {
|
|
60
|
+
expect(isEqualBase(1, 1)).toBe(true)
|
|
61
|
+
})
|
|
62
|
+
it('should return false for non-equal values', () => {
|
|
63
|
+
expect(isEqualBase(1, 2)).toBe(false)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
describe('isAbortError', () => {
|
|
68
|
+
it('should return true for an AbortError', () => {
|
|
69
|
+
expect(isAbortError(new DOMException('', Abort.Error))).toBe(true)
|
|
70
|
+
})
|
|
71
|
+
it('should return false for a non-AbortError', () => {
|
|
72
|
+
expect(isAbortError(new DOMException('', 'Error'))).toBe(false)
|
|
73
|
+
})
|
|
74
|
+
})
|
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
import { shallow } from '../shallow'
|
|
2
|
+
|
|
3
|
+
describe('shallow', () => {
|
|
4
|
+
it('should return true for identical primitive values', () => {
|
|
5
|
+
expect(shallow(1, 1)).toBe(true)
|
|
6
|
+
expect(shallow('a', 'a')).toBe(true)
|
|
7
|
+
expect(shallow(true, true)).toBe(true)
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('should return false for different primitive values', () => {
|
|
11
|
+
expect(shallow(1, 2)).toBe(false)
|
|
12
|
+
expect(shallow('a', 'b')).toBe(false)
|
|
13
|
+
expect(shallow(true, false)).toBe(false)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should return true for identical objects', () => {
|
|
17
|
+
const object = { a: 1 }
|
|
18
|
+
expect(shallow(object, object)).toBe(true)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('should return false for different objects with diff properties', () => {
|
|
22
|
+
expect(shallow({ a: 1 }, { a: 2 })).toBe(false)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should return true for identical arrays', () => {
|
|
26
|
+
const array = [1, 2, 3]
|
|
27
|
+
expect(shallow(array, array)).toBe(true)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('should return true for different arrays with same elements', () => {
|
|
31
|
+
expect(shallow([1, 2, 3], [1, 2, 3])).toBe(true)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('should return true for identical Maps', () => {
|
|
35
|
+
const map = new Map([['a', 1]])
|
|
36
|
+
expect(shallow(map, map)).toBe(true)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('should return true for different Maps with same entries', () => {
|
|
40
|
+
expect(shallow(new Map([['a', 1]]), new Map([['a', 1]]))).toBe(true)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('should return true for identical Sets', () => {
|
|
44
|
+
const set = new Set([1, 2, 3])
|
|
45
|
+
expect(shallow(set, set)).toBe(true)
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('should return true for different Sets with same elements', () => {
|
|
49
|
+
expect(shallow(new Set([1, 2, 3]), new Set([1, 2, 3]))).toBe(true)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('should return true for objects with same reference', () => {
|
|
53
|
+
const object = { a: 1 }
|
|
54
|
+
expect(shallow(object, object)).toBe(true)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('should return true for objects with different references', () => {
|
|
58
|
+
expect(shallow({ a: 1 }, { a: 1 })).toBe(true)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('should return true for arrays with same reference', () => {
|
|
62
|
+
const array = [1, 2, 3]
|
|
63
|
+
expect(shallow(array, array)).toBe(true)
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('should return true for arrays with different references', () => {
|
|
67
|
+
expect(shallow([1, 2, 3], [1, 2, 3])).toBe(true)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('should return true for Maps with same reference', () => {
|
|
71
|
+
const map = new Map([['a', 1]])
|
|
72
|
+
expect(shallow(map, map)).toBe(true)
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('should return true for Maps with different references', () => {
|
|
76
|
+
expect(shallow(new Map([['a', 1]]), new Map([['a', 1]]))).toBe(true)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should return true for Sets with same reference', () => {
|
|
80
|
+
const set = new Set([1, 2, 3])
|
|
81
|
+
expect(shallow(set, set)).toBe(true)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('should return true for Sets with different references', () => {
|
|
85
|
+
expect(shallow(new Set([1, 2, 3]), new Set([1, 2, 3]))).toBe(true)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should return true for objects with same keys and values', () => {
|
|
89
|
+
const objectA = { a: 1, b: 2 }
|
|
90
|
+
const objectB = { a: 1, b: 2 }
|
|
91
|
+
expect(shallow(objectA, objectB)).toBe(true)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('should return false for objects with different keys or values', () => {
|
|
95
|
+
const objectA = { a: 1, b: 2 }
|
|
96
|
+
const objectB = { a: 1, b: 3 }
|
|
97
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('should return true for arrays with same elements', () => {
|
|
101
|
+
const arrayA = [1, 2, 3]
|
|
102
|
+
const arrayB = [1, 2, 3]
|
|
103
|
+
expect(shallow(arrayA, arrayB)).toBe(true)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('should return false for arrays with different elements', () => {
|
|
107
|
+
const arrayA = [1, 2, 3]
|
|
108
|
+
const arrayB = [1, 2, 4]
|
|
109
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('should return true for Maps with same entries', () => {
|
|
113
|
+
const mapA = new Map([
|
|
114
|
+
['a', 1],
|
|
115
|
+
['b', 2],
|
|
116
|
+
])
|
|
117
|
+
const mapB = new Map([
|
|
118
|
+
['a', 1],
|
|
119
|
+
['b', 2],
|
|
120
|
+
])
|
|
121
|
+
expect(shallow(mapA, mapB)).toBe(true)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('should return false for Maps with different entries', () => {
|
|
125
|
+
const mapA = new Map([
|
|
126
|
+
['a', 1],
|
|
127
|
+
['b', 2],
|
|
128
|
+
])
|
|
129
|
+
const mapB = new Map([
|
|
130
|
+
['a', 1],
|
|
131
|
+
['b', 3],
|
|
132
|
+
])
|
|
133
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
it('should return true for Sets with same elements', () => {
|
|
137
|
+
const setA = new Set([1, 2, 3])
|
|
138
|
+
const setB = new Set([1, 2, 3])
|
|
139
|
+
expect(shallow(setA, setB)).toBe(true)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('should return false for Sets with different elements', () => {
|
|
143
|
+
const setA = new Set([1, 2, 3])
|
|
144
|
+
const setB = new Set([1, 2, 4])
|
|
145
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('should return false for different objects with same properties', () => {
|
|
149
|
+
expect(shallow({ a: 1 }, { a: 2 })).toBe(false)
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
it('should return false for different arrays with same elements', () => {
|
|
153
|
+
expect(shallow([1, 2, 3], [1, 2, 4])).toBe(false)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('should return false for different Maps with same entries', () => {
|
|
157
|
+
expect(shallow(new Map([['a', 1]]), new Map([['a', 2]]))).toBe(false)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('should return false for different Sets with same elements', () => {
|
|
161
|
+
expect(shallow(new Set([1, 2, 3]), new Set([1, 2, 4]))).toBe(false)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('should return false for objects with different reference', () => {
|
|
165
|
+
expect(shallow({ a: 1 }, { a: 2 })).toBe(false)
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
it('should return false for arrays with different reference', () => {
|
|
169
|
+
expect(shallow([1, 2, 3], [1, 2, 4])).toBe(false)
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
it('should return false for Maps with different reference', () => {
|
|
173
|
+
expect(shallow(new Map([['a', 1]]), new Map([['a', 2]]))).toBe(false)
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('should return false for Sets with different reference', () => {
|
|
177
|
+
expect(shallow(new Set([1, 2, 3]), new Set([1, 2, 4]))).toBe(false)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
it('should return false for objects with different keys or values in', () => {
|
|
181
|
+
const objectA = { a: 1, b: 2 }
|
|
182
|
+
const objectB = { a: 1, b: 3 }
|
|
183
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
it('should return false for arrays with different elements', () => {
|
|
187
|
+
const arrayA = [1, 2, 3]
|
|
188
|
+
const arrayB = [1, 2, 4]
|
|
189
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('should return false for Maps with different entries', () => {
|
|
193
|
+
const mapA = new Map([
|
|
194
|
+
['a', 1],
|
|
195
|
+
['b', 2],
|
|
196
|
+
])
|
|
197
|
+
const mapB = new Map([
|
|
198
|
+
['a', 1],
|
|
199
|
+
['b', 3],
|
|
200
|
+
])
|
|
201
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('should return false for Sets with different elements', () => {
|
|
205
|
+
const setA = new Set([1, 2, 3])
|
|
206
|
+
const setB = new Set([1, 2, 4])
|
|
207
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
it('should return false for objects with different keys or values', () => {
|
|
211
|
+
const objectA = { a: 1, b: 2 }
|
|
212
|
+
const objectB = { a: 1, b: 3 }
|
|
213
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('should return false for arrays with different elements', () => {
|
|
217
|
+
const arrayA = [1, 2, 3]
|
|
218
|
+
const arrayB = [1, 2, 4]
|
|
219
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('should return false for Maps with different entries', () => {
|
|
223
|
+
const mapA = new Map([
|
|
224
|
+
['a', 1],
|
|
225
|
+
['b', 2],
|
|
226
|
+
])
|
|
227
|
+
const mapB = new Map([
|
|
228
|
+
['a', 1],
|
|
229
|
+
['b', 3],
|
|
230
|
+
])
|
|
231
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('should return false for Sets with different elements', () => {
|
|
235
|
+
const setA = new Set([1, 2, 3])
|
|
236
|
+
const setB = new Set([1, 2, 4])
|
|
237
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
it('should return false for objects with different keys or values', () => {
|
|
241
|
+
const objectA = { a: 1, b: 2 }
|
|
242
|
+
const objectB = { a: 1, b: 3 }
|
|
243
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('should return false for arrays with different elements', () => {
|
|
247
|
+
const arrayA = [1, 2, 3]
|
|
248
|
+
const arrayB = [1, 2, 4]
|
|
249
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
it('should return false for Maps with different entries', () => {
|
|
253
|
+
const mapA = new Map([
|
|
254
|
+
['a', 1],
|
|
255
|
+
['b', 2],
|
|
256
|
+
])
|
|
257
|
+
const mapB = new Map([
|
|
258
|
+
['a', 1],
|
|
259
|
+
['b', 3],
|
|
260
|
+
])
|
|
261
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
it('should return false for Sets with different elements', () => {
|
|
265
|
+
const setA = new Set([1, 2, 3])
|
|
266
|
+
const setB = new Set([1, 2, 4])
|
|
267
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('should return false for objects with different keys or values', () => {
|
|
271
|
+
const objectA = { a: 1, b: 2 }
|
|
272
|
+
const objectB = { a: 1, b: 3 }
|
|
273
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
it('should return false for arrays with different elements', () => {
|
|
277
|
+
const arrayA = [1, 2, 3]
|
|
278
|
+
const arrayB = [1, 2, 4]
|
|
279
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
it('should return false for Maps with different entries', () => {
|
|
283
|
+
const mapA = new Map([
|
|
284
|
+
['a', 1],
|
|
285
|
+
['b', 2],
|
|
286
|
+
])
|
|
287
|
+
const mapB = new Map([
|
|
288
|
+
['a', 1],
|
|
289
|
+
['b', 3],
|
|
290
|
+
])
|
|
291
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
it('should return false for Sets with different elements', () => {
|
|
295
|
+
const setA = new Set([1, 2, 3])
|
|
296
|
+
const setB = new Set([1, 2, 4])
|
|
297
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
it('should return false for objects with different keys or values', () => {
|
|
301
|
+
const objectA = { a: 1, b: 2 }
|
|
302
|
+
const objectB = { a: 1, b: 3 }
|
|
303
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
it('should return false for arrays with different elements', () => {
|
|
307
|
+
const arrayA = [1, 2, 3]
|
|
308
|
+
const arrayB = [1, 2, 4]
|
|
309
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
it('should return false for Maps with different entries', () => {
|
|
313
|
+
const mapA = new Map([
|
|
314
|
+
['a', 1],
|
|
315
|
+
['b', 2],
|
|
316
|
+
])
|
|
317
|
+
const mapB = new Map([
|
|
318
|
+
['a', 1],
|
|
319
|
+
['b', 3],
|
|
320
|
+
])
|
|
321
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
it('should return false for Sets with different elements', () => {
|
|
325
|
+
const setA = new Set([1, 2, 3])
|
|
326
|
+
const setB = new Set([1, 2, 4])
|
|
327
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it('should return false for objects with different keys or values', () => {
|
|
331
|
+
const objectA = { a: 1, b: 2 }
|
|
332
|
+
const objectB = { a: 1, b: 3 }
|
|
333
|
+
expect(shallow(objectA, objectB)).toBe(false)
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
it('should return false for arrays with different elements', () => {
|
|
337
|
+
const arrayA = [1, 2, 3]
|
|
338
|
+
const arrayB = [1, 2, 4]
|
|
339
|
+
expect(shallow(arrayA, arrayB)).toBe(false)
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('should return false for Maps with different entries', () => {
|
|
343
|
+
const mapA = new Map([
|
|
344
|
+
['a', 1],
|
|
345
|
+
['b', 2],
|
|
346
|
+
])
|
|
347
|
+
const mapB = new Map([
|
|
348
|
+
['a', 1],
|
|
349
|
+
['b', 3],
|
|
350
|
+
])
|
|
351
|
+
expect(shallow(mapA, mapB)).toBe(false)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('should return false for Sets with different elements', () => {
|
|
355
|
+
const setA = new Set([1, 2, 3])
|
|
356
|
+
const setB = new Set([1, 2, 4])
|
|
357
|
+
expect(shallow(setA, setB)).toBe(false)
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('should return false for null and non-null values', () => {
|
|
361
|
+
expect(shallow(null, {})).toBe(false)
|
|
362
|
+
expect(shallow({}, null)).toBe(false)
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
it('should return false for objects with different number of keys', () => {
|
|
366
|
+
expect(shallow({ a: 1 }, { a: 1, b: 2 })).toBe(false)
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
it('should return false for objects with different keys', () => {
|
|
370
|
+
expect(shallow({ a: 1 }, { b: 1 })).toBe(false)
|
|
371
|
+
})
|
|
372
|
+
|
|
373
|
+
it('should return false for objects with different values', () => {
|
|
374
|
+
expect(shallow({ a: 1 }, { a: 2 })).toBe(false)
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('should return false for arrays with different lengths', () => {
|
|
378
|
+
expect(shallow([1, 2], [1, 2, 3])).toBe(false)
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
it('should return false for arrays with different elements', () => {
|
|
382
|
+
expect(shallow([1, 2, 3], [1, 2, 4])).toBe(false)
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('should return false for Maps with different sizes', () => {
|
|
386
|
+
expect(
|
|
387
|
+
shallow(
|
|
388
|
+
new Map([['a', 1]]),
|
|
389
|
+
new Map([
|
|
390
|
+
['a', 1],
|
|
391
|
+
['b', 2],
|
|
392
|
+
]),
|
|
393
|
+
),
|
|
394
|
+
).toBe(false)
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
it('should return false for Maps with different keys', () => {
|
|
398
|
+
expect(shallow(new Map([['a', 1]]), new Map([['b', 1]]))).toBe(false)
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
it('should return false for Maps with different values', () => {
|
|
402
|
+
expect(shallow(new Map([['a', 1]]), new Map([['a', 2]]))).toBe(false)
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
it('should return false for Sets with different sizes', () => {
|
|
406
|
+
expect(shallow(new Set([1, 2]), new Set([1, 2, 3]))).toBe(false)
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
it('should return false for Sets with different elements', () => {
|
|
410
|
+
expect(shallow(new Set([1, 2, 3]), new Set([1, 2, 4]))).toBe(false)
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
it('should return true compare simple values', () => {
|
|
414
|
+
expect(shallow(1, 1)).toBe(true)
|
|
415
|
+
expect(shallow('a', 'a')).toBe(true)
|
|
416
|
+
expect(shallow(true, true)).toBe(true)
|
|
417
|
+
})
|
|
418
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/* eslint-disable unicorn/consistent-function-scoping */
|
|
2
|
+
import { subMemo } from '../sub-memo'
|
|
3
|
+
|
|
4
|
+
describe('memo-fn', () => {
|
|
5
|
+
it('should create memo fn', () => {
|
|
6
|
+
function toBeMemoized(): boolean {
|
|
7
|
+
return true
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const memoized = subMemo(toBeMemoized)
|
|
11
|
+
expect(memoized.call().emitter).toBeDefined()
|
|
12
|
+
})
|
|
13
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Cache, IsEqual } from '../types'
|
|
2
|
+
import { isUndefined } from './is'
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line no-shadow
|
|
5
|
+
export enum Abort {
|
|
6
|
+
Error = 'StateAbortError',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface CancelablePromise<T> {
|
|
10
|
+
promise?: Promise<T>
|
|
11
|
+
controller?: AbortController
|
|
12
|
+
resolveInitialPromise?: (value: T) => void
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Cancelable promise function, return promise and controller
|
|
16
|
+
*/
|
|
17
|
+
export function cancelablePromise<T>(promise: Promise<T>, previousController?: AbortController): CancelablePromise<T> {
|
|
18
|
+
if (previousController) {
|
|
19
|
+
previousController.abort()
|
|
20
|
+
}
|
|
21
|
+
const controller = new AbortController()
|
|
22
|
+
const { signal } = controller
|
|
23
|
+
|
|
24
|
+
const cancelable = new Promise<T>((resolve, reject) => {
|
|
25
|
+
// Listen for the abort event
|
|
26
|
+
signal.addEventListener('abort', () => {
|
|
27
|
+
reject(new DOMException('Promise was aborted', Abort.Error))
|
|
28
|
+
})
|
|
29
|
+
// When the original promise settles, resolve or reject accordingly
|
|
30
|
+
promise.then(resolve).catch(reject)
|
|
31
|
+
})
|
|
32
|
+
return { promise: cancelable, controller }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let id = 0
|
|
36
|
+
export function generateId() {
|
|
37
|
+
return id++
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function canUpdate<T>(cache: Cache<T>, isEqual: IsEqual<T> = (previous, next) => previous === next): boolean {
|
|
41
|
+
if (!isUndefined(cache.current)) {
|
|
42
|
+
if (!isUndefined(cache.previous) && isEqual(cache.current, cache.previous)) {
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
cache.previous = cache.current
|
|
46
|
+
}
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { isPromise } from './is'
|
|
2
|
+
|
|
3
|
+
const EMPTY_CONTEXT = Symbol('_')
|
|
4
|
+
|
|
5
|
+
export function createContext<T>(defaultContextValue: T) {
|
|
6
|
+
const contextStack: Array<T | typeof EMPTY_CONTEXT> = []
|
|
7
|
+
|
|
8
|
+
function use(): T | undefined {
|
|
9
|
+
if (contextStack.length === 0) {
|
|
10
|
+
return defaultContextValue
|
|
11
|
+
}
|
|
12
|
+
const currentContext = contextStack.at(-1)
|
|
13
|
+
return currentContext === EMPTY_CONTEXT ? defaultContextValue : currentContext
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function run<R>(ctxValue: T, cb: () => R | Promise<R>): R {
|
|
17
|
+
contextStack.push(ctxValue)
|
|
18
|
+
const result = cb()
|
|
19
|
+
const isResultPromise = isPromise(result)
|
|
20
|
+
if (isResultPromise) {
|
|
21
|
+
return (async () => {
|
|
22
|
+
try {
|
|
23
|
+
return await result
|
|
24
|
+
} finally {
|
|
25
|
+
contextStack.pop()
|
|
26
|
+
}
|
|
27
|
+
})() as R
|
|
28
|
+
} else {
|
|
29
|
+
contextStack.pop()
|
|
30
|
+
return result
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function wrap<X>(cb: () => X | Promise<X>): () => X | Promise<X> {
|
|
35
|
+
const capturedContext = use()
|
|
36
|
+
return () => {
|
|
37
|
+
contextStack.push(capturedContext!)
|
|
38
|
+
const result = cb()
|
|
39
|
+
const isResultPromise = isPromise(result)
|
|
40
|
+
if (isResultPromise) {
|
|
41
|
+
return (async () => {
|
|
42
|
+
try {
|
|
43
|
+
return await result
|
|
44
|
+
} finally {
|
|
45
|
+
contextStack.pop()
|
|
46
|
+
}
|
|
47
|
+
})()
|
|
48
|
+
} else {
|
|
49
|
+
contextStack.pop()
|
|
50
|
+
return result
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
run,
|
|
57
|
+
use,
|
|
58
|
+
wrap,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export type EmitterSubscribe<P = undefined> = (listener: (...params: P[]) => void) => () => void
|
|
2
|
+
export interface Emitter<T, P = undefined> {
|
|
3
|
+
subscribe: EmitterSubscribe<P>
|
|
4
|
+
subscribeToOtherEmitter: (emitter: Emitter<unknown>) => void
|
|
5
|
+
getSnapshot: () => T
|
|
6
|
+
getInitialSnapshot?: () => T
|
|
7
|
+
emit: (...params: P[]) => void
|
|
8
|
+
getSize: () => number
|
|
9
|
+
clear: () => void
|
|
10
|
+
contains: (listener: (...params: P[]) => void) => boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generics parameters are:
|
|
15
|
+
* T: Type of the state
|
|
16
|
+
* R: Type of the snapshot
|
|
17
|
+
* P: Type of the parameters
|
|
18
|
+
* @param getSnapshot
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
export function createEmitter<T, P = undefined>(getSnapshot: () => T, getInitialSnapshot?: () => T): Emitter<T, P> {
|
|
22
|
+
const listeners = new Set<(...params: P[]) => void>()
|
|
23
|
+
// const listeners = new WeakSet<(...params: P[]) => void>()
|
|
24
|
+
const otherCleaners: Array<() => void> = []
|
|
25
|
+
return {
|
|
26
|
+
clear: () => {
|
|
27
|
+
for (const cleaner of otherCleaners) {
|
|
28
|
+
cleaner()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
listeners.clear()
|
|
32
|
+
},
|
|
33
|
+
subscribe: (listener) => {
|
|
34
|
+
listeners.add(listener)
|
|
35
|
+
return () => {
|
|
36
|
+
listeners.delete(listener)
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
emit: (...params) => {
|
|
40
|
+
for (const listener of listeners) {
|
|
41
|
+
listener(...params)
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
contains: (listener) => listeners.has(listener),
|
|
45
|
+
getSnapshot,
|
|
46
|
+
getInitialSnapshot,
|
|
47
|
+
getSize: () => listeners.size,
|
|
48
|
+
subscribeToOtherEmitter(emitter) {
|
|
49
|
+
const clean = emitter.subscribe(() => {
|
|
50
|
+
this.emit()
|
|
51
|
+
})
|
|
52
|
+
otherCleaners.push(clean)
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
}
|