@@ -97,7 +97,7 @@ export function sandBox(
9797 }
9898 } ) ;
9999 } else {
100- // IO-3: Object.assign statt Object.keys().forEach() – kein temporäres Keys-Array
100+ // IO-3: Object.assign instead of Object.keys().forEach() – no temporary keys array
101101 adapter . getForeignStates ( pattern , ( _err , _states ) => _states && Object . assign ( states , _states ) ) ;
102102 }
103103 } else {
@@ -533,7 +533,7 @@ export function sandBox(
533533 if ( ! ( adapter . config as JavaScriptAdapterConfig ) . subscribe && context . interimStateValues [ id ] ) {
534534 // if the state is changed, we will compare it with interimStateValues
535535 const oldState = context . interimStateValues [ id ] ;
536- // IO-1: for…in statt Object.keys().filter().every() – kein temporäres Array pro Aufruf
536+ // IO-1: for…in instead of Object.keys().filter().every() – no temporary array per call
537537 let stateHasChanged = false ;
538538 for ( const attr in stateAsObject ) {
539539 if ( attr === 'ts' ) {
@@ -1027,7 +1027,7 @@ export function sandBox(
10271027 }
10281028 }
10291029
1030- // IO-2: O(1) Deduplizierung via Set statt O(n²) resUnique.includes()
1030+ // IO-2: O(1) deduplication via Set instead of O(n²) resUnique.includes()
10311031 const resUnique : string [ ] = [ ...new Set ( res ) ] ;
10321032
10331033 for ( let i = 0 ; i < resUnique . length ; i ++ ) {
@@ -1691,7 +1691,7 @@ export function sandBox(
16911691 if ( oPattern ?. id && Array . isArray ( oPattern . id ) ) {
16921692 const result : ( IobSchedule | string | null | undefined ) [ ] = [ ] ;
16931693 for ( let t = 0 ; t < oPattern . id . length ; t ++ ) {
1694- // IO-4: Spread statt JSON.parse(JSON.stringify()) – kein tiefer Clone nötig (nur primitive Felder )
1694+ // IO-4: Spread instead of JSON.parse(JSON.stringify()) – no deep clone needed (only primitive fields )
16951695 const pa : Pattern = { ...oPattern , id : oPattern . id [ t ] } ;
16961696 result . push (
16971697 sandbox . subscribe ( pa , callbackOrChangeTypeOrId , value ) as
@@ -1944,7 +1944,7 @@ export function sandBox(
19441944
19451945 // Subscribe to all members of enum
19461946 for ( const objId of members ) {
1947- // IO-6: `in` Operator statt Object.keys().includes() – O(1) statt O(n)
1947+ // IO-6: `in` operator instead of Object.keys().includes() – O(1) instead of O(n)
19481948 if ( ! ( objId in subscriptions ) ) {
19491949 if ( objects ?. [ objId ] ?. type === 'state' ) {
19501950 // Just subscribe to states
@@ -2653,14 +2653,14 @@ export function sandBox(
26532653 Object . keys ( context . scripts ) . forEach (
26542654 name =>
26552655 context . scripts [ name ] . schedules &&
2656- // IO-8: Spread statt JSON.parse(JSON.stringify()) – _ioBroker hat nur primitive Felder
2656+ // IO-8: Spread instead of JSON.parse(JSON.stringify()) – _ioBroker has only primitive fields
26572657 context . scripts [ name ] . schedules . forEach ( s =>
26582658 schedules . push ( { ...s . _ioBroker } as unknown as ScheduleName ) ,
26592659 ) ,
26602660 ) ;
26612661 } else {
26622662 script . schedules &&
2663- // IO-8: Spread statt JSON.parse(JSON.stringify())
2663+ // IO-8: Spread instead of JSON.parse(JSON.stringify())
26642664 script . schedules . forEach ( s => schedules . push ( { ...s . _ioBroker } as unknown as ScheduleName ) ) ;
26652665 }
26662666 return schedules ;
@@ -2846,13 +2846,14 @@ export function sandBox(
28462846 const removedScripts = new Set < string > ( ) ;
28472847 for ( let i = timers [ id ] . length - 1 ; i >= 0 ; i -- ) {
28482848 if ( timerId === undefined || timers [ id ] [ i ] . id === timerId ) {
2849+ const clearedTimerId = timers [ id ] [ i ] . id ;
28492850 removedScripts . add ( timers [ id ] [ i ] . scriptName ) ;
28502851 clearTimeout ( timers [ id ] [ i ] . t ) ;
28512852 if ( timerId !== undefined ) {
28522853 timers [ id ] . splice ( i , 1 ) ;
28532854 }
28542855 if ( sandbox . verbose ) {
2855- sandbox . log ( `clearStateDelayed: clear timer ${ timers [ id ] [ i ] ?. id ?? timerId } ` , 'info' ) ;
2856+ sandbox . log ( `clearStateDelayed: clear timer ${ clearedTimerId } ` , 'info' ) ;
28562857 }
28572858 }
28582859 }
@@ -2863,15 +2864,22 @@ export function sandBox(
28632864 delete timers [ id ] ;
28642865 }
28652866 }
2866- // IO-7: timersByScript Reverse-Index aktualisieren wenn State keine Timer mehr hat
2867- if ( ! timers [ id ] ) {
2867+ // IO-7: keep the timersByScript reverse-index in sync. For every script whose
2868+ // timer(s) we just removed, drop `id` from its set – unless that script still has
2869+ // another timer for this state (other scripts' timers may keep timers[id] alive).
2870+ if ( removedScripts . size ) {
2871+ const remaining = timers [ id ] ; // undefined if the whole entry was deleted
28682872 for ( const scriptName of removedScripts ) {
28692873 const stateIds = context . timersByScript . get ( scriptName ) ;
2870- if ( stateIds ) {
2871- stateIds . delete ( id ) ;
2872- if ( ! stateIds . size ) {
2873- context . timersByScript . delete ( scriptName ) ;
2874- }
2874+ if ( ! stateIds ) {
2875+ continue ;
2876+ }
2877+ if ( remaining ?. some ( e => e . scriptName === scriptName ) ) {
2878+ continue ;
2879+ }
2880+ stateIds . delete ( id ) ;
2881+ if ( ! stateIds . size ) {
2882+ context . timersByScript . delete ( scriptName ) ;
28752883 }
28762884 }
28772885 }
@@ -4093,7 +4101,7 @@ export function sandBox(
40934101 errorInCallback ( err as Error ) ;
40944102 }
40954103 } , ms ) ;
4096- // IO-10: Set.add() – O(1) statt Array.push()
4104+ // IO-10: Set.add() – O(1) instead of Array.push()
40974105 script . intervals . add ( int ) ;
40984106
40994107 if ( sandbox . verbose ) {
@@ -4105,7 +4113,7 @@ export function sandBox(
41054113 return null ;
41064114 } ,
41074115 clearInterval : function ( id : NodeJS . Timeout ) : void {
4108- // IO-10: Set.has/delete – O(1) statt Array.indexOf+splice O(n)
4116+ // IO-10: Set.has/delete – O(1) instead of Array.indexOf+splice O(n)
41094117 if ( script . intervals . has ( id ) ) {
41104118 if ( sandbox . verbose ) {
41114119 sandbox . log ( 'clearInterval() => cleared' , 'info' ) ;
@@ -4121,7 +4129,7 @@ export function sandBox(
41214129 setTimeout : function ( callback : ( args ?: any [ ] ) => void , ms : number , ...args : any [ ] ) : NodeJS . Timeout | null {
41224130 if ( typeof callback === 'function' ) {
41234131 const to = setTimeout ( ( ) => {
4124- // IO-10: Set.delete – O(1) statt Array.indexOf+splice O(n)
4132+ // IO-10: Set.delete – O(1) instead of Array.indexOf+splice O(n)
41254133 script . timeouts . delete ( to ) ;
41264134
41274135 try {
@@ -4133,15 +4141,15 @@ export function sandBox(
41334141 if ( sandbox . verbose ) {
41344142 sandbox . log ( `setTimeout(ms=${ ms } )` , 'info' ) ;
41354143 }
4136- // IO-10: Set.add – O(1) statt Array.push
4144+ // IO-10: Set.add – O(1) instead of Array.push
41374145 script . timeouts . add ( to ) ;
41384146 return to ;
41394147 }
41404148 sandbox . log ( `Invalid callback for setTimeout! - ${ typeof callback } ` , 'error' ) ;
41414149 return null ;
41424150 } ,
41434151 clearTimeout : function ( id : NodeJS . Timeout ) : void {
4144- // IO-10: Set.has/delete – O(1) statt Array.indexOf+splice O(n)
4152+ // IO-10: Set.has/delete – O(1) instead of Array.indexOf+splice O(n)
41454153 if ( script . timeouts . has ( id ) ) {
41464154 if ( sandbox . verbose ) {
41474155 sandbox . log ( 'clearTimeout() => cleared' , 'info' ) ;
0 commit comments