@@ -9,12 +9,13 @@ import { type IMetadataSource, type Metadata } from 'packages/core/src/metadata/
9
9
import { MetadataSubscription } from 'packages/core/src/metadata/MetadataSubscription' ;
10
10
import { type BindTargetDeclaration } from 'packages/core/src/parsers/bindTargetParser/BindTargetDeclaration' ;
11
11
import { type Signal } from 'packages/core/src/utils/Signal' ;
12
- import { areArraysEqual , arrayStartsWith } from 'packages/core/src/utils/Utils' ;
13
12
import {
14
13
ErrorLevel ,
15
14
MetaBindBindTargetError ,
16
15
MetaBindInternalError ,
17
16
} from 'packages/core/src/utils/errors/MetaBindErrors' ;
17
+ import { PropUtils } from 'packages/core/src/utils/prop/PropUtils' ;
18
+ import { type PropPath } from 'packages/core/src/utils/prop/PropPath' ;
18
19
19
20
export const METADATA_CACHE_UPDATE_CYCLE_THRESHOLD = 5 ; // {syncInterval (200)} * 5 = 1s
20
21
export const METADATA_CACHE_INACTIVE_CYCLE_THRESHOLD = 5 * 60 ; // {syncInterval (200)} * 5 * 60 = 1 minute
@@ -40,34 +41,40 @@ export function hasUpdateOverlap(a: BindTargetDeclaration | undefined, b: BindTa
40
41
return false ;
41
42
}
42
43
43
- return metadataPathHasUpdateOverlap (
44
- a . storageProp . toStringArray ( ) ,
45
- b . storageProp . toStringArray ( ) ,
46
- b . listenToChildren ,
47
- ) ;
44
+ // TODO: this can be faster, no need to create new arrays
45
+ return metadataPathHasUpdateOverlap ( a . storageProp , b . storageProp , b . listenToChildren ) ;
48
46
}
49
47
50
48
/**
51
49
* Checks if path `b` should receive an update when path `a` changes.
52
50
* The rules are as follows:
53
- * - if they are equal
54
- * - if `b` starts with `a` (`a = foo.bar` and `b = foo.bar.baz`)
55
- * - if `b` has `listenToChildren` and `a` starts with `b` (`a = foo.bar.baz` and `b = foo.bar`)
51
+ *
52
+ * - b = foo.bar.baz
53
+ * - a = foo.bar -> true
54
+ * - a = foo.bar.baz -> true
55
+ * - a = foo.bar.baz.baz -> true
56
+ * - a = foo.bar.foo -> false
57
+ * - a = foo.foo -> false
56
58
*
57
59
* @param a
58
60
* @param b
59
61
* @param listenToChildren whether b listens to updates in children
60
62
*/
61
- export function metadataPathHasUpdateOverlap ( a : string [ ] , b : string [ ] , listenToChildren : boolean ) : boolean {
62
- if ( areArraysEqual ( a , b ) ) {
63
- return true ;
63
+ export function metadataPathHasUpdateOverlap ( a : PropPath , b : PropPath , listenToChildren : boolean ) : boolean {
64
+ const aPath = a . path ;
65
+ const bPath = b . path ;
66
+
67
+ for ( let i = 0 ; i < Math . min ( aPath . length , bPath . length ) ; i ++ ) {
68
+ if ( aPath [ i ] . type !== bPath [ i ] . type || aPath [ i ] . prop !== bPath [ i ] . prop ) {
69
+ return false ;
70
+ }
64
71
}
65
72
66
- if ( arrayStartsWith ( b , a ) ) {
73
+ if ( aPath . length > bPath . length ) {
74
+ return listenToChildren ;
75
+ } else {
67
76
return true ;
68
77
}
69
-
70
- return listenToChildren && arrayStartsWith ( a , b ) ;
71
78
}
72
79
73
80
export function bindTargetToString ( a : BindTargetDeclaration | undefined ) : string {
@@ -359,12 +366,12 @@ export class MetadataManager {
359
366
if ( source === undefined ) {
360
367
throw new MetaBindInternalError ( {
361
368
errorLevel : ErrorLevel . ERROR ,
362
- effect : 'can not update metadata ' ,
369
+ effect : 'can not write to cache ' ,
363
370
cause : `Source "${ bindTarget . storageType } " does not exist` ,
364
371
} ) ;
365
372
}
366
373
367
- const cacheItem = source . updateCache ( value , bindTarget ) ;
374
+ const cacheItem = source . writeCache ( value , bindTarget ) ;
368
375
cacheItem . pendingInternalChange = true ;
369
376
cacheItem . cyclesSinceInternalChange = 0 ;
370
377
this . notifyListeners ( bindTarget , updateSourceUuid ) ;
@@ -431,8 +438,8 @@ export class MetadataManager {
431
438
432
439
if (
433
440
metadataPathHasUpdateOverlap (
434
- bindTarget . storageProp . toStringArray ( ) ,
435
- cacheSubscription . bindTarget . storageProp . toStringArray ( ) ,
441
+ bindTarget . storageProp ,
442
+ cacheSubscription . bindTarget . storageProp ,
436
443
cacheSubscription . bindTarget . listenToChildren ,
437
444
)
438
445
) {
@@ -501,8 +508,24 @@ export class MetadataManager {
501
508
return ;
502
509
}
503
510
504
- source . updateEntireCache ( value , cacheItem ) ;
505
- this . notifyAllListeners ( source , cacheItem ) ;
511
+ const oldValue = source . readEntireCacheItem ( cacheItem ) ;
512
+
513
+ source . writeEntireCache ( value , cacheItem ) ;
514
+
515
+ for ( const subscription of cacheItem . subscriptions ) {
516
+ if ( subscription . bindTarget === undefined ) {
517
+ continue ;
518
+ }
519
+
520
+ const propPath = subscription . bindTarget . storageProp ;
521
+
522
+ const newBoundValue = PropUtils . tryGet ( value , propPath ) ;
523
+ const oldBoundValue = PropUtils . tryGet ( oldValue , propPath ) ;
524
+
525
+ if ( newBoundValue !== oldBoundValue ) {
526
+ subscription . notify ( newBoundValue ) ;
527
+ }
528
+ }
506
529
}
507
530
508
531
/**
0 commit comments