@@ -461,6 +461,11 @@ function codegenReactiveScope(
461461) : void {
462462 const cacheStoreStatements : Array < t . Statement > = [ ] ;
463463 const cacheLoadStatements : Array < t . Statement > = [ ] ;
464+ const cacheLoads : Array < {
465+ name : t . Identifier ;
466+ index : number ;
467+ value : t . Expression ;
468+ } > = [ ] ;
464469 const changeExpressions : Array < t . Expression > = [ ] ;
465470 const changeExpressionComments : Array < string > = [ ] ;
466471 const outputComments : Array < string > = [ ] ;
@@ -488,6 +493,10 @@ function codegenReactiveScope(
488493 } else {
489494 changeExpressions . push ( comparison ) ;
490495 }
496+ /*
497+ * Adding directly to cacheStoreStatements rather than cacheLoads, because there
498+ * is no corresponding cacheLoadStatement for dependencies
499+ */
491500 cacheStoreStatements . push (
492501 t . expressionStatement (
493502 t . assignmentExpression (
@@ -523,32 +532,7 @@ function codegenReactiveScope(
523532 t . variableDeclaration ( "let" , [ t . variableDeclarator ( name ) ] )
524533 ) ;
525534 }
526- cacheStoreStatements . push (
527- t . expressionStatement (
528- t . assignmentExpression (
529- "=" ,
530- t . memberExpression (
531- t . identifier ( cx . synthesizeName ( "$" ) ) ,
532- t . numericLiteral ( index ) ,
533- true
534- ) ,
535- wrapCacheDep ( cx , name )
536- )
537- )
538- ) ;
539- cacheLoadStatements . push (
540- t . expressionStatement (
541- t . assignmentExpression (
542- "=" ,
543- name ,
544- t . memberExpression (
545- t . identifier ( cx . synthesizeName ( "$" ) ) ,
546- t . numericLiteral ( index ) ,
547- true
548- )
549- )
550- )
551- ) ;
535+ cacheLoads . push ( { name, index, value : wrapCacheDep ( cx , name ) } ) ;
552536 cx . declare ( identifier ) ;
553537 }
554538 for ( const reassignment of scope . reassignments ) {
@@ -558,34 +542,9 @@ function codegenReactiveScope(
558542 }
559543 const name = convertIdentifier ( reassignment ) ;
560544 outputComments . push ( name . name ) ;
561-
562- cacheStoreStatements . push (
563- t . expressionStatement (
564- t . assignmentExpression (
565- "=" ,
566- t . memberExpression (
567- t . identifier ( cx . synthesizeName ( "$" ) ) ,
568- t . numericLiteral ( index ) ,
569- true
570- ) ,
571- wrapCacheDep ( cx , name )
572- )
573- )
574- ) ;
575- cacheLoadStatements . push (
576- t . expressionStatement (
577- t . assignmentExpression (
578- "=" ,
579- name ,
580- t . memberExpression (
581- t . identifier ( cx . synthesizeName ( "$" ) ) ,
582- t . numericLiteral ( index ) ,
583- true
584- )
585- )
586- )
587- ) ;
545+ cacheLoads . push ( { name, index, value : wrapCacheDep ( cx , name ) } ) ;
588546 }
547+
589548 let testCondition = ( changeExpressions as Array < t . Expression > ) . reduce (
590549 ( acc : t . Expression | null , ident : t . Expression ) => {
591550 if ( acc == null ) {
@@ -632,67 +591,116 @@ function codegenReactiveScope(
632591 ) ;
633592 }
634593 let computationBlock = codegenBlock ( cx , block ) ;
594+
635595 let memoStatement ;
636- const memoBlock = t . blockStatement ( cacheLoadStatements ) ;
637596 if (
638597 cx . env . config . enableChangeDetectionForDebugging != null &&
639598 changeExpressions . length > 0
640599 ) {
641600 const detectionFunction =
642601 cx . env . config . enableChangeDetectionForDebugging . importSpecifierName ;
602+ const cacheLoadOldValueStatements : Array < t . Statement > = [ ] ;
643603 const changeDetectionStatements : Array < t . Statement > = [ ] ;
644- const oldVarDeclarationStatements : Array < t . Statement > = [ ] ;
645- memoBlock . body . forEach ( ( stmt ) => {
646- if (
647- stmt . type === "ExpressionStatement" &&
648- stmt . expression . type === "AssignmentExpression" &&
649- stmt . expression . left . type === "Identifier"
650- ) {
651- const name = stmt . expression . left . name ;
652- const loadName = cx . synthesizeName ( `old$${ name } ` ) ;
653- oldVarDeclarationStatements . push (
654- t . variableDeclaration ( "let" , [
655- t . variableDeclarator ( t . identifier ( loadName ) ) ,
604+ const idempotenceDetectionStatements : Array < t . Statement > = [ ] ;
605+
606+ for ( const { name, index, value } of cacheLoads ) {
607+ const loadName = cx . synthesizeName ( `old$${ name . name } ` ) ;
608+ const slot = t . memberExpression (
609+ t . identifier ( cx . synthesizeName ( "$" ) ) ,
610+ t . numericLiteral ( index ) ,
611+ true
612+ ) ;
613+ cacheStoreStatements . push (
614+ t . expressionStatement ( t . assignmentExpression ( "=" , slot , value ) )
615+ ) ;
616+ cacheLoadOldValueStatements . push (
617+ t . variableDeclaration ( "let" , [
618+ t . variableDeclarator ( t . identifier ( loadName ) , slot ) ,
619+ ] )
620+ ) ;
621+ changeDetectionStatements . push (
622+ t . expressionStatement (
623+ t . callExpression ( t . identifier ( detectionFunction ) , [
624+ t . identifier ( loadName ) ,
625+ name ,
626+ t . stringLiteral ( name . name ) ,
627+ t . stringLiteral ( cx . fnName ) ,
628+ t . stringLiteral ( "cached" ) ,
656629 ] )
657- ) ;
658- stmt . expression . left = t . identifier ( loadName ) ;
659- changeDetectionStatements . push (
660- t . expressionStatement (
661- t . callExpression ( t . identifier ( detectionFunction ) , [
662- t . identifier ( loadName ) ,
663- t . identifier ( name ) ,
664- t . stringLiteral ( name ) ,
665- t . stringLiteral ( cx . fnName ) ,
666- ] )
667- )
668- ) ;
669- changeDetectionStatements . push (
670- t . expressionStatement (
671- t . assignmentExpression (
672- "=" ,
673- t . identifier ( name ) ,
674- t . identifier ( loadName )
675- )
676- )
677- ) ;
678- }
679- } ) ;
630+ )
631+ ) ;
632+ idempotenceDetectionStatements . push (
633+ t . expressionStatement (
634+ t . callExpression ( t . identifier ( detectionFunction ) , [
635+ slot ,
636+ name ,
637+ t . stringLiteral ( name . name ) ,
638+ t . stringLiteral ( cx . fnName ) ,
639+ t . stringLiteral ( "recomputed" ) ,
640+ ] )
641+ )
642+ ) ;
643+ idempotenceDetectionStatements . push (
644+ t . expressionStatement ( t . assignmentExpression ( "=" , name , slot ) )
645+ ) ;
646+ }
647+ const condition = cx . synthesizeName ( "condition" ) ;
680648 memoStatement = t . blockStatement ( [
681649 ...computationBlock . body ,
650+ t . variableDeclaration ( "let" , [
651+ t . variableDeclarator ( t . identifier ( condition ) , testCondition ) ,
652+ ] ) ,
682653 t . ifStatement (
683- t . unaryExpression ( "!" , testCondition ) ,
654+ t . unaryExpression ( "!" , t . identifier ( condition ) ) ,
684655 t . blockStatement ( [
685- ...oldVarDeclarationStatements ,
686- ...memoBlock . body ,
656+ ...cacheLoadOldValueStatements ,
687657 ...changeDetectionStatements ,
688658 ] )
689659 ) ,
690660 ...cacheStoreStatements ,
661+ t . ifStatement (
662+ t . identifier ( condition ) ,
663+ t . blockStatement ( [
664+ ...computationBlock . body ,
665+ ...idempotenceDetectionStatements ,
666+ ] )
667+ ) ,
691668 ] ) ;
692669 } else {
670+ for ( const { name, index, value } of cacheLoads ) {
671+ cacheStoreStatements . push (
672+ t . expressionStatement (
673+ t . assignmentExpression (
674+ "=" ,
675+ t . memberExpression (
676+ t . identifier ( cx . synthesizeName ( "$" ) ) ,
677+ t . numericLiteral ( index ) ,
678+ true
679+ ) ,
680+ value
681+ )
682+ )
683+ ) ;
684+ cacheLoadStatements . push (
685+ t . expressionStatement (
686+ t . assignmentExpression (
687+ "=" ,
688+ name ,
689+ t . memberExpression (
690+ t . identifier ( cx . synthesizeName ( "$" ) ) ,
691+ t . numericLiteral ( index ) ,
692+ true
693+ )
694+ )
695+ )
696+ ) ;
697+ }
693698 computationBlock . body . push ( ...cacheStoreStatements ) ;
694-
695- memoStatement = t . ifStatement ( testCondition , computationBlock , memoBlock ) ;
699+ memoStatement = t . ifStatement (
700+ testCondition ,
701+ computationBlock ,
702+ t . blockStatement ( cacheLoadStatements )
703+ ) ;
696704 }
697705
698706 if ( cx . env . config . enableMemoizationComments ) {
@@ -734,9 +742,9 @@ function codegenReactiveScope(
734742 true
735743 ) ;
736744 }
737- if ( memoBlock . body . length > 0 ) {
745+ if ( cacheLoadStatements . length > 0 ) {
738746 t . addComment (
739- memoBlock . body [ 0 ] ! ,
747+ cacheLoadStatements [ 0 ] ! ,
740748 "leading" ,
741749 ` Inputs did not change, use cached value` ,
742750 true
0 commit comments