@barefootjs/rust 0.30.0 → 0.30.3

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.
@@ -188317,6 +188317,7 @@ class MinijinjaAdapter extends BaseAdapter {
188317
188317
  _loweringMatchers = [];
188318
188318
  localConstants = [];
188319
188319
  staticLoopSourceBoundNames = new Set;
188320
+ loopBoundNames = new Map;
188320
188321
  nullableOptionalProps = new Set;
188321
188322
  constructor(options = {}) {
188322
188323
  super();
@@ -188333,6 +188334,7 @@ class MinijinjaAdapter extends BaseAdapter {
188333
188334
  this.booleanTypedProps = collectBooleanTypedProps(ir);
188334
188335
  this.localConstants = ir.metadata.localConstants ?? [];
188335
188336
  this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
188337
+ this.loopBoundNames.clear();
188336
188338
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
188337
188339
  this.stringValueNames = collectStringValueNames(ir);
188338
188340
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -188665,7 +188667,37 @@ ${whenTrue}
188665
188667
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
188666
188668
  this.currentLoopKeyDepth = loop.depth;
188667
188669
  const preambleLines = (loop.preamble?.declarations ?? []).map((d) => `{% set ${minijinjaIdent(d.name)} = ${this.convertExpressionToJinja(d.raw, d.valueParsed)} %}`);
188670
+ const loopBound = [];
188671
+ if (loop.objectIteration === "entries") {
188672
+ loopBound.push(loop.index ?? param, param);
188673
+ } else if (loop.objectIteration === "keys") {
188674
+ loopBound.push(param, "__bf_v");
188675
+ } else if (loop.objectIteration === "values") {
188676
+ loopBound.push("__bf_k", param);
188677
+ } else if (loop.iterationShape === "keys") {
188678
+ loopBound.push("__bf_item", param);
188679
+ } else if (supportableDestructure) {
188680
+ loopBound.push("__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name));
188681
+ if (loop.index)
188682
+ loopBound.push(loop.index);
188683
+ } else {
188684
+ loopBound.push(param);
188685
+ if (loop.index)
188686
+ loopBound.push(loop.index);
188687
+ }
188688
+ for (const d of loop.preamble?.declarations ?? [])
188689
+ loopBound.push(d.name);
188690
+ for (const n of loopBound) {
188691
+ this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
188692
+ }
188668
188693
  const childrenUnderLoop = this.renderChildren(loop.children);
188694
+ for (const n of loopBound) {
188695
+ const c = (this.loopBoundNames.get(n) ?? 1) - 1;
188696
+ if (c <= 0)
188697
+ this.loopBoundNames.delete(n);
188698
+ else
188699
+ this.loopBoundNames.set(n, c);
188700
+ }
188669
188701
  this.currentLoopKeyDepth = prevLoopKeyDepth;
188670
188702
  this.inLoop = prevInLoop;
188671
188703
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{{ bf.comment("loop-i:" ~ bf.string(${this.convertExpressionToJinja(loop.key)})) | safe }}
@@ -188844,7 +188876,7 @@ ${children}`;
188844
188876
  }
188845
188877
  const bareId = value.expr.trim();
188846
188878
  const normalizedBareId = this.propsObjectName && bareId.startsWith(`${this.propsObjectName}.`) ? bareId.slice(this.propsObjectName.length + 1) : bareId;
188847
- if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId)) {
188879
+ if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.isLoopBoundName(normalizedBareId)) {
188848
188880
  const jinja2 = this.convertExpressionToJinja(value.expr);
188849
188881
  const body = this.shouldBoolStr(value.expr, name) ? `${name}="{{ bf.bool_str(${jinja2}) }}"` : `${name}="{{ bf.string(${jinja2}) }}"`;
188850
188882
  return `
@@ -189131,8 +189163,13 @@ Options:
189131
189163
  }
189132
189164
  if (!/^[A-Za-z_$][\w$]*$/.test(bare))
189133
189165
  return false;
189166
+ if (this.isLoopBoundName(bare))
189167
+ return false;
189134
189168
  return this.booleanTypedProps.has(bare);
189135
189169
  }
189170
+ isLoopBoundName(name) {
189171
+ return this.loopBoundNames.has(name);
189172
+ }
189136
189173
  shouldBoolStr(expr, name) {
189137
189174
  if (isExplicitStringCall(expr))
189138
189175
  return false;
@@ -203,6 +203,20 @@ export declare class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitt
203
203
  * `collectLoopBoundNames` use in `collectStringValueNames`.
204
204
  */
205
205
  private staticLoopSourceBoundNames;
206
+ /**
207
+ * Names currently bound by an enclosing loop body — the block-param
208
+ * locals `renderLoop` introduces (item, index, per-binding destructure
209
+ * fields, `.map()` preamble declarations) — ref-counted so nested loops
210
+ * compose. This is the POSITION-ACCURATE twin of the coarse
211
+ * `staticLoopSourceBoundNames` above: that set is a whole-component
212
+ * union used only to guard static-const inlining (safe to over-suppress
213
+ * there — the fallback is just "don't inline"), whereas the boolean-prop
214
+ * and nullable-optional classification sites need to know whether a name
215
+ * is loop-bound AT THIS POSITION, because for those two the coarse
216
+ * fallback would silently mis-render a genuine prop occurrence outside
217
+ * the loop too (#2488).
218
+ */
219
+ private loopBoundNames;
206
220
  /**
207
221
  * Optional, no-default props that are `None` when the caller omits them.
208
222
  * Their bare-reference attribute emission is guarded with a Jinja
@@ -417,6 +431,8 @@ export declare class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitt
417
431
  consequent: string;
418
432
  } | null;
419
433
  isBooleanTypedPropRef(expr: string): boolean;
434
+ /** Position-accurate loop-bound-name check — see `loopBoundNames`'s docstring. */
435
+ private isLoopBoundName;
420
436
  /**
421
437
  * Whether an attribute-value expression should route through
422
438
  * `bf.bool_str` (vs. plain `bf.string`) at its interpolation site.
@@ -1 +1 @@
1
- {"version":3,"file":"minijinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/minijinja-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minijinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/minijinja-adapter.ts"],"names":[],"mappings":"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"}
package/dist/build.js CHANGED
@@ -188317,6 +188317,7 @@ class MinijinjaAdapter extends BaseAdapter {
188317
188317
  _loweringMatchers = [];
188318
188318
  localConstants = [];
188319
188319
  staticLoopSourceBoundNames = new Set;
188320
+ loopBoundNames = new Map;
188320
188321
  nullableOptionalProps = new Set;
188321
188322
  constructor(options = {}) {
188322
188323
  super();
@@ -188333,6 +188334,7 @@ class MinijinjaAdapter extends BaseAdapter {
188333
188334
  this.booleanTypedProps = collectBooleanTypedProps(ir);
188334
188335
  this.localConstants = ir.metadata.localConstants ?? [];
188335
188336
  this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
188337
+ this.loopBoundNames.clear();
188336
188338
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
188337
188339
  this.stringValueNames = collectStringValueNames(ir);
188338
188340
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -188665,7 +188667,37 @@ ${whenTrue}
188665
188667
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
188666
188668
  this.currentLoopKeyDepth = loop.depth;
188667
188669
  const preambleLines = (loop.preamble?.declarations ?? []).map((d) => `{% set ${minijinjaIdent(d.name)} = ${this.convertExpressionToJinja(d.raw, d.valueParsed)} %}`);
188670
+ const loopBound = [];
188671
+ if (loop.objectIteration === "entries") {
188672
+ loopBound.push(loop.index ?? param, param);
188673
+ } else if (loop.objectIteration === "keys") {
188674
+ loopBound.push(param, "__bf_v");
188675
+ } else if (loop.objectIteration === "values") {
188676
+ loopBound.push("__bf_k", param);
188677
+ } else if (loop.iterationShape === "keys") {
188678
+ loopBound.push("__bf_item", param);
188679
+ } else if (supportableDestructure) {
188680
+ loopBound.push("__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name));
188681
+ if (loop.index)
188682
+ loopBound.push(loop.index);
188683
+ } else {
188684
+ loopBound.push(param);
188685
+ if (loop.index)
188686
+ loopBound.push(loop.index);
188687
+ }
188688
+ for (const d of loop.preamble?.declarations ?? [])
188689
+ loopBound.push(d.name);
188690
+ for (const n of loopBound) {
188691
+ this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
188692
+ }
188668
188693
  const childrenUnderLoop = this.renderChildren(loop.children);
188694
+ for (const n of loopBound) {
188695
+ const c = (this.loopBoundNames.get(n) ?? 1) - 1;
188696
+ if (c <= 0)
188697
+ this.loopBoundNames.delete(n);
188698
+ else
188699
+ this.loopBoundNames.set(n, c);
188700
+ }
188669
188701
  this.currentLoopKeyDepth = prevLoopKeyDepth;
188670
188702
  this.inLoop = prevInLoop;
188671
188703
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{{ bf.comment("loop-i:" ~ bf.string(${this.convertExpressionToJinja(loop.key)})) | safe }}
@@ -188844,7 +188876,7 @@ ${children}`;
188844
188876
  }
188845
188877
  const bareId = value.expr.trim();
188846
188878
  const normalizedBareId = this.propsObjectName && bareId.startsWith(`${this.propsObjectName}.`) ? bareId.slice(this.propsObjectName.length + 1) : bareId;
188847
- if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId)) {
188879
+ if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.isLoopBoundName(normalizedBareId)) {
188848
188880
  const jinja2 = this.convertExpressionToJinja(value.expr);
188849
188881
  const body = this.shouldBoolStr(value.expr, name) ? `${name}="{{ bf.bool_str(${jinja2}) }}"` : `${name}="{{ bf.string(${jinja2}) }}"`;
188850
188882
  return `
@@ -189131,8 +189163,13 @@ Options:
189131
189163
  }
189132
189164
  if (!/^[A-Za-z_$][\w$]*$/.test(bare))
189133
189165
  return false;
189166
+ if (this.isLoopBoundName(bare))
189167
+ return false;
189134
189168
  return this.booleanTypedProps.has(bare);
189135
189169
  }
189170
+ isLoopBoundName(name) {
189171
+ return this.loopBoundNames.has(name);
189172
+ }
189136
189173
  shouldBoolStr(expr, name) {
189137
189174
  if (isExplicitStringCall(expr))
189138
189175
  return false;
package/dist/index.js CHANGED
@@ -188317,6 +188317,7 @@ class MinijinjaAdapter extends BaseAdapter {
188317
188317
  _loweringMatchers = [];
188318
188318
  localConstants = [];
188319
188319
  staticLoopSourceBoundNames = new Set;
188320
+ loopBoundNames = new Map;
188320
188321
  nullableOptionalProps = new Set;
188321
188322
  constructor(options = {}) {
188322
188323
  super();
@@ -188333,6 +188334,7 @@ class MinijinjaAdapter extends BaseAdapter {
188333
188334
  this.booleanTypedProps = collectBooleanTypedProps(ir);
188334
188335
  this.localConstants = ir.metadata.localConstants ?? [];
188335
188336
  this.staticLoopSourceBoundNames = collectLoopBoundNames(ir);
188337
+ this.loopBoundNames.clear();
188336
188338
  this.nullableOptionalProps = collectNullableOptionalProps(ir);
188337
188339
  this.stringValueNames = collectStringValueNames(ir);
188338
188340
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants);
@@ -188665,7 +188667,37 @@ ${whenTrue}
188665
188667
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
188666
188668
  this.currentLoopKeyDepth = loop.depth;
188667
188669
  const preambleLines = (loop.preamble?.declarations ?? []).map((d) => `{% set ${minijinjaIdent(d.name)} = ${this.convertExpressionToJinja(d.raw, d.valueParsed)} %}`);
188670
+ const loopBound = [];
188671
+ if (loop.objectIteration === "entries") {
188672
+ loopBound.push(loop.index ?? param, param);
188673
+ } else if (loop.objectIteration === "keys") {
188674
+ loopBound.push(param, "__bf_v");
188675
+ } else if (loop.objectIteration === "values") {
188676
+ loopBound.push("__bf_k", param);
188677
+ } else if (loop.iterationShape === "keys") {
188678
+ loopBound.push("__bf_item", param);
188679
+ } else if (supportableDestructure) {
188680
+ loopBound.push("__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name));
188681
+ if (loop.index)
188682
+ loopBound.push(loop.index);
188683
+ } else {
188684
+ loopBound.push(param);
188685
+ if (loop.index)
188686
+ loopBound.push(loop.index);
188687
+ }
188688
+ for (const d of loop.preamble?.declarations ?? [])
188689
+ loopBound.push(d.name);
188690
+ for (const n of loopBound) {
188691
+ this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
188692
+ }
188668
188693
  const childrenUnderLoop = this.renderChildren(loop.children);
188694
+ for (const n of loopBound) {
188695
+ const c = (this.loopBoundNames.get(n) ?? 1) - 1;
188696
+ if (c <= 0)
188697
+ this.loopBoundNames.delete(n);
188698
+ else
188699
+ this.loopBoundNames.set(n, c);
188700
+ }
188669
188701
  this.currentLoopKeyDepth = prevLoopKeyDepth;
188670
188702
  this.inLoop = prevInLoop;
188671
188703
  const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{{ bf.comment("loop-i:" ~ bf.string(${this.convertExpressionToJinja(loop.key)})) | safe }}
@@ -188844,7 +188876,7 @@ ${children}`;
188844
188876
  }
188845
188877
  const bareId = value.expr.trim();
188846
188878
  const normalizedBareId = this.propsObjectName && bareId.startsWith(`${this.propsObjectName}.`) ? bareId.slice(this.propsObjectName.length + 1) : bareId;
188847
- if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId)) {
188879
+ if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.isLoopBoundName(normalizedBareId)) {
188848
188880
  const jinja2 = this.convertExpressionToJinja(value.expr);
188849
188881
  const body = this.shouldBoolStr(value.expr, name) ? `${name}="{{ bf.bool_str(${jinja2}) }}"` : `${name}="{{ bf.string(${jinja2}) }}"`;
188850
188882
  return `
@@ -189131,8 +189163,13 @@ Options:
189131
189163
  }
189132
189164
  if (!/^[A-Za-z_$][\w$]*$/.test(bare))
189133
189165
  return false;
189166
+ if (this.isLoopBoundName(bare))
189167
+ return false;
189134
189168
  return this.booleanTypedProps.has(bare);
189135
189169
  }
189170
+ isLoopBoundName(name) {
189171
+ return this.loopBoundNames.has(name);
189172
+ }
189136
189173
  shouldBoolStr(expr, name) {
189137
189174
  if (isExplicitStringCall(expr))
189138
189175
  return false;
@@ -189221,7 +189258,8 @@ var conformancePins = {
189221
189258
  // src/render-divergences.ts
189222
189259
  var renderDivergences = {
189223
189260
  "aliased-destructured-prop": "aliased destructured prop `{ n: count }` loses its rename — template vars, ssr-defaults, and the props bridge all key off the local name, so the prop is always undefined (https://github.com/piconic-ai/barefootjs/issues/2460)",
189224
- "composite-row-child-aliased-prop": "same #2460 defect as `aliased-destructured-prop`, inside a keyed `.map()` loop row: the nested child's renamed prop (`{ n: count }`) is always undefined, so both rows render an empty count (https://github.com/piconic-ai/barefootjs/issues/2460)"
189261
+ "composite-row-child-aliased-prop": "same #2460 defect as `aliased-destructured-prop`, inside a keyed `.map()` loop row: the nested child's renamed prop (`{ n: count }`) is always undefined, so both rows render an empty count (https://github.com/piconic-ai/barefootjs/issues/2460)",
189262
+ "loop-param-shadows-spread-const": "a .map() param shadowing an object const is resolved by `emitSpread` against `localConstants` with no loop-shadow check, so every row spreads the OUTER const instead of the row value (https://github.com/piconic-ai/barefootjs/issues/2489)"
189225
189263
  };
189226
189264
  export {
189227
189265
  renderDivergences,
@@ -1 +1 @@
1
- {"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBAkB/B,CAAA"}
1
+ {"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBAwB/B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/rust",
3
- "version": "0.30.0",
3
+ "version": "0.30.3",
4
4
  "description": "minijinja (Rust) adapter for BarefootJS — compiles IR to .j2 templates and ships a Rust rendering runtime (packages/adapter-rust/runtime/); runs under any Rust web framework (axum, etc.)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -54,14 +54,14 @@
54
54
  "directory": "packages/adapter-rust"
55
55
  },
56
56
  "dependencies": {
57
- "@barefootjs/shared": "0.30.0"
57
+ "@barefootjs/shared": "0.30.3"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@barefootjs/jsx": ">=0.2.0"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@barefootjs/adapter-tests": "0.1.0",
64
- "@barefootjs/jsx": "0.30.0",
64
+ "@barefootjs/jsx": "0.30.2",
65
65
  "typescript": "^5.0.0"
66
66
  }
67
67
  }
@@ -333,6 +333,21 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
333
333
  */
334
334
  private staticLoopSourceBoundNames: Set<string> = new Set()
335
335
 
336
+ /**
337
+ * Names currently bound by an enclosing loop body — the block-param
338
+ * locals `renderLoop` introduces (item, index, per-binding destructure
339
+ * fields, `.map()` preamble declarations) — ref-counted so nested loops
340
+ * compose. This is the POSITION-ACCURATE twin of the coarse
341
+ * `staticLoopSourceBoundNames` above: that set is a whole-component
342
+ * union used only to guard static-const inlining (safe to over-suppress
343
+ * there — the fallback is just "don't inline"), whereas the boolean-prop
344
+ * and nullable-optional classification sites need to know whether a name
345
+ * is loop-bound AT THIS POSITION, because for those two the coarse
346
+ * fallback would silently mis-render a genuine prop occurrence outside
347
+ * the loop too (#2488).
348
+ */
349
+ private loopBoundNames: Map<string, number> = new Map()
350
+
336
351
  /**
337
352
  * Optional, no-default props that are `None` when the caller omits them.
338
353
  * Their bare-reference attribute emission is guarded with a Jinja
@@ -366,6 +381,7 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
366
381
  this.booleanTypedProps = collectBooleanTypedProps(ir)
367
382
  this.localConstants = ir.metadata.localConstants ?? []
368
383
  this.staticLoopSourceBoundNames = collectLoopBoundNames(ir)
384
+ this.loopBoundNames.clear()
369
385
  this.nullableOptionalProps = collectNullableOptionalProps(ir)
370
386
  this.stringValueNames = collectStringValueNames(ir)
371
387
  this.moduleStringConsts = collectModuleStringConsts(ir.metadata.localConstants)
@@ -952,7 +968,42 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
952
968
  const preambleLines = (loop.preamble?.declarations ?? []).map(
953
969
  d => `{% set ${minijinjaIdent(d.name)} = ${this.convertExpressionToJinja(d.raw, d.valueParsed)} %}`,
954
970
  )
971
+ // Names this loop binds in body scope, for the position-accurate
972
+ // `loopBoundNames` guard (#2488) — mirrors the ERB adapter's `loopBound`
973
+ // derivation, adapted to what THIS renderLoop actually binds: the
974
+ // for-header target(s) (`loopVar` / `objectIteration` key+value /
975
+ // `iterationShape === 'keys'`'s `param`), each `indexLocalLines` name
976
+ // (explicit index, or a destructure binding), and the `.map()`
977
+ // preamble's declared locals. Ref-counted so nested loops compose.
978
+ const loopBound: string[] = []
979
+ if (loop.objectIteration === 'entries') {
980
+ loopBound.push(loop.index ?? param, param)
981
+ } else if (loop.objectIteration === 'keys') {
982
+ // `|items` binds both slots; the unused one is a throwaway (#2488).
983
+ loopBound.push(param, '__bf_v')
984
+ } else if (loop.objectIteration === 'values') {
985
+ loopBound.push('__bf_k', param)
986
+ } else if (loop.iterationShape === 'keys') {
987
+ // The header still binds the throwaway loop var; `param` is only the
988
+ // index alias set beneath it (#2488).
989
+ loopBound.push('__bf_item', param)
990
+ } else if (supportableDestructure) {
991
+ loopBound.push('__bf_item', ...(loop.paramBindings ?? []).map(b => b.name))
992
+ if (loop.index) loopBound.push(loop.index)
993
+ } else {
994
+ loopBound.push(param)
995
+ if (loop.index) loopBound.push(loop.index)
996
+ }
997
+ for (const d of loop.preamble?.declarations ?? []) loopBound.push(d.name)
998
+ for (const n of loopBound) {
999
+ this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1)
1000
+ }
955
1001
  const childrenUnderLoop = this.renderChildren(loop.children)
1002
+ for (const n of loopBound) {
1003
+ const c = (this.loopBoundNames.get(n) ?? 1) - 1
1004
+ if (c <= 0) this.loopBoundNames.delete(n)
1005
+ else this.loopBoundNames.set(n, c)
1006
+ }
956
1007
  this.currentLoopKeyDepth = prevLoopKeyDepth
957
1008
  this.inLoop = prevInLoop
958
1009
  void renderedChildren
@@ -1352,7 +1403,11 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
1352
1403
  !isBooleanAttr(name) &&
1353
1404
  !value.presenceOrUndefined &&
1354
1405
  /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) &&
1355
- this.nullableOptionalProps.has(normalizedBareId)
1406
+ this.nullableOptionalProps.has(normalizedBareId) &&
1407
+ // Inside a `.map()` callback, a param that shadows a nullable
1408
+ // optional prop's name is the row binding, not the prop — skip the
1409
+ // spurious "is defined and is not none" guard (#2488).
1410
+ !this.isLoopBoundName(normalizedBareId)
1356
1411
  ) {
1357
1412
  const jinja = this.convertExpressionToJinja(value.expr)
1358
1413
  const body = this.shouldBoolStr(value.expr, name)
@@ -1861,9 +1916,18 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
1861
1916
  bare = bare.slice(this.propsObjectName.length + 1)
1862
1917
  }
1863
1918
  if (!/^[A-Za-z_$][\w$]*$/.test(bare)) return false
1919
+ // Inside a `.map()` callback, a param that shares a boolean prop's name
1920
+ // is the ROW binding, not the prop — route it through plain string
1921
+ // emission instead of `bf.bool_str` (#2488).
1922
+ if (this.isLoopBoundName(bare)) return false
1864
1923
  return this.booleanTypedProps.has(bare)
1865
1924
  }
1866
1925
 
1926
+ /** Position-accurate loop-bound-name check — see `loopBoundNames`'s docstring. */
1927
+ private isLoopBoundName(name: string): boolean {
1928
+ return this.loopBoundNames.has(name)
1929
+ }
1930
+
1867
1931
  /**
1868
1932
  * Whether an attribute-value expression should route through
1869
1933
  * `bf.bool_str` (vs. plain `bf.string`) at its interpolation site.
@@ -34,4 +34,10 @@ export const renderDivergences: RenderDivergences = {
34
34
  'aliased destructured prop `{ n: count }` loses its rename — template vars, ssr-defaults, and the props bridge all key off the local name, so the prop is always undefined (https://github.com/piconic-ai/barefootjs/issues/2460)',
35
35
  'composite-row-child-aliased-prop':
36
36
  'same #2460 defect as `aliased-destructured-prop`, inside a keyed `.map()` loop row: the nested child\'s renamed prop (`{ n: count }`) is always undefined, so both rows render an empty count (https://github.com/piconic-ai/barefootjs/issues/2460)',
37
+
38
+ // #2482 audit follow-ups: loop-scope holes in per-adapter name
39
+ // classification. Graduate by applying the loop-bound-name guards
40
+ // described in each issue and deleting the line.
41
+ 'loop-param-shadows-spread-const':
42
+ 'a .map() param shadowing an object const is resolved by `emitSpread` against `localConstants` with no loop-shadow check, so every row spreads the OUTER const instead of the row value (https://github.com/piconic-ai/barefootjs/issues/2489)',
37
43
  }