@e280/strata 0.2.8 → 0.3.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/README.md +11 -47
- package/package.json +3 -3
- package/s/index.ts +0 -1
- package/s/prism/prism.test.ts +2 -1
- package/s/prism/prism.ts +1 -1
- package/s/signals/derived/class.ts +34 -0
- package/s/signals/derived/fn.ts +35 -0
- package/s/signals/{tests/derived.test.ts → derived/test.ts} +25 -14
- package/s/signals/effect/effect.ts +7 -0
- package/s/signals/effect/test.ts +172 -0
- package/s/signals/effect/watch.ts +32 -0
- package/s/signals/index.ts +11 -7
- package/s/signals/lazy/class.ts +74 -0
- package/s/signals/lazy/fn.ts +22 -0
- package/s/signals/{tests/lazy.test.ts → lazy/test.ts} +23 -12
- package/s/signals/signal/class.ts +77 -0
- package/s/signals/signal/fn.ts +31 -0
- package/s/signals/{tests/signal.test.ts → signal/test.ts} +56 -59
- package/s/signals/signals.test.ts +8 -8
- package/s/signals/types.ts +4 -23
- package/s/signals/utils/default-compare.ts +1 -1
- package/s/signals/utils/symbols.ts +9 -0
- package/s/tests.test.ts +1 -57
- package/x/index.d.ts +0 -1
- package/x/index.js +0 -1
- package/x/index.js.map +1 -1
- package/x/prism/prism.js.map +1 -1
- package/x/prism/prism.test.js +1 -1
- package/x/prism/prism.test.js.map +1 -1
- package/x/signals/derived/class.d.ts +14 -0
- package/x/signals/derived/class.js +23 -0
- package/x/signals/derived/class.js.map +1 -0
- package/x/signals/derived/fn.d.ts +3 -0
- package/x/signals/derived/fn.js +27 -0
- package/x/signals/derived/fn.js.map +1 -0
- package/x/signals/{tests/derived.test.d.ts → derived/test.d.ts} +2 -3
- package/x/signals/{tests/derived.test.js → derived/test.js} +25 -15
- package/x/signals/derived/test.js.map +1 -0
- package/x/signals/effect/effect.d.ts +1 -0
- package/x/signals/effect/effect.js +5 -0
- package/x/signals/effect/effect.js.map +1 -0
- package/x/signals/{tests/effect.test.d.ts → effect/test.d.ts} +7 -0
- package/x/signals/effect/test.js +132 -0
- package/x/signals/effect/test.js.map +1 -0
- package/x/signals/effect/watch.d.ts +4 -0
- package/x/signals/effect/watch.js +25 -0
- package/x/signals/effect/watch.js.map +1 -0
- package/x/signals/index.d.ts +8 -7
- package/x/signals/index.js +8 -7
- package/x/signals/index.js.map +1 -1
- package/x/signals/lazy/class.d.ts +19 -0
- package/x/signals/lazy/class.js +59 -0
- package/x/signals/lazy/class.js.map +1 -0
- package/x/signals/lazy/fn.d.ts +3 -0
- package/x/signals/lazy/fn.js +17 -0
- package/x/signals/lazy/fn.js.map +1 -0
- package/x/signals/{tests/lazy.test.d.ts → lazy/test.d.ts} +2 -3
- package/x/signals/{tests/lazy.test.js → lazy/test.js} +23 -13
- package/x/signals/lazy/test.js.map +1 -0
- package/x/signals/signal/class.d.ts +20 -0
- package/x/signals/signal/class.js +57 -0
- package/x/signals/signal/class.js.map +1 -0
- package/x/signals/signal/fn.d.ts +7 -0
- package/x/signals/signal/fn.js +23 -0
- package/x/signals/signal/fn.js.map +1 -0
- package/x/signals/{tests/signal.test.d.ts → signal/test.d.ts} +8 -7
- package/x/signals/{tests/signal.test.js → signal/test.js} +50 -46
- package/x/signals/signal/test.js.map +1 -0
- package/x/signals/signals.test.d.ts +26 -20
- package/x/signals/signals.test.js +8 -8
- package/x/signals/signals.test.js.map +1 -1
- package/x/signals/types.d.ts +4 -19
- package/x/signals/utils/default-compare.js +1 -1
- package/x/signals/utils/default-compare.js.map +1 -1
- package/x/signals/utils/symbols.d.ts +7 -0
- package/x/signals/utils/symbols.js +8 -0
- package/x/signals/utils/symbols.js.map +1 -0
- package/x/tests.test.js +1 -45
- package/x/tests.test.js.map +1 -1
- package/s/signals/core/derived.ts +0 -65
- package/s/signals/core/effect.ts +0 -31
- package/s/signals/core/lazy.ts +0 -78
- package/s/signals/core/parts/reactive.ts +0 -12
- package/s/signals/core/parts/readable.ts +0 -16
- package/s/signals/core/signal.ts +0 -101
- package/s/signals/porcelain.ts +0 -30
- package/s/signals/tests/effect.test.ts +0 -89
- package/s/tree/index.ts +0 -7
- package/s/tree/parts/branch.ts +0 -55
- package/s/tree/parts/chronobranch.ts +0 -86
- package/s/tree/parts/persistence.ts +0 -31
- package/s/tree/parts/trunk.ts +0 -70
- package/s/tree/parts/types.ts +0 -70
- package/s/tree/parts/utils/immute.ts +0 -43
- package/s/tree/parts/utils/process-options.ts +0 -7
- package/s/tree/parts/utils/setup.ts +0 -40
- package/s/tree/tree.test.ts +0 -366
- package/x/signals/core/derived.d.ts +0 -10
- package/x/signals/core/derived.js +0 -52
- package/x/signals/core/derived.js.map +0 -1
- package/x/signals/core/effect.d.ts +0 -5
- package/x/signals/core/effect.js +0 -17
- package/x/signals/core/effect.js.map +0 -1
- package/x/signals/core/lazy.d.ts +0 -11
- package/x/signals/core/lazy.js +0 -60
- package/x/signals/core/lazy.js.map +0 -1
- package/x/signals/core/parts/reactive.d.ts +0 -5
- package/x/signals/core/parts/reactive.js +0 -9
- package/x/signals/core/parts/reactive.js.map +0 -1
- package/x/signals/core/parts/readable.d.ts +0 -6
- package/x/signals/core/parts/readable.js +0 -15
- package/x/signals/core/parts/readable.js.map +0 -1
- package/x/signals/core/signal.d.ts +0 -13
- package/x/signals/core/signal.js +0 -77
- package/x/signals/core/signal.js.map +0 -1
- package/x/signals/porcelain.d.ts +0 -8
- package/x/signals/porcelain.js +0 -15
- package/x/signals/porcelain.js.map +0 -1
- package/x/signals/tests/derived.test.js.map +0 -1
- package/x/signals/tests/effect.test.js +0 -72
- package/x/signals/tests/effect.test.js.map +0 -1
- package/x/signals/tests/lazy.test.js.map +0 -1
- package/x/signals/tests/signal.test.js.map +0 -1
- package/x/tree/index.d.ts +0 -5
- package/x/tree/index.js +0 -6
- package/x/tree/index.js.map +0 -1
- package/x/tree/parts/branch.d.ts +0 -14
- package/x/tree/parts/branch.js +0 -42
- package/x/tree/parts/branch.js.map +0 -1
- package/x/tree/parts/chronobranch.d.ts +0 -25
- package/x/tree/parts/chronobranch.js +0 -75
- package/x/tree/parts/chronobranch.js.map +0 -1
- package/x/tree/parts/persistence.d.ts +0 -2
- package/x/tree/parts/persistence.js +0 -23
- package/x/tree/parts/persistence.js.map +0 -1
- package/x/tree/parts/trunk.d.ts +0 -19
- package/x/tree/parts/trunk.js +0 -57
- package/x/tree/parts/trunk.js.map +0 -1
- package/x/tree/parts/types.d.ts +0 -28
- package/x/tree/parts/types.js +0 -2
- package/x/tree/parts/types.js.map +0 -1
- package/x/tree/parts/utils/immute.d.ts +0 -11
- package/x/tree/parts/utils/immute.js +0 -33
- package/x/tree/parts/utils/immute.js.map +0 -1
- package/x/tree/parts/utils/process-options.d.ts +0 -2
- package/x/tree/parts/utils/process-options.js +0 -4
- package/x/tree/parts/utils/process-options.js.map +0 -1
- package/x/tree/parts/utils/setup.d.ts +0 -8
- package/x/tree/parts/utils/setup.js +0 -24
- package/x/tree/parts/utils/setup.js.map +0 -1
- package/x/tree/tree.test.d.ts +0 -40
- package/x/tree/tree.test.js +0 -325
- package/x/tree/tree.test.js.map +0 -1
package/s/tree/tree.test.ts
DELETED
|
@@ -1,366 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import {nap} from "@e280/stz"
|
|
3
|
-
import {Science, expect} from "@e280/science"
|
|
4
|
-
|
|
5
|
-
import {Trunk} from "./parts/trunk.js"
|
|
6
|
-
import {effect} from "../signals/core/effect.js"
|
|
7
|
-
|
|
8
|
-
export default Science.suite({
|
|
9
|
-
"trunk": Science.suite({
|
|
10
|
-
"get state": Science.test(async() => {
|
|
11
|
-
const trunk = new Trunk({count: 0})
|
|
12
|
-
expect(trunk.state.count).is(0)
|
|
13
|
-
}),
|
|
14
|
-
|
|
15
|
-
"state is immutable": Science.test(async() => {
|
|
16
|
-
const trunk = new Trunk({count: 0})
|
|
17
|
-
expect(() => (trunk.state as any).count++).throws()
|
|
18
|
-
}),
|
|
19
|
-
|
|
20
|
-
"run a proper mutation": Science.test(async() => {
|
|
21
|
-
const trunk = new Trunk({count: 0})
|
|
22
|
-
expect(trunk.state.count).is(0)
|
|
23
|
-
await trunk.mutate(state => state.count++)
|
|
24
|
-
expect(trunk.state.count).is(1)
|
|
25
|
-
await trunk.mutate(state => state.count++)
|
|
26
|
-
expect(trunk.state.count).is(2)
|
|
27
|
-
}),
|
|
28
|
-
|
|
29
|
-
"forbidden mutation nesting": Science.test(async() => {
|
|
30
|
-
const trunk = new Trunk({count: 0})
|
|
31
|
-
await expect(async() => {
|
|
32
|
-
let promise!: Promise<any>
|
|
33
|
-
await trunk.mutate(() => {
|
|
34
|
-
promise = trunk.mutate(() => {})
|
|
35
|
-
})
|
|
36
|
-
await promise
|
|
37
|
-
}).throwsAsync()
|
|
38
|
-
}),
|
|
39
|
-
|
|
40
|
-
"state after mutation is frozen": Science.test(async () => {
|
|
41
|
-
const trunk = new Trunk({x: 1})
|
|
42
|
-
await trunk.mutate(s => { s.x = 2 })
|
|
43
|
-
expect(() => (trunk.state as any).x = 3).throws()
|
|
44
|
-
}),
|
|
45
|
-
|
|
46
|
-
"effect reacts to trunk mutation": Science.test(async() => {
|
|
47
|
-
const trunk = new Trunk({count: 0})
|
|
48
|
-
await nap(10)
|
|
49
|
-
let mutationCount = 0
|
|
50
|
-
effect(() => {
|
|
51
|
-
void trunk.state.count
|
|
52
|
-
mutationCount++
|
|
53
|
-
})
|
|
54
|
-
expect(mutationCount).is(1)
|
|
55
|
-
await trunk.mutate(state => state.count++)
|
|
56
|
-
expect(mutationCount).is(2)
|
|
57
|
-
}),
|
|
58
|
-
|
|
59
|
-
"trunk.on is debounced": Science.test.skip(async() => {
|
|
60
|
-
const trunk = new Trunk({count: 0})
|
|
61
|
-
let mutationCount = 0
|
|
62
|
-
trunk.on.sub(() => {mutationCount++})
|
|
63
|
-
await Promise.all([
|
|
64
|
-
trunk.mutate(state => state.count++),
|
|
65
|
-
trunk.mutate(state => state.count++),
|
|
66
|
-
trunk.mutate(state => state.count++),
|
|
67
|
-
])
|
|
68
|
-
expect(mutationCount).is(1)
|
|
69
|
-
}),
|
|
70
|
-
|
|
71
|
-
"listeners are fired when array item is pushed": Science.test(async() => {
|
|
72
|
-
const trunk = new Trunk({items: ["hello", "world"]})
|
|
73
|
-
let mutationCount = 0
|
|
74
|
-
trunk.on.sub(() => {mutationCount++})
|
|
75
|
-
await trunk.mutate(state => state.items.push("lol"))
|
|
76
|
-
expect(mutationCount).is(1)
|
|
77
|
-
expect(trunk.state.items.length).is(3)
|
|
78
|
-
}),
|
|
79
|
-
|
|
80
|
-
// // conceptually incompatible with sequential synchronous mutations
|
|
81
|
-
// "prevent mutation loops": Science.test(async() => {
|
|
82
|
-
// const trunk = new Trunk({count: 0})
|
|
83
|
-
// let mutationCount = 0
|
|
84
|
-
// trunk.on.sub(async() => {
|
|
85
|
-
// mutationCount++
|
|
86
|
-
// if (mutationCount > 100)
|
|
87
|
-
// return
|
|
88
|
-
// await trunk.mutate(s => s.count++)
|
|
89
|
-
// })
|
|
90
|
-
// await expect(async() => {
|
|
91
|
-
// await trunk.mutate(state => state.count++)
|
|
92
|
-
// }).throwsAsync()
|
|
93
|
-
// expect(mutationCount).is(1)
|
|
94
|
-
// }),
|
|
95
|
-
|
|
96
|
-
"sync coherence": Science.test(async() => {
|
|
97
|
-
const trunk = new Trunk({count: 0})
|
|
98
|
-
const p1 = trunk.mutate(s => s.count++)
|
|
99
|
-
expect(trunk.state.count).is(1)
|
|
100
|
-
const p2 = trunk.mutate(s => s.count++)
|
|
101
|
-
expect(trunk.state.count).is(2)
|
|
102
|
-
await p1
|
|
103
|
-
await p2
|
|
104
|
-
}),
|
|
105
|
-
}),
|
|
106
|
-
|
|
107
|
-
"branch": Science.suite({
|
|
108
|
-
"get state": Science.test(async() => {
|
|
109
|
-
const trunk = new Trunk({count: 0, sub: {rofls: 0}})
|
|
110
|
-
const branch = trunk.branch(s => s.sub)
|
|
111
|
-
expect(branch.state.rofls).is(0)
|
|
112
|
-
}),
|
|
113
|
-
|
|
114
|
-
"mutation triggers effect": Science.test(async() => {
|
|
115
|
-
const trunk = new Trunk({a: {x: 0}})
|
|
116
|
-
const branch = trunk.branch(s => s.a)
|
|
117
|
-
expect(branch.state.x).is(0)
|
|
118
|
-
let triggered = 0
|
|
119
|
-
effect(() => {
|
|
120
|
-
void branch.state.x
|
|
121
|
-
triggered++
|
|
122
|
-
})
|
|
123
|
-
expect(triggered).is(1)
|
|
124
|
-
await branch.mutate(s => s.x++)
|
|
125
|
-
expect(triggered).is(2)
|
|
126
|
-
}),
|
|
127
|
-
|
|
128
|
-
"sync coherence": Science.test(async() => {
|
|
129
|
-
const trunk = new Trunk({count: 0, sub: {rofls: 0}})
|
|
130
|
-
const branch = trunk.branch(s => s.sub)
|
|
131
|
-
expect(branch.state.rofls).is(0)
|
|
132
|
-
const p = branch.mutate(s => s.rofls++)
|
|
133
|
-
expect(branch.state.rofls).is(1)
|
|
134
|
-
await p
|
|
135
|
-
}),
|
|
136
|
-
|
|
137
|
-
"nullable selector": Science.test(async () => {
|
|
138
|
-
const trunk = new Trunk({
|
|
139
|
-
a: {b: 0} as (null | {b: number}),
|
|
140
|
-
})
|
|
141
|
-
const a = trunk.branch(s => s.a)
|
|
142
|
-
expect(trunk.state.a?.b).is(0)
|
|
143
|
-
expect(a.state?.b).is(0)
|
|
144
|
-
await a.mutate(a => { a!.b = 1 })
|
|
145
|
-
expect(trunk.state.a?.b).is(1)
|
|
146
|
-
expect(a.state?.b).is(1)
|
|
147
|
-
await trunk.mutate(s => s.a = null)
|
|
148
|
-
expect(trunk.state.a?.b).is(undefined)
|
|
149
|
-
expect(a.state?.b).is(undefined)
|
|
150
|
-
}),
|
|
151
|
-
|
|
152
|
-
"composition": Science.test(async () => {
|
|
153
|
-
const trunk = new Trunk({a: {b: {c: 0}}})
|
|
154
|
-
const a = trunk.branch(s => s.a)
|
|
155
|
-
const b = a.branch(s => s.b)
|
|
156
|
-
expect(trunk.state.a.b.c).is(0)
|
|
157
|
-
expect(b.state.c).is(0)
|
|
158
|
-
}),
|
|
159
|
-
|
|
160
|
-
"deep mutations": Science.test(async () => {
|
|
161
|
-
const trunk = new Trunk({a: {b: {c: 0}}})
|
|
162
|
-
const a = trunk.branch(s => s.a)
|
|
163
|
-
const b = a.branch(s => s.b)
|
|
164
|
-
await b.mutate(b => { b.c = 101 })
|
|
165
|
-
expect(trunk.state.a.b.c).is(101)
|
|
166
|
-
expect(a.state.b.c).is(101)
|
|
167
|
-
expect(b.state.c).is(101)
|
|
168
|
-
await a.mutate(a => { a.b = {c: 102} })
|
|
169
|
-
expect(trunk.state.a.b.c).is(102)
|
|
170
|
-
expect(a.state.b.c).is(102)
|
|
171
|
-
expect(b.state.c).is(102)
|
|
172
|
-
await trunk.mutate(s => { s.a = {b: {c: 103}} })
|
|
173
|
-
expect(trunk.state.a.b.c).is(103)
|
|
174
|
-
expect(a.state.b.c).is(103)
|
|
175
|
-
expect(b.state.c).is(103)
|
|
176
|
-
}),
|
|
177
|
-
|
|
178
|
-
"branch.on ignores outside mutations": Science.test(async() => {
|
|
179
|
-
const trunk = new Trunk({a: {x: 0}, b: {x: 0}})
|
|
180
|
-
const a = trunk.branch(s => s.a)
|
|
181
|
-
const b = trunk.branch(s => s.b)
|
|
182
|
-
let counted = 0
|
|
183
|
-
b.on(() => {counted++})
|
|
184
|
-
expect(counted).is(0)
|
|
185
|
-
await a.mutate(a => a.x = 1)
|
|
186
|
-
expect(counted).is(0)
|
|
187
|
-
}),
|
|
188
|
-
|
|
189
|
-
"effects ignore outside mutations": Science.test(async() => {
|
|
190
|
-
const trunk = new Trunk({a: {x: 0}, b: {x: 0}})
|
|
191
|
-
const a = trunk.branch(s => s.a)
|
|
192
|
-
const b = trunk.branch(s => s.b)
|
|
193
|
-
let counted = 0
|
|
194
|
-
effect(() => {
|
|
195
|
-
void b.state.x
|
|
196
|
-
counted++
|
|
197
|
-
})
|
|
198
|
-
expect(counted).is(1)
|
|
199
|
-
await a.mutate(a => a.x++)
|
|
200
|
-
expect(counted).is(1)
|
|
201
|
-
}),
|
|
202
|
-
|
|
203
|
-
"forbid submutation in mutation": Science.test(async() => {
|
|
204
|
-
const trunk = new Trunk({a: {b: 0}})
|
|
205
|
-
const a = trunk.branch(s => s.a)
|
|
206
|
-
await expect(async() => {
|
|
207
|
-
let promise!: Promise<any>
|
|
208
|
-
await trunk.mutate(() => {
|
|
209
|
-
promise = a.mutate(() => {})
|
|
210
|
-
})
|
|
211
|
-
await promise
|
|
212
|
-
}).throwsAsync()
|
|
213
|
-
}),
|
|
214
|
-
|
|
215
|
-
"forbid mutation in submutation": Science.test(async() => {
|
|
216
|
-
const trunk = new Trunk({a: {b: 0}})
|
|
217
|
-
const a = trunk.branch(s => s.a)
|
|
218
|
-
await expect(async() => {
|
|
219
|
-
let promise!: Promise<any>
|
|
220
|
-
await a.mutate(() => {
|
|
221
|
-
promise = trunk.mutate(() => {})
|
|
222
|
-
})
|
|
223
|
-
await promise
|
|
224
|
-
}).throwsAsync()
|
|
225
|
-
}),
|
|
226
|
-
}),
|
|
227
|
-
|
|
228
|
-
"chronobranch": (() => {
|
|
229
|
-
const setup = () => {
|
|
230
|
-
const trunk = new Trunk({
|
|
231
|
-
chron: Trunk.chronicle({count: 0}),
|
|
232
|
-
})
|
|
233
|
-
const chron = trunk.chronobranch(64, s => s.chron)
|
|
234
|
-
return {trunk, chron}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return Science.suite({
|
|
238
|
-
"get state": Science.test(async() => {
|
|
239
|
-
const {chron} = setup()
|
|
240
|
-
expect(chron.state.count).is(0)
|
|
241
|
-
}),
|
|
242
|
-
|
|
243
|
-
"mutate": Science.test(async() => {
|
|
244
|
-
const {chron} = setup()
|
|
245
|
-
expect(chron.state.count).is(0)
|
|
246
|
-
await chron.mutate(s => s.count++)
|
|
247
|
-
expect(chron.state.count).is(1)
|
|
248
|
-
await chron.mutate(s => s.count++)
|
|
249
|
-
expect(chron.state.count).is(2)
|
|
250
|
-
}),
|
|
251
|
-
|
|
252
|
-
"undoable/redoable": Science.test(async() => {
|
|
253
|
-
const {chron} = setup()
|
|
254
|
-
expect(chron.undoable).is(0)
|
|
255
|
-
expect(chron.redoable).is(0)
|
|
256
|
-
expect(chron.state.count).is(0)
|
|
257
|
-
await chron.mutate(s => s.count++)
|
|
258
|
-
expect(chron.undoable).is(1)
|
|
259
|
-
await chron.mutate(s => s.count++)
|
|
260
|
-
expect(chron.undoable).is(2)
|
|
261
|
-
await chron.undo()
|
|
262
|
-
expect(chron.undoable).is(1)
|
|
263
|
-
expect(chron.redoable).is(1)
|
|
264
|
-
await chron.undo()
|
|
265
|
-
expect(chron.undoable).is(0)
|
|
266
|
-
expect(chron.redoable).is(2)
|
|
267
|
-
await chron.redo()
|
|
268
|
-
expect(chron.undoable).is(1)
|
|
269
|
-
expect(chron.redoable).is(1)
|
|
270
|
-
}),
|
|
271
|
-
|
|
272
|
-
"undo": Science.test(async() => {
|
|
273
|
-
const {chron} = setup()
|
|
274
|
-
await chron.mutate(s => s.count++)
|
|
275
|
-
await chron.undo()
|
|
276
|
-
expect(chron.state.count).is(0)
|
|
277
|
-
}),
|
|
278
|
-
|
|
279
|
-
"redo": Science.test(async() => {
|
|
280
|
-
const {chron} = setup()
|
|
281
|
-
await chron.mutate(s => s.count++)
|
|
282
|
-
await chron.undo()
|
|
283
|
-
expect(chron.state.count).is(0)
|
|
284
|
-
await chron.redo()
|
|
285
|
-
expect(chron.state.count).is(1)
|
|
286
|
-
}),
|
|
287
|
-
|
|
288
|
-
"undo/redo well ordered": Science.test(async() => {
|
|
289
|
-
const {chron} = setup()
|
|
290
|
-
await chron.mutate(s => s.count++)
|
|
291
|
-
await chron.mutate(s => s.count++)
|
|
292
|
-
await chron.mutate(s => s.count++)
|
|
293
|
-
expect(chron.state.count).is(3)
|
|
294
|
-
|
|
295
|
-
await chron.undo()
|
|
296
|
-
expect(chron.state.count).is(2)
|
|
297
|
-
|
|
298
|
-
await chron.undo()
|
|
299
|
-
expect(chron.state.count).is(1)
|
|
300
|
-
|
|
301
|
-
await chron.redo()
|
|
302
|
-
expect(chron.state.count).is(2)
|
|
303
|
-
|
|
304
|
-
await chron.redo()
|
|
305
|
-
expect(chron.state.count).is(3)
|
|
306
|
-
|
|
307
|
-
await chron.undo()
|
|
308
|
-
expect(chron.state.count).is(2)
|
|
309
|
-
|
|
310
|
-
await chron.undo()
|
|
311
|
-
expect(chron.state.count).is(1)
|
|
312
|
-
|
|
313
|
-
await chron.undo()
|
|
314
|
-
expect(chron.state.count).is(0)
|
|
315
|
-
}),
|
|
316
|
-
|
|
317
|
-
"undo nothing does nothing": Science.test(async() => {
|
|
318
|
-
const {chron} = setup()
|
|
319
|
-
await chron.undo()
|
|
320
|
-
expect(chron.state.count).is(0)
|
|
321
|
-
}),
|
|
322
|
-
|
|
323
|
-
"redo nothing does nothing": Science.test(async() => {
|
|
324
|
-
const {chron} = setup()
|
|
325
|
-
await chron.redo()
|
|
326
|
-
expect(chron.state.count).is(0)
|
|
327
|
-
}),
|
|
328
|
-
|
|
329
|
-
"undo 2x": Science.test(async() => {
|
|
330
|
-
const {chron} = setup()
|
|
331
|
-
await chron.mutate(s => s.count++)
|
|
332
|
-
await chron.mutate(s => s.count++)
|
|
333
|
-
expect(chron.state.count).is(2)
|
|
334
|
-
await chron.undo(2)
|
|
335
|
-
expect(chron.state.count).is(0)
|
|
336
|
-
}),
|
|
337
|
-
|
|
338
|
-
"redo 2x": Science.test(async() => {
|
|
339
|
-
const {chron} = setup()
|
|
340
|
-
await chron.mutate(s => s.count++)
|
|
341
|
-
await chron.mutate(s => s.count++)
|
|
342
|
-
expect(chron.state.count).is(2)
|
|
343
|
-
await chron.undo(2)
|
|
344
|
-
expect(chron.state.count).is(0)
|
|
345
|
-
await chron.redo(2)
|
|
346
|
-
expect(chron.state.count).is(2)
|
|
347
|
-
}),
|
|
348
|
-
|
|
349
|
-
"substrata mutations are tracked": Science.test(async() => {
|
|
350
|
-
const strata = new Trunk({
|
|
351
|
-
chron: Trunk.chronicle({
|
|
352
|
-
group: {count: 0},
|
|
353
|
-
}),
|
|
354
|
-
})
|
|
355
|
-
const chron = strata.chronobranch(64, s => s.chron)
|
|
356
|
-
const group = chron.branch(s => s.group)
|
|
357
|
-
expect(group.state.count).is(0)
|
|
358
|
-
await group.mutate(g => g.count = 101)
|
|
359
|
-
expect(group.state.count).is(101)
|
|
360
|
-
await chron.undo()
|
|
361
|
-
expect(group.state.count).is(0)
|
|
362
|
-
}),
|
|
363
|
-
})
|
|
364
|
-
})(),
|
|
365
|
-
})
|
|
366
|
-
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Reactive } from "./parts/reactive.js";
|
|
2
|
-
import { DerivedFn, SignalOptions } from "../types.js";
|
|
3
|
-
export declare class Derived<V> extends Reactive<V> {
|
|
4
|
-
#private;
|
|
5
|
-
constructor(formula: () => V, options?: Partial<SignalOptions>);
|
|
6
|
-
toString(): string;
|
|
7
|
-
dispose(): void;
|
|
8
|
-
get core(): this;
|
|
9
|
-
fn(): DerivedFn<V>;
|
|
10
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { collectorEffect } from "./effect.js";
|
|
2
|
-
import { Reactive } from "./parts/reactive.js";
|
|
3
|
-
import { tracker } from "../../tracker/tracker.js";
|
|
4
|
-
import { defaultCompare } from "../utils/default-compare.js";
|
|
5
|
-
export class Derived extends Reactive {
|
|
6
|
-
#dispose;
|
|
7
|
-
constructor(formula, options) {
|
|
8
|
-
const compare = options?.compare ?? defaultCompare;
|
|
9
|
-
const { result, dispose } = collectorEffect(formula, async () => {
|
|
10
|
-
const value = formula();
|
|
11
|
-
const isChanged = !compare(this.sneak, value);
|
|
12
|
-
if (isChanged) {
|
|
13
|
-
this.sneak = value;
|
|
14
|
-
await Promise.all([
|
|
15
|
-
tracker.notifyWrite(this),
|
|
16
|
-
this.on.pub(value),
|
|
17
|
-
]);
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
super(result);
|
|
21
|
-
this.#dispose = dispose;
|
|
22
|
-
}
|
|
23
|
-
toString() {
|
|
24
|
-
return `(derived "${String(this.get())}")`;
|
|
25
|
-
}
|
|
26
|
-
dispose() {
|
|
27
|
-
super.dispose();
|
|
28
|
-
this.#dispose();
|
|
29
|
-
}
|
|
30
|
-
get core() {
|
|
31
|
-
return this;
|
|
32
|
-
}
|
|
33
|
-
fn() {
|
|
34
|
-
const that = this;
|
|
35
|
-
function f() {
|
|
36
|
-
return that.get();
|
|
37
|
-
}
|
|
38
|
-
f.core = that;
|
|
39
|
-
f.get = that.get.bind(that);
|
|
40
|
-
f.on = that.on;
|
|
41
|
-
f.dispose = that.dispose.bind(that);
|
|
42
|
-
f.fn = that.fn.bind(that);
|
|
43
|
-
Object.defineProperty(f, "value", {
|
|
44
|
-
get: () => that.value,
|
|
45
|
-
});
|
|
46
|
-
Object.defineProperty(f, "sneak", {
|
|
47
|
-
get: () => that.sneak,
|
|
48
|
-
});
|
|
49
|
-
return f;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
//# sourceMappingURL=derived.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"derived.js","sourceRoot":"","sources":["../../../s/signals/core/derived.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,0BAA0B,CAAA;AAEhD,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAE1D,MAAM,OAAO,OAAW,SAAQ,QAAW;IAC1C,QAAQ,CAAY;IAEpB,YAAY,OAAgB,EAAE,OAAgC;QAC7D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,CAAA;QAClD,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,eAAe,CAAC,OAAO,EAAE,KAAK,IAAG,EAAE;YAC5D,MAAM,KAAK,GAAG,OAAO,EAAE,CAAA;YACvB,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YAC7C,IAAI,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;gBAClB,MAAM,OAAO,CAAC,GAAG,CAAC;oBACjB,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC;oBACzB,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;iBAClB,CAAC,CAAA;YACH,CAAC;QACF,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,MAAM,CAAC,CAAA;QACb,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,QAAQ;QACP,OAAO,aAAa,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAA;IAC3C,CAAC;IAED,OAAO;QACN,KAAK,CAAC,OAAO,EAAE,CAAA;QACf,IAAI,CAAC,QAAQ,EAAE,CAAA;IAChB,CAAC;IAED,IAAI,IAAI;QACP,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,EAAE;QACD,MAAM,IAAI,GAAG,IAAkB,CAAA;QAE/B,SAAS,CAAC;YACT,OAAO,IAAI,CAAC,GAAG,EAAE,CAAA;QAClB,CAAC;QAED,CAAC,CAAC,IAAI,GAAG,IAAI,CAAA;QACb,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QACd,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEzB,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE;YACjC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;SACrB,CAAC,CAAA;QAEF,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE;YACjC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;SACrB,CAAC,CAAA;QAEF,OAAO,CAAiB,CAAA;IACzB,CAAC;CACD"}
|
package/x/signals/core/effect.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { microbounce } from "@e280/stz";
|
|
2
|
-
import { tracker } from "../../tracker/tracker.js";
|
|
3
|
-
export function effect(collector, responder = collector) {
|
|
4
|
-
return collectorEffect(collector, responder).dispose;
|
|
5
|
-
}
|
|
6
|
-
export function collectorEffect(collector, responder = collector) {
|
|
7
|
-
const { seen, result } = tracker.observe(collector);
|
|
8
|
-
const fn = microbounce(responder);
|
|
9
|
-
const disposers = [];
|
|
10
|
-
const dispose = () => disposers.forEach(d => d());
|
|
11
|
-
for (const saw of seen) {
|
|
12
|
-
const dispose = tracker.subscribe(saw, fn);
|
|
13
|
-
disposers.push(dispose);
|
|
14
|
-
}
|
|
15
|
-
return { result, dispose };
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=effect.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"effect.js","sourceRoot":"","sources":["../../../s/signals/core/effect.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,WAAW,CAAA;AACrC,OAAO,EAAC,OAAO,EAAC,MAAM,0BAA0B,CAAA;AAEhD,MAAM,UAAU,MAAM,CACpB,SAAqB,EACrB,YAAwB,SAAS;IAGlC,OAAO,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,OAAO,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,SAAkB,EAClB,YAAwB,SAAS;IAGlC,MAAM,EAAC,IAAI,EAAE,MAAM,EAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjD,MAAM,EAAE,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;IAEjC,MAAM,SAAS,GAAmB,EAAE,CAAA;IACpC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IAEjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC1C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,EAAC,MAAM,EAAE,OAAO,EAAC,CAAA;AACzB,CAAC"}
|
package/x/signals/core/lazy.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Readable } from "./parts/readable.js";
|
|
2
|
-
import { LazyFn, SignalOptions } from "../types.js";
|
|
3
|
-
export declare class Lazy<V> extends Readable<V> {
|
|
4
|
-
#private;
|
|
5
|
-
constructor(formula: () => V, options?: Partial<SignalOptions>);
|
|
6
|
-
toString(): string;
|
|
7
|
-
get(): V;
|
|
8
|
-
dispose(): void;
|
|
9
|
-
get core(): this;
|
|
10
|
-
fn(): LazyFn<V>;
|
|
11
|
-
}
|
package/x/signals/core/lazy.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { collectorEffect } from "./effect.js";
|
|
2
|
-
import { Readable } from "./parts/readable.js";
|
|
3
|
-
import { tracker } from "../../tracker/tracker.js";
|
|
4
|
-
import { defaultCompare } from "../utils/default-compare.js";
|
|
5
|
-
export class Lazy extends Readable {
|
|
6
|
-
#formula;
|
|
7
|
-
#compare;
|
|
8
|
-
#dirty = false;
|
|
9
|
-
#effect;
|
|
10
|
-
constructor(formula, options) {
|
|
11
|
-
super(undefined);
|
|
12
|
-
this.#formula = formula;
|
|
13
|
-
this.#compare = options?.compare ?? defaultCompare;
|
|
14
|
-
}
|
|
15
|
-
toString() {
|
|
16
|
-
return `($lazy "${String(this.get())}")`;
|
|
17
|
-
}
|
|
18
|
-
get() {
|
|
19
|
-
if (!this.#effect) {
|
|
20
|
-
const { result, dispose } = collectorEffect(this.#formula, () => this.#dirty = true);
|
|
21
|
-
this.#effect = dispose;
|
|
22
|
-
this.sneak = result;
|
|
23
|
-
}
|
|
24
|
-
if (this.#dirty) {
|
|
25
|
-
this.#dirty = false;
|
|
26
|
-
const v = this.#formula();
|
|
27
|
-
const isChanged = !this.#compare(this.sneak, v);
|
|
28
|
-
if (isChanged) {
|
|
29
|
-
this.sneak = v;
|
|
30
|
-
tracker.notifyWrite(this);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return super.get();
|
|
34
|
-
}
|
|
35
|
-
dispose() {
|
|
36
|
-
if (this.#effect)
|
|
37
|
-
this.#effect();
|
|
38
|
-
}
|
|
39
|
-
get core() {
|
|
40
|
-
return this;
|
|
41
|
-
}
|
|
42
|
-
fn() {
|
|
43
|
-
const that = this;
|
|
44
|
-
function f() {
|
|
45
|
-
return that.get();
|
|
46
|
-
}
|
|
47
|
-
f.core = that;
|
|
48
|
-
f.get = that.get.bind(that);
|
|
49
|
-
f.dispose = that.dispose.bind(that);
|
|
50
|
-
f.fn = that.fn.bind(that);
|
|
51
|
-
Object.defineProperty(f, "value", {
|
|
52
|
-
get: () => that.value,
|
|
53
|
-
});
|
|
54
|
-
Object.defineProperty(f, "sneak", {
|
|
55
|
-
get: () => that.sneak,
|
|
56
|
-
});
|
|
57
|
-
return f;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=lazy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../../s/signals/core/lazy.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,0BAA0B,CAAA;AAEhD,OAAO,EAAC,cAAc,EAAC,MAAM,6BAA6B,CAAA;AAE1D,MAAM,OAAO,IAAQ,SAAQ,QAAW;IACvC,QAAQ,CAAS;IACjB,QAAQ,CAA6B;IACrC,MAAM,GAAG,KAAK,CAAA;IACd,OAAO,CAA0B;IAEjC,YAAY,OAAgB,EAAE,OAAgC;QAC7D,KAAK,CAAC,SAAgB,CAAC,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,CAAA;IACnD,CAAC;IAED,QAAQ;QACP,OAAO,WAAW,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAA;IACzC,CAAC;IAED,GAAG;QACF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,eAAe,CACxC,IAAI,CAAC,QAAQ,EACb,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CACxB,CAAA;YACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;YACtB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACpB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;YAEnB,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;YACzB,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YAC/C,IAAI,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;gBACd,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YAC1B,CAAC;QACF,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,EAAE,CAAA;IACnB,CAAC;IAED,OAAO;QACN,IAAI,IAAI,CAAC,OAAO;YACf,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAED,IAAI,IAAI;QACP,OAAO,IAAI,CAAA;IACZ,CAAC;IAED,EAAE;QACD,MAAM,IAAI,GAAG,IAAe,CAAA;QAE5B,SAAS,CAAC;YACT,OAAO,IAAI,CAAC,GAAG,EAAE,CAAA;QAClB,CAAC;QAED,CAAC,CAAC,IAAI,GAAG,IAAI,CAAA;QACb,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAEzB,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE;YACjC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;SACrB,CAAC,CAAA;QAEF,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE;YACjC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;SACrB,CAAC,CAAA;QAEF,OAAO,CAAc,CAAA;IACtB,CAAC;CACD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../../../s/signals/core/parts/reactive.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAAC,MAAM,WAAW,CAAA;AAC7B,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AAEtC,MAAM,OAAO,QAAY,SAAQ,QAAW;IAC3C,EAAE,GAAG,GAAG,EAAO,CAAA;IAEf,OAAO;QACN,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAA;IAChB,CAAC;CACD"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { tracker } from "../../../tracker/tracker.js";
|
|
2
|
-
export class Readable {
|
|
3
|
-
sneak;
|
|
4
|
-
constructor(sneak) {
|
|
5
|
-
this.sneak = sneak;
|
|
6
|
-
}
|
|
7
|
-
get() {
|
|
8
|
-
tracker.notifyRead(this);
|
|
9
|
-
return this.sneak;
|
|
10
|
-
}
|
|
11
|
-
get value() {
|
|
12
|
-
return this.get();
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=readable.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"readable.js","sourceRoot":"","sources":["../../../../s/signals/core/parts/readable.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAC,MAAM,6BAA6B,CAAA;AAEnD,MAAM,OAAO,QAAQ;IACD;IAAnB,YAAmB,KAAQ;QAAR,UAAK,GAAL,KAAK,CAAG;IAAG,CAAC;IAE/B,GAAG;QACF,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACxB,OAAO,IAAI,CAAC,KAAK,CAAA;IAClB,CAAC;IAED,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,GAAG,EAAE,CAAA;IAClB,CAAC;CACD"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { Reactive } from "./parts/reactive.js";
|
|
2
|
-
import { SignalFn, SignalOptions } from "../types.js";
|
|
3
|
-
export declare class Signal<V> extends Reactive<V> {
|
|
4
|
-
#private;
|
|
5
|
-
constructor(value: V, options?: Partial<SignalOptions>);
|
|
6
|
-
toString(): string;
|
|
7
|
-
set(v: V, forcePublish?: boolean): Promise<V>;
|
|
8
|
-
get value(): V;
|
|
9
|
-
set value(v: V);
|
|
10
|
-
publish(): Promise<V>;
|
|
11
|
-
get core(): this;
|
|
12
|
-
fn(): SignalFn<V>;
|
|
13
|
-
}
|
package/x/signals/core/signal.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { Reactive } from "./parts/reactive.js";
|
|
2
|
-
import { tracker } from "../../tracker/tracker.js";
|
|
3
|
-
import { defaultCompare } from "../utils/default-compare.js";
|
|
4
|
-
export class Signal extends Reactive {
|
|
5
|
-
#lock = false;
|
|
6
|
-
#compare;
|
|
7
|
-
constructor(value, options) {
|
|
8
|
-
super(value);
|
|
9
|
-
this.#compare = options?.compare ?? defaultCompare;
|
|
10
|
-
}
|
|
11
|
-
toString() {
|
|
12
|
-
return `($signal "${String(this.get())}")`;
|
|
13
|
-
}
|
|
14
|
-
async set(v, forcePublish = false) {
|
|
15
|
-
const previous = this.sneak;
|
|
16
|
-
this.sneak = v;
|
|
17
|
-
if (forcePublish || !this.#compare(previous, v))
|
|
18
|
-
await this.publish();
|
|
19
|
-
return v;
|
|
20
|
-
}
|
|
21
|
-
get value() {
|
|
22
|
-
return this.get();
|
|
23
|
-
}
|
|
24
|
-
set value(v) {
|
|
25
|
-
void this.set(v);
|
|
26
|
-
}
|
|
27
|
-
async publish() {
|
|
28
|
-
// only wizards are allowed beyond this point.
|
|
29
|
-
// - the implementation is subtle
|
|
30
|
-
// - it looks wrong, but it's right
|
|
31
|
-
// - tarnished alchemists, take heed: lock engages only for sync activity of the async fns (think of the value setter!)
|
|
32
|
-
if (this.#lock)
|
|
33
|
-
throw new Error("forbid circularity");
|
|
34
|
-
const value = this.sneak;
|
|
35
|
-
let promise = Promise.resolve();
|
|
36
|
-
try {
|
|
37
|
-
this.#lock = true;
|
|
38
|
-
promise = Promise.all([
|
|
39
|
-
tracker.notifyWrite(this),
|
|
40
|
-
this.on.publish(value),
|
|
41
|
-
]);
|
|
42
|
-
}
|
|
43
|
-
finally {
|
|
44
|
-
this.#lock = false;
|
|
45
|
-
}
|
|
46
|
-
await promise;
|
|
47
|
-
return value;
|
|
48
|
-
}
|
|
49
|
-
get core() {
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
52
|
-
fn() {
|
|
53
|
-
const that = this;
|
|
54
|
-
function f(_v) {
|
|
55
|
-
return (arguments.length === 0)
|
|
56
|
-
? that.get()
|
|
57
|
-
: that.set(arguments[0]);
|
|
58
|
-
}
|
|
59
|
-
f.core = that;
|
|
60
|
-
f.get = that.get.bind(that);
|
|
61
|
-
f.set = that.set.bind(that);
|
|
62
|
-
f.on = that.on;
|
|
63
|
-
f.dispose = that.dispose.bind(that);
|
|
64
|
-
f.publish = that.publish.bind(that);
|
|
65
|
-
f.fn = that.fn.bind(that);
|
|
66
|
-
Object.defineProperty(f, "value", {
|
|
67
|
-
get: () => that.value,
|
|
68
|
-
set: (v) => that.value = v,
|
|
69
|
-
});
|
|
70
|
-
Object.defineProperty(f, "sneak", {
|
|
71
|
-
get: () => that.sneak,
|
|
72
|
-
set: (v) => that.sneak = v,
|
|
73
|
-
});
|
|
74
|
-
return f;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
//# sourceMappingURL=signal.js.map
|