@@ -29,6 +29,28 @@ describe("signal", () => {
29
29
expect ( a + b ) . to . equal ( 3 ) ;
30
30
} ) ;
31
31
32
+ it ( "should notify other listeners of changes after one listener is disposed" , ( ) => {
33
+ const s = signal ( 0 ) ;
34
+ const spy1 = sinon . spy ( ( ) => s . value ) ;
35
+ const spy2 = sinon . spy ( ( ) => s . value ) ;
36
+ const spy3 = sinon . spy ( ( ) => s . value ) ;
37
+
38
+ effect ( spy1 ) ;
39
+ const dispose = effect ( spy2 ) ;
40
+ effect ( spy3 ) ;
41
+
42
+ expect ( spy1 ) . to . be . calledOnce ;
43
+ expect ( spy2 ) . to . be . calledOnce ;
44
+ expect ( spy3 ) . to . be . calledOnce ;
45
+
46
+ dispose ( ) ;
47
+
48
+ s . value = 1 ;
49
+ expect ( spy1 ) . to . be . calledTwice ;
50
+ expect ( spy2 ) . to . be . calledOnce ;
51
+ expect ( spy3 ) . to . be . calledTwice ;
52
+ } ) ;
53
+
32
54
describe ( ".peek()" , ( ) => {
33
55
it ( "should get value" , ( ) => {
34
56
const s = signal ( 1 ) ;
@@ -865,7 +887,7 @@ describe("computed()", () => {
865
887
expect ( ( ) => effect ( ( ) => a . value ) ) . to . not . throw ( ) ;
866
888
} ) ;
867
889
868
- it ( "should store failures and recompute only after a dependency changes" , ( ) => {
890
+ it ( "should store thrown errors and recompute only after a dependency changes" , ( ) => {
869
891
const a = signal ( 0 ) ;
870
892
const spy = sinon . spy ( ( ) => {
871
893
a . value ;
@@ -880,6 +902,39 @@ describe("computed()", () => {
880
902
expect ( spy ) . to . be . calledTwice ;
881
903
} ) ;
882
904
905
+ it ( "should store thrown non-errors and recompute only after a dependency changes" , ( ) => {
906
+ const a = signal ( 0 ) ;
907
+ const spy = sinon . spy ( ) ;
908
+ const c = computed ( ( ) => {
909
+ a . value ;
910
+ spy ( ) ;
911
+ throw undefined ;
912
+ } ) ;
913
+
914
+ try {
915
+ c . value ;
916
+ expect . fail ( ) ;
917
+ } catch ( err ) {
918
+ expect ( err ) . to . be . undefined ;
919
+ }
920
+ try {
921
+ c . value ;
922
+ expect . fail ( ) ;
923
+ } catch ( err ) {
924
+ expect ( err ) . to . be . undefined ;
925
+ }
926
+ expect ( spy ) . to . be . calledOnce ;
927
+
928
+ a . value = 1 ;
929
+ try {
930
+ c . value ;
931
+ expect . fail ( ) ;
932
+ } catch ( err ) {
933
+ expect ( err ) . to . be . undefined ;
934
+ }
935
+ expect ( spy ) . to . be . calledTwice ;
936
+ } ) ;
937
+
883
938
it ( "should conditionally unsubscribe from signals" , ( ) => {
884
939
const a = signal ( "a" ) ;
885
940
const b = signal ( "b" ) ;
@@ -967,6 +1022,30 @@ describe("computed()", () => {
967
1022
expect ( c . value ) . to . equal ( 1 ) ;
968
1023
} ) ;
969
1024
1025
+ it ( "should propagate notification to other listeners after one listener is disposed" , ( ) => {
1026
+ const s = signal ( 0 ) ;
1027
+ const c = computed ( ( ) => s . value ) ;
1028
+
1029
+ const spy1 = sinon . spy ( ( ) => c . value ) ;
1030
+ const spy2 = sinon . spy ( ( ) => c . value ) ;
1031
+ const spy3 = sinon . spy ( ( ) => c . value ) ;
1032
+
1033
+ effect ( spy1 ) ;
1034
+ const dispose = effect ( spy2 ) ;
1035
+ effect ( spy3 ) ;
1036
+
1037
+ expect ( spy1 ) . to . be . calledOnce ;
1038
+ expect ( spy2 ) . to . be . calledOnce ;
1039
+ expect ( spy3 ) . to . be . calledOnce ;
1040
+
1041
+ dispose ( ) ;
1042
+
1043
+ s . value = 1 ;
1044
+ expect ( spy1 ) . to . be . calledTwice ;
1045
+ expect ( spy2 ) . to . be . calledOnce ;
1046
+ expect ( spy3 ) . to . be . calledTwice ;
1047
+ } ) ;
1048
+
970
1049
it ( "should not recompute dependencies out of order" , ( ) => {
971
1050
const a = signal ( 1 ) ;
972
1051
const b = signal ( 1 ) ;
@@ -1042,6 +1121,19 @@ describe("computed()", () => {
1042
1121
expect ( b . peek ( ) ) . to . equal ( 2 ) ;
1043
1122
} ) ;
1044
1123
1124
+ it ( "should detect simple dependency cycles" , ( ) => {
1125
+ const a : Signal = computed ( ( ) => a . peek ( ) ) ;
1126
+ expect ( ( ) => a . peek ( ) ) . to . throw ( / C y c l e d e t e c t e d / ) ;
1127
+ } ) ;
1128
+
1129
+ it ( "should detect deep dependency cycles" , ( ) => {
1130
+ const a : Signal = computed ( ( ) => b . value ) ;
1131
+ const b : Signal = computed ( ( ) => c . value ) ;
1132
+ const c : Signal = computed ( ( ) => d . value ) ;
1133
+ const d : Signal = computed ( ( ) => a . peek ( ) ) ;
1134
+ expect ( ( ) => a . peek ( ) ) . to . throw ( / C y c l e d e t e c t e d / ) ;
1135
+ } ) ;
1136
+
1045
1137
it ( "should not make surrounding effect depend on the computed" , ( ) => {
1046
1138
const s = signal ( 1 ) ;
1047
1139
const c = computed ( ( ) => s . value ) ;
@@ -1516,14 +1608,25 @@ describe("batch/transaction", () => {
1516
1608
expect ( batch ( ( ) => 1 ) ) . to . equal ( 1 ) ;
1517
1609
} ) ;
1518
1610
1519
- it ( "should throw the error raised from the callback" , ( ) => {
1611
+ it ( "should throw errors throws from the callback" , ( ) => {
1520
1612
expect ( ( ) =>
1521
1613
batch ( ( ) => {
1522
1614
throw Error ( "hello" ) ;
1523
1615
} )
1524
1616
) . to . throw ( "hello" ) ;
1525
1617
} ) ;
1526
1618
1619
+ it ( "should throw non-errors thrown from the callback" , ( ) => {
1620
+ try {
1621
+ batch ( ( ) => {
1622
+ throw undefined ;
1623
+ } ) ;
1624
+ expect . fail ( ) ;
1625
+ } catch ( err ) {
1626
+ expect ( err ) . to . be . undefined ;
1627
+ }
1628
+ } ) ;
1629
+
1527
1630
it ( "should delay writes" , ( ) => {
1528
1631
const a = signal ( "a" ) ;
1529
1632
const b = signal ( "b" ) ;
0 commit comments