@@ -1078,6 +1078,109 @@ test('local function reference with use server stays server', async () => {
10781078 }
10791079} )
10801080
1081+ test ( 'infers client when const function reference passed as prop' , async ( ) => {
1082+ const project = createProject ( {
1083+ 'Toggle.tsx' : [
1084+ 'export function Toggle() {' ,
1085+ ' const handleEnter = () => {};' ,
1086+ ' return <div onMouseEnter={handleEnter} />;' ,
1087+ '}' ,
1088+ ] . join ( '\n' ) ,
1089+ } )
1090+
1091+ try {
1092+ const analyzer = createAnalyzer ( project . host )
1093+ const filePath = project . filePath ( 'Toggle.tsx' )
1094+ const source = project . readFile ( 'Toggle.tsx' )
1095+ const scope : ScopeConfig = {
1096+ declaration : true ,
1097+ element : false ,
1098+ export : false ,
1099+ import : false ,
1100+ type : false ,
1101+ }
1102+ const usages = await analyzer . analyzeDocument (
1103+ filePath ,
1104+ source ,
1105+ project . signature ( 'Toggle.tsx' ) ,
1106+ scope ,
1107+ )
1108+
1109+ expect ( usages . length ) . toBe ( 1 )
1110+ expect ( usages [ 0 ] ?. kind ) . toBe ( 'client' )
1111+ } finally {
1112+ project [ Symbol . dispose ] ( )
1113+ }
1114+ } )
1115+
1116+ test ( 'forwardRef component infers client from function props' , async ( ) => {
1117+ const project = createProject ( {
1118+ 'Button.tsx' : [
1119+ 'const Button = forwardRef((props) => {' ,
1120+ ' return <button onClick={() => {}} />;' ,
1121+ '});' ,
1122+ ] . join ( '\n' ) ,
1123+ } )
1124+
1125+ try {
1126+ const analyzer = createAnalyzer ( project . host )
1127+ const filePath = project . filePath ( 'Button.tsx' )
1128+ const source = project . readFile ( 'Button.tsx' )
1129+ const scope : ScopeConfig = {
1130+ declaration : true ,
1131+ element : false ,
1132+ export : false ,
1133+ import : false ,
1134+ type : false ,
1135+ }
1136+ const usages = await analyzer . analyzeDocument (
1137+ filePath ,
1138+ source ,
1139+ project . signature ( 'Button.tsx' ) ,
1140+ scope ,
1141+ )
1142+
1143+ expect ( usages . length ) . toBe ( 1 )
1144+ expect ( usages [ 0 ] ?. kind ) . toBe ( 'client' )
1145+ } finally {
1146+ project [ Symbol . dispose ] ( )
1147+ }
1148+ } )
1149+
1150+ test ( 'async arrow component stays server even with function props' , async ( ) => {
1151+ const project = createProject ( {
1152+ 'Page.tsx' : [
1153+ 'const Page = async () => {' ,
1154+ ' return <div onClick={() => {}} />;' ,
1155+ '};' ,
1156+ ] . join ( '\n' ) ,
1157+ } )
1158+
1159+ try {
1160+ const analyzer = createAnalyzer ( project . host )
1161+ const filePath = project . filePath ( 'Page.tsx' )
1162+ const source = project . readFile ( 'Page.tsx' )
1163+ const scope : ScopeConfig = {
1164+ declaration : true ,
1165+ element : false ,
1166+ export : false ,
1167+ import : false ,
1168+ type : false ,
1169+ }
1170+ const usages = await analyzer . analyzeDocument (
1171+ filePath ,
1172+ source ,
1173+ project . signature ( 'Page.tsx' ) ,
1174+ scope ,
1175+ )
1176+
1177+ expect ( usages . length ) . toBe ( 1 )
1178+ expect ( usages [ 0 ] ?. kind ) . toBe ( 'server' )
1179+ } finally {
1180+ project [ Symbol . dispose ] ( )
1181+ }
1182+ } )
1183+
10811184test ( 'arrow component infers client from function props' , async ( ) => {
10821185 const project = createProject ( {
10831186 'Toggle.tsx' : [
0 commit comments