11import { emit , eventize , off , on , once , Priority } from '@spearwolf/eventize' ;
22import {
33 batch ,
4+ type CompareFunc ,
45 createEffect ,
56 createMemo ,
67 createSignal ,
78 destroySignal ,
89 isSignal ,
910 link ,
10- Signal ,
11- type CompareFunc ,
11+ type Signal ,
1212 type SignalReader ,
1313} from '@spearwolf/signalize' ;
1414import { ComponentChangeType , MessageToView } from '../constants.js' ;
15- import type { IComponentChangeType , IComponentEvent , ShadowObjectConstructor , ShadowObjectType , SyncEvent } from '../types.js' ;
15+ import type {
16+ IComponentChangeType ,
17+ IComponentEvent ,
18+ ProvideContextOptions ,
19+ ShadowObjectConstructor ,
20+ ShadowObjectType ,
21+ SyncEvent ,
22+ } from '../types.js' ;
1623import { ConsoleLogger } from '../utils/ConsoleLogger.js' ;
1724import { Entity } from './Entity.js' ;
18- import { onCreate , onDestroy , onParentChanged , type OnCreate , type OnDestroy } from './events.js' ;
25+ import { type OnCreate , onCreate , type OnDestroy , onDestroy , onParentChanged } from './events.js' ;
1926import { Registry } from './Registry.js' ;
2027import { SignalsPath } from './SignalsPath.js' ;
2128
@@ -46,7 +53,9 @@ enum ShadowObjectAction {
4653 DestroyOnly ,
4754}
4855
49- const getDisplayName = ( constructor : ShadowObjectConstructor ) => constructor . displayName || constructor . name ;
56+ const getDisplayName = ( construct : ShadowObjectConstructor ) => construct . displayName || construct . name ;
57+
58+ let provideContextOptionsDeprecatedShown = false ;
5059
5160/**
5261 * The entity kernel manages the lifecycle of all entities and shadow-objects.
@@ -107,12 +116,13 @@ export class Kernel {
107116 }
108117 } ;
109118
110- this . #rootEntities. forEach ( ( uuid ) => traverse ( uuid , 0 ) ) ;
119+ this . #rootEntities. forEach ( ( uuid ) => {
120+ traverse ( uuid , 0 ) ;
121+ } ) ;
111122
112123 this . #allEntities = Array . from ( lvl . entries ( ) )
113124 . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] )
114- . map ( ( [ , entities ] ) => entities )
115- . flat ( ) ;
125+ . flatMap ( ( [ , entities ] ) => entities ) ;
116126
117127 this . #allEntitiesReversed = this . #allEntities. slice ( ) . reverse ( ) ;
118128 this . #allEntitiesNeedUpdate = false ;
@@ -311,9 +321,9 @@ export class Kernel {
311321 // destroy all shadow-objects created by constructors no longer in the list
312322 //
313323 if ( shouldDestroy ) {
314- for ( const [ constructor , shadowObjects ] of entry . usedConstructors ) {
315- if ( ! nextConstructors . has ( constructor ) ) {
316- entry . usedConstructors . delete ( constructor ) ;
324+ for ( const [ construct , shadowObjects ] of entry . usedConstructors ) {
325+ if ( ! nextConstructors . has ( construct ) ) {
326+ entry . usedConstructors . delete ( construct ) ;
317327 for ( const obj of shadowObjects ) {
318328 this . destroyShadowObject ( obj , entry . entity ) ;
319329 }
@@ -324,17 +334,17 @@ export class Kernel {
324334 // shadow-objects for new constructors are now created using the updated constructor list
325335 //
326336 if ( shouldCreate ) {
327- for ( const constructor of nextConstructors ) {
328- if ( ! entry . usedConstructors . has ( constructor ) ) {
329- this . constructShadowObject ( constructor , entry ) ;
337+ for ( const construct of nextConstructors ) {
338+ if ( ! entry . usedConstructors . has ( construct ) ) {
339+ this . constructShadowObject ( construct , entry ) ;
330340 }
331341 }
332342 }
333343
334344 return nextConstructors ;
335345 }
336346
337- private constructShadowObject ( constructor : ShadowObjectConstructor , entry : EntityEntry ) : ShadowObjectType {
347+ private constructShadowObject ( construct : ShadowObjectConstructor , entry : EntityEntry ) : ShadowObjectType {
338348 const unsubscribePrimary = new Set < ( ) => any > ( ) ;
339349 const unsubscribeSecondary = new Set < ( ) => any > ( ) ;
340350
@@ -357,17 +367,30 @@ export class Kernel {
357367 } ;
358368
359369 const shadowObject = eventize (
360- new constructor ( {
370+ new construct ( {
361371 entity : entry . entity ,
362372
363- provideContext < T = unknown > ( name : string | symbol , sourceOrInitialValue ?: T | SignalReader < T > , isEqual ?: CompareFunc < T > ) {
373+ provideContext < T = unknown > (
374+ name : string | symbol ,
375+ sourceOrInitialValue ?: T | SignalReader < T > ,
376+ options ?: ProvideContextOptions < T > | CompareFunc < T > ,
377+ ) {
364378 let ctxProvider = contextProviders . get ( name ) ;
365379
380+ if ( ! provideContextOptionsDeprecatedShown && typeof options !== 'function' ) {
381+ console . warn (
382+ '[shadow-objects] Deprecation Warning: The "isEqual" option of "provideContext()" and "provideGlobalContext()" is now passed as {compare} argument. Please update your code accordingly.' ,
383+ ) ;
384+ provideContextOptionsDeprecatedShown = true ;
385+ }
386+
387+ const opts = typeof options === 'function' ? { compare : options } : options ;
388+
366389 if ( ctxProvider == null ) {
367390 const isSig = isSignal ( sourceOrInitialValue ) ;
368391 const initialValue = isSig ? undefined : ( sourceOrInitialValue as T ) ;
369392
370- ctxProvider = createSignal ( initialValue , isEqual ? { compare : isEqual } : undefined ) ;
393+ ctxProvider = createSignal ( initialValue , opts ?. compare ? { compare : opts . compare } : undefined ) ;
371394
372395 if ( isSig ) {
373396 const ln = link ( sourceOrInitialValue as SignalReader < T > , ctxProvider ) ;
@@ -379,21 +402,36 @@ export class Kernel {
379402 contextProviders . set ( name , ctxProvider ) ;
380403 }
381404
405+ if ( ctxProvider != null && ( opts ?. clearOnDestroy ?? true ) ) {
406+ unsubscribePrimary . add ( ( ) => {
407+ ctxProvider . set ( undefined ) ;
408+ } ) ;
409+ }
410+
382411 return ctxProvider ;
383412 } ,
384413
385414 provideGlobalContext < T = unknown > (
386415 name : string | symbol ,
387416 sourceOrInitialValue ?: T | SignalReader < T > ,
388- isEqual ?: CompareFunc < T > ,
417+ options ?: ProvideContextOptions < T > | CompareFunc < T > ,
389418 ) {
390419 let ctxProvider = contextRootProviders . get ( name ) ;
391420
421+ if ( ! provideContextOptionsDeprecatedShown && typeof options !== 'function' ) {
422+ console . warn (
423+ '[shadow-objects] Deprecation Warning: The "isEqual" option of "provideContext()" and "provideGlobalContext()" is now passed as {compare} argument. Please update your code accordingly.' ,
424+ ) ;
425+ provideContextOptionsDeprecatedShown = true ;
426+ }
427+
428+ const opts = typeof options === 'function' ? { compare : options } : options ;
429+
392430 if ( ctxProvider == null ) {
393431 const isSig = isSignal ( sourceOrInitialValue ) ;
394432 const initialValue = isSig ? undefined : ( sourceOrInitialValue as T ) ;
395433
396- ctxProvider = createSignal ( initialValue , isEqual ? { compare : isEqual } : undefined ) ;
434+ ctxProvider = createSignal ( initialValue , opts ?. compare ? { compare : opts . compare } : undefined ) ;
397435
398436 if ( isSig ) {
399437 const ln = link ( sourceOrInitialValue as SignalReader < T > , ctxProvider ) ;
@@ -405,6 +443,12 @@ export class Kernel {
405443 contextRootProviders . set ( name , ctxProvider ) ;
406444 }
407445
446+ if ( ctxProvider != null && ( opts ?. clearOnDestroy ?? true ) ) {
447+ unsubscribePrimary . add ( ( ) => {
448+ ctxProvider . set ( undefined ) ;
449+ } ) ;
450+ }
451+
408452 return ctxProvider ;
409453 } ,
410454
@@ -435,7 +479,7 @@ export class Kernel {
435479 useProperties < K extends string > ( props : Record < K , string > ) : Record < K , SignalReader < any > > {
436480 const result = { } as Record < K , SignalReader < any > > ;
437481 for ( const key in props ) {
438- if ( Object . prototype . hasOwnProperty . call ( props , key ) ) {
482+ if ( Object . hasOwn ( props , key ) ) {
439483 result [ key ] = getUseProperty ( props [ key ] ) ;
440484 }
441485 }
@@ -508,12 +552,12 @@ export class Kernel {
508552 ) ;
509553
510554 if ( this . logger . isInfo ) {
511- this . logger . info ( 'create shadow-object' , getDisplayName ( constructor ) , { shadowObject, entity : entry . entity } ) ;
555+ this . logger . info ( 'create shadow-object' , getDisplayName ( construct ) , { shadowObject, entity : entry . entity } ) ;
512556 }
513557
514558 once ( entry . entity , onDestroy , Priority . Low , ( ) => {
515559 if ( this . logger . isInfo ) {
516- this . logger . info ( 'destroy shadow-object' , getDisplayName ( constructor ) , { shadowObject, entity : entry . entity } ) ;
560+ this . logger . info ( 'destroy shadow-object' , getDisplayName ( construct ) , { shadowObject, entity : entry . entity } ) ;
517561 }
518562
519563 for ( const callback of unsubscribePrimary ) {
@@ -552,22 +596,22 @@ export class Kernel {
552596 contextProviders . clear ( ) ;
553597 contextRootProviders . clear ( ) ;
554598
555- const otherShadowObjects = entry . usedConstructors . get ( constructor ) ;
599+ const otherShadowObjects = entry . usedConstructors . get ( construct ) ;
556600 if ( otherShadowObjects ) {
557601 otherShadowObjects . delete ( shadowObject ) ;
558602 if ( otherShadowObjects . size === 0 ) {
559- entry . usedConstructors . delete ( constructor ) ;
603+ entry . usedConstructors . delete ( construct ) ;
560604 }
561605 }
562606 } ) ;
563607
564608 // We want to keep track which shadow-objects are created by which constructors.
565609 // This will all
566610 //
567- if ( entry . usedConstructors . has ( constructor ) ) {
568- entry . usedConstructors . get ( constructor ) . add ( shadowObject ) ;
611+ if ( entry . usedConstructors . has ( construct ) ) {
612+ entry . usedConstructors . get ( construct ) . add ( shadowObject ) ;
569613 } else {
570- entry . usedConstructors . set ( constructor , new Set ( [ shadowObject ] ) ) ;
614+ entry . usedConstructors . set ( construct , new Set ( [ shadowObject ] ) ) ;
571615 }
572616
573617 this . attachShadowObject ( shadowObject , entry . entity ) ;
@@ -578,8 +622,8 @@ export class Kernel {
578622 private createShadowObjects ( uuid : string ) : void {
579623 const entry = this . #entities. get ( uuid ) ;
580624
581- this . registry . findConstructors ( entry . token , entry . entity . truthyProps ( ) ) ?. forEach ( ( constructor ) => {
582- this . constructShadowObject ( constructor , entry ) ;
625+ this . registry . findConstructors ( entry . token , entry . entity . truthyProps ( ) ) ?. forEach ( ( construct ) => {
626+ this . constructShadowObject ( construct , entry ) ;
583627 } ) ;
584628 }
585629
@@ -588,13 +632,7 @@ export class Kernel {
588632
589633 const { usedConstructors} = this . #entities. get ( uuid ) ;
590634
591- return Array . from (
592- new Set (
593- Array . from ( usedConstructors . values ( ) )
594- . map ( ( objs ) => Array . from ( objs ) )
595- . flat ( ) ,
596- ) ,
597- ) ;
635+ return Array . from ( new Set ( Array . from ( usedConstructors . values ( ) ) . flatMap ( ( objs ) => Array . from ( objs ) ) ) ) ;
598636 }
599637
600638 private attachShadowObject ( shadowObject : object , entity : Entity ) : void {
0 commit comments