@@ -6,7 +6,7 @@ import type { JSCodeshift } from "jscodeshift";
66import type { SelectorResolveResult } from "../../adapter.js" ;
77import type { DeclProcessingState } from "./decl-setup.js" ;
88import type { StyledDecl } from "../transform-types.js" ;
9- import type { CssDeclarationIR } from "../css-ir.js" ;
9+ import type { CssDeclarationIR , CssValuePart } from "../css-ir.js" ;
1010import { computeSelectorWarningLoc } from "../css-ir.js" ;
1111import { cssDeclarationToStylexDeclarations } from "../css-prop-mapping.js" ;
1212import { addPropComments } from "./comments.js" ;
@@ -499,6 +499,16 @@ export function processDeclRules(ctx: DeclProcessingState): void {
499499 { bailOnUnresolved : true } ,
500500 ) ;
501501 if ( result === "bail" ) {
502+ // Clear partially-processed entries from the firstBucket before
503+ // attempting the dynamic fallback. processDeclarationsIntoBucket may
504+ // have written some static declarations before encountering the
505+ // unresolvable interpolation that caused the bail. The fallback
506+ // re-processes ALL declarations itself, so stale entries in the
507+ // bucket would create duplicate outputs in finalizeRelationOverrides.
508+ for ( const key of Object . keys ( firstBucket ) ) {
509+ delete firstBucket [ key ] ;
510+ }
511+
502512 // Try dynamic style fallback before bailing: if the unresolved
503513 // interpolations are prop-based arrow functions, we can emit styleFn
504514 // entries with ancestor pseudo wrapping instead.
@@ -2069,10 +2079,11 @@ function tryDynamicRelationOverrideFallback(args: {
20692079 return false ;
20702080 }
20712081
2072- // Extract slots — only support single-slot interpolations for now
2073- const parts : Array < { kind ?: string ; slotId ?: number } > = d . value . parts ?? [ ] ;
2082+ // Extract slots — only support single-slot interpolations for now.
2083+ // After the kind === "interpolated" check above, d.value is guaranteed to have parts.
2084+ const parts : CssValuePart [ ] = ( d . value as { parts : CssValuePart [ ] } ) . parts ;
20742085 const slotParts = parts . filter (
2075- ( p ) : p is { kind : "slot" ; slotId : number } => p . kind === "slot" && p . slotId !== undefined ,
2086+ ( p ) : p is CssValuePart & { kind : "slot" ; slotId : number } => p . kind === "slot" ,
20762087 ) ;
20772088 if ( slotParts . length !== 1 ) {
20782089 return false ;
@@ -2148,16 +2159,12 @@ function tryDynamicRelationOverrideFallback(args: {
21482159 }
21492160
21502161 // Build { default: null, [stylex.when.ancestor(pseudo, marker?)]: paramExpr }
2151- const pseudoEntries = ancestorPseudos . map ( ( pseudo ) => {
2152- const ancestorKey = makeAncestorKeyExpr ( j , pseudo , markerVarName ) ;
2153- return Object . assign ( j . property ( "init" , ancestorKey , j . identifier ( outParamName ) ) , {
2154- computed : true ,
2155- } ) ;
2156- } ) ;
2157- const conditionalMap = j . objectExpression ( [
2158- j . property ( "init" , j . identifier ( "default" ) , j . literal ( null ) ) ,
2159- ...pseudoEntries ,
2160- ] ) ;
2162+ const conditionalMap = buildAncestorPseudoMap (
2163+ j ,
2164+ j . identifier ( outParamName ) ,
2165+ ancestorPseudos ,
2166+ markerVarName ,
2167+ ) ;
21612168
21622169 const cssPropKeyNode = makeCssPropKey ( j , out . prop ) ;
21632170 const bodyProp = j . property ( "init" , cssPropKeyNode , conditionalMap ) ;
0 commit comments