@@ -50,85 +50,79 @@ export function validateNoSetStateInEffects(
5050 const errors = new CompilerError ( ) ;
5151
5252 // In order to ensure that all HIR components that could contain setState have been iterated,
53- // we run the reconnaissance logic until a stable number of state functions has been achieved.
54- // this makes setState HIR analysis order independent.
55- // We will then handle error on a separate pass.
56- let iterationSize = Number . MAX_SAFE_INTEGER ;
57- while ( iterationSize !== setStateFunctions . size ) {
58- iterationSize = setStateFunctions . size ;
59- for ( const [ , block ] of fn . body . blocks ) {
60- for ( const instr of block . instructions ) {
61- switch ( instr . value . kind ) {
62- case 'LoadLocal' : {
63- if ( setStateFunctions . has ( instr . value . place . identifier . id ) ) {
64- setStateFunctions . set (
65- instr . lvalue . identifier . id ,
66- instr . value . place ,
67- ) ;
68- }
69- break ;
53+ // we fully run the reconnaissance logic, then handle error finding on a separate pass.
54+ // This makes setState HIR error analysis order independent.
55+ for ( const [ , block ] of fn . body . blocks ) {
56+ for ( const instr of block . instructions ) {
57+ switch ( instr . value . kind ) {
58+ case 'LoadLocal' : {
59+ if ( setStateFunctions . has ( instr . value . place . identifier . id ) ) {
60+ setStateFunctions . set (
61+ instr . lvalue . identifier . id ,
62+ instr . value . place ,
63+ ) ;
7064 }
71- case 'StoreLocal' : {
72- if ( setStateFunctions . has ( instr . value . value . identifier . id ) ) {
73- setStateFunctions . set (
74- instr . value . lvalue . place . identifier . id ,
75- instr . value . value ,
76- ) ;
77- setStateFunctions . set (
78- instr . lvalue . identifier . id ,
79- instr . value . value ,
80- ) ;
81- }
82- break ;
65+ break ;
66+ }
67+ case 'StoreLocal' : {
68+ if ( setStateFunctions . has ( instr . value . value . identifier . id ) ) {
69+ setStateFunctions . set (
70+ instr . value . lvalue . place . identifier . id ,
71+ instr . value . value ,
72+ ) ;
73+ setStateFunctions . set (
74+ instr . lvalue . identifier . id ,
75+ instr . value . value ,
76+ ) ;
8377 }
84- case 'FunctionExpression' : {
85- if (
86- // faster-path to check if the function expression references a setState
87- [ ...eachInstructionValueOperand ( instr . value ) ] . some (
88- operand =>
89- isSetStateType ( operand . identifier ) ||
90- setStateFunctions . has ( operand . identifier . id ) ,
91- )
92- ) {
93- const callee = getSetStateCall (
94- instr . value . loweredFunc . func ,
95- setStateFunctions ,
96- env ,
97- ) ;
98- if ( callee !== null ) {
99- setStateFunctions . set ( instr . lvalue . identifier . id , callee ) ;
100- }
78+ break ;
79+ }
80+ case 'FunctionExpression' : {
81+ if (
82+ // faster-path to check if the function expression references a setState
83+ [ ...eachInstructionValueOperand ( instr . value ) ] . some (
84+ operand =>
85+ isSetStateType ( operand . identifier ) ||
86+ setStateFunctions . has ( operand . identifier . id ) ,
87+ )
88+ ) {
89+ const callee = getSetStateCall (
90+ instr . value . loweredFunc . func ,
91+ setStateFunctions ,
92+ env ,
93+ ) ;
94+ if ( callee !== null ) {
95+ setStateFunctions . set ( instr . lvalue . identifier . id , callee ) ;
10196 }
102- break ;
10397 }
104- case 'MethodCall' :
105- case 'CallExpression' : {
106- const callee =
107- instr . value . kind === 'MethodCall'
108- ? instr . value . property
109- : instr . value . callee ;
98+ break ;
99+ }
100+ case 'MethodCall' :
101+ case 'CallExpression' : {
102+ const callee =
103+ instr . value . kind === 'MethodCall'
104+ ? instr . value . property
105+ : instr . value . callee ;
110106
111- if ( isUseEffectEventType ( callee . identifier ) ) {
112- const arg = instr . value . args [ 0 ] ;
113- if ( arg !== undefined && arg . kind === 'Identifier' ) {
114- const setState = setStateFunctions . get ( arg . identifier . id ) ;
115- if ( setState !== undefined ) {
116- /**
117- * This effect event function calls setState synchonously,
118- * treat it as a setState function for transitive tracking
119- */
120- setStateFunctions . set ( instr . lvalue . identifier . id , setState ) ;
121- }
107+ if ( isUseEffectEventType ( callee . identifier ) ) {
108+ const arg = instr . value . args [ 0 ] ;
109+ if ( arg !== undefined && arg . kind === 'Identifier' ) {
110+ const setState = setStateFunctions . get ( arg . identifier . id ) ;
111+ if ( setState !== undefined ) {
112+ /**
113+ * This effect event function calls setState synchonously,
114+ * treat it as a setState function for transitive tracking
115+ */
116+ setStateFunctions . set ( instr . lvalue . identifier . id , setState ) ;
122117 }
123118 }
124- break ;
125119 }
120+ break ;
126121 }
127122 }
128123 }
129124 }
130125
131- // Report errors in second pass to ensure HIR has been fully evaluated at error reporting time.
132126 for ( const [ , block ] of fn . body . blocks ) {
133127 for ( const instr of block . instructions ) {
134128 if (
0 commit comments