@@ -11,7 +11,6 @@ export function emitStylesAndImports(args: {
1111 resolverImports : Map < string , any > ;
1212 resolvedStyleObjects : Map < string , any > ;
1313 styledDecls : StyledDecl [ ] ;
14- cssHelperNames : Set < string > ;
1514 isAstNode : ( v : unknown ) => boolean ;
1615 objectToAst : ( j : any , v : Record < string , unknown > ) => any ;
1716 literalToAst : ( j : any , v : unknown ) => any ;
@@ -24,7 +23,6 @@ export function emitStylesAndImports(args: {
2423 resolverImports,
2524 resolvedStyleObjects,
2625 styledDecls,
27- cssHelperNames,
2826 isAstNode,
2927 objectToAst,
3028 literalToAst,
@@ -513,163 +511,8 @@ export function emitStylesAndImports(args: {
513511 ( stylesDecl as any ) . comments = deduped ;
514512 }
515513
516- // If styles reference identifiers declared later in the file (e.g. string-interpolation fixture),
517- // insert `styles` after the last such declaration to satisfy StyleX evaluation order.
518- const referencedIdents = new Set < string > ( ) ;
519- {
520- const seen = new WeakSet < object > ( ) ;
521- const visit = ( cur : any ) => {
522- if ( ! cur ) {
523- return ;
524- }
525- if ( Array . isArray ( cur ) ) {
526- for ( const c of cur ) {
527- visit ( c ) ;
528- }
529- return ;
530- }
531- if ( typeof cur !== "object" ) {
532- return ;
533- }
534- if ( seen . has ( cur as object ) ) {
535- return ;
536- }
537- seen . add ( cur as object ) ;
538- if ( cur . type === "Identifier" && typeof cur . name === "string" ) {
539- referencedIdents . add ( cur . name ) ;
540- }
541- for ( const v of Object . values ( cur ) ) {
542- if ( typeof v === "object" ) {
543- visit ( v ) ;
544- }
545- }
546- } ;
547- for ( const v of resolvedStyleObjects . values ( ) ) {
548- if ( isAstNode ( v ) ) {
549- visit ( v ) ;
550- } else if ( v && typeof v === "object" ) {
551- visit ( objectToAst ( j , v as any ) ) ;
552- }
553- }
554- }
555-
514+ // Place `styles` at the very end of the file.
515+ // This keeps component logic first, styles last for better readability.
556516 const programBody = root . get ( ) . node . program . body as any [ ] ;
557- const declsRefIdx = ( ( ) => {
558- let last = - 1 ;
559- for ( let i = 0 ; i < programBody . length ; i ++ ) {
560- const stmt = programBody [ i ] ;
561- if ( ! stmt ) {
562- continue ;
563- }
564- if ( stmt . type === "VariableDeclaration" ) {
565- for ( const d of stmt . declarations ?? [ ] ) {
566- const id = d ?. id ;
567- if ( id ?. type === "Identifier" && referencedIdents . has ( id . name ) ) {
568- last = i ;
569- }
570- }
571- } else if ( stmt . type === "FunctionDeclaration" ) {
572- const id = stmt . id ;
573- if ( id ?. type === "Identifier" && referencedIdents . has ( id . name ) ) {
574- last = i ;
575- }
576- }
577- }
578- return last >= 0 ? last : null ;
579- } ) ( ) ;
580-
581- // Try to place `styles` where the first styled component declaration used to be:
582- // insert right before the earliest styled decl statement (i.e. after the statement before it).
583- const firstStyledDeclInsertionAfterIdx = ( ( ) => {
584- if ( ! styledDecls . length ) {
585- return null ;
586- }
587- const styledLocalNames = new Set ( styledDecls . map ( ( d ) => d . localName ) ) ;
588- let firstIdx : number | null = null ;
589- for ( let i = 0 ; i < programBody . length ; i ++ ) {
590- const stmt = programBody [ i ] ;
591- if ( stmt ?. type !== "VariableDeclaration" ) {
592- continue ;
593- }
594- for ( const d of stmt . declarations ?? [ ] ) {
595- const id = d ?. id ;
596- if ( id ?. type !== "Identifier" ) {
597- continue ;
598- }
599- if ( ! styledLocalNames . has ( id . name ) ) {
600- continue ;
601- }
602- firstIdx = firstIdx === null ? i : Math . min ( firstIdx , i ) ;
603- }
604- }
605- return firstIdx === null ? null : firstIdx - 1 ;
606- } ) ( ) ;
607-
608- const lastImportIdx = ( ( ) => {
609- let last = - 1 ;
610- for ( let i = 0 ; i < programBody . length ; i ++ ) {
611- if ( programBody [ i ] ?. type === "ImportDeclaration" ) {
612- last = i ;
613- }
614- }
615- return last ;
616- } ) ( ) ;
617-
618- const lastKeyframesIdx = ( ( ) => {
619- let last = - 1 ;
620- for ( let i = 0 ; i < programBody . length ; i ++ ) {
621- const stmt = programBody [ i ] ;
622- if ( stmt ?. type !== "VariableDeclaration" ) {
623- continue ;
624- }
625- for ( const d of stmt . declarations ?? [ ] ) {
626- const init : any = d ?. init ;
627- if (
628- init &&
629- init . type === "CallExpression" &&
630- init . callee ?. type === "MemberExpression" &&
631- init . callee . object ?. type === "Identifier" &&
632- init . callee . object . name === "stylex" &&
633- init . callee . property ?. type === "Identifier" &&
634- init . callee . property . name === "keyframes"
635- ) {
636- last = i ;
637- }
638- }
639- }
640- return last ;
641- } ) ( ) ;
642-
643- const lastCssHelperIdx = ( ( ) => {
644- let last = - 1 ;
645- for ( let i = 0 ; i < programBody . length ; i ++ ) {
646- const stmt = programBody [ i ] ;
647- if ( stmt ?. type !== "VariableDeclaration" ) {
648- continue ;
649- }
650- for ( const d of stmt . declarations ?? [ ] ) {
651- const id : any = d ?. id ;
652- if ( id ?. type === "Identifier" && cssHelperNames . has ( id . name ) ) {
653- last = i ;
654- }
655- }
656- }
657- return last ;
658- } ) ( ) ;
659-
660- // Pick the latest safe insertion point: after imports, after any keyframes/css helpers,
661- // after any referenced identifier declarations, and after the original styled-decl anchor.
662- const insertAfterIdx = Math . max (
663- lastImportIdx ,
664- lastKeyframesIdx ,
665- lastCssHelperIdx ,
666- declsRefIdx ?? - 1 ,
667- firstStyledDeclInsertionAfterIdx ?? - 1 ,
668- ) ;
669-
670- if ( insertAfterIdx >= 0 ) {
671- programBody . splice ( insertAfterIdx + 1 , 0 , stylesDecl as any ) ;
672- } else {
673- programBody . unshift ( stylesDecl as any ) ;
674- }
517+ programBody . push ( stylesDecl as any ) ;
675518}
0 commit comments