@barefootjs/jsx 0.33.0 → 0.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/analyzer.d.ts.map +1 -1
  2. package/dist/errors.d.ts +1 -0
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/index.js +145 -40
  5. package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
  6. package/dist/ir-to-client-js/control-flow/plan/build-inner-loop.d.ts.map +1 -1
  7. package/dist/ir-to-client-js/control-flow/plan/build-loop-child-arm.d.ts +8 -0
  8. package/dist/ir-to-client-js/control-flow/plan/build-loop-child-arm.d.ts.map +1 -1
  9. package/dist/ir-to-client-js/control-flow/plan/build-reactive-effects.d.ts.map +1 -1
  10. package/dist/ir-to-client-js/control-flow/plan/inner-loop.d.ts +12 -0
  11. package/dist/ir-to-client-js/control-flow/plan/inner-loop.d.ts.map +1 -1
  12. package/dist/ir-to-client-js/control-flow/stringify/inner-loop.d.ts +1 -0
  13. package/dist/ir-to-client-js/control-flow/stringify/inner-loop.d.ts.map +1 -1
  14. package/dist/ir-to-client-js/control-flow/stringify/lazy-row.d.ts.map +1 -1
  15. package/dist/ir-to-client-js/element-refs.d.ts.map +1 -1
  16. package/dist/ir-to-client-js/emit-reactive.d.ts.map +1 -1
  17. package/dist/ir-to-client-js/imports.d.ts +2 -2
  18. package/dist/ir-to-client-js/imports.d.ts.map +1 -1
  19. package/dist/ir-to-client-js/phases/provider-and-child-inits.d.ts.map +1 -1
  20. package/dist/ir-to-client-js/types.d.ts +21 -0
  21. package/dist/ir-to-client-js/types.d.ts.map +1 -1
  22. package/package.json +2 -2
  23. package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +2 -4
  24. package/src/__tests__/child-components-in-map.test.ts +11 -3
  25. package/src/__tests__/client-js-generation.test.ts +37 -1
  26. package/src/__tests__/inline-jsx-callback.test.ts +55 -0
  27. package/src/__tests__/ir-jsx-props.test.ts +148 -0
  28. package/src/__tests__/issue-2705-branch-inner-loop-container.test.ts +91 -0
  29. package/src/__tests__/markup-prop-brand.test.ts +49 -0
  30. package/src/__tests__/nested-loop-conditional.test.ts +20 -11
  31. package/src/__tests__/return-through-local-var.test.ts +269 -0
  32. package/src/analyzer.ts +71 -0
  33. package/src/errors.ts +17 -1
  34. package/src/ir-to-client-js/collect-elements.ts +31 -20
  35. package/src/ir-to-client-js/control-flow/plan/build-inner-loop.ts +19 -0
  36. package/src/ir-to-client-js/control-flow/plan/build-loop-child-arm.ts +22 -3
  37. package/src/ir-to-client-js/control-flow/plan/build-reactive-effects.ts +5 -2
  38. package/src/ir-to-client-js/control-flow/plan/inner-loop.ts +12 -0
  39. package/src/ir-to-client-js/control-flow/stringify/inner-loop.ts +9 -0
  40. package/src/ir-to-client-js/control-flow/stringify/lazy-row.ts +7 -1
  41. package/src/ir-to-client-js/element-refs.ts +8 -0
  42. package/src/ir-to-client-js/emit-reactive.ts +91 -23
  43. package/src/ir-to-client-js/imports.ts +5 -0
  44. package/src/ir-to-client-js/index.ts +4 -0
  45. package/src/ir-to-client-js/phases/provider-and-child-inits.ts +5 -1
  46. package/src/ir-to-client-js/types.ts +21 -0
  47. package/src/jsx-to-ir.ts +157 -8
