@@ -118,6 +118,79 @@ function buildPropertyPath(memberExpr) {
118118 return parts . join ( '.' ) ;
119119}
120120
121+ // Replace all references to original variables with temp variables
122+ // and wrap literal assignments in strandsNode calls
123+ function replaceReferences ( node , tempVarMap ) {
124+ const internalReplaceReferences = ( node ) => {
125+ if ( ! node || typeof node !== 'object' ) return ;
126+
127+ // Check if this MemberExpression matches a tracked property path
128+ if ( node . type === 'MemberExpression' ) {
129+ const propName = node . property . name || node . property . value ;
130+ if ( isSwizzle ( propName ) ) {
131+ // For swizzles, only replace the object part, keep the swizzle
132+ internalReplaceReferences ( node . object ) ;
133+ return ;
134+ }
135+ const propertyPath = buildPropertyPath ( node ) ;
136+ if ( propertyPath && tempVarMap . has ( propertyPath ) ) {
137+ // Replace entire member expression with temp variable
138+ Object . assign ( node , {
139+ type : 'Identifier' ,
140+ name : tempVarMap . get ( propertyPath )
141+ } ) ;
142+ return ; // Don't recurse into replaced node
143+ }
144+ }
145+
146+ // Handle simple identifier replacements
147+ if ( node . type === 'Identifier' && tempVarMap . has ( node . name ) ) {
148+ node . name = tempVarMap . get ( node . name ) ;
149+ }
150+
151+ // Handle literal assignments to temp variables
152+ if ( node . type === 'AssignmentExpression' ) {
153+ let leftPath = null ;
154+ if ( node . left . type === 'Identifier' ) {
155+ leftPath = node . left . name ;
156+ } else if ( node . left . type === 'MemberExpression' ) {
157+ leftPath = buildPropertyPath ( node . left ) ;
158+ }
159+
160+ if ( leftPath && tempVarMap . has ( leftPath ) &&
161+ ( node . right . type === 'Literal' || node . right . type === 'ArrayExpression' ) ) {
162+ // Wrap the right hand side in a strandsNode call to make sure
163+ // it's not just a literal and has a type
164+ node . right = {
165+ type : 'CallExpression' ,
166+ callee : {
167+ type : 'Identifier' ,
168+ name : '__p5.strandsNode'
169+ } ,
170+ arguments : [ node . right ]
171+ } ;
172+ }
173+ }
174+
175+ // Recursively process all properties
176+ for ( const key in node ) {
177+ if ( node . hasOwnProperty ( key ) && key !== 'parent' ) {
178+ // Don't recurse into property names of non-computed member expressions
179+ if ( node . type === 'MemberExpression' && key === 'property' && ! node . computed ) {
180+ continue ;
181+ }
182+ if ( Array . isArray ( node [ key ] ) ) {
183+ node [ key ] . forEach ( internalReplaceReferences ) ;
184+ } else if ( typeof node [ key ] === 'object' ) {
185+ internalReplaceReferences ( node [ key ] ) ;
186+ }
187+ }
188+ }
189+ } ;
190+
191+ internalReplaceReferences ( node ) ;
192+ }
193+
121194const ASTCallbacks = {
122195 UnaryExpression ( node , _state , ancestors ) {
123196 if ( ancestors . some ( nodeIsUniform ) ) { return ; }
@@ -538,76 +611,8 @@ const ASTCallbacks = {
538611 kind : 'let'
539612 } ) ;
540613 }
541- // Replace all references to original variables with temp variables
542- // and wrap literal assignments in strandsNode calls
543- const replaceReferences = ( node ) => {
544- if ( ! node || typeof node !== 'object' ) return ;
545-
546- // Check if this MemberExpression matches a tracked property path
547- if ( node . type === 'MemberExpression' ) {
548- const propName = node . property . name || node . property . value ;
549- if ( isSwizzle ( propName ) ) {
550- // For swizzles, only replace the object part, keep the swizzle
551- replaceReferences ( node . object ) ;
552- return ;
553- }
554- const propertyPath = buildPropertyPath ( node ) ;
555- if ( propertyPath && tempVarMap . has ( propertyPath ) ) {
556- // Replace entire member expression with temp variable
557- Object . assign ( node , {
558- type : 'Identifier' ,
559- name : tempVarMap . get ( propertyPath )
560- } ) ;
561- return ; // Don't recurse into replaced node
562- }
563- }
564-
565- // Handle simple identifier replacements
566- if ( node . type === 'Identifier' && tempVarMap . has ( node . name ) ) {
567- node . name = tempVarMap . get ( node . name ) ;
568- }
569-
570- // Handle literal assignments to temp variables
571- if ( node . type === 'AssignmentExpression' ) {
572- let leftPath = null ;
573- if ( node . left . type === 'Identifier' ) {
574- leftPath = node . left . name ;
575- } else if ( node . left . type === 'MemberExpression' ) {
576- leftPath = buildPropertyPath ( node . left ) ;
577- }
578-
579- if ( leftPath && tempVarMap . has ( leftPath ) &&
580- ( node . right . type === 'Literal' || node . right . type === 'ArrayExpression' ) ) {
581- // Wrap the right hand side in a strandsNode call to make sure
582- // it's not just a literal and has a type
583- node . right = {
584- type : 'CallExpression' ,
585- callee : {
586- type : 'Identifier' ,
587- name : '__p5.strandsNode'
588- } ,
589- arguments : [ node . right ]
590- } ;
591- }
592- }
593-
594- // Recursively process all properties
595- for ( const key in node ) {
596- if ( node . hasOwnProperty ( key ) && key !== 'parent' ) {
597- // Don't recurse into property names of non-computed member expressions
598- if ( node . type === 'MemberExpression' && key === 'property' && ! node . computed ) {
599- continue ;
600- }
601- if ( Array . isArray ( node [ key ] ) ) {
602- node [ key ] . forEach ( replaceReferences ) ;
603- } else if ( typeof node [ key ] === 'object' ) {
604- replaceReferences ( node [ key ] ) ;
605- }
606- }
607- }
608- } ;
609614 // Apply reference replacement to all statements
610- functionBody . body . forEach ( replaceReferences ) ;
615+ functionBody . body . forEach ( node => replaceReferences ( node , tempVarMap ) ) ;
611616 // Insert copy statements at the beginning
612617 functionBody . body . unshift ( ...copyStatements ) ;
613618 // Add return statement with flat object using property paths as keys
@@ -971,46 +976,7 @@ const ASTCallbacks = {
971976 } ) ;
972977 }
973978
974- // Replace references to original variables with temp variables
975- const replaceReferences = ( node ) => {
976- if ( ! node || typeof node !== 'object' ) return ;
977-
978- if ( node . type === 'MemberExpression' ) {
979- const propName = node . property . name || node . property . value ;
980- if ( isSwizzle ( propName ) ) {
981- replaceReferences ( node . object ) ;
982- return ;
983- }
984- const propertyPath = buildPropertyPath ( node ) ;
985- if ( propertyPath && tempVarMap . has ( propertyPath ) ) {
986- Object . assign ( node , {
987- type : 'Identifier' ,
988- name : tempVarMap . get ( propertyPath )
989- } ) ;
990- return ;
991- }
992- }
993-
994- if ( node . type === 'Identifier' && tempVarMap . has ( node . name ) ) {
995- node . name = tempVarMap . get ( node . name ) ;
996- }
997-
998- for ( const key in node ) {
999- if ( node . hasOwnProperty ( key ) && key !== 'parent' ) {
1000- // Don't recurse into property names of non-computed member expressions
1001- if ( node . type === 'MemberExpression' && key === 'property' && ! node . computed ) {
1002- continue ;
1003- }
1004- if ( Array . isArray ( node [ key ] ) ) {
1005- node [ key ] . forEach ( replaceReferences ) ;
1006- } else if ( typeof node [ key ] === 'object' ) {
1007- replaceReferences ( node [ key ] ) ;
1008- }
1009- }
1010- }
1011- } ;
1012-
1013- functionBody . body . forEach ( replaceReferences ) ;
979+ functionBody . body . forEach ( node => replaceReferences ( node , tempVarMap ) ) ;
1014980 functionBody . body . unshift ( ...copyStatements ) ;
1015981
1016982 // Add return statement with flat object using property paths as keys
0 commit comments