@planet-matrix/mobius-model 0.1.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/.oxlintrc.json +5 -0
- package/CHANGELOG.md +13 -0
- package/README.md +5 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +13 -0
- package/dist/signal-core/flags.d.ts +99 -0
- package/dist/signal-core/flags.d.ts.map +1 -0
- package/dist/signal-core/index.d.ts +4 -0
- package/dist/signal-core/index.d.ts.map +1 -0
- package/dist/signal-core/primitive.d.ts +67 -0
- package/dist/signal-core/primitive.d.ts.map +1 -0
- package/dist/signal-core/reactive-system.d.ts +161 -0
- package/dist/signal-core/reactive-system.d.ts.map +1 -0
- package/dist/signal-operators/index.d.ts +4 -0
- package/dist/signal-operators/index.d.ts.map +1 -0
- package/package.json +44 -0
- package/scripts/build.ts +53 -0
- package/src/index.ts +2 -0
- package/src/signal-core/README.md +4 -0
- package/src/signal-core/flags.ts +275 -0
- package/src/signal-core/index.ts +3 -0
- package/src/signal-core/primitive.ts +275 -0
- package/src/signal-core/reactive-system.ts +658 -0
- package/src/signal-operators/index.ts +19 -0
- package/tests/unit/signals/computed.spec.ts +92 -0
- package/tests/unit/signals/effect.spec.ts +108 -0
- package/tsconfig.json +3 -0
- package/vite.config.ts +8 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { computed, signal } from '../../../src';
|
|
2
|
+
import { expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
test('should correctly propagate changes through computed signals', () => {
|
|
5
|
+
/**
|
|
6
|
+
* src
|
|
7
|
+
* |
|
|
8
|
+
* c1
|
|
9
|
+
* |
|
|
10
|
+
* c2
|
|
11
|
+
* |
|
|
12
|
+
* c3
|
|
13
|
+
*/
|
|
14
|
+
const src = signal(0);
|
|
15
|
+
const c1 = computed(() => src.get() % 2);
|
|
16
|
+
const c2 = computed(() => c1.get());
|
|
17
|
+
const c3 = computed(() => c2.get());
|
|
18
|
+
|
|
19
|
+
expect(c3.get()).toBe(0);
|
|
20
|
+
src.set(1);
|
|
21
|
+
expect(c2.get()).toBe(1);
|
|
22
|
+
src.set(3);
|
|
23
|
+
expect(c3.get()).toBe(1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('should propagate updated source value through chained computations', () => {
|
|
27
|
+
/**
|
|
28
|
+
* src
|
|
29
|
+
* / \
|
|
30
|
+
* a c
|
|
31
|
+
* | |
|
|
32
|
+
* b |
|
|
33
|
+
* \ /
|
|
34
|
+
* d
|
|
35
|
+
*/
|
|
36
|
+
const src = signal(0);
|
|
37
|
+
const a = computed(() => src.get());
|
|
38
|
+
const b = computed(() => a.get() % 2);
|
|
39
|
+
const c = computed(() => src.get());
|
|
40
|
+
const d = computed(() => b.get() + c.get());
|
|
41
|
+
|
|
42
|
+
expect(d.get()).toBe(0);
|
|
43
|
+
src.set(2);
|
|
44
|
+
expect(d.get()).toBe(2);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('should handle flags are indirectly updated during resolve pending', () => {
|
|
48
|
+
/**
|
|
49
|
+
* a
|
|
50
|
+
* |
|
|
51
|
+
* b
|
|
52
|
+
* / \
|
|
53
|
+
* c d
|
|
54
|
+
* \ /
|
|
55
|
+
* d
|
|
56
|
+
*/
|
|
57
|
+
const a = signal(false);
|
|
58
|
+
const b = computed(() => a.get());
|
|
59
|
+
const c = computed(() => {
|
|
60
|
+
b.get();
|
|
61
|
+
return 0;
|
|
62
|
+
});
|
|
63
|
+
const d = computed(() => {
|
|
64
|
+
c.get();
|
|
65
|
+
return b.get();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(d.get()).toBe(false);
|
|
69
|
+
a.set(true);
|
|
70
|
+
expect(d.get()).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('should not update if the signal value is reverted', () => {
|
|
74
|
+
/**
|
|
75
|
+
* src
|
|
76
|
+
* |
|
|
77
|
+
* c1
|
|
78
|
+
*/
|
|
79
|
+
let times = 0;
|
|
80
|
+
const src = signal(0);
|
|
81
|
+
const c1 = computed(() => {
|
|
82
|
+
times = times + 1;
|
|
83
|
+
return src.get();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(c1.get()).toBe(0);
|
|
87
|
+
expect(times).toBe(1);
|
|
88
|
+
src.set(1);
|
|
89
|
+
src.set(0);
|
|
90
|
+
expect(c1.get()).toBe(0);
|
|
91
|
+
expect(times).toBe(1);
|
|
92
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { computed, effect, endBatch, signal, startBatch } from '../../../src';
|
|
2
|
+
import { expect, test } from 'vitest';
|
|
3
|
+
|
|
4
|
+
test('should clear subscriptions when untracked by all subscribers', () => {
|
|
5
|
+
/**
|
|
6
|
+
* a
|
|
7
|
+
* |
|
|
8
|
+
* b
|
|
9
|
+
* |
|
|
10
|
+
* e
|
|
11
|
+
*/
|
|
12
|
+
let bRunTimes = 0;
|
|
13
|
+
const a = signal(1);
|
|
14
|
+
const b = computed(() => {
|
|
15
|
+
bRunTimes = bRunTimes + 1;
|
|
16
|
+
return a.get() * 2;
|
|
17
|
+
});
|
|
18
|
+
const e = effect(() => {
|
|
19
|
+
b.get();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
expect(bRunTimes).toBe(1);
|
|
23
|
+
a.set(2);
|
|
24
|
+
expect(bRunTimes).toBe(2);
|
|
25
|
+
e.stop();
|
|
26
|
+
a.set(3);
|
|
27
|
+
expect(bRunTimes).toBe(2);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('should not run untracked inner effect', () => {
|
|
31
|
+
/**
|
|
32
|
+
* a
|
|
33
|
+
* / \
|
|
34
|
+
* b e2(inner)
|
|
35
|
+
* \ /
|
|
36
|
+
* e1(outer)
|
|
37
|
+
*/
|
|
38
|
+
let countOfInnerEffect = 0;
|
|
39
|
+
const a = signal(3);
|
|
40
|
+
const b = computed(() => a.get() > 0);
|
|
41
|
+
effect(() => {
|
|
42
|
+
if (b.get() === true) {
|
|
43
|
+
countOfInnerEffect = countOfInnerEffect + 1;
|
|
44
|
+
effect(() => {
|
|
45
|
+
if (a.get() === 0) {
|
|
46
|
+
throw new Error("bad");
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
a.set(2);
|
|
53
|
+
a.set(1);
|
|
54
|
+
a.set(0);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('should run outer effect first', () => {
|
|
58
|
+
/**
|
|
59
|
+
* a b
|
|
60
|
+
* | \ /
|
|
61
|
+
* | \ /
|
|
62
|
+
* | e2(inner)
|
|
63
|
+
* \ /
|
|
64
|
+
* e1(outer)
|
|
65
|
+
*/
|
|
66
|
+
const a = signal(1);
|
|
67
|
+
const b = signal(1);
|
|
68
|
+
effect(() => {
|
|
69
|
+
if (a.get() !== 0) {
|
|
70
|
+
effect(() => {
|
|
71
|
+
b.get();
|
|
72
|
+
if (a.get() === 0) {
|
|
73
|
+
throw new Error("bad");
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
startBatch();
|
|
80
|
+
b.set(0);
|
|
81
|
+
a.set(0);
|
|
82
|
+
endBatch();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('should not trigger inner effect when resolve maybe dirty', () => {
|
|
86
|
+
/**
|
|
87
|
+
* a
|
|
88
|
+
* |
|
|
89
|
+
* b
|
|
90
|
+
* e2(inner)
|
|
91
|
+
* |
|
|
92
|
+
* e1(outer)
|
|
93
|
+
*/
|
|
94
|
+
const a = signal(0);
|
|
95
|
+
const b = computed(() => a.get() % 2);
|
|
96
|
+
let innerTriggerTimes = 0;
|
|
97
|
+
effect(() => {
|
|
98
|
+
effect(() => {
|
|
99
|
+
b.get();
|
|
100
|
+
innerTriggerTimes = innerTriggerTimes + 1;
|
|
101
|
+
if (innerTriggerTimes >= 2) {
|
|
102
|
+
throw new Error("bad");
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
a.set(2);
|
|
108
|
+
});
|
package/tsconfig.json
ADDED