@@ -61,40 +61,46 @@ ChainWatchers.prototype = {
61
61
return false ;
62
62
} ,
63
63
64
- finishAllChains ( ) {
64
+ revalidateAll ( ) {
65
65
for ( let key in this . nodes ) {
66
- this . finishChains ( key ) ;
66
+ this . notify ( key , true , undefined ) ;
67
67
}
68
68
} ,
69
69
70
- finishChains ( key ) {
71
- let nodes = this . nodes [ key ] ;
72
- if ( nodes && nodes . length ) {
73
- for ( var i = 0 , l = nodes . length ; i < l ; i ++ ) {
74
- nodes [ i ] . didChange ( null ) ;
75
- }
76
- }
70
+ revalidate ( key ) {
71
+ this . notify ( key , true , undefined ) ;
77
72
} ,
78
73
79
- willChange ( key ) {
74
+ // key: the string key that is part of a path changed
75
+ // revalidate: boolean the chains that are watching this value should revalidate
76
+ // callback: function that will be called with the the object and path that
77
+ // will be/are invalidated by this key change depending on the
78
+ // whether the revalidate flag is passed
79
+ notify ( key , revalidate , callback ) {
80
80
let nodes = this . nodes [ key ] ;
81
- if ( nodes && nodes . length ) {
82
- let events = [ ] ;
83
- for ( var i = 0 , l = nodes . length ; i < l ; i ++ ) {
84
- nodes [ i ] . willChange ( events ) ;
85
- }
86
- return events ;
81
+ if ( nodes === undefined || nodes . length === 0 ) {
82
+ return ;
87
83
}
88
- } ,
89
84
90
- didChange ( key ) {
91
- let nodes = this . nodes [ key ] ;
92
- if ( nodes && nodes . length ) {
93
- let events = [ ] ;
94
- for ( var i = 0 , l = nodes . length ; i < l ; i ++ ) {
95
- nodes [ i ] . didChange ( events ) ;
96
- }
97
- return events ;
85
+ let affected ;
86
+
87
+ if ( callback ) {
88
+ affected = [ ] ;
89
+ }
90
+
91
+ for ( let i = 0 , l = nodes . length ; i < l ; i ++ ) {
92
+ nodes [ i ] . notify ( revalidate , affected ) ;
93
+ }
94
+
95
+ if ( callback === undefined ) {
96
+ return ;
97
+ }
98
+
99
+ // we gather callbacks so we don't notify them during revalidation
100
+ for ( let i = 0 , l = affected . length ; i < l ; i += 2 ) {
101
+ let obj = affected [ i ] ;
102
+ let path = affected [ i + 1 ] ;
103
+ callback ( obj , path ) ;
98
104
}
99
105
}
100
106
} ;
@@ -356,44 +362,8 @@ ChainNode.prototype = {
356
362
}
357
363
} ,
358
364
359
- willChange ( events ) {
360
- var chains = this . _chains ;
361
- var node ;
362
- if ( chains ) {
363
- for ( var key in chains ) {
364
- node = chains [ key ] ;
365
- if ( node !== undefined ) {
366
- node . willChange ( events ) ;
367
- }
368
- }
369
- }
370
-
371
- if ( this . _parent ) {
372
- this . _parent . notifyChainChange ( this , this . _key , 1 , events ) ;
373
- }
374
- } ,
375
-
376
- notifyChainChange ( chain , path , depth , events ) {
377
- if ( this . _key ) {
378
- path = this . _key + '.' + path ;
379
- }
380
-
381
- if ( this . _parent ) {
382
- this . _parent . notifyChainChange ( this , path , depth + 1 , events ) ;
383
- } else {
384
- if ( depth > 1 ) {
385
- events . push ( this . value ( ) , path ) ;
386
- }
387
- path = 'this.' + path ;
388
- if ( this . _paths [ path ] > 0 ) {
389
- events . push ( this . value ( ) , path ) ;
390
- }
391
- }
392
- } ,
393
-
394
- didChange ( events ) {
395
- // invalidate my own value first.
396
- if ( this . _watching ) {
365
+ notify ( revalidate , affected ) {
366
+ if ( revalidate && this . _watching ) {
397
367
var obj = this . _parent . value ( ) ;
398
368
if ( obj !== this . _object ) {
399
369
removeChainWatcher ( this . _object , this . _key , this ) ;
@@ -416,19 +386,31 @@ ChainNode.prototype = {
416
386
for ( var key in chains ) {
417
387
node = chains [ key ] ;
418
388
if ( node !== undefined ) {
419
- node . didChange ( events ) ;
389
+ node . notify ( revalidate , affected ) ;
420
390
}
421
391
}
422
392
}
423
393
424
- // if no events are passed in then we only care about the above wiring update
425
- if ( events === null ) {
426
- return ;
394
+ if ( affected && this . _parent ) {
395
+ this . _parent . populateAffected ( this , this . _key , 1 , affected ) ;
396
+ }
397
+ } ,
398
+
399
+ populateAffected ( chain , path , depth , affected ) {
400
+ if ( this . _key ) {
401
+ path = this . _key + '.' + path ;
427
402
}
428
403
429
- // and finally tell parent about my path changing...
430
404
if ( this . _parent ) {
431
- this . _parent . notifyChainChange ( this , this . _key , 1 , events ) ;
405
+ this . _parent . populateAffected ( this , path , depth + 1 , affected ) ;
406
+ } else {
407
+ if ( depth > 1 ) {
408
+ affected . push ( this . value ( ) , path ) ;
409
+ }
410
+ path = 'this.' + path ;
411
+ if ( this . _paths [ path ] > 0 ) {
412
+ affected . push ( this . value ( ) , path ) ;
413
+ }
432
414
}
433
415
}
434
416
} ;
@@ -440,7 +422,7 @@ export function finishChains(obj) {
440
422
// finish any current chains node watchers that reference obj
441
423
let chainWatchers = m . chainWatchers ;
442
424
if ( chainWatchers ) {
443
- chainWatchers . finishAllChains ( ) ;
425
+ chainWatchers . revalidateAll ( ) ;
444
426
}
445
427
// copy chains from prototype
446
428
let chains = m . chains ;
0 commit comments