@@ -47,6 +47,43 @@ type ValidationContext = {
4747class DerivationCache {
4848 hasChanges : boolean = false ;
4949 cache : Map < IdentifierId , DerivationMetadata > = new Map ( ) ;
50+ private previousCache : Map < IdentifierId , DerivationMetadata > | null = null ;
51+
52+ takeSnapshot ( ) : void {
53+ this . previousCache = new Map ( ) ;
54+ for ( const [ key , value ] of this . cache . entries ( ) ) {
55+ this . previousCache . set ( key , {
56+ place : value . place ,
57+ sourcesIds : new Set ( value . sourcesIds ) ,
58+ typeOfValue : value . typeOfValue ,
59+ } ) ;
60+ }
61+ }
62+
63+ checkForChanges ( ) : void {
64+ if ( this . previousCache === null ) {
65+ this . hasChanges = true ;
66+ return ;
67+ }
68+
69+ for ( const [ key , value ] of this . cache . entries ( ) ) {
70+ const previousValue = this . previousCache . get ( key ) ;
71+ if (
72+ previousValue === undefined ||
73+ ! this . isDerivationEqual ( previousValue , value )
74+ ) {
75+ this . hasChanges = true ;
76+ return ;
77+ }
78+ }
79+
80+ if ( this . cache . size !== this . previousCache . size ) {
81+ this . hasChanges = true ;
82+ return ;
83+ }
84+
85+ this . hasChanges = false ;
86+ }
5087
5188 snapshot ( ) : boolean {
5289 const hasChanges = this . hasChanges ;
@@ -92,14 +129,7 @@ class DerivationCache {
92129 newValue . sourcesIds . add ( derivedVar . identifier . id ) ;
93130 }
94131
95- const existingValue = this . cache . get ( derivedVar . identifier . id ) ;
96- if (
97- existingValue === undefined ||
98- ! this . isDerivationEqual ( existingValue , newValue )
99- ) {
100- this . cache . set ( derivedVar . identifier . id , newValue ) ;
101- this . hasChanges = true ;
102- }
132+ this . cache . set ( derivedVar . identifier . id , newValue ) ;
103133 }
104134
105135 private isDerivationEqual (
@@ -175,7 +205,6 @@ export function validateNoDerivedComputationsInEffects_exp(
175205 sourcesIds : new Set ( [ param . identifier . id ] ) ,
176206 typeOfValue : 'fromProps' ,
177207 } ) ;
178- context . derivationCache . hasChanges = true ;
179208 }
180209 }
181210 } else if ( fn . fnType === 'Component' ) {
@@ -186,19 +215,21 @@ export function validateNoDerivedComputationsInEffects_exp(
186215 sourcesIds : new Set ( [ props . identifier . id ] ) ,
187216 typeOfValue : 'fromProps' ,
188217 } ) ;
189- context . derivationCache . hasChanges = true ;
190218 }
191219 }
192220
193221 let isFirstPass = true ;
194222 do {
223+ context . derivationCache . takeSnapshot ( ) ;
224+
195225 for ( const block of fn . body . blocks . values ( ) ) {
196- recordPhiDerivations ( block , context ) ;
197226 for ( const instr of block . instructions ) {
198227 recordInstructionDerivations ( instr , context , isFirstPass ) ;
199228 }
229+ recordPhiDerivations ( block , context ) ;
200230 }
201231
232+ context . derivationCache . checkForChanges ( ) ;
202233 isFirstPass = false ;
203234 } while ( context . derivationCache . snapshot ( ) ) ;
204235
@@ -330,12 +361,20 @@ function recordInstructionDerivations(
330361 case Effect . ConditionallyMutate :
331362 case Effect . ConditionallyMutateIterator :
332363 case Effect . Mutate : {
333- if ( isMutable ( instr , operand ) ) {
334- context . derivationCache . addDerivationEntry (
335- operand ,
336- sources ,
337- typeOfValue ,
364+ if (
365+ isMutable ( instr , operand ) &&
366+ context . derivationCache . cache . has ( operand . identifier . id )
367+ ) {
368+ const operandMetadata = context . derivationCache . cache . get (
369+ operand . identifier . id ,
338370 ) ;
371+
372+ if ( operandMetadata !== undefined ) {
373+ operandMetadata . typeOfValue = joinValue (
374+ typeOfValue ,
375+ operandMetadata . typeOfValue ,
376+ ) ;
377+ }
339378 }
340379 break ;
341380 }
0 commit comments