@@ -77,6 +77,27 @@ export interface ClientJsContext {
77
77
  * registration-template emit so both agree on which children defer.
78
78
  */
79
79
  deferredChildSlots: Set<string>;
80
+ /**
81
+ * Slot id of the component's own root, when the ENTIRE render is a single
82
+ * child component call (`ir.root.type === 'component'` — the IR shape is
83
+ * the sole source of truth; `emit-registration.ts`'s `isCommentScope`
84
+ * derives the def's `comment: true` from the same shape). Such a child
85
+ * never gets its own DOM node: `materializeComponent`/`renderChild` leave
86
+ * `bf-s` unset and the child's markup becomes `__scope` itself (#2649).
87
+ * A generic `$c(__scope, slotId)` lookup for this one slot is therefore
88
+ * not just redundant but actively ambiguous — a genuine grandchild
89
+ * nested inside it can derive a `bf-s` whose suffix collides with this
90
+ * same slot id (see `component.ts`'s `_parentScopeId` push), and
91
+ * `$cSingle` cannot tell "I already am this slot" apart from "a
92
+ * coincidentally-matching descendant is this slot" from the DOM alone.
93
+ * Emission sites that would otherwise query this slot via `$c`
94
+ * (`element-refs.ts`, `provider-and-child-inits.ts`,
95
+ * `emit-reactive.ts`) use `__scope` directly instead, sidestepping the
96
+ * ambiguity entirely rather than trying to make the query precise
97
+ * enough to resolve it. `null` for a component whose root is a regular
98
+ * element/fragment (the overwhelmingly common case).
99
+ */
100
+ commentScopeRootSlotId: string | null;
80
101
  reactiveProps: ReactiveComponentProp[];
81
102
  reactiveChildProps: ReactiveChildProp[];
82
103
  reactiveAttrs: ReactiveAttribute[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ir-to-client-js/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EACV,QAAQ,EACR,OAAO,EACP,oBAAoB,EACpB,UAAU,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,EACR,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAE3D,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAChC;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,gFAAgF;IAChF,cAAc,EAAE,iBAAiB,EAAE,CAAA;IACnC,cAAc,EAAE,YAAY,EAAE,CAAA;IAC9B,cAAc,EAAE,YAAY,EAAE,CAAA;IAC9B;;;;;;;OAOG;IACH,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,WAAW,EAAE,SAAS,EAAE,CAAA;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC3B,eAAe,CAAC,EAAE,cAAc,EAAE,CAAA;IAGlC,mBAAmB,EAAE,kBAAkB,EAAE,CAAA;IACzC,eAAe,EAAE,cAAc,EAAE,CAAA;IACjC,mBAAmB,EAAE,kBAAkB,EAAE,CAAA;IACzC,YAAY,EAAE,YAAY,EAAE,CAAA;IAC5B,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB;;;;;;;;OAQG;IACH,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAA;IACrC,aAAa,EAAE,qBAAqB,EAAE,CAAA;IACtC,kBAAkB,EAAE,iBAAiB,EAAE,CAAA;IACvC,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC,kBAAkB,EAAE,iBAAiB,EAAE,CAAA;IACvC,sBAAsB,EAAE,kBAAkB,EAAE,CAAA;IAC5C,cAAc,EAAE,KAAK,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjE,8FAA8F;IAC9F,gBAAgB,EAAE,eAAe,EAAE,CAAA;IACnC,qDAAqD;IACrD,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,yBAAyB,CAAA;IAC9C;;;OAGG;IACH,mBAAmB,CAAC,EAAE,oBAAoB,CAAA;IAC1C;;;;;;;;;;;;;OAaG;IACH,YAAY,EAAE,kBAAkB,CAAA;CACjC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,6BAA8B,SAAQ,QAAQ;IAC7D,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,WAAW,EAAE,MAAM,CAAA;IACnB,oFAAoF;IACpF,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,OAAO,aAAa,EAAE,gBAAgB,EAAE,CAAA;IACjE;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC1C;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,iBAAiB,CAAA;IAE3B;;;OAGG;IACH,cAAc,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAEnC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAA;IAE/C;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAA;IAEhE;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;CAClD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,oEAAoE;IACpE,aAAa,EAAE,qBAAqB,EAAE,CAAA;IACtC,yDAAyD;IACzD,aAAa,EAAE,qBAAqB,EAAE,CAAA;IACtC,iEAAiE;IACjE,IAAI,EAAE,YAAY,EAAE,CAAA;IACpB,kDAAkD;IAClD,YAAY,EAAE,oBAAoB,EAAE,CAAA;CACrC;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAA;IACnB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,iFAAiF;AACjF,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,IAAI,EAAE,QAAQ,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAE9B,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACzC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB,wBAAwB,CAAC,EAAE,OAAO,CAAA;IAIlC,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,cAAc,CAAC,EAAE;QACf,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,CAAA;QACd,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,UAAU,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;CAG3C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,sBAAsB,EAAE,CAAA;IAChC,IAAI,EAAE,oBAAoB,EAAE,CAAA;IAC5B,eAAe,EAAE,+BAA+B,EAAE,CAAA;IAClD,WAAW,EAAE,2BAA2B,EAAE,CAAA;IAC1C;;;;OAIG;IACH,aAAa,EAAE,6BAA6B,EAAE,CAAA;IAC9C,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,YAAY,EAAE,kBAAkB,EAAE,CAAA;CACnC;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,EAAE,aAAa,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,MAAM,4BAA4B,GAAG,kBAAkB,CAAA;AAE7D,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,IAAI,EAAE,QAAQ,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb;;;;;;;;;;OAUG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,mBAAmB,CAAA;IAC9B,wFAAwF;IACxF,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,OAAO,aAAa,EAAE,oBAAoB,EAAE,CAAA;IAC9D,kGAAkG;IAClG,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,iFAAiF;IACjF,MAAM,CAAC,EAAE,UAAU,CAAA;CAGpB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,+EAA+E;IAC/E,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,iGAAiG;IACjG,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,qBAAsB,SAAQ,QAAQ;IACrD,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CACtC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,aAAa,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,OAAO,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;IAChJ,8DAA8D;IAC9D,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB,wEAAwE;IACxE,YAAY,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACrC,sFAAsF;IACtF,MAAM,CAAC,EAAE,sBAAsB,EAAE,CAAA;IACjC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACvC;;;;OAIG;IACH,aAAa,CAAC,EAAE,qBAAqB,EAAE,CAAA;CACxC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,sBAAsB,CAAA;IAChC,SAAS,EAAE,sBAAsB,CAAA;IACjC;;;;;OAKG;IACH,wBAAwB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAC9C;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,IAAI,EAAE,WAAW,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,iBAAiB,CAAA;IACjC,kBAAkB,EAAE,MAAM,EAAE,CAAA;IAC5B,cAAc,CAAC,EAAE,oBAAoB,CAAA;IACrC,gBAAgB,CAAC,EAAE,oBAAoB,EAAE,CAAA;IAGzC,aAAa,EAAE,OAAO,CAAA;IACtB,wBAAwB,CAAC,EAAE,OAAO,CAAA;IAClC,8FAA8F;IAC9F,UAAU,CAAC,EAAE,UAAU,EAAE,CAAA;IACzB,iFAAiF;IACjF,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,eAAe,CAAC,EAAE;QAChB,KAAK,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,cAAc,CAAC,EAAE;QACf,MAAM,EAAE,MAAM,CAAA;QACd,MAAM,EAAE,MAAM,CAAA;QACd,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,UAAU,CAAC,EAAE,aAAa,GAAG,aAAa,CAAA;IAC1C,QAAQ,CAAC,EAAE,mBAAmB,CAAA;CAC/B;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,CAAA;AAElE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B;AAGD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAA;IACd;;;;;;;OAOG;IACH,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/jsx",
3
- "version": "0.33.0",
3
+ "version": "0.33.1",
4
4
  "description": "JSX compiler for BarefootJS - transforms JSX to server HTML + client JS",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,7 @@
49
49
  "directory": "packages/jsx"
50
50
  },
51
51
  "dependencies": {
52
- "@barefootjs/shared": "0.33.0"
52
+ "@barefootjs/shared": "0.33.1"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@barefootjs/client": ">=0.2.0",
@@ -2630,8 +2630,7 @@ export function initExample(__scope, _p = {}) {
2630
2630
  // Reactive prop bindings
2631
2631
  createEffect(() => {
2632
2632
  if (_s0) {
2633
- const __val = String(count())
2634
- if (_s0.value !== __val) _s0.value = __val
2633
+ if ('value' in _s0) { const __val = String(count()); if (_s0.value !== __val) _s0.value = __val }
2635
2634
  }
2636
2635
  })
2637
2636
 
@@ -2639,8 +2638,7 @@ export function initExample(__scope, _p = {}) {
2639
2638
  createEffect(() => {
2640
2639
  const [__Child_s0El] = $c(__scope, 's0')
2641
2640
  if (__Child_s0El) {
2642
- const __val = String(count())
2643
- if (__Child_s0El.value !== __val) __Child_s0El.value = __val
2641
+ if ('value' in __Child_s0El) { const __val = String(count()); if (__Child_s0El.value !== __val) __Child_s0El.value = __val }
2644
2642
  }
2645
2643
  })
2646
2644
 
@@ -292,6 +292,12 @@ describe('child components inside .map() (#344)', () => {
292
292
  })
293
293
 
294
294
  test('no duplicate variable declaration when .map() slot ID matches component slot ID (#360)', () => {
295
+ // Wrapped in a `<div>` so `Wrapper` is a genuine, separately-addressed
296
+ // child (needs a `$c` ref) rather than the component's own `comment:
297
+ // true` root child — a BARE `<Wrapper>{...}</Wrapper>` return needs no
298
+ // `$c` ref at all since #2649 (the child IS `__scope`), which would
299
+ // make this test's collision between the component's `$c` ref and the
300
+ // loop's `mapArray` ref never arise in the first place.
295
301
  const source = `
296
302
  'use client'
297
303
  import { createSignal } from '@barefootjs/client'
@@ -299,9 +305,11 @@ describe('child components inside .map() (#344)', () => {
299
305
  export function Parent() {
300
306
  const [items, setItems] = createSignal([{ name: 'a' }, { name: 'b' }])
301
307
  return (
302
- <Wrapper>
303
- {items().map((item, i) => <span key={i}>{item.name}</span>)}
304
- </Wrapper>
308
+ <div>
309
+ <Wrapper>
310
+ {items().map((item, i) => <span key={i}>{item.name}</span>)}
311
+ </Wrapper>
312
+ </div>
305
313
  )
306
314
  }
307
315
  `
@@ -1245,7 +1245,14 @@ describe('Client JS generation', () => {
1245
1245
 
1246
1246
  const clientJs = result.files.find(f => f.type === 'clientJs')
1247
1247
  expect(clientJs).toBeDefined()
1248
- // Should use .value = for value prop, not setAttribute
1248
+ // `value={text()}` on a CHILD COMPONENT drives the child-root MIRROR
1249
+ // path (emitReactivePropBindings/emitReactiveChildProps), gated by a
1250
+ // runtime `'value' in el` check (#2716): a genuine form-control root
1251
+ // still gets the live `.value =` property write, but a non-form root
1252
+ // gets NOTHING (no setAttribute fallback either) since this mirror has
1253
+ // no SSR-rendered counterpart to stay in sync with — see
1254
+ // `emitChildValueMirrorStatements`'s docstring.
1255
+ expect(clientJs!.content).toContain("'value' in")
1249
1256
  expect(clientJs!.content).toContain('.value =')
1250
1257
  expect(clientJs!.content).not.toContain("setAttribute('value'")
1251
1258
  })
@@ -1275,6 +1282,35 @@ describe('Client JS generation', () => {
1275
1282
  expect(clientJs!.content).toContain('.disabled = !!')
1276
1283
  expect(clientJs!.content).not.toContain("setAttribute('disabled'")
1277
1284
  })
1285
+
1286
+ // #2716: a `value` prop passed to a CHILD COMPONENT (above) drives the
1287
+ // no-SSR-fallback mirror path; a `value` ATTRIBUTE the developer writes
1288
+ // directly on a plain HOST element is the opposite case — SSR renders
1289
+ // that attribute, so `emitAttrUpdate`'s dispatch (used here, not the
1290
+ // mirror helper) correctly keeps the attribute fallback for a
1291
+ // non-form-control target.
1292
+ test('compiles a directly-authored value attribute on a plain element with an attribute fallback (emitAttrUpdate)', () => {
1293
+ const source = `
1294
+ 'use client'
1295
+ import { createSignal } from '@barefootjs/client'
1296
+
1297
+ export function LabeledValue() {
1298
+ const [count, setCount] = createSignal(0)
1299
+ return <div value={count()}>{count()}</div>
1300
+ }
1301
+ `
1302
+
1303
+ const result = compileJSX(source, 'LabeledValue.tsx', { adapter })
1304
+ expect(result.errors).toHaveLength(0)
1305
+
1306
+ const clientJs = result.files.find(f => f.type === 'clientJs')
1307
+ expect(clientJs).toBeDefined()
1308
+ // Gated the same way as the mirror path, but WITH an attribute
1309
+ // fallback — this is a literal attribute SSR already rendered.
1310
+ expect(clientJs!.content).toContain("'value' in")
1311
+ expect(clientJs!.content).toContain('.value =')
1312
+ expect(clientJs!.content).toContain("setAttribute('value'")
1313
+ })
1278
1314
  })
1279
1315
 
1280
1316
  describe('comment scope flag for fragment roots (#381)', () => {
@@ -464,3 +464,58 @@ describe('inline JSX as object-literal arrow value (#1663)', () => {
464
464
  expect(js).toMatch(/lazySlots[^']*from '@barefootjs\/client\/runtime'/)
465
465
  })
466
466
  })
467
+
468
+ describe('synthesized wrapper root-child resolution (#2649)', () => {
469
+ test('the wrapper\'s own (comment: true) child init uses __scope directly, not a $c lookup', () => {
470
+ // `Flow`'s callback is hoisted into a `comment: true` synthesized
471
+ // wrapper (BFInlineJsxCallback1) whose entire body is the single
472
+ // `<Body id={n.id} />` call — the wrapper's element IS Body's own
473
+ // element, no separate DOM node exists to look up. Body itself
474
+ // nests two REAL child components (Handle) whose own slot suffixes
475
+ // (`s0`, `s1`) can coincide with whatever slot the wrapper is
476
+ // mounted at in ITS caller once a grandchild's scope is correctly
477
+ // derived from Body's own scope (#2649) — so the wrapper's init
478
+ // must reference `__scope` directly rather than re-deriving it via
479
+ // `$c`, which cannot distinguish "I already am this slot" from a
480
+ // same-suffix grandchild underneath it.
481
+ const source = `
482
+ 'use client'
483
+ import { Flow } from './Flow'
484
+
485
+ function Handle(props: { kind: string }) {
486
+ return <div class="handle">{props.kind}</div>
487
+ }
488
+
489
+ function Body(props: { id: string }) {
490
+ return (
491
+ <div>
492
+ <Handle kind="target" />
493
+ <span>{props.id}</span>
494
+ <Handle kind="source" />
495
+ </div>
496
+ )
497
+ }
498
+
499
+ export function Demo() {
500
+ return <Flow renderNode={(n) => <Body id={n.id} />} />
501
+ }
502
+ `
503
+ const js = clientJs(source)
504
+
505
+ // The synthesized wrapper's init must not query its own root child
506
+ // via $c — it already has it as `__scope`.
507
+ const wrapperInit = js.match(/function initBFInlineJsxCallback1\b[\s\S]*?\n\}/)
508
+ expect(wrapperInit).not.toBeNull()
509
+ expect(wrapperInit![0]).not.toMatch(/\$c\(__scope/)
510
+ expect(wrapperInit![0]).toMatch(/initChild\('Body[^,]*',\s*__scope,/)
511
+
512
+ // Body's OWN nested Handle children are unaffected — they are real,
513
+ // separate DOM nodes and still resolve through $c as normal (slot
514
+ // numbering interleaves with the `<span>` text marker in between, so
515
+ // the second Handle isn't necessarily 's1' — only that both go
516
+ // through $c, unlike the wrapper's own root child above).
517
+ const bodyInit = js.match(/function initBody\b[\s\S]*?\n\}/)
518
+ expect(bodyInit).not.toBeNull()
519
+ expect(bodyInit![0]).toMatch(/\$c\(__scope,\s*'s0',\s*'s\d+'\)/)
520
+ })
521
+ })
@@ -367,4 +367,152 @@ describe('JSX props (#559)', () => {
367
367
  expect(clientJs!.content).toContain("kind: 'markup'")
368
368
  })
369
369
  })
370
+
371
+ // #2703 (Copilot review on #2667's PR): the naked ternary/array wrapper
372
+ // refusal, and the direct-JSX classification it sits beside, both used
373
+ // to unwrap only `ParenthesizedExpression` — a JSX-wrapping ternary/
374
+ // array (or a direct JSX element) additionally wrapped in a transparent
375
+ // TS annotation (`as`, `satisfies`, postfix non-null `!`) slipped past
376
+ // both checks and still spliced raw JSX into the emitted client JS.
377
+ describe('#2667/#2703: transparent TS wrappers around JSX in prop position', () => {
378
+ test('ternary wrapping `as`-cast JSX branches still refuses with BF021', () => {
379
+ const source = `
380
+ 'use client'
381
+ import { createSignal } from '@barefootjs/client'
382
+ export function App() {
383
+ const [cond, setCond] = createSignal(true)
384
+ return (
385
+ <Layout header={cond() ? (<a>x</a> as any) : (<b>y</b> as any)} />
386
+ )
387
+ }
388
+ `
389
+ const result = compileJSX(source, 'App.tsx', { adapter })
390
+ const errors = result.errors.filter(e => e.severity === 'error')
391
+ expect(errors).toHaveLength(1)
392
+ expect(errors[0].code).toBe('BF021')
393
+ // No raw JSX syntax leaked into the client bundle.
394
+ const clientJs = result.files.find(f => f.type === 'clientJs')
395
+ expect(clientJs?.content ?? '').not.toMatch(/<a>x<\/a>|<b>y<\/b>/)
396
+ })
397
+
398
+ test('ternary wrapping `satisfies`-annotated JSX branches still refuses with BF021', () => {
399
+ const source = `
400
+ 'use client'
401
+ import { createSignal } from '@barefootjs/client'
402
+ export function App() {
403
+ const [cond, setCond] = createSignal(true)
404
+ return (
405
+ <Layout header={cond() ? (<a>x</a> satisfies any) : (<b>y</b> satisfies any)} />
406
+ )
407
+ }
408
+ `
409
+ const result = compileJSX(source, 'App.tsx', { adapter })
410
+ const errors = result.errors.filter(e => e.severity === 'error')
411
+ expect(errors).toHaveLength(1)
412
+ expect(errors[0].code).toBe('BF021')
413
+ })
414
+
415
+ test('ternary wrapping non-null-asserted JSX branches still refuses with BF021', () => {
416
+ // `!` must trail the CLOSING paren, not sit inside it: TS's parser
417
+ // mis-parses `(<a/>!)` (non-null touching the JSX closing tag
418
+ // directly, inside the parens) — confirmed by direct AST dump
419
+ // during #2703's investigation, unrelated to this fix.
420
+ const source = `
421
+ 'use client'
422
+ import { createSignal } from '@barefootjs/client'
423
+ export function App() {
424
+ const [cond, setCond] = createSignal(true)
425
+ return (
426
+ <Layout header={cond() ? (<a>x</a>)! : (<b>y</b>)!} />
427
+ )
428
+ }
429
+ `
430
+ const result = compileJSX(source, 'App.tsx', { adapter })
431
+ const errors = result.errors.filter(e => e.severity === 'error')
432
+ expect(errors).toHaveLength(1)
433
+ expect(errors[0].code).toBe('BF021')
434
+ })
435
+
436
+ test('array literal wrapping `as`-cast JSX elements still refuses with BF021', () => {
437
+ const source = `
438
+ export function App() {
439
+ return (
440
+ <Layout header={[<a>x</a> as any, <b>y</b> as any]} />
441
+ )
442
+ }
443
+ `
444
+ const result = compileJSX(source, 'App.tsx', { adapter })
445
+ const errors = result.errors.filter(e => e.severity === 'error')
446
+ expect(errors).toHaveLength(1)
447
+ expect(errors[0].code).toBe('BF021')
448
+ })
449
+
450
+ test('a bare `as`-cast JSX element (no ternary) still classifies as jsx-children, not a refusal', () => {
451
+ const source = `
452
+ export function App() {
453
+ return <Layout header={<a>x</a> as any} />
454
+ }
455
+ `
456
+ const ctx = analyzeComponent(source, 'App.tsx')
457
+ const ir = jsxToIR(ctx)
458
+ expect(ir).not.toBeNull()
459
+ const layout = findComponent(ir!, 'Layout')
460
+ const headerProp = layout!.props.find(p => p.name === 'header')
461
+ expect(headerProp!.value.kind).toBe('jsx-children')
462
+
463
+ // Phase 2: the compiled client JS brands it (#2651), matching the
464
+ // bare `<a>x</a>` form byte-for-byte — `as any` is erased, not
465
+ // spliced as source text.
466
+ const result = compileJSX(source, 'App.tsx', { adapter })
467
+ expect(result.errors.filter(e => e.severity === 'error')).toHaveLength(0)
468
+ const clientJs = result.files.find(f => f.type === 'clientJs')
469
+ expect(clientJs!.content).toMatch(/bfMarkup\(`<a>x<\/a>`\)/)
470
+ })
471
+
472
+ test('a bare `satisfies`-annotated JSX element (no ternary) still classifies as jsx-children', () => {
473
+ const source = `
474
+ export function App() {
475
+ return <Layout header={<a>x</a> satisfies any} />
476
+ }
477
+ `
478
+ const ctx = analyzeComponent(source, 'App.tsx')
479
+ const ir = jsxToIR(ctx)
480
+ const layout = findComponent(ir!, 'Layout')
481
+ const headerProp = layout!.props.find(p => p.name === 'header')
482
+ expect(headerProp!.value.kind).toBe('jsx-children')
483
+ })
484
+
485
+ test('a bare non-null-asserted JSX element (no ternary) still classifies as jsx-children', () => {
486
+ // `!` must trail the closing paren (`(<a/>)!`), not touch the JSX
487
+ // closing tag directly (`<a/>!`) — the latter does not reliably
488
+ // parse as a NonNullExpression at all inside a JSX attribute
489
+ // expression (confirmed by direct AST dump during #2703's
490
+ // investigation: the bare form leaves stray tokens outside the
491
+ // JsxExpression entirely, so it never reaches this code path as a
492
+ // NonNullExpression in the first place — unrelated to this fix).
493
+ const source = `
494
+ export function App() {
495
+ return <Layout header={(<a>x</a>)!} />
496
+ }
497
+ `
498
+ const ctx = analyzeComponent(source, 'App.tsx')
499
+ const ir = jsxToIR(ctx)
500
+ const layout = findComponent(ir!, 'Layout')
501
+ const headerProp = layout!.props.find(p => p.name === 'header')
502
+ expect(headerProp!.value.kind).toBe('jsx-children')
503
+ })
504
+
505
+ test('a ternary with NO JSX inside, wrapped in `as`, is unaffected (ordinary expression, no refusal)', () => {
506
+ const source = `
507
+ 'use client'
508
+ import { createSignal } from '@barefootjs/client'
509
+ export function App() {
510
+ const [cond, setCond] = createSignal(true)
511
+ return <Layout disabled={(cond() ? true : false) as any} />
512
+ }
513
+ `
514
+ const result = compileJSX(source, 'App.tsx', { adapter })
515
+ expect(result.errors.filter(e => e.severity === 'error')).toHaveLength(0)
516
+ })
517
+ })
370
518
  })
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Compiler-unit regression pin for #2705 (fixed).
3
+ *
4
+ * A loop nested inside a loop-row conditional's branch, behind a wrapper
5
+ * element the branch's own IR subtree never sees (`<article>{cond &&
6
+ * items.map(...)}</article>`), gets no `containerSlotId` of its own
7
+ * (`collectInnerLoops`'s branch walk in ir-to-client-js/collect-elements.ts
8
+ * never observes an ancestor outside the branch). `buildBranchInnerLoopsPlan`
9
+ * (control-flow/plan/build-loop-child-arm.ts) must fall back to
10
+ * `findCondContainer(__branchScope, '<condSlotId>')` — NOT the raw
11
+ * `__branchScope` (the whole conditional's bind scope, several elements
12
+ * wider than the loop's actual container; the pre-fix behavior that caused
13
+ * the runtime defect in issue-2705-nested-loop-branch-container-slot.test.ts).
14
+ */
15
+ import { describe, test, expect } from 'bun:test'
16
+ import { compileJSX } from '../compiler'
17
+ import { TestAdapter } from '../adapters/test-adapter'
18
+
19
+ const adapter = new TestAdapter()
20
+
21
+ describe('#2705 — branch inner-loop container fallback', () => {
22
+ test('inner loop behind a wrapped loop-row `&&` conditional resolves its container via findCondContainer', () => {
23
+ const source = `
24
+ "use client";
25
+ import { createSignal } from '@barefootjs/client'
26
+ type Item = { id: string; label: string }
27
+ type Group = { id: string; show: boolean; items: Item[] }
28
+ export function Repro() {
29
+ const [groups] = createSignal<Group[]>([])
30
+ return (
31
+ <div>
32
+ {groups().map((group) => (
33
+ <div key={group.id}>
34
+ <article>
35
+ Group
36
+ {group.show &&
37
+ group.items.map((item) => (
38
+ <section key={item.id}>{item.label}</section>
39
+ ))}
40
+ </article>
41
+ </div>
42
+ ))}
43
+ </div>
44
+ )
45
+ }
46
+ `
47
+ const result = compileJSX(source, 'Repro.tsx', { adapter })
48
+ expect(result.errors.filter(e => e.severity === 'error')).toHaveLength(0)
49
+ const content = result.files.find(f => f.type === 'clientJs')!.content
50
+
51
+ // The conditional's own slot id feeds `findCondContainer` — never a raw
52
+ // `__branchScope` container for this inner mapArray.
53
+ expect(content).toMatch(/const __bic\w+ = findCondContainer\(__branchScope, '(s\d+)'\)/)
54
+ expect(content).not.toMatch(/const __bic\w+ = __branchScope\s*$/m)
55
+ expect(content).toContain('findCondContainer')
56
+ })
57
+
58
+ test('an existing (non-null containerSlotId) inner-loop container is unaffected', () => {
59
+ // Control: a loop DIRECTLY inside a component whose own element carries
60
+ // a slot id continues to resolve via the qsa/bf-h fallback chain, not
61
+ // `findCondContainer` — the fix only changes the previously-null path.
62
+ const source = `
63
+ "use client";
64
+ import { createSignal } from '@barefootjs/client'
65
+ type TreeNode = { id: number; name: string; type: 'file' | 'folder'; expanded: boolean; children: TreeNode[] }
66
+ export function FileBrowser() {
67
+ const [tree] = createSignal<TreeNode[]>([])
68
+ return (
69
+ <div>
70
+ {tree().map(node => (
71
+ <div key={node.id}>
72
+ {node.expanded ? (
73
+ <div>
74
+ {node.children.map(child => (
75
+ <div key={child.id}>{child.name}</div>
76
+ ))}
77
+ </div>
78
+ ) : null}
79
+ </div>
80
+ ))}
81
+ </div>
82
+ )
83
+ }
84
+ `
85
+ const result = compileJSX(source, 'FileBrowser.tsx', { adapter })
86
+ expect(result.errors.filter(e => e.severity === 'error')).toHaveLength(0)
87
+ const content = result.files.find(f => f.type === 'clientJs')!.content
88
+ expect(content).not.toContain('findCondContainer')
89
+ expect(content).toMatch(/\.querySelector\('\[bf="s\d+"\]'\)/)
90
+ })
91
+ })
@@ -158,4 +158,53 @@ describe('markup-prop brand (#2651)', () => {
158
158
  // `__slot(...)` live-node wrapping — not itself re-wrapped in bfMarkup.
159
159
  expect(clientJs).toMatch(/get header\(\)\s*\{\s*return __slot\(/)
160
160
  })
161
+
162
+ // KNOWN BUG (#2702) — pins the CURRENT (broken) emission, not the
163
+ // correct one. `isSingleElementJsxChildren` (`ir-to-client-js/collect-
164
+ // elements.ts`) only brands the single-element jsx-children shape;
165
+ // #2651's PR body enumerated "conditional-in-fragment" as deliberately
166
+ // out of that PR's scope, and #2702 confirms it is actually broken, not
167
+ // merely unbranded-but-harmless: the child's own `escapeTextOrNode`
168
+ // reactive effect re-escapes the chosen branch's HTML as literal text
169
+ // the moment it first runs (real DOM corruption, verified directly —
170
+ // see `jsx-element-prop-fragment-conditional`'s fixture docstring,
171
+ // `packages/adapter-tests/fixtures/`, for the full mechanism and why no
172
+ // other shared conformance suite observes it: SSR is genuinely correct,
173
+ // and CSR conformance's `createEffect` mock never runs the effect).
174
+ //
175
+ // Graduation: once `bfMarkup()` branding is extended to this multi-part
176
+ // shape, this assertion starts failing — replace it with a positive
177
+ // `bfMarkup(...)`-wrapped assertion (mirroring test (b) above) and
178
+ // delete this comment block; that is the fixture's own graduation
179
+ // trigger too (its `expectedHtml` is already the correct SSR output, so
180
+ // no fixture change is needed, only this pin's removal and #2667's
181
+ // BF021 suggestion regaining the fragment-wrap escape).
182
+ test('(h) KNOWN BUG (#2702): a conditional-in-fragment jsx-children prop reaches initChild UNbranded', () => {
183
+ const source = `
184
+ 'use client'
185
+ import { createSignal } from '@barefootjs/client'
186
+ export function Card(props: { header?: any; children?: any }) {
187
+ return (
188
+ <section>
189
+ <header>{props.header}</header>
190
+ <div>{props.children}</div>
191
+ </section>
192
+ )
193
+ }
194
+ export function JsxElementPropFragmentConditional() {
195
+ const [cond, setCond] = createSignal(true)
196
+ return (
197
+ <Card header={<>{cond() ? <a>x</a> : <b>y</b>}</>}>
198
+ <p>body text</p>
199
+ </Card>
200
+ )
201
+ }
202
+ `
203
+ const clientJs = clientJsFor(source)
204
+ // Bug: the getter returns a bare template-literal ternary — NOT
205
+ // wrapped in bfMarkup(...). If this ever starts matching bfMarkup(...)
206
+ // the bug is fixed; see the graduation note above.
207
+ expect(clientJs).toMatch(/get header\(\)\s*\{\s*return cond\(\)\s*\?\s*`<a>x<\/a>`\s*:\s*`<b>y<\/b>`\s*\}/)
208
+ expect(clientJs).not.toMatch(/get header\(\)\s*\{\s*return bfMarkup\(/)
209
+ })
161
210
  })
@@ -134,14 +134,15 @@ describe('nested loops/conditionals inside mapArray (#830, #839)', () => {
134
134
  expect(mapArrayCount).toBeGreaterThanOrEqual(3)
135
135
  })
136
136
 
137
- test('reactive text inside conditional inside inner loop uses re-claim pattern (#840)', () => {
138
- // When a reactive text is inside a conditional branch inside a nested (inner) loop,
139
- // insert() may replace the SSR element after the text node is captured.
140
- // Slot unification A3: the generated code must re-claim on EVERY run via
141
- // a fresh `claimSlots(...).write(...)` call inside the effect body not
142
- // a `lazySlots` writer built once outside it, which would go stale once
143
- // insert() swaps the branch's DOM (see `stringifyInnerLoops`' docstring
144
- // in `ir-to-client-js/control-flow/stringify/inner-loop.ts`).
137
+ test('reactive text inside conditional inside inner loop gets a real insert() (#840, fixed by #2706)', () => {
138
+ // A per-item conditional living inside a NESTED (inner) loop's row now
139
+ // gets full insert() parity with a top-level loop's row conditional
140
+ // (#2706) the condition is a real reactive `createEffect` dependency,
141
+ // not baked once at row creation, and the branch's reactive text binds
142
+ // through the arm's own `lazySlots(__branchScope, ...)` +
143
+ // `createDisposableEffect` (same shape `stringifyLoopChildArm` emits for
144
+ // any other insert() arm), never a bare-claimSlots reclaim racing
145
+ // against a marker the active branch may not have rendered.
145
146
  const source = `
146
147
  'use client'
147
148
  import { createSignal } from '@barefootjs/client'
@@ -176,9 +177,17 @@ describe('nested loops/conditionals inside mapArray (#830, #839)', () => {
176
177
  expect(clientJs).toBeDefined()
177
178
  const content = clientJs!.content
178
179
 
179
- // Re-claim pattern: a fresh `claimSlots(...)` call inside createEffect so
180
- // it always resolves against the live node, never a cached stale ref.
181
- expect(content).toMatch(/createEffect\(\(\) => \{ claimSlots\(__innerEl\w*, \[\{ id: 's\d+', kind: 'text', path: \[\] \}\]\)\.write\('s\d+', String\(/)
180
+ // A real insert() over the row's own element, keyed to the conditional's
181
+ // slot id and condition not a static bake.
182
+ expect(content).toMatch(/insert\(__innerEl\w*, 's\d+', \(\) => child\(\)\.type === 'text', \{/)
183
+
184
+ // The branch's reactive text binds inside `bindEvents` via the standard
185
+ // arm-text shape (`lazySlots` + `createDisposableEffect`), scoped to
186
+ // `__branchScope` — the node insert() actually mounts for this branch —
187
+ // never a bare `claimSlots` reclaim against `__innerEl<uid>` racing the
188
+ // branch's own mount/unmount.
189
+ expect(content).toMatch(/const __bfw_s\d+ = lazySlots\(__branchScope, \[\{ id: 's\d+', kind: 'markup', path: \[\] \}\]\)/)
190
+ expect(content).toMatch(/createDisposableEffect\(\(\) => \{ __bfw_s\d+\('s\d+', escapeTextOrNode\(child\(\)\.label\)\) \}\)/)
182
191
  })
183
192
 
184
193
  test('event handler inside conditional branch of loop item appears in bindEvents (#839)', () => {