1
-
1
+ // signal / effect
2
2
const relatedEffects = new WeakMap ( ) ;
3
3
let currentEffect = null ;
4
4
@@ -7,18 +7,16 @@ export function effect(fn){
7
7
currentEffect = fn ;
8
8
if ( outer ) {
9
9
( outer . nested ??= new Set ( ) ) . add ( fn ) ;
10
+ if ( fn . parent && fn . parent !== outer ) throw ( 'effect(cb) callbacks should not be reused for other effects' ) ;
10
11
fn . parent = outer ;
11
12
}
12
13
fn ( ) ;
13
14
currentEffect = outer ;
14
15
return ( ) => fn . disposed = true
15
16
}
16
-
17
-
18
17
let batches = null ;
19
18
function batch ( effect ) {
20
19
if ( batches ) return batches . add ( effect ) ;
21
-
22
20
batches = new Set ( [ effect ] ) ;
23
21
Promise . resolve ( ) . then ( ( ) => { // setImmediate-alternative
24
22
batches . forEach ( fn => {
@@ -29,23 +27,21 @@ function batch(effect) {
29
27
batches = null ; // restart batch
30
28
} ) ;
31
29
}
32
-
33
-
34
- export function signalize ( item ) {
35
- item . addEventListener ( 'getIn' , ( { detail :{ item} } ) => {
36
- if ( ! currentEffect ) return ;
37
- if ( ! relatedEffects . has ( item ) ) relatedEffects . set ( item , new Set ( ) ) ;
38
- relatedEffects . get ( item ) . add ( currentEffect ) ;
39
- } ) ;
40
- item . addEventListener ( 'changeIn' , ( { detail :{ item} } ) => {
41
- const effects = relatedEffects . get ( item ) ;
42
- if ( ! effects ) return ;
30
+ function registerCurrentEffectFor ( signal ) {
31
+ if ( currentEffect ) {
32
+ if ( ! relatedEffects . has ( signal ) ) relatedEffects . set ( signal , new Set ( ) ) ;
33
+ relatedEffects . get ( signal ) . add ( currentEffect ) ;
34
+ }
35
+ }
36
+ function triggerEffectsFor ( signal ) {
37
+ const effects = relatedEffects . get ( signal ) ;
38
+ if ( effects ) { // "&& effects.size" faster?
43
39
effects . forEach ( fn => {
44
40
fn . nested ?. forEach ( fn => fn . disposed = true ) ; // dispose child-effects
45
41
if ( fn . disposed ) return effects . delete ( fn ) ;
46
42
batch ( fn ) ;
47
43
} ) ;
48
- } ) ;
44
+ }
49
45
}
50
46
51
47
@@ -62,6 +58,7 @@ export class Item extends EventTarget {
62
58
super ( ) ;
63
59
this . #parent = parent ;
64
60
this . #key = key ;
61
+ this . addEventListener ( 'change' , ( ) => triggerEffectsFor ( this ) ) ;
65
62
}
66
63
67
64
get key ( ) { return this . #key }
@@ -72,8 +69,8 @@ export class Item extends EventTarget {
72
69
if ( this . #isgetting) throw new Error ( 'circular get' ) ;
73
70
this . #isgetting = true ;
74
71
dispatchEvent ( this , 'get' , { item : this , value :this . #value } ) ;
72
+ registerCurrentEffectFor ( this ) ;
75
73
this . #isgetting = false ;
76
- //if (!this.#filled) throw new Error('value was never set');
77
74
return this . $get ( ) ;
78
75
}
79
76
set value ( value ) {
@@ -90,7 +87,6 @@ export class Item extends EventTarget {
90
87
} else {
91
88
const value = this . #value ??= Object . create ( null ) ; // if undefined, create object (todo? should always be object)
92
89
return Object . fromEntries ( Object . entries ( value ) . map ( ( [ key , { value} ] ) => [ key , value ] ) ) ;
93
- //return Object.fromEntries(Object.entries(this.#value).map(([key, {value}]) => [key, value]));
94
90
}
95
91
}
96
92
$set ( value ) {
0 commit comments