@zeix/cause-effect 0.13.1 → 0.13.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 +2 -2
- package/eslint.config.js +35 -0
- package/index.d.ts +7 -7
- package/index.js +1 -1
- package/index.ts +19 -9
- package/package.json +32 -29
- package/{lib → src}/computed.ts +83 -61
- package/{lib → src}/effect.ts +27 -19
- package/{lib → src}/scheduler.d.ts +1 -1
- package/{lib → src}/scheduler.ts +30 -35
- package/{lib → src}/signal.d.ts +1 -1
- package/{lib → src}/signal.ts +1 -1
- package/{lib → src}/state.ts +35 -34
- package/{lib → src}/util.d.ts +1 -1
- package/{lib → src}/util.ts +21 -11
- package/test/batch.test.ts +18 -19
- package/test/benchmark.test.ts +36 -36
- package/test/computed.test.ts +43 -42
- package/test/effect.test.ts +18 -21
- package/test/state.test.ts +15 -31
- 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 → src}/computed.d.ts +0 -0
- /package/{lib → src}/effect.d.ts +0 -0
- /package/{lib → src}/state.d.ts +0 -0
package/{lib → src}/signal.ts
RENAMED
|
@@ -21,7 +21,7 @@ const UNSET: any = Symbol()
|
|
|
21
21
|
* @param {unknown} value - value to check
|
|
22
22
|
* @returns {boolean} - true if value is a Signal, false otherwise
|
|
23
23
|
*/
|
|
24
|
-
const isSignal = /*#__PURE__*/ <T extends {}>(value:
|
|
24
|
+
const isSignal = /*#__PURE__*/ <T extends {}>(value: unknown): value is Signal<T> =>
|
|
25
25
|
isState(value) || isComputed(value)
|
|
26
26
|
|
|
27
27
|
/**
|
package/{lib → src}/state.ts
RENAMED
|
@@ -7,10 +7,10 @@ import { type TapMatcher, type EffectMatcher, effect } from './effect'
|
|
|
7
7
|
/* === Types === */
|
|
8
8
|
|
|
9
9
|
export type State<T extends {}> = {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
[Symbol.toStringTag]: 'State'
|
|
11
|
+
get(): T
|
|
12
|
+
set(v: T): void
|
|
13
|
+
update(fn: (v: T) => T): void
|
|
14
14
|
map<U extends {}>(fn: (v: T) => U | Promise<U>): Computed<U>
|
|
15
15
|
tap(matcher: TapMatcher<T> | ((v: T) => void | (() => void))): () => void
|
|
16
16
|
}
|
|
@@ -23,12 +23,14 @@ const TYPE_STATE = 'State'
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Create a new state signal
|
|
26
|
-
*
|
|
26
|
+
*
|
|
27
27
|
* @since 0.9.0
|
|
28
28
|
* @param {T} initialValue - initial value of the state
|
|
29
29
|
* @returns {State<T>} - new state signal
|
|
30
30
|
*/
|
|
31
|
-
export const state = /*#__PURE__*/ <T extends {}>(
|
|
31
|
+
export const state = /*#__PURE__*/ <T extends {}>(
|
|
32
|
+
initialValue: T,
|
|
33
|
+
): State<T> => {
|
|
32
34
|
const watchers: Set<Watcher> = new Set()
|
|
33
35
|
let value: T = initialValue
|
|
34
36
|
|
|
@@ -37,71 +39,69 @@ export const state = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> =>
|
|
|
37
39
|
|
|
38
40
|
/**
|
|
39
41
|
* Get the current value of the state
|
|
40
|
-
*
|
|
42
|
+
*
|
|
41
43
|
* @since 0.9.0
|
|
42
44
|
* @returns {T} - current value of the state
|
|
43
45
|
*/
|
|
44
|
-
|
|
46
|
+
get: (): T => {
|
|
45
47
|
subscribe(watchers)
|
|
46
|
-
|
|
48
|
+
return value
|
|
47
49
|
},
|
|
48
50
|
|
|
49
51
|
/**
|
|
50
52
|
* Set a new value of the state
|
|
51
|
-
*
|
|
53
|
+
*
|
|
52
54
|
* @since 0.9.0
|
|
53
55
|
* @param {T} v
|
|
54
56
|
* @returns {void}
|
|
55
57
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
set: (v: T): void => {
|
|
59
|
+
if (Object.is(value, v)) return
|
|
60
|
+
value = v
|
|
61
|
+
notify(watchers)
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
// Setting to UNSET clears the watchers so the signal can be garbage collected
|
|
64
|
+
if (UNSET === value) watchers.clear()
|
|
65
|
+
},
|
|
64
66
|
|
|
65
67
|
/**
|
|
66
68
|
* Update the state with a new value using a function
|
|
67
|
-
*
|
|
69
|
+
*
|
|
68
70
|
* @since 0.10.0
|
|
69
71
|
* @param {(v: T) => T} fn - function to update the state
|
|
70
72
|
* @returns {void} - updates the state with the result of the function
|
|
71
73
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
update: (fn: (v: T) => T): void => {
|
|
75
|
+
s.set(fn(value))
|
|
76
|
+
},
|
|
75
77
|
|
|
76
78
|
/**
|
|
77
79
|
* Create a computed signal from the current state signal
|
|
78
|
-
*
|
|
80
|
+
*
|
|
79
81
|
* @since 0.9.0
|
|
80
82
|
* @param {(v: T) => U | Promise<U>} fn - computed callback
|
|
81
83
|
* @returns {Computed<U>} - computed signal
|
|
82
84
|
*/
|
|
83
|
-
map: <U extends {}>(
|
|
84
|
-
fn: (v: T) => U | Promise<U>
|
|
85
|
-
): Computed<U> =>
|
|
85
|
+
map: <U extends {}>(fn: (v: T) => U | Promise<U>): Computed<U> =>
|
|
86
86
|
computed({
|
|
87
87
|
signals: [s],
|
|
88
|
-
ok: fn
|
|
88
|
+
ok: fn,
|
|
89
89
|
}),
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
92
|
* Case matching for the state signal with effect callbacks
|
|
93
|
-
*
|
|
93
|
+
*
|
|
94
94
|
* @since 0.13.0
|
|
95
95
|
* @param {TapMatcher<T> | ((v: T) => void | (() => void))} matcher - tap matcher or effect callback
|
|
96
96
|
* @returns {() => void} - cleanup function for the effect
|
|
97
97
|
*/
|
|
98
98
|
tap: (
|
|
99
|
-
matcher: TapMatcher<T> | ((v: T) => void | (() => void))
|
|
100
|
-
): () => void =>
|
|
99
|
+
matcher: TapMatcher<T> | ((v: T) => void | (() => void)),
|
|
100
|
+
): (() => void) =>
|
|
101
101
|
effect({
|
|
102
102
|
signals: [s],
|
|
103
|
-
...(isFunction(matcher) ? { ok: matcher } : matcher)
|
|
104
|
-
} as EffectMatcher<[State<T>]>)
|
|
103
|
+
...(isFunction(matcher) ? { ok: matcher } : matcher),
|
|
104
|
+
} as EffectMatcher<[State<T>]>),
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
return s
|
|
@@ -109,10 +109,11 @@ export const state = /*#__PURE__*/ <T extends {}>(initialValue: T): State<T> =>
|
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
111
|
* Check if the provided value is a State instance
|
|
112
|
-
*
|
|
112
|
+
*
|
|
113
113
|
* @since 0.9.0
|
|
114
114
|
* @param {unknown} value - value to check
|
|
115
115
|
* @returns {boolean} - true if the value is a State instance, false otherwise
|
|
116
116
|
*/
|
|
117
|
-
export const isState = /*#__PURE__*/ <T extends {}>(
|
|
118
|
-
|
|
117
|
+
export const isState = /*#__PURE__*/ <T extends {}>(
|
|
118
|
+
value: unknown,
|
|
119
|
+
): value is State<T> => isObjectOfType(value, TYPE_STATE)
|
package/{lib → src}/util.d.ts
RENAMED
|
@@ -8,4 +8,4 @@ declare const toError: (reason: unknown) => Error;
|
|
|
8
8
|
declare class CircularDependencyError extends Error {
|
|
9
9
|
constructor(where: string);
|
|
10
10
|
}
|
|
11
|
-
export { isFunction, isAsyncFunction, isObjectOfType, isError, isAbortError, isPromise, toError, CircularDependencyError };
|
|
11
|
+
export { isFunction, isAsyncFunction, isObjectOfType, isError, isAbortError, isPromise, toError, CircularDependencyError, };
|
package/{lib → src}/util.ts
RENAMED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/* === Utility Functions === */
|
|
2
2
|
|
|
3
|
-
const isFunction = /*#__PURE__*/ <T>(
|
|
4
|
-
|
|
3
|
+
const isFunction = /*#__PURE__*/ <T>(
|
|
4
|
+
value: unknown,
|
|
5
|
+
): value is (...args: unknown[]) => T => typeof value === 'function'
|
|
5
6
|
|
|
6
|
-
const isAsyncFunction = /*#__PURE__*/ <T>(
|
|
7
|
+
const isAsyncFunction = /*#__PURE__*/ <T>(
|
|
8
|
+
value: unknown,
|
|
9
|
+
): value is (...args: unknown[]) => Promise<T> =>
|
|
7
10
|
isFunction(value) && value.constructor.name === 'AsyncFunction'
|
|
8
11
|
|
|
9
|
-
const isObjectOfType = /*#__PURE__*/ <T>(
|
|
10
|
-
|
|
12
|
+
const isObjectOfType = /*#__PURE__*/ <T>(
|
|
13
|
+
value: unknown,
|
|
14
|
+
type: string,
|
|
15
|
+
): value is T => Object.prototype.toString.call(value) === `[object ${type}]`
|
|
11
16
|
|
|
12
17
|
const isError = /*#__PURE__*/ (value: unknown): value is Error =>
|
|
13
18
|
value instanceof Error
|
|
@@ -20,13 +25,18 @@ const toError = (reason: unknown): Error =>
|
|
|
20
25
|
|
|
21
26
|
class CircularDependencyError extends Error {
|
|
22
27
|
constructor(where: string) {
|
|
23
|
-
|
|
28
|
+
super(`Circular dependency in ${where} detected`)
|
|
24
29
|
return this
|
|
25
|
-
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
export {
|
|
29
|
-
isFunction,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
isFunction,
|
|
35
|
+
isAsyncFunction,
|
|
36
|
+
isObjectOfType,
|
|
37
|
+
isError,
|
|
38
|
+
isAbortError,
|
|
39
|
+
isPromise,
|
|
40
|
+
toError,
|
|
41
|
+
CircularDependencyError,
|
|
42
|
+
}
|
package/test/batch.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect } from 'bun:test'
|
|
2
|
-
import { state, computed,
|
|
2
|
+
import { state, computed, batch } from '../'
|
|
3
3
|
|
|
4
4
|
/* === Utility Functions === */
|
|
5
5
|
|
|
@@ -8,8 +8,7 @@ const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
|
|
|
8
8
|
/* === Tests === */
|
|
9
9
|
|
|
10
10
|
describe('Batch', function () {
|
|
11
|
-
|
|
12
|
-
test('should be triggered only once after repeated state change', function() {
|
|
11
|
+
test('should be triggered only once after repeated state change', function () {
|
|
13
12
|
const cause = state(0)
|
|
14
13
|
let result = 0
|
|
15
14
|
let count = 0
|
|
@@ -23,10 +22,10 @@ describe('Batch', function () {
|
|
|
23
22
|
}
|
|
24
23
|
})
|
|
25
24
|
expect(result).toBe(10)
|
|
26
|
-
expect(count).toBe(2)
|
|
25
|
+
expect(count).toBe(2) // + 1 for effect initialization
|
|
27
26
|
})
|
|
28
27
|
|
|
29
|
-
test('should be triggered only once when multiple signals are set', function() {
|
|
28
|
+
test('should be triggered only once when multiple signals are set', function () {
|
|
30
29
|
const a = state(3)
|
|
31
30
|
const b = state(4)
|
|
32
31
|
const c = state(5)
|
|
@@ -46,25 +45,26 @@ describe('Batch', function () {
|
|
|
46
45
|
c.set(10)
|
|
47
46
|
})
|
|
48
47
|
expect(result).toBe(24)
|
|
49
|
-
expect(count).toBe(2)
|
|
48
|
+
expect(count).toBe(2) // + 1 for effect initialization
|
|
50
49
|
})
|
|
51
50
|
|
|
52
|
-
test('should prove example from README works', function() {
|
|
53
|
-
|
|
51
|
+
test('should prove example from README works', function () {
|
|
54
52
|
// State: define an array of Signal<number>
|
|
55
53
|
const signals = [state(2), state(3), state(5)]
|
|
56
54
|
|
|
57
55
|
// Computed: derive a calculation ...
|
|
58
|
-
const sum = computed(() =>
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
const sum = computed(() =>
|
|
57
|
+
signals.reduce((total, v) => total + v.get(), 0),
|
|
58
|
+
).map(v => {
|
|
59
|
+
// ... perform validation and handle errors
|
|
60
|
+
if (!Number.isFinite(v)) throw new Error('Invalid value')
|
|
61
|
+
return v
|
|
62
|
+
})
|
|
63
63
|
|
|
64
64
|
let result = 0
|
|
65
65
|
let okCount = 0
|
|
66
66
|
let errCount = 0
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
// Effect: switch cases for the result
|
|
69
69
|
sum.tap({
|
|
70
70
|
ok: v => {
|
|
@@ -75,7 +75,7 @@ describe('Batch', function () {
|
|
|
75
75
|
err: _error => {
|
|
76
76
|
errCount++
|
|
77
77
|
// console.error('Error:', error)
|
|
78
|
-
}
|
|
78
|
+
},
|
|
79
79
|
})
|
|
80
80
|
|
|
81
81
|
expect(okCount).toBe(1)
|
|
@@ -92,9 +92,8 @@ describe('Batch', function () {
|
|
|
92
92
|
// Provoke an error
|
|
93
93
|
signals[0].set(NaN)
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
expect(okCount).toBe(2)
|
|
97
|
-
|
|
95
|
+
expect(errCount).toBe(1)
|
|
96
|
+
expect(okCount).toBe(2) // should not have changed due to error
|
|
97
|
+
expect(result).toBe(20) // should not have changed due to error
|
|
98
98
|
})
|
|
99
|
-
|
|
100
99
|
})
|
package/test/benchmark.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, test, expect, mock } from 'bun:test'
|
|
2
2
|
import { state, computed, effect, batch } from '../'
|
|
3
|
-
import { makeGraph, runGraph, Counter } from
|
|
3
|
+
import { makeGraph, runGraph, Counter } from './util/dependency-graph'
|
|
4
4
|
|
|
5
5
|
/* === Utility Functions === */
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ const busy = () => {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const framework = {
|
|
15
|
-
name:
|
|
15
|
+
name: 'Cause & Effect',
|
|
16
16
|
signal: <T extends {}>(initialValue: T) => {
|
|
17
17
|
const s = state<T>(initialValue)
|
|
18
18
|
return {
|
|
@@ -45,7 +45,7 @@ function makeConfig() {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/* === Test functions === */
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
/** some basic tests to validate the reactive framework
|
|
50
50
|
* wrapper works and can run performance tests.
|
|
51
51
|
*/
|
|
@@ -55,24 +55,24 @@ describe('Basic test', function () {
|
|
|
55
55
|
framework.withBuild(() => {
|
|
56
56
|
const s = framework.signal(2)
|
|
57
57
|
const c = framework.computed(() => s.read() * 2)
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
expect(c.read()).toEqual(4)
|
|
60
60
|
})
|
|
61
61
|
})
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
test(`${name} | simple write`, () => {
|
|
64
64
|
framework.withBuild(() => {
|
|
65
65
|
const s = framework.signal(2)
|
|
66
66
|
const c = framework.computed(() => s.read() * 2)
|
|
67
67
|
expect(s.read()).toEqual(2)
|
|
68
68
|
expect(c.read()).toEqual(4)
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
s.write(3)
|
|
71
71
|
expect(s.read()).toEqual(3)
|
|
72
72
|
expect(c.read()).toEqual(6)
|
|
73
73
|
})
|
|
74
74
|
})
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
test(`${name} | static graph`, () => {
|
|
77
77
|
const config = makeConfig()
|
|
78
78
|
const counter = new Counter()
|
|
@@ -87,7 +87,7 @@ describe('Basic test', function () {
|
|
|
87
87
|
expect(counter.count).toBeGreaterThanOrEqual(11)
|
|
88
88
|
}
|
|
89
89
|
})
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
test(`${name} | static graph, read 2/3 of leaves`, () => {
|
|
92
92
|
framework.withBuild(() => {
|
|
93
93
|
const config = makeConfig()
|
|
@@ -98,7 +98,7 @@ describe('Basic test', function () {
|
|
|
98
98
|
const graph = makeGraph(framework, config, counter)
|
|
99
99
|
// @ts-expect-error
|
|
100
100
|
const sum = runGraph(graph, 10, 2 / 3, framework)
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
expect(sum).toEqual(71)
|
|
103
103
|
if (testPullCounts) {
|
|
104
104
|
expect(counter.count).toEqual(41)
|
|
@@ -107,7 +107,7 @@ describe('Basic test', function () {
|
|
|
107
107
|
}
|
|
108
108
|
})
|
|
109
109
|
})
|
|
110
|
-
|
|
110
|
+
|
|
111
111
|
test(`${name} | dynamic graph`, () => {
|
|
112
112
|
framework.withBuild(() => {
|
|
113
113
|
const config = makeConfig()
|
|
@@ -119,7 +119,7 @@ describe('Basic test', function () {
|
|
|
119
119
|
const graph = makeGraph(framework, config, counter)
|
|
120
120
|
// @ts-expect-error
|
|
121
121
|
const sum = runGraph(graph, 10, 1, framework)
|
|
122
|
-
|
|
122
|
+
|
|
123
123
|
expect(sum).toEqual(72)
|
|
124
124
|
if (testPullCounts) {
|
|
125
125
|
expect(counter.count).toEqual(22)
|
|
@@ -128,38 +128,38 @@ describe('Basic test', function () {
|
|
|
128
128
|
}
|
|
129
129
|
})
|
|
130
130
|
})
|
|
131
|
-
|
|
131
|
+
|
|
132
132
|
test(`${name} | withBuild`, () => {
|
|
133
133
|
const r = framework.withBuild(() => {
|
|
134
134
|
const s = framework.signal(2)
|
|
135
135
|
const c = framework.computed(() => s.read() * 2)
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
expect(c.read()).toEqual(4)
|
|
138
138
|
return c.read()
|
|
139
139
|
})
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
// @ts-expect-error
|
|
142
142
|
expect(r).toEqual(4)
|
|
143
143
|
})
|
|
144
|
-
|
|
144
|
+
|
|
145
145
|
test(`${name} | effect`, () => {
|
|
146
|
-
const spy =
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
const spy = _v => {}
|
|
147
|
+
const spyMock = mock(spy)
|
|
148
|
+
|
|
149
149
|
const s = framework.signal(2)
|
|
150
150
|
let c: any
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
framework.withBuild(() => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
c = framework.computed(() => s.read() * 2)
|
|
154
|
+
|
|
155
|
+
framework.effect(() => {
|
|
156
|
+
spyMock(c.read())
|
|
157
|
+
})
|
|
158
158
|
})
|
|
159
159
|
expect(spyMock.mock.calls.length).toBe(1)
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
framework.withBatch(() => {
|
|
162
|
-
|
|
162
|
+
s.write(3)
|
|
163
163
|
})
|
|
164
164
|
expect(s.read()).toEqual(3)
|
|
165
165
|
expect(c.read()).toEqual(6)
|
|
@@ -174,12 +174,14 @@ describe('Kairo tests', function () {
|
|
|
174
174
|
const head = framework.signal(0)
|
|
175
175
|
const computed1 = framework.computed(() => head.read())
|
|
176
176
|
const computed2 = framework.computed(() => (computed1.read(), 0))
|
|
177
|
-
const computed3 = framework.computed(
|
|
177
|
+
const computed3 = framework.computed(
|
|
178
|
+
() => (busy(), computed2.read()! + 1),
|
|
179
|
+
) // heavy computation
|
|
178
180
|
const computed4 = framework.computed(() => computed3.read()! + 2)
|
|
179
181
|
const computed5 = framework.computed(() => computed4.read()! + 3)
|
|
180
182
|
framework.effect(() => {
|
|
181
183
|
computed5.read()
|
|
182
|
-
busy()
|
|
184
|
+
busy() // heavy side effect
|
|
183
185
|
})
|
|
184
186
|
|
|
185
187
|
return () => {
|
|
@@ -268,9 +270,7 @@ describe('Kairo tests', function () {
|
|
|
268
270
|
const head = framework.signal(0)
|
|
269
271
|
let current: { read(): number }[] = []
|
|
270
272
|
for (let i = 0; i < width; i++) {
|
|
271
|
-
current.push(
|
|
272
|
-
framework.computed(() => head.read() + 1)
|
|
273
|
-
)
|
|
273
|
+
current.push(framework.computed(() => head.read() + 1))
|
|
274
274
|
}
|
|
275
275
|
let sum = framework.computed(() => {
|
|
276
276
|
return current.map(x => x.read()).reduce((a, b) => a + b, 0)
|
|
@@ -299,15 +299,15 @@ describe('Kairo tests', function () {
|
|
|
299
299
|
})
|
|
300
300
|
|
|
301
301
|
test(`${name} | mux`, function () {
|
|
302
|
-
let heads = new Array(100).fill(null).map(
|
|
302
|
+
let heads = new Array(100).fill(null).map(_ => framework.signal(0))
|
|
303
303
|
const mux = framework.computed(() => {
|
|
304
|
-
return Object.fromEntries(heads.map(
|
|
304
|
+
return Object.fromEntries(heads.map(h => h.read()).entries())
|
|
305
305
|
})
|
|
306
306
|
const splited = heads
|
|
307
307
|
.map((_, index) => framework.computed(() => mux.read()[index]))
|
|
308
|
-
.map(
|
|
308
|
+
.map(x => framework.computed(() => x.read() + 1))
|
|
309
309
|
|
|
310
|
-
splited.forEach(
|
|
310
|
+
splited.forEach(x => {
|
|
311
311
|
framework.effect(() => x.read())
|
|
312
312
|
})
|
|
313
313
|
|
|
@@ -373,7 +373,7 @@ describe('Kairo tests', function () {
|
|
|
373
373
|
})
|
|
374
374
|
}
|
|
375
375
|
let sum = framework.computed(() => {
|
|
376
|
-
return list.map(
|
|
376
|
+
return list.map(x => x.read()).reduce((a, b) => a + b, 0)
|
|
377
377
|
})
|
|
378
378
|
let callCounter = new Counter()
|
|
379
379
|
framework.effect(() => {
|