@zeix/cause-effect 0.13.1 → 0.14.0
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 +161 -131
- package/eslint.config.js +35 -0
- package/index.d.ts +9 -7
- package/index.js +1 -1
- package/index.ts +20 -10
- package/package.json +32 -29
- package/src/computed.d.ts +31 -0
- package/src/computed.ts +54 -0
- package/src/effect.d.ts +19 -0
- package/src/effect.ts +95 -0
- package/src/memo.d.ts +13 -0
- package/src/memo.ts +91 -0
- package/{lib → src}/scheduler.d.ts +15 -11
- package/{lib → src}/scheduler.ts +60 -48
- package/src/signal.d.ts +31 -0
- package/src/signal.ts +69 -0
- package/{lib → src}/state.d.ts +4 -7
- package/src/state.ts +89 -0
- package/src/task.d.ts +17 -0
- package/src/task.ts +153 -0
- package/{lib → src}/util.d.ts +1 -1
- package/{lib → src}/util.ts +23 -11
- package/test/batch.test.ts +23 -28
- package/test/benchmark.test.ts +115 -103
- package/test/computed.test.ts +133 -147
- package/test/effect.test.ts +42 -37
- package/test/state.test.ts +12 -79
- package/test/util/dependency-graph.ts +147 -145
- package/test/util/framework-types.ts +22 -22
- package/test/util/perf-tests.ts +28 -28
- package/test/util/reactive-framework.ts +11 -12
- package/lib/computed.d.ts +0 -33
- package/lib/computed.ts +0 -206
- package/lib/effect.d.ts +0 -22
- package/lib/effect.ts +0 -61
- package/lib/signal.d.ts +0 -45
- package/lib/signal.ts +0 -102
- package/lib/state.ts +0 -118
package/test/benchmark.test.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { describe, test, expect, mock } from 'bun:test'
|
|
2
|
-
import { state,
|
|
3
|
-
import { makeGraph, runGraph, Counter } from
|
|
2
|
+
import { state, memo, effect, batch } from '../'
|
|
3
|
+
import { makeGraph, runGraph, Counter } from './util/dependency-graph'
|
|
4
|
+
import {
|
|
5
|
+
type ReactiveFramework,
|
|
6
|
+
type Computed,
|
|
7
|
+
} from './util/reactive-framework'
|
|
4
8
|
|
|
5
9
|
/* === Utility Functions === */
|
|
6
10
|
|
|
7
11
|
const busy = () => {
|
|
8
|
-
let
|
|
12
|
+
let _a = 0
|
|
9
13
|
for (let i = 0; i < 1_00; i++) {
|
|
10
|
-
|
|
14
|
+
_a++
|
|
11
15
|
}
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
const framework = {
|
|
15
|
-
name:
|
|
19
|
+
name: 'Cause & Effect',
|
|
16
20
|
signal: <T extends {}>(initialValue: T) => {
|
|
17
21
|
const s = state<T>(initialValue)
|
|
18
22
|
return {
|
|
@@ -21,14 +25,14 @@ const framework = {
|
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
computed: <T extends {}>(fn: () => T) => {
|
|
24
|
-
const c =
|
|
28
|
+
const c = memo(fn)
|
|
25
29
|
return {
|
|
26
30
|
read: () => c.get(),
|
|
27
31
|
}
|
|
28
32
|
},
|
|
29
33
|
effect: (fn: () => void) => effect(fn),
|
|
30
34
|
withBatch: (fn: () => void) => batch(fn),
|
|
31
|
-
withBuild: (fn: () =>
|
|
35
|
+
withBuild: <T>(fn: () => T) => fn(),
|
|
32
36
|
}
|
|
33
37
|
const testPullCounts = true
|
|
34
38
|
|
|
@@ -45,7 +49,7 @@ function makeConfig() {
|
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
/* === Test functions === */
|
|
48
|
-
|
|
52
|
+
|
|
49
53
|
/** some basic tests to validate the reactive framework
|
|
50
54
|
* wrapper works and can run performance tests.
|
|
51
55
|
*/
|
|
@@ -55,30 +59,30 @@ describe('Basic test', function () {
|
|
|
55
59
|
framework.withBuild(() => {
|
|
56
60
|
const s = framework.signal(2)
|
|
57
61
|
const c = framework.computed(() => s.read() * 2)
|
|
58
|
-
|
|
62
|
+
|
|
59
63
|
expect(c.read()).toEqual(4)
|
|
60
64
|
})
|
|
61
65
|
})
|
|
62
|
-
|
|
66
|
+
|
|
63
67
|
test(`${name} | simple write`, () => {
|
|
64
68
|
framework.withBuild(() => {
|
|
65
69
|
const s = framework.signal(2)
|
|
66
70
|
const c = framework.computed(() => s.read() * 2)
|
|
67
71
|
expect(s.read()).toEqual(2)
|
|
68
72
|
expect(c.read()).toEqual(4)
|
|
69
|
-
|
|
73
|
+
|
|
70
74
|
s.write(3)
|
|
71
75
|
expect(s.read()).toEqual(3)
|
|
72
76
|
expect(c.read()).toEqual(6)
|
|
73
77
|
})
|
|
74
78
|
})
|
|
75
|
-
|
|
79
|
+
|
|
76
80
|
test(`${name} | static graph`, () => {
|
|
77
81
|
const config = makeConfig()
|
|
78
82
|
const counter = new Counter()
|
|
79
|
-
// @ts-expect-error
|
|
83
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
80
84
|
const graph = makeGraph(framework, config, counter)
|
|
81
|
-
// @ts-expect-error
|
|
85
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
82
86
|
const sum = runGraph(graph, 2, 1, framework)
|
|
83
87
|
expect(sum).toEqual(16)
|
|
84
88
|
if (testPullCounts) {
|
|
@@ -87,18 +91,18 @@ describe('Basic test', function () {
|
|
|
87
91
|
expect(counter.count).toBeGreaterThanOrEqual(11)
|
|
88
92
|
}
|
|
89
93
|
})
|
|
90
|
-
|
|
94
|
+
|
|
91
95
|
test(`${name} | static graph, read 2/3 of leaves`, () => {
|
|
92
96
|
framework.withBuild(() => {
|
|
93
97
|
const config = makeConfig()
|
|
94
98
|
config.readFraction = 2 / 3
|
|
95
99
|
config.iterations = 10
|
|
96
100
|
const counter = new Counter()
|
|
97
|
-
// @ts-expect-error
|
|
101
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
98
102
|
const graph = makeGraph(framework, config, counter)
|
|
99
|
-
// @ts-expect-error
|
|
103
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
100
104
|
const sum = runGraph(graph, 10, 2 / 3, framework)
|
|
101
|
-
|
|
105
|
+
|
|
102
106
|
expect(sum).toEqual(71)
|
|
103
107
|
if (testPullCounts) {
|
|
104
108
|
expect(counter.count).toEqual(41)
|
|
@@ -107,7 +111,7 @@ describe('Basic test', function () {
|
|
|
107
111
|
}
|
|
108
112
|
})
|
|
109
113
|
})
|
|
110
|
-
|
|
114
|
+
|
|
111
115
|
test(`${name} | dynamic graph`, () => {
|
|
112
116
|
framework.withBuild(() => {
|
|
113
117
|
const config = makeConfig()
|
|
@@ -115,11 +119,11 @@ describe('Basic test', function () {
|
|
|
115
119
|
config.width = 4
|
|
116
120
|
config.totalLayers = 2
|
|
117
121
|
const counter = new Counter()
|
|
118
|
-
// @ts-expect-error
|
|
122
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
119
123
|
const graph = makeGraph(framework, config, counter)
|
|
120
|
-
// @ts-expect-error
|
|
124
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
121
125
|
const sum = runGraph(graph, 10, 1, framework)
|
|
122
|
-
|
|
126
|
+
|
|
123
127
|
expect(sum).toEqual(72)
|
|
124
128
|
if (testPullCounts) {
|
|
125
129
|
expect(counter.count).toEqual(22)
|
|
@@ -128,38 +132,36 @@ describe('Basic test', function () {
|
|
|
128
132
|
}
|
|
129
133
|
})
|
|
130
134
|
})
|
|
131
|
-
|
|
135
|
+
|
|
132
136
|
test(`${name} | withBuild`, () => {
|
|
133
137
|
const r = framework.withBuild(() => {
|
|
134
138
|
const s = framework.signal(2)
|
|
135
139
|
const c = framework.computed(() => s.read() * 2)
|
|
136
|
-
|
|
140
|
+
|
|
137
141
|
expect(c.read()).toEqual(4)
|
|
138
142
|
return c.read()
|
|
139
143
|
})
|
|
140
|
-
|
|
141
|
-
// @ts-expect-error
|
|
142
144
|
expect(r).toEqual(4)
|
|
143
145
|
})
|
|
144
|
-
|
|
146
|
+
|
|
145
147
|
test(`${name} | effect`, () => {
|
|
146
|
-
const spy =
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
const spy = _v => {}
|
|
149
|
+
const spyMock = mock(spy)
|
|
150
|
+
|
|
149
151
|
const s = framework.signal(2)
|
|
150
152
|
let c: any
|
|
151
|
-
|
|
153
|
+
|
|
152
154
|
framework.withBuild(() => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
c = framework.computed(() => s.read() * 2)
|
|
156
|
+
|
|
157
|
+
framework.effect(() => {
|
|
158
|
+
spyMock(c.read())
|
|
159
|
+
})
|
|
158
160
|
})
|
|
159
161
|
expect(spyMock.mock.calls.length).toBe(1)
|
|
160
|
-
|
|
162
|
+
|
|
161
163
|
framework.withBatch(() => {
|
|
162
|
-
|
|
164
|
+
s.write(3)
|
|
163
165
|
})
|
|
164
166
|
expect(s.read()).toEqual(3)
|
|
165
167
|
expect(c.read()).toEqual(6)
|
|
@@ -174,12 +176,14 @@ describe('Kairo tests', function () {
|
|
|
174
176
|
const head = framework.signal(0)
|
|
175
177
|
const computed1 = framework.computed(() => head.read())
|
|
176
178
|
const computed2 = framework.computed(() => (computed1.read(), 0))
|
|
177
|
-
const computed3 = framework.computed(
|
|
179
|
+
const computed3 = framework.computed(
|
|
180
|
+
() => (busy(), computed2.read()! + 1),
|
|
181
|
+
) // heavy computation
|
|
178
182
|
const computed4 = framework.computed(() => computed3.read()! + 2)
|
|
179
183
|
const computed5 = framework.computed(() => computed4.read()! + 3)
|
|
180
184
|
framework.effect(() => {
|
|
181
185
|
computed5.read()
|
|
182
|
-
busy()
|
|
186
|
+
busy() // heavy side effect
|
|
183
187
|
})
|
|
184
188
|
|
|
185
189
|
return () => {
|
|
@@ -201,10 +205,10 @@ describe('Kairo tests', function () {
|
|
|
201
205
|
let last = head as { read: () => number }
|
|
202
206
|
const callCounter = new Counter()
|
|
203
207
|
for (let i = 0; i < 50; i++) {
|
|
204
|
-
|
|
208
|
+
const current = framework.computed(() => {
|
|
205
209
|
return head.read()! + i
|
|
206
210
|
})
|
|
207
|
-
|
|
211
|
+
const current2 = framework.computed(() => {
|
|
208
212
|
return current.read()! + 1
|
|
209
213
|
})
|
|
210
214
|
framework.effect(() => {
|
|
@@ -231,16 +235,16 @@ describe('Kairo tests', function () {
|
|
|
231
235
|
})
|
|
232
236
|
|
|
233
237
|
test(`${name} | deep propagation`, () => {
|
|
234
|
-
|
|
238
|
+
const len = 50
|
|
235
239
|
const head = framework.signal(0)
|
|
236
240
|
let current = head as { read: () => number }
|
|
237
241
|
for (let i = 0; i < len; i++) {
|
|
238
|
-
|
|
242
|
+
const c = current
|
|
239
243
|
current = framework.computed(() => {
|
|
240
244
|
return c.read() + 1
|
|
241
245
|
})
|
|
242
246
|
}
|
|
243
|
-
|
|
247
|
+
const callCounter = new Counter()
|
|
244
248
|
framework.effect(() => {
|
|
245
249
|
current.read()
|
|
246
250
|
callCounter.count++
|
|
@@ -264,18 +268,16 @@ describe('Kairo tests', function () {
|
|
|
264
268
|
})
|
|
265
269
|
|
|
266
270
|
test(`${name} | diamond`, function () {
|
|
267
|
-
|
|
271
|
+
const width = 5
|
|
268
272
|
const head = framework.signal(0)
|
|
269
|
-
|
|
273
|
+
const current: { read(): number }[] = []
|
|
270
274
|
for (let i = 0; i < width; i++) {
|
|
271
|
-
current.push(
|
|
272
|
-
framework.computed(() => head.read() + 1)
|
|
273
|
-
)
|
|
275
|
+
current.push(framework.computed(() => head.read() + 1))
|
|
274
276
|
}
|
|
275
|
-
|
|
277
|
+
const sum = framework.computed(() => {
|
|
276
278
|
return current.map(x => x.read()).reduce((a, b) => a + b, 0)
|
|
277
279
|
})
|
|
278
|
-
|
|
280
|
+
const callCounter = new Counter()
|
|
279
281
|
framework.effect(() => {
|
|
280
282
|
sum.read()
|
|
281
283
|
callCounter.count++
|
|
@@ -299,15 +301,15 @@ describe('Kairo tests', function () {
|
|
|
299
301
|
})
|
|
300
302
|
|
|
301
303
|
test(`${name} | mux`, function () {
|
|
302
|
-
|
|
304
|
+
const heads = new Array(100).fill(null).map(_ => framework.signal(0))
|
|
303
305
|
const mux = framework.computed(() => {
|
|
304
|
-
return Object.fromEntries(heads.map(
|
|
306
|
+
return Object.fromEntries(heads.map(h => h.read()).entries())
|
|
305
307
|
})
|
|
306
308
|
const splited = heads
|
|
307
309
|
.map((_, index) => framework.computed(() => mux.read()[index]))
|
|
308
|
-
.map(
|
|
310
|
+
.map(x => framework.computed(() => x.read() + 1))
|
|
309
311
|
|
|
310
|
-
splited.forEach(
|
|
312
|
+
splited.forEach(x => {
|
|
311
313
|
framework.effect(() => x.read())
|
|
312
314
|
})
|
|
313
315
|
|
|
@@ -329,15 +331,15 @@ describe('Kairo tests', function () {
|
|
|
329
331
|
|
|
330
332
|
test(`${name} | repeated observers`, function () {
|
|
331
333
|
const size = 30
|
|
332
|
-
|
|
333
|
-
|
|
334
|
+
const head = framework.signal(0)
|
|
335
|
+
const current = framework.computed(() => {
|
|
334
336
|
let result = 0
|
|
335
337
|
for (let i = 0; i < size; i++) {
|
|
336
338
|
result += head.read()
|
|
337
339
|
}
|
|
338
340
|
return result
|
|
339
341
|
})
|
|
340
|
-
|
|
342
|
+
const callCounter = new Counter()
|
|
341
343
|
framework.effect(() => {
|
|
342
344
|
current.read()
|
|
343
345
|
callCounter.count++
|
|
@@ -361,28 +363,28 @@ describe('Kairo tests', function () {
|
|
|
361
363
|
})
|
|
362
364
|
|
|
363
365
|
test(`${name} | triangle`, function () {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
+
const width = 10
|
|
367
|
+
const head = framework.signal(0)
|
|
366
368
|
let current = head as { read: () => number }
|
|
367
|
-
|
|
369
|
+
const list: { read: () => number }[] = []
|
|
368
370
|
for (let i = 0; i < width; i++) {
|
|
369
|
-
|
|
371
|
+
const c = current
|
|
370
372
|
list.push(current)
|
|
371
373
|
current = framework.computed(() => {
|
|
372
374
|
return c.read() + 1
|
|
373
375
|
})
|
|
374
376
|
}
|
|
375
|
-
|
|
376
|
-
return list.map(
|
|
377
|
+
const sum = framework.computed(() => {
|
|
378
|
+
return list.map(x => x.read()).reduce((a, b) => a + b, 0)
|
|
377
379
|
})
|
|
378
|
-
|
|
380
|
+
const callCounter = new Counter()
|
|
379
381
|
framework.effect(() => {
|
|
380
382
|
sum.read()
|
|
381
383
|
callCounter.count++
|
|
382
384
|
})
|
|
383
385
|
|
|
384
386
|
return () => {
|
|
385
|
-
const count = (number:
|
|
387
|
+
const count = (number: number) => {
|
|
386
388
|
return new Array(number)
|
|
387
389
|
.fill(0)
|
|
388
390
|
.map((_, i) => i + 1)
|
|
@@ -406,17 +408,17 @@ describe('Kairo tests', function () {
|
|
|
406
408
|
})
|
|
407
409
|
|
|
408
410
|
test(`${name} | unstable`, function () {
|
|
409
|
-
|
|
411
|
+
const head = framework.signal(0)
|
|
410
412
|
const double = framework.computed(() => head.read() * 2)
|
|
411
413
|
const inverse = framework.computed(() => -head.read())
|
|
412
|
-
|
|
414
|
+
const current = framework.computed(() => {
|
|
413
415
|
let result = 0
|
|
414
416
|
for (let i = 0; i < 20; i++) {
|
|
415
417
|
result += head.read() % 2 ? double.read() : inverse.read()
|
|
416
418
|
}
|
|
417
419
|
return result
|
|
418
420
|
})
|
|
419
|
-
|
|
421
|
+
const callCounter = new Counter()
|
|
420
422
|
framework.effect(() => {
|
|
421
423
|
current.read()
|
|
422
424
|
callCounter.count++
|
|
@@ -440,39 +442,45 @@ describe('Kairo tests', function () {
|
|
|
440
442
|
})
|
|
441
443
|
})
|
|
442
444
|
|
|
443
|
-
|
|
445
|
+
describe('$mol_wire tests', function () {
|
|
444
446
|
const name = framework.name
|
|
445
447
|
|
|
446
|
-
test(`${name} | $mol_wire benchmark`, function() {
|
|
448
|
+
test(`${name} | $mol_wire benchmark`, function () {
|
|
447
449
|
const fib = (n: number) => {
|
|
448
450
|
if (n < 2) return 1
|
|
449
451
|
return fib(n - 1) + fib(n - 2)
|
|
450
452
|
}
|
|
451
|
-
const hard = (n: number,
|
|
453
|
+
const hard = (n: number, _log: string) => {
|
|
452
454
|
return n + fib(16)
|
|
453
455
|
}
|
|
454
456
|
const numbers = Array.from({ length: 5 }, (_, i) => i)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
+
const res: (() => any)[] = []
|
|
458
|
+
framework.withBuild(() => {
|
|
457
459
|
const A = framework.signal(0)
|
|
458
460
|
const B = framework.signal(0)
|
|
459
461
|
const C = framework.computed(() => (A.read() % 2) + (B.read() % 2))
|
|
460
462
|
const D = framework.computed(() =>
|
|
461
|
-
numbers.map(
|
|
463
|
+
numbers.map(i => ({ x: i + (A.read() % 2) - (B.read() % 2) })),
|
|
462
464
|
)
|
|
463
465
|
const E = framework.computed(() =>
|
|
464
|
-
hard(C.read() + A.read() + D.read()[0].x,
|
|
466
|
+
hard(C.read() + A.read() + D.read()[0].x, 'E'),
|
|
467
|
+
)
|
|
468
|
+
const F = framework.computed(() =>
|
|
469
|
+
hard(D.read()[2].x || B.read(), 'F'),
|
|
465
470
|
)
|
|
466
|
-
const F = framework.computed(() => hard(D.read()[2].x || B.read(), "F"))
|
|
467
471
|
const G = framework.computed(
|
|
468
|
-
() =>
|
|
472
|
+
() =>
|
|
473
|
+
C.read() +
|
|
474
|
+
(C.read() || E.read() % 2) +
|
|
475
|
+
D.read()[4].x +
|
|
476
|
+
F.read(),
|
|
469
477
|
)
|
|
470
|
-
framework.effect(() => res.push(hard(G.read(),
|
|
471
|
-
framework.effect(() => res.push(G.read()))
|
|
472
|
-
framework.effect(() => res.push(hard(F.read(),
|
|
473
|
-
framework.effect(() => res[0] = hard(G.read(),
|
|
474
|
-
framework.effect(() => res[1] = G.read())
|
|
475
|
-
framework.effect(() => res[2] = hard(F.read(),
|
|
478
|
+
framework.effect(() => res.push(hard(G.read(), 'H')))
|
|
479
|
+
framework.effect(() => res.push(G.read())) // I
|
|
480
|
+
framework.effect(() => res.push(hard(F.read(), 'J')))
|
|
481
|
+
framework.effect(() => (res[0] = hard(G.read(), 'H')))
|
|
482
|
+
framework.effect(() => (res[1] = G.read())) // I
|
|
483
|
+
framework.effect(() => (res[2] = hard(F.read(), 'J')))
|
|
476
484
|
|
|
477
485
|
return (i: number) => {
|
|
478
486
|
res.length = 0
|
|
@@ -494,39 +502,42 @@ describe('Kairo tests', function () {
|
|
|
494
502
|
describe('CellX tests', function () {
|
|
495
503
|
const name = framework.name
|
|
496
504
|
|
|
497
|
-
test(`${name} | CellX benchmark`, function() {
|
|
505
|
+
test(`${name} | CellX benchmark`, function () {
|
|
498
506
|
const expected = {
|
|
499
|
-
|
|
500
|
-
[
|
|
501
|
-
[
|
|
502
|
-
],
|
|
503
|
-
2500: [
|
|
504
|
-
[-3, -6, -2, 2],
|
|
505
|
-
[-2, -4, 2, 3],
|
|
507
|
+
10: [
|
|
508
|
+
[3, 6, 2, -2],
|
|
509
|
+
[2, 4, -2, -3],
|
|
506
510
|
],
|
|
507
|
-
|
|
511
|
+
20: [
|
|
508
512
|
[2, 4, -1, -6],
|
|
509
513
|
[-2, 1, -4, -4],
|
|
510
|
-
]
|
|
514
|
+
],
|
|
515
|
+
50: [
|
|
516
|
+
[-2, -4, 1, 6],
|
|
517
|
+
[2, -1, 4, 4],
|
|
518
|
+
],
|
|
511
519
|
}
|
|
512
|
-
const results = {}
|
|
513
520
|
|
|
514
|
-
const cellx = (framework, layers) => {
|
|
521
|
+
const cellx = (framework: ReactiveFramework, layers: number) => {
|
|
515
522
|
const start = {
|
|
516
523
|
prop1: framework.signal(1),
|
|
517
524
|
prop2: framework.signal(2),
|
|
518
525
|
prop3: framework.signal(3),
|
|
519
526
|
prop4: framework.signal(4),
|
|
520
527
|
}
|
|
521
|
-
let layer = start
|
|
528
|
+
let layer: Record<string, Computed<number>> = start
|
|
522
529
|
|
|
523
530
|
for (let i = layers; i > 0; i--) {
|
|
524
531
|
const m = layer
|
|
525
532
|
const s = {
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
533
|
+
prop1: framework.computed(() => m.prop2.read()),
|
|
534
|
+
prop2: framework.computed(
|
|
535
|
+
() => m.prop1.read() - m.prop3.read(),
|
|
536
|
+
),
|
|
537
|
+
prop3: framework.computed(
|
|
538
|
+
() => m.prop2.read() + m.prop4.read(),
|
|
539
|
+
),
|
|
540
|
+
prop4: framework.computed(() => m.prop3.read()),
|
|
530
541
|
}
|
|
531
542
|
|
|
532
543
|
framework.effect(() => s.prop1.read())
|
|
@@ -569,10 +580,11 @@ describe('CellX tests', function () {
|
|
|
569
580
|
}
|
|
570
581
|
|
|
571
582
|
for (const layers in expected) {
|
|
583
|
+
// @ts-expect-error - Framework object has incompatible type constraints with ReactiveFramework
|
|
572
584
|
const [before, after] = cellx(framework, layers)
|
|
573
585
|
const [expectedBefore, expectedAfter] = expected[layers]
|
|
574
586
|
expect(before.toString()).toBe(expectedBefore.toString())
|
|
575
587
|
expect(after.toString()).toBe(expectedAfter.toString())
|
|
576
588
|
}
|
|
577
589
|
})
|
|
578
|
-
})
|
|
590
|
+
})
|