@@ -31,7 +31,7 @@ import {
3131 extractKeyExpression ,
3232 ITEM_IS_KEY ,
3333} from './helpers.ts'
34- import { collectExpressionDependencies , collectTemplateSetupStatements } from './binding-resolver.ts'
34+ import { collectExpressionDependencies , collectTemplateSetupStatements , isStateDep } from './binding-resolver.ts'
3535import type { StateRefMeta } from '../parse/state-refs.ts'
3636import {
3737 resolveHelperCallExpression ,
@@ -92,9 +92,7 @@ export function analyzeAttributes(
9292 if ( templateSetupContext && ! t . isJSXEmptyExpression ( expr ) ) {
9393 const setupStatements = collectTemplateSetupStatements ( expr , templateSetupContext )
9494 const dependencies = collectExpressionDependencies ( expr , stateRefs , setupStatements )
95- const stateDeps = dependencies . filter (
96- ( d ) => d . storeVar || ( d . pathParts . length > 0 && d . pathParts [ 0 ] !== 'props' ) ,
97- )
95+ const stateDeps = dependencies . filter ( isStateDep )
9896 if ( stateDeps . length > 0 ) {
9997 const selector = generateSelector ( elementPath )
10098 propBindings . push ( {
@@ -153,7 +151,7 @@ export function analyzeAttributes(
153151 if ( isNativeElement && templateSetupContext && ! t . isJSXEmptyExpression ( expr ) ) {
154152 const setupStatements = collectTemplateSetupStatements ( expr , templateSetupContext )
155153 const dependencies = collectExpressionDependencies ( expr , stateRefs , setupStatements )
156- const stateDeps = dependencies . filter ( ( d ) => d . storeVar || ( d . pathParts . length > 0 && d . pathParts [ 0 ] !== 'props' ) )
154+ const stateDeps = dependencies . filter ( isStateDep )
157155 if ( stateDeps . length > 0 ) {
158156 const selector = generateSelector ( elementPath )
159157 propBindings . push ( {
@@ -793,6 +791,22 @@ function handleTextBinding(
793791 ...( textNodeIndex !== undefined ? { textNodeIndex } : { } ) ,
794792 } ) ) ,
795793 )
794+ const templateStateDeps = collectExpressionDependencies ( derivedTemplateExpr , stateRefs , setupStatements ) . filter (
795+ isStateDep ,
796+ )
797+ if ( templateStateDeps . length > 0 ) {
798+ const stateOnlyBinding : PropBinding = {
799+ propName : '__state__' ,
800+ selector,
801+ type : 'text' ,
802+ elementPath : [ ...elementPath ] ,
803+ expression : t . cloneNode ( derivedTemplateExpr , true ) as t . Expression ,
804+ setupStatements : setupStatements . map ( ( s ) => t . cloneNode ( s , true ) as t . Statement ) ,
805+ stateOnly : true ,
806+ }
807+ if ( textNodeIndex !== undefined ) stateOnlyBinding . textNodeIndex = textNodeIndex
808+ propBindings . push ( stateOnlyBinding )
809+ }
796810 return
797811 }
798812 }
@@ -811,6 +825,26 @@ function handleTextBinding(
811825 for ( const d of derived ) d . textNodeIndex = textNodeIndex
812826 }
813827 propBindings . push ( ...derived )
828+ // When the expression also has state deps, add a stateOnly binding so the state
829+ // observer reads this.props.X live rather than inheriting `value` from the prop
830+ // binding's patch body (where `value` is the incoming prop value, not the new state).
831+ const setupStatements = derived [ 0 ] . setupStatements
832+ const stateDeps = collectExpressionDependencies ( expr as t . Expression , stateRefs , setupStatements ?? [ ] ) . filter (
833+ isStateDep ,
834+ )
835+ if ( stateDeps . length > 0 ) {
836+ const stateOnlyBinding : PropBinding = {
837+ propName : '__state__' ,
838+ selector : generateSelector ( elementPath ) ,
839+ type : 'text' ,
840+ elementPath : [ ...elementPath ] ,
841+ expression : t . cloneNode ( expr , true ) as t . Expression ,
842+ setupStatements,
843+ stateOnly : true ,
844+ }
845+ if ( textNodeIndex !== undefined ) stateOnlyBinding . textNodeIndex = textNodeIndex
846+ propBindings . push ( stateOnlyBinding )
847+ }
814848 return
815849 }
816850 }
@@ -875,7 +909,7 @@ function handleTextBinding(
875909 : expr
876910 const setupStatements = collectTemplateSetupStatements ( exprToUse , templateSetupContext )
877911 const dependencies = collectExpressionDependencies ( exprToUse , stateRefs , setupStatements )
878- const stateDeps = dependencies . filter ( ( d ) => d . storeVar || ( d . pathParts . length > 0 && d . pathParts [ 0 ] !== 'props' ) )
912+ const stateDeps = dependencies . filter ( isStateDep )
879913 if ( stateDeps . length > 0 ) {
880914 const selector = generateSelector ( elementPath )
881915 const isChildrenPropBinding =
0 commit comments