@@ -22,6 +22,7 @@ var _MODE_GETTER_ = 3;
22
22
var _MODE_MAP_FIELD_ = 4 ;
23
23
var _MODE_ITERABLE_ = 5 ;
24
24
var _MODE_MAP_ = 6 ;
25
+ var _MODE_MAP_FIELD_NOTIFY_ONLY_ = 10 ;
25
26
export class GetterCache {
26
27
constructor ( map ) {
27
28
this . _map = map ;
@@ -186,9 +187,10 @@ export class DirtyCheckingChangeDetectorGroup extends ChangeDetector {
186
187
}
187
188
}
188
189
export class DirtyCheckingChangeDetector extends DirtyCheckingChangeDetectorGroup {
189
- constructor ( cache ) {
190
+ constructor ( cache , notifier = new ChangeNotifier ( ) ) {
190
191
super ( null , cache ) ;
191
192
this . _fakeHead = DirtyCheckingRecord . marker ( ) ;
193
+ this . _notifier = notifier ;
192
194
}
193
195
194
196
_assertRecordsOk ( ) {
@@ -276,6 +278,47 @@ class ChangeIterator {
276
278
}
277
279
}
278
280
281
+ // TODO: Add unit tests for this!
282
+ export class ChangeNotifier {
283
+ constructor ( ) {
284
+ this . objectRecords = new WeakMap ( ) ;
285
+ }
286
+ notify ( object ) {
287
+ var records = this . objectRecords . get ( object ) || [ ] ;
288
+ records . forEach ( ( record ) => {
289
+ // TODO: Is this the correct way of manually dirty checking
290
+ // some records??
291
+ var watch = record . _handler . _watchHead ;
292
+ if ( watch && record . check ( true ) ) {
293
+ watch . _dirty = true ;
294
+ watch . invoke ( ) ;
295
+ }
296
+ } ) ;
297
+ }
298
+ isNotifyOnly ( object , fieldName ) {
299
+ return false ;
300
+ }
301
+ addWatch ( object , fieldName , record ) {
302
+ var records = this . objectRecords . get ( object ) ;
303
+ if ( ! records ) {
304
+ records = [ ] ;
305
+ this . objectRecords . set ( object , records ) ;
306
+ }
307
+ records . push ( record ) ;
308
+ return records . length ;
309
+ }
310
+ removeWatch ( object , fieldName , record ) {
311
+ var records = this . objectRecords . get ( object ) ;
312
+ if ( records ) {
313
+ var index = records . indexOf ( record ) ;
314
+ if ( index !== - 1 ) {
315
+ records . splice ( index , 1 ) ;
316
+ }
317
+ }
318
+ return records ? records . length : 0 ;
319
+ }
320
+ }
321
+
279
322
class DirtyCheckingRecord extends ChangeRecord {
280
323
constructor ( group , object , fieldName , getter , handler ) {
281
324
this . _group = group ;
@@ -307,7 +350,17 @@ class DirtyCheckingRecord extends ChangeRecord {
307
350
get object ( ) {
308
351
return this . _object ;
309
352
}
353
+ _clearObject ( ) {
354
+ var notifier = this . _group && this . _group . _root . _notifier ;
355
+ if ( notifier && this . _object && (
356
+ this . _mode === _MODE_MAP_FIELD_NOTIFY_ONLY_ || this . _mode === _MODE_MAP_FIELD_ )
357
+ ) {
358
+ notifier . removeWatch ( this . _object , this . _field , this ) ;
359
+ }
360
+ this . _object = null ;
361
+ }
310
362
set object ( obj ) {
363
+ this . _clearObject ( obj ) ;
311
364
this . _object = obj ;
312
365
if ( obj === null ) {
313
366
this . _mode = _MODE_IDENTITY_ ;
@@ -333,7 +386,13 @@ class DirtyCheckingRecord extends ChangeRecord {
333
386
return ;
334
387
}
335
388
if ( typeof obj === "object" ) {
336
- this . _mode = _MODE_MAP_FIELD_ ;
389
+ var notifier = this . _group && this . _group . _root . _notifier ;
390
+ if ( notifier && notifier . isNotifyOnly ( obj , this . _field ) ) {
391
+ this . _mode = _MODE_MAP_FIELD_NOTIFY_ONLY_ ;
392
+ } else {
393
+ this . _mode = _MODE_MAP_FIELD_ ;
394
+ }
395
+ notifier . addWatch ( obj , this . _field , this ) ;
337
396
// _instanceMirror = null; --- Reflection needed?
338
397
} else if ( this . _getter !== null ) {
339
398
this . _mode = _MODE_GETTER_ ;
@@ -343,7 +402,7 @@ class DirtyCheckingRecord extends ChangeRecord {
343
402
// _instanceMirror = reflect(obj); --- I'm really not sure about this!
344
403
}
345
404
}
346
- check ( ) {
405
+ check ( inNotify ) {
347
406
// assert(_mode != null); --- Traceur v0.0.24 missing assert()
348
407
var current ;
349
408
switch ( this . _mode ) {
@@ -359,6 +418,13 @@ class DirtyCheckingRecord extends ChangeRecord {
359
418
case _MODE_GETTER_ :
360
419
current = this . _getter ( this . object ) ;
361
420
break ;
421
+ case _MODE_MAP_FIELD_NOTIFY_ONLY_ :
422
+ if ( inNotify ) {
423
+ current = this . object [ this . field ] ;
424
+ } else {
425
+ return false ;
426
+ }
427
+ break ;
362
428
case _MODE_MAP_FIELD_ :
363
429
if ( ! this . object ) return undefined ;
364
430
current = this . object [ this . field ] ;
@@ -395,6 +461,9 @@ class DirtyCheckingRecord extends ChangeRecord {
395
461
return false ;
396
462
}
397
463
remove ( ) {
464
+ // TODO: This is not called when a WatchGroup is destroyed.
465
+ // TODO: Should also be called when a parent WatchGroup is destroyed!
466
+ this . _clearObject ( ) ;
398
467
this . _group . _recordRemove ( this ) ;
399
468
}
400
469
toString ( ) {
0 commit comments