@zeix/cause-effect 0.14.0 → 0.14.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 +68 -72
- package/biome.json +35 -0
- package/index.d.ts +6 -8
- package/index.dev.js +294 -0
- package/index.js +1 -1
- package/index.ts +26 -14
- package/package.json +5 -6
- package/src/computed.d.ts +11 -9
- package/src/computed.ts +138 -14
- package/src/effect.d.ts +7 -9
- package/src/effect.ts +43 -58
- package/src/scheduler.d.ts +15 -6
- package/src/scheduler.ts +39 -16
- package/src/signal.d.ts +5 -10
- package/src/signal.ts +10 -15
- package/src/state.d.ts +2 -1
- package/src/state.ts +1 -1
- package/src/util.d.ts +1 -5
- package/src/util.ts +3 -23
- package/test/batch.test.ts +13 -13
- package/test/benchmark.test.ts +79 -43
- package/test/computed.test.ts +76 -78
- package/test/effect.test.ts +24 -24
- package/test/state.test.ts +33 -33
- package/test/util/framework-types.ts +2 -2
- package/test/util/perf-tests.ts +2 -2
- package/test/util/reactive-framework.ts +1 -1
- package/src/memo.d.ts +0 -13
- package/src/memo.ts +0 -91
- package/src/task.d.ts +0 -17
- package/src/task.ts +0 -153
package/test/state.test.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { describe,
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
2
|
import { isComputed, isState, state } from '../'
|
|
3
3
|
|
|
4
4
|
/* === Tests === */
|
|
5
5
|
|
|
6
|
-
describe('State',
|
|
6
|
+
describe('State', () => {
|
|
7
7
|
describe('State type guard', () => {
|
|
8
8
|
test('isState identifies state signals', () => {
|
|
9
9
|
const count = state(42)
|
|
@@ -12,108 +12,108 @@ describe('State', function () {
|
|
|
12
12
|
})
|
|
13
13
|
})
|
|
14
14
|
|
|
15
|
-
describe('Boolean cause',
|
|
16
|
-
test('should be boolean',
|
|
15
|
+
describe('Boolean cause', () => {
|
|
16
|
+
test('should be boolean', () => {
|
|
17
17
|
const cause = state(false)
|
|
18
18
|
expect(typeof cause.get()).toBe('boolean')
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
test('should set initial value to false',
|
|
21
|
+
test('should set initial value to false', () => {
|
|
22
22
|
const cause = state(false)
|
|
23
23
|
expect(cause.get()).toBe(false)
|
|
24
24
|
})
|
|
25
25
|
|
|
26
|
-
test('should set initial value to true',
|
|
26
|
+
test('should set initial value to true', () => {
|
|
27
27
|
const cause = state(true)
|
|
28
28
|
expect(cause.get()).toBe(true)
|
|
29
29
|
})
|
|
30
30
|
|
|
31
|
-
test('should set new value with .set(true)',
|
|
31
|
+
test('should set new value with .set(true)', () => {
|
|
32
32
|
const cause = state(false)
|
|
33
33
|
cause.set(true)
|
|
34
34
|
expect(cause.get()).toBe(true)
|
|
35
35
|
})
|
|
36
36
|
|
|
37
|
-
test('should toggle initial value with .set(v => !v)',
|
|
37
|
+
test('should toggle initial value with .set(v => !v)', () => {
|
|
38
38
|
const cause = state(false)
|
|
39
39
|
cause.update(v => !v)
|
|
40
40
|
expect(cause.get()).toBe(true)
|
|
41
41
|
})
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
describe('Number cause',
|
|
45
|
-
test('should be number',
|
|
44
|
+
describe('Number cause', () => {
|
|
45
|
+
test('should be number', () => {
|
|
46
46
|
const cause = state(0)
|
|
47
47
|
expect(typeof cause.get()).toBe('number')
|
|
48
48
|
})
|
|
49
49
|
|
|
50
|
-
test('should set initial value to 0',
|
|
50
|
+
test('should set initial value to 0', () => {
|
|
51
51
|
const cause = state(0)
|
|
52
52
|
expect(cause.get()).toBe(0)
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
test('should set new value with .set(42)',
|
|
55
|
+
test('should set new value with .set(42)', () => {
|
|
56
56
|
const cause = state(0)
|
|
57
57
|
cause.set(42)
|
|
58
58
|
expect(cause.get()).toBe(42)
|
|
59
59
|
})
|
|
60
60
|
|
|
61
|
-
test('should increment value with .set(v => ++v)',
|
|
61
|
+
test('should increment value with .set(v => ++v)', () => {
|
|
62
62
|
const cause = state(0)
|
|
63
63
|
cause.update(v => ++v)
|
|
64
64
|
expect(cause.get()).toBe(1)
|
|
65
65
|
})
|
|
66
66
|
})
|
|
67
67
|
|
|
68
|
-
describe('String cause',
|
|
69
|
-
test('should be string',
|
|
68
|
+
describe('String cause', () => {
|
|
69
|
+
test('should be string', () => {
|
|
70
70
|
const cause = state('foo')
|
|
71
71
|
expect(typeof cause.get()).toBe('string')
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
test('should set initial value to "foo"',
|
|
74
|
+
test('should set initial value to "foo"', () => {
|
|
75
75
|
const cause = state('foo')
|
|
76
76
|
expect(cause.get()).toBe('foo')
|
|
77
77
|
})
|
|
78
78
|
|
|
79
|
-
test('should set new value with .set("bar")',
|
|
79
|
+
test('should set new value with .set("bar")', () => {
|
|
80
80
|
const cause = state('foo')
|
|
81
81
|
cause.set('bar')
|
|
82
82
|
expect(cause.get()).toBe('bar')
|
|
83
83
|
})
|
|
84
84
|
|
|
85
|
-
test('should upper case value with .set(v => v.toUpperCase())',
|
|
85
|
+
test('should upper case value with .set(v => v.toUpperCase())', () => {
|
|
86
86
|
const cause = state('foo')
|
|
87
87
|
cause.update(v => (v ? v.toUpperCase() : ''))
|
|
88
88
|
expect(cause.get()).toBe('FOO')
|
|
89
89
|
})
|
|
90
90
|
})
|
|
91
91
|
|
|
92
|
-
describe('Array cause',
|
|
93
|
-
test('should be array',
|
|
92
|
+
describe('Array cause', () => {
|
|
93
|
+
test('should be array', () => {
|
|
94
94
|
const cause = state([1, 2, 3])
|
|
95
95
|
expect(Array.isArray(cause.get())).toBe(true)
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
test('should set initial value to [1, 2, 3]',
|
|
98
|
+
test('should set initial value to [1, 2, 3]', () => {
|
|
99
99
|
const cause = state([1, 2, 3])
|
|
100
100
|
expect(cause.get()).toEqual([1, 2, 3])
|
|
101
101
|
})
|
|
102
102
|
|
|
103
|
-
test('should set new value with .set([4, 5, 6])',
|
|
103
|
+
test('should set new value with .set([4, 5, 6])', () => {
|
|
104
104
|
const cause = state([1, 2, 3])
|
|
105
105
|
cause.set([4, 5, 6])
|
|
106
106
|
expect(cause.get()).toEqual([4, 5, 6])
|
|
107
107
|
})
|
|
108
108
|
|
|
109
|
-
test('should reflect current value of array after modification',
|
|
109
|
+
test('should reflect current value of array after modification', () => {
|
|
110
110
|
const array = [1, 2, 3]
|
|
111
111
|
const cause = state(array)
|
|
112
112
|
array.push(4) // don't do this! the result will be correct, but we can't trigger effects
|
|
113
113
|
expect(cause.get()).toEqual([1, 2, 3, 4])
|
|
114
114
|
})
|
|
115
115
|
|
|
116
|
-
test('should set new value with .set([...array, 4])',
|
|
116
|
+
test('should set new value with .set([...array, 4])', () => {
|
|
117
117
|
const array = [1, 2, 3]
|
|
118
118
|
const cause = state(array)
|
|
119
119
|
cause.set([...array, 4]) // use destructuring instead!
|
|
@@ -121,34 +121,34 @@ describe('State', function () {
|
|
|
121
121
|
})
|
|
122
122
|
})
|
|
123
123
|
|
|
124
|
-
describe('Object cause',
|
|
125
|
-
test('should be object',
|
|
124
|
+
describe('Object cause', () => {
|
|
125
|
+
test('should be object', () => {
|
|
126
126
|
const cause = state({ a: 'a', b: 1 })
|
|
127
127
|
expect(typeof cause.get()).toBe('object')
|
|
128
128
|
})
|
|
129
129
|
|
|
130
|
-
test('should set initial value to { a: "a", b: 1 }',
|
|
130
|
+
test('should set initial value to { a: "a", b: 1 }', () => {
|
|
131
131
|
const cause = state({ a: 'a', b: 1 })
|
|
132
132
|
expect(cause.get()).toEqual({ a: 'a', b: 1 })
|
|
133
133
|
})
|
|
134
134
|
|
|
135
|
-
test('should set new value with .set({ c: true })',
|
|
136
|
-
const cause = state<Record<string,
|
|
135
|
+
test('should set new value with .set({ c: true })', () => {
|
|
136
|
+
const cause = state<Record<string, unknown>>({ a: 'a', b: 1 })
|
|
137
137
|
cause.set({ c: true })
|
|
138
138
|
expect(cause.get()).toEqual({ c: true })
|
|
139
139
|
})
|
|
140
140
|
|
|
141
|
-
test('should reflect current value of object after modification',
|
|
141
|
+
test('should reflect current value of object after modification', () => {
|
|
142
142
|
const obj = { a: 'a', b: 1 }
|
|
143
|
-
const cause = state<Record<string,
|
|
143
|
+
const cause = state<Record<string, unknown>>(obj)
|
|
144
144
|
// @ts-expect-error Property 'c' does not exist on type '{ a: string; b: number; }'. (ts 2339)
|
|
145
145
|
obj.c = true // don't do this! the result will be correct, but we can't trigger effects
|
|
146
146
|
expect(cause.get()).toEqual({ a: 'a', b: 1, c: true })
|
|
147
147
|
})
|
|
148
148
|
|
|
149
|
-
test('should set new value with .set({...obj, c: true})',
|
|
149
|
+
test('should set new value with .set({...obj, c: true})', () => {
|
|
150
150
|
const obj = { a: 'a', b: 1 }
|
|
151
|
-
const cause = state<Record<string,
|
|
151
|
+
const cause = state<Record<string, unknown>>(obj)
|
|
152
152
|
cause.set({ ...obj, c: true }) // use destructuring instead!
|
|
153
153
|
expect(cause.get()).toEqual({ a: 'a', b: 1, c: true })
|
|
154
154
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TestResult } from './perf-tests'
|
|
2
|
-
import { ReactiveFramework } from './reactive-framework'
|
|
1
|
+
import type { TestResult } from './perf-tests'
|
|
2
|
+
import type { ReactiveFramework } from './reactive-framework'
|
|
3
3
|
|
|
4
4
|
/** Parameters for a running a performance benchmark test
|
|
5
5
|
*
|
package/test/util/perf-tests.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FrameworkInfo, TestConfig } from './framework-types'
|
|
1
|
+
import type { FrameworkInfo, TestConfig } from './framework-types'
|
|
2
2
|
|
|
3
3
|
export interface TestResult {
|
|
4
4
|
sum: number
|
|
@@ -25,7 +25,7 @@ export function verifyBenchResult(
|
|
|
25
25
|
|
|
26
26
|
if (expected.sum) {
|
|
27
27
|
console.assert(
|
|
28
|
-
result.sum
|
|
28
|
+
result.sum === expected.sum,
|
|
29
29
|
`sum ${framework.name} ${config.name} result:${result.sum} expected:${expected.sum}`,
|
|
30
30
|
)
|
|
31
31
|
}
|
|
@@ -6,7 +6,7 @@ export interface ReactiveFramework {
|
|
|
6
6
|
name: string
|
|
7
7
|
signal<T>(initialValue: T): Signal<T>
|
|
8
8
|
computed<T>(fn: () => T): Computed<T>
|
|
9
|
-
effect(fn: () =>
|
|
9
|
+
effect(fn: () => undefined): void
|
|
10
10
|
withBatch<T>(fn: () => T): void
|
|
11
11
|
withBuild<T>(fn: () => T): T
|
|
12
12
|
}
|
package/src/memo.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { type Computed } from './computed';
|
|
2
|
-
type MemoCallback<T extends {} & {
|
|
3
|
-
then?: void;
|
|
4
|
-
}> = () => T;
|
|
5
|
-
/**
|
|
6
|
-
* Create a derived signal for synchronous computations
|
|
7
|
-
*
|
|
8
|
-
* @since 0.14.0
|
|
9
|
-
* @param {MemoCallback<T>} fn - synchronous computation callback
|
|
10
|
-
* @returns {Computed<T>} - Computed signal
|
|
11
|
-
*/
|
|
12
|
-
declare const memo: <T extends {}>(fn: MemoCallback<T>) => Computed<T>;
|
|
13
|
-
export { type MemoCallback, memo };
|
package/src/memo.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { UNSET } from './signal'
|
|
2
|
-
import { CircularDependencyError } from './util'
|
|
3
|
-
import {
|
|
4
|
-
type Cleanup,
|
|
5
|
-
type Watcher,
|
|
6
|
-
flush,
|
|
7
|
-
notify,
|
|
8
|
-
subscribe,
|
|
9
|
-
watch,
|
|
10
|
-
} from './scheduler'
|
|
11
|
-
import { type Computed, TYPE_COMPUTED } from './computed'
|
|
12
|
-
|
|
13
|
-
/* === Types === */
|
|
14
|
-
|
|
15
|
-
type MemoCallback<T extends {} & { then?: void }> = () => T
|
|
16
|
-
|
|
17
|
-
/* === Functions === */
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Create a derived signal for synchronous computations
|
|
21
|
-
*
|
|
22
|
-
* @since 0.14.0
|
|
23
|
-
* @param {MemoCallback<T>} fn - synchronous computation callback
|
|
24
|
-
* @returns {Computed<T>} - Computed signal
|
|
25
|
-
*/
|
|
26
|
-
const memo = <T extends {}>(fn: MemoCallback<T>): Computed<T> => {
|
|
27
|
-
const watchers: Set<Watcher> = new Set()
|
|
28
|
-
|
|
29
|
-
// Internal state - simplified for sync only
|
|
30
|
-
let value: T = UNSET
|
|
31
|
-
let error: Error | undefined
|
|
32
|
-
let dirty = true
|
|
33
|
-
let computing = false
|
|
34
|
-
|
|
35
|
-
// Called when notified from sources (push)
|
|
36
|
-
const mark = (() => {
|
|
37
|
-
dirty = true
|
|
38
|
-
if (watchers.size) {
|
|
39
|
-
notify(watchers)
|
|
40
|
-
} else {
|
|
41
|
-
mark.cleanups.forEach(fn => fn())
|
|
42
|
-
mark.cleanups.clear()
|
|
43
|
-
}
|
|
44
|
-
}) as Watcher
|
|
45
|
-
mark.cleanups = new Set<Cleanup>()
|
|
46
|
-
|
|
47
|
-
// Called when requested by dependencies (pull)
|
|
48
|
-
const compute = () =>
|
|
49
|
-
watch(() => {
|
|
50
|
-
if (computing) throw new CircularDependencyError('memo')
|
|
51
|
-
computing = true
|
|
52
|
-
try {
|
|
53
|
-
const result = fn()
|
|
54
|
-
if (null == result || UNSET === result) {
|
|
55
|
-
value = UNSET
|
|
56
|
-
error = undefined
|
|
57
|
-
} else {
|
|
58
|
-
value = result
|
|
59
|
-
dirty = false
|
|
60
|
-
error = undefined
|
|
61
|
-
}
|
|
62
|
-
} catch (e) {
|
|
63
|
-
value = UNSET
|
|
64
|
-
error = e instanceof Error ? e : new Error(String(e))
|
|
65
|
-
} finally {
|
|
66
|
-
computing = false
|
|
67
|
-
}
|
|
68
|
-
}, mark)
|
|
69
|
-
|
|
70
|
-
const c: Computed<T> = {
|
|
71
|
-
[Symbol.toStringTag]: TYPE_COMPUTED,
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Get the current value of the computed
|
|
75
|
-
*
|
|
76
|
-
* @returns {T} - current value of the computed
|
|
77
|
-
*/
|
|
78
|
-
get: (): T => {
|
|
79
|
-
subscribe(watchers)
|
|
80
|
-
flush()
|
|
81
|
-
if (dirty) compute()
|
|
82
|
-
if (error) throw error
|
|
83
|
-
return value
|
|
84
|
-
},
|
|
85
|
-
}
|
|
86
|
-
return c
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/* === Exports === */
|
|
90
|
-
|
|
91
|
-
export { type MemoCallback, memo }
|
package/src/task.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type Computed } from './computed';
|
|
2
|
-
/**
|
|
3
|
-
* Callback for async computation tasks
|
|
4
|
-
* This explicitly returns a Promise<T> to differentiate from MemoCallback
|
|
5
|
-
*
|
|
6
|
-
* @since 0.14.0
|
|
7
|
-
*/
|
|
8
|
-
type TaskCallback<T extends {}> = (abort: AbortSignal) => Promise<T>;
|
|
9
|
-
/**
|
|
10
|
-
* Create a derived signal that supports asynchronous computations
|
|
11
|
-
*
|
|
12
|
-
* @since 0.14.0
|
|
13
|
-
* @param {TaskCallback<T>} fn - async computation callback
|
|
14
|
-
* @returns {Computed<T>} - Computed signal
|
|
15
|
-
*/
|
|
16
|
-
declare const task: <T extends {}>(fn: TaskCallback<T>) => Computed<T>;
|
|
17
|
-
export { type TaskCallback, task };
|
package/src/task.ts
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { UNSET } from './signal'
|
|
2
|
-
import {
|
|
3
|
-
CircularDependencyError,
|
|
4
|
-
isAbortError,
|
|
5
|
-
isPromise,
|
|
6
|
-
toError,
|
|
7
|
-
} from './util'
|
|
8
|
-
import {
|
|
9
|
-
type Cleanup,
|
|
10
|
-
type Watcher,
|
|
11
|
-
flush,
|
|
12
|
-
notify,
|
|
13
|
-
subscribe,
|
|
14
|
-
watch,
|
|
15
|
-
} from './scheduler'
|
|
16
|
-
import {
|
|
17
|
-
type Computed,
|
|
18
|
-
TYPE_COMPUTED,
|
|
19
|
-
} from './computed'
|
|
20
|
-
|
|
21
|
-
/* === Types === */
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Callback for async computation tasks
|
|
25
|
-
* This explicitly returns a Promise<T> to differentiate from MemoCallback
|
|
26
|
-
*
|
|
27
|
-
* @since 0.14.0
|
|
28
|
-
*/
|
|
29
|
-
type TaskCallback<T extends {}> = (abort: AbortSignal) => Promise<T>
|
|
30
|
-
|
|
31
|
-
/* === Function === */
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Create a derived signal that supports asynchronous computations
|
|
35
|
-
*
|
|
36
|
-
* @since 0.14.0
|
|
37
|
-
* @param {TaskCallback<T>} fn - async computation callback
|
|
38
|
-
* @returns {Computed<T>} - Computed signal
|
|
39
|
-
*/
|
|
40
|
-
const task = <T extends {}>(fn: TaskCallback<T>): Computed<T> => {
|
|
41
|
-
const watchers: Set<Watcher> = new Set()
|
|
42
|
-
|
|
43
|
-
// Internal state
|
|
44
|
-
let value: T = UNSET
|
|
45
|
-
let error: Error | undefined
|
|
46
|
-
let dirty = true
|
|
47
|
-
let changed = false
|
|
48
|
-
let computing = false
|
|
49
|
-
let controller: AbortController | undefined
|
|
50
|
-
|
|
51
|
-
// Functions to update internal state
|
|
52
|
-
const ok = (v: T) => {
|
|
53
|
-
if (!Object.is(v, value)) {
|
|
54
|
-
value = v
|
|
55
|
-
dirty = false
|
|
56
|
-
error = undefined
|
|
57
|
-
changed = true
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const nil = () => {
|
|
61
|
-
changed = UNSET !== value
|
|
62
|
-
value = UNSET
|
|
63
|
-
error = undefined
|
|
64
|
-
}
|
|
65
|
-
const err = (e: unknown) => {
|
|
66
|
-
const newError = toError(e)
|
|
67
|
-
changed = !(
|
|
68
|
-
error &&
|
|
69
|
-
newError.name === error.name &&
|
|
70
|
-
newError.message === error.message
|
|
71
|
-
)
|
|
72
|
-
value = UNSET
|
|
73
|
-
error = newError
|
|
74
|
-
}
|
|
75
|
-
const resolve = (v: T) => {
|
|
76
|
-
computing = false
|
|
77
|
-
controller = undefined
|
|
78
|
-
ok(v)
|
|
79
|
-
if (changed) notify(watchers)
|
|
80
|
-
}
|
|
81
|
-
const reject = (e: unknown) => {
|
|
82
|
-
computing = false
|
|
83
|
-
controller = undefined
|
|
84
|
-
err(e)
|
|
85
|
-
if (changed) notify(watchers)
|
|
86
|
-
}
|
|
87
|
-
const abort = () => {
|
|
88
|
-
computing = false
|
|
89
|
-
controller = undefined
|
|
90
|
-
compute() // retry
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Called when notified from sources (push)
|
|
94
|
-
const mark = (() => {
|
|
95
|
-
dirty = true
|
|
96
|
-
controller?.abort('Aborted because source signal changed')
|
|
97
|
-
if (watchers.size) {
|
|
98
|
-
notify(watchers)
|
|
99
|
-
} else {
|
|
100
|
-
mark.cleanups.forEach(fn => fn())
|
|
101
|
-
mark.cleanups.clear()
|
|
102
|
-
}
|
|
103
|
-
}) as Watcher
|
|
104
|
-
mark.cleanups = new Set<Cleanup>()
|
|
105
|
-
|
|
106
|
-
// Called when requested by dependencies (pull)
|
|
107
|
-
const compute = () =>
|
|
108
|
-
watch(() => {
|
|
109
|
-
if (computing) throw new CircularDependencyError('task')
|
|
110
|
-
changed = false
|
|
111
|
-
controller = new AbortController()
|
|
112
|
-
controller.signal.addEventListener('abort', abort, {
|
|
113
|
-
once: true,
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
let result: T | Promise<T>
|
|
117
|
-
computing = true
|
|
118
|
-
try {
|
|
119
|
-
result = fn(controller.signal)
|
|
120
|
-
} catch (e) {
|
|
121
|
-
if (isAbortError(e)) nil()
|
|
122
|
-
else err(e)
|
|
123
|
-
computing = false
|
|
124
|
-
return
|
|
125
|
-
}
|
|
126
|
-
if (isPromise(result)) result.then(resolve, reject)
|
|
127
|
-
else if (null == result || UNSET === result) nil()
|
|
128
|
-
else ok(result)
|
|
129
|
-
computing = false
|
|
130
|
-
}, mark)
|
|
131
|
-
|
|
132
|
-
const c: Computed<T> = {
|
|
133
|
-
[Symbol.toStringTag]: TYPE_COMPUTED,
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Get the current value of the computed
|
|
137
|
-
*
|
|
138
|
-
* @returns {T} - current value of the computed
|
|
139
|
-
*/
|
|
140
|
-
get: (): T => {
|
|
141
|
-
subscribe(watchers)
|
|
142
|
-
flush()
|
|
143
|
-
if (dirty) compute()
|
|
144
|
-
if (error) throw error
|
|
145
|
-
return value
|
|
146
|
-
},
|
|
147
|
-
}
|
|
148
|
-
return c
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/* === Exports === */
|
|
152
|
-
|
|
153
|
-
export { type TaskCallback, task }
|