@barefootjs/mojolicious 0.29.0 → 0.30.2

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.
@@ -24,7 +24,8 @@ import {
24
24
  resolveDangerousInnerHtml,
25
25
  dangerousInnerHtmlMetacharViolation,
26
26
  dangerousInnerHtmlDiagnostic,
27
- resolveStaticLoopSource
27
+ resolveStaticLoopSource,
28
+ derivesScopeFromSlot
28
29
  } from "@barefootjs/jsx";
29
30
 
30
31
  // src/adapter/boolean-result.ts
@@ -1046,7 +1047,6 @@ class MojoAdapter extends BaseAdapter {
1046
1047
  rootScopeNodes = new Set;
1047
1048
  options;
1048
1049
  errors = [];
1049
- inLoop = false;
1050
1050
  currentLoopKeyDepth = 0;
1051
1051
  propsObjectName = null;
1052
1052
  propsParams = [];
@@ -1436,16 +1436,16 @@ ${whenTrue}
1436
1436
  const param = loop.param;
1437
1437
  const indexVar = loop.iterationShape === "keys" ? `$${param}` : loop.index ? `$${loop.index}` : "$_i";
1438
1438
  const loopBound = loop.objectIteration === "entries" ? [param, loop.index ?? "_k"] : loop.objectIteration === "keys" || loop.objectIteration === "values" || loop.iterationShape === "keys" ? [param] : supportableDestructure ? ["__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name), loop.index ?? "_i"] : [param, loop.index ?? "_i"];
1439
+ const preambleDecls = loop.preamble?.declarations ?? [];
1440
+ for (const d of preambleDecls)
1441
+ loopBound.push(d.name);
1439
1442
  for (const n of loopBound) {
1440
1443
  this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
1441
1444
  }
1442
- const prevInLoop = this.inLoop;
1443
- this.inLoop = true;
1444
1445
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
1445
1446
  this.currentLoopKeyDepth = loop.depth;
1446
1447
  const renderedChildren = this.renderChildren(loop.children);
1447
1448
  this.currentLoopKeyDepth = prevLoopKeyDepth;
1448
- this.inLoop = prevInLoop;
1449
1449
  const children = loop.bodyIsItemConditional && loop.key ? `<%== bf->comment("loop-i:" . ${this.convertExpressionToPerl(loop.key)}) %>
1450
1450
  ${renderedChildren}` : renderedChildren;
1451
1451
  const lines = [];
@@ -1505,6 +1505,7 @@ ${renderedChildren}` : renderedChildren;
1505
1505
  }
1506
1506
  }
1507
1507
  }
1508
+ const preambleLines = preambleDecls.map((d) => `% my $${d.name} = ${this.convertExpressionToPerl(d.raw, d.valueParsed)};`);
1508
1509
  if (loop.filterPredicate) {
1509
1510
  let filterCond;
1510
1511
  if (loop.filterPredicate.predicate) {
@@ -1516,9 +1517,11 @@ ${renderedChildren}` : renderedChildren;
1516
1517
  filterCond = filterCond.replace(new RegExp(`\\$${loop.filterPredicate.param}\\b`, "g"), `$${param}`);
1517
1518
  }
1518
1519
  lines.push(`% if (${filterCond}) {`);
1520
+ lines.push(...preambleLines);
1519
1521
  lines.push(children);
1520
1522
  lines.push(`% }`);
1521
1523
  } else {
1524
+ lines.push(...preambleLines);
1522
1525
  lines.push(children);
1523
1526
  }
1524
1527
  for (const n of loopBound) {
@@ -1562,10 +1565,7 @@ ${renderedChildren}` : renderedChildren;
1562
1565
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
1563
1566
  continue;
1564
1567
  if (p.value.kind === "jsx-children" && p.name !== "children") {
1565
- const prevInLoop = this.inLoop;
1566
- this.inLoop = false;
1567
1568
  const slotBody = this.renderChildren(p.value.children);
1568
- this.inLoop = prevInLoop;
1569
1569
  const varName = `$bf_prop_${this.childrenCaptureCounter++}`;
1570
1570
  namedSlotCaptures.push(`<% my ${varName} = begin %>${slotBody}<% end %>`);
1571
1571
  propParts.push(`${perlHashKey(p.name)} => ${varName}`);
@@ -1575,17 +1575,14 @@ ${renderedChildren}` : renderedChildren;
1575
1575
  if (lowered)
1576
1576
  propParts.push(lowered);
1577
1577
  }
1578
- if (comp.slotId && !this.inLoop) {
1578
+ if (derivesScopeFromSlot(comp)) {
1579
1579
  propParts.push(`_bf_slot => '${comp.slotId}'`);
1580
1580
  }
1581
1581
  const propsStr = propParts.length > 0 ? ", " + propParts.join(", ") : "";
1582
1582
  const tplName = this.toTemplateName(comp.name);
1583
1583
  const effectiveChildren = comp.children.length > 0 ? comp.children : resolveJsxChildrenProp(comp.props);
1584
1584
  if (effectiveChildren.length > 0) {
1585
- const prevInLoop = this.inLoop;
1586
- this.inLoop = false;
1587
1585
  const childrenBody = this.renderChildren(effectiveChildren);
1588
- this.inLoop = prevInLoop;
1589
1586
  const varName = `$bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`;
1590
1587
  return `${namedSlotCaptures.join("")}<% my ${varName} = begin %>${childrenBody}<% end %><%== bf->render_child('${tplName}'${propsStr}, children => ${varName}) %>`;
1591
1588
  }
@@ -35,7 +35,6 @@ export declare class MojoAdapter extends BaseAdapter implements IRNodeEmitter<Mo
35
35
  private rootScopeNodes;
36
36
  private options;
37
37
  private errors;
38
- private inLoop;
39
38
  /**
40
39
  * `IRLoop.depth` of the loop currently being rendered (save/restore
41
40
  * around `renderChildren(loop.children)`, mirroring `inLoop` above).
@@ -1 +1 @@
1
- {"version":3,"file":"mojo-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/mojo-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mojo-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/mojo-adapter.ts"],"names":[],"mappings":"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"}
package/dist/build.js CHANGED
@@ -24,7 +24,8 @@ import {
24
24
  resolveDangerousInnerHtml,
25
25
  dangerousInnerHtmlMetacharViolation,
26
26
  dangerousInnerHtmlDiagnostic,
27
- resolveStaticLoopSource
27
+ resolveStaticLoopSource,
28
+ derivesScopeFromSlot
28
29
  } from "@barefootjs/jsx";
29
30
 
30
31
  // src/adapter/boolean-result.ts
@@ -1046,7 +1047,6 @@ class MojoAdapter extends BaseAdapter {
1046
1047
  rootScopeNodes = new Set;
1047
1048
  options;
1048
1049
  errors = [];
1049
- inLoop = false;
1050
1050
  currentLoopKeyDepth = 0;
1051
1051
  propsObjectName = null;
1052
1052
  propsParams = [];
@@ -1436,16 +1436,16 @@ ${whenTrue}
1436
1436
  const param = loop.param;
1437
1437
  const indexVar = loop.iterationShape === "keys" ? `$${param}` : loop.index ? `$${loop.index}` : "$_i";
1438
1438
  const loopBound = loop.objectIteration === "entries" ? [param, loop.index ?? "_k"] : loop.objectIteration === "keys" || loop.objectIteration === "values" || loop.iterationShape === "keys" ? [param] : supportableDestructure ? ["__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name), loop.index ?? "_i"] : [param, loop.index ?? "_i"];
1439
+ const preambleDecls = loop.preamble?.declarations ?? [];
1440
+ for (const d of preambleDecls)
1441
+ loopBound.push(d.name);
1439
1442
  for (const n of loopBound) {
1440
1443
  this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
1441
1444
  }
1442
- const prevInLoop = this.inLoop;
1443
- this.inLoop = true;
1444
1445
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
1445
1446
  this.currentLoopKeyDepth = loop.depth;
1446
1447
  const renderedChildren = this.renderChildren(loop.children);
1447
1448
  this.currentLoopKeyDepth = prevLoopKeyDepth;
1448
- this.inLoop = prevInLoop;
1449
1449
  const children = loop.bodyIsItemConditional && loop.key ? `<%== bf->comment("loop-i:" . ${this.convertExpressionToPerl(loop.key)}) %>
1450
1450
  ${renderedChildren}` : renderedChildren;
1451
1451
  const lines = [];
@@ -1505,6 +1505,7 @@ ${renderedChildren}` : renderedChildren;
1505
1505
  }
1506
1506
  }
1507
1507
  }
1508
+ const preambleLines = preambleDecls.map((d) => `% my $${d.name} = ${this.convertExpressionToPerl(d.raw, d.valueParsed)};`);
1508
1509
  if (loop.filterPredicate) {
1509
1510
  let filterCond;
1510
1511
  if (loop.filterPredicate.predicate) {
@@ -1516,9 +1517,11 @@ ${renderedChildren}` : renderedChildren;
1516
1517
  filterCond = filterCond.replace(new RegExp(`\\$${loop.filterPredicate.param}\\b`, "g"), `$${param}`);
1517
1518
  }
1518
1519
  lines.push(`% if (${filterCond}) {`);
1520
+ lines.push(...preambleLines);
1519
1521
  lines.push(children);
1520
1522
  lines.push(`% }`);
1521
1523
  } else {
1524
+ lines.push(...preambleLines);
1522
1525
  lines.push(children);
1523
1526
  }
1524
1527
  for (const n of loopBound) {
@@ -1562,10 +1565,7 @@ ${renderedChildren}` : renderedChildren;
1562
1565
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
1563
1566
  continue;
1564
1567
  if (p.value.kind === "jsx-children" && p.name !== "children") {
1565
- const prevInLoop = this.inLoop;
1566
- this.inLoop = false;
1567
1568
  const slotBody = this.renderChildren(p.value.children);
1568
- this.inLoop = prevInLoop;
1569
1569
  const varName = `$bf_prop_${this.childrenCaptureCounter++}`;
1570
1570
  namedSlotCaptures.push(`<% my ${varName} = begin %>${slotBody}<% end %>`);
1571
1571
  propParts.push(`${perlHashKey(p.name)} => ${varName}`);
@@ -1575,17 +1575,14 @@ ${renderedChildren}` : renderedChildren;
1575
1575
  if (lowered)
1576
1576
  propParts.push(lowered);
1577
1577
  }
1578
- if (comp.slotId && !this.inLoop) {
1578
+ if (derivesScopeFromSlot(comp)) {
1579
1579
  propParts.push(`_bf_slot => '${comp.slotId}'`);
1580
1580
  }
1581
1581
  const propsStr = propParts.length > 0 ? ", " + propParts.join(", ") : "";
1582
1582
  const tplName = this.toTemplateName(comp.name);
1583
1583
  const effectiveChildren = comp.children.length > 0 ? comp.children : resolveJsxChildrenProp(comp.props);
1584
1584
  if (effectiveChildren.length > 0) {
1585
- const prevInLoop = this.inLoop;
1586
- this.inLoop = false;
1587
1585
  const childrenBody = this.renderChildren(effectiveChildren);
1588
- this.inLoop = prevInLoop;
1589
1586
  const varName = `$bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`;
1590
1587
  return `${namedSlotCaptures.join("")}<% my ${varName} = begin %>${childrenBody}<% end %><%== bf->render_child('${tplName}'${propsStr}, children => ${varName}) %>`;
1591
1588
  }
@@ -1 +1 @@
1
- {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAwL7B,CAAA"}
1
+ {"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAmL7B,CAAA"}
package/dist/index.js CHANGED
@@ -24,7 +24,8 @@ import {
24
24
  resolveDangerousInnerHtml,
25
25
  dangerousInnerHtmlMetacharViolation,
26
26
  dangerousInnerHtmlDiagnostic,
27
- resolveStaticLoopSource
27
+ resolveStaticLoopSource,
28
+ derivesScopeFromSlot
28
29
  } from "@barefootjs/jsx";
29
30
 
30
31
  // src/adapter/boolean-result.ts
@@ -1046,7 +1047,6 @@ class MojoAdapter extends BaseAdapter {
1046
1047
  rootScopeNodes = new Set;
1047
1048
  options;
1048
1049
  errors = [];
1049
- inLoop = false;
1050
1050
  currentLoopKeyDepth = 0;
1051
1051
  propsObjectName = null;
1052
1052
  propsParams = [];
@@ -1436,16 +1436,16 @@ ${whenTrue}
1436
1436
  const param = loop.param;
1437
1437
  const indexVar = loop.iterationShape === "keys" ? `$${param}` : loop.index ? `$${loop.index}` : "$_i";
1438
1438
  const loopBound = loop.objectIteration === "entries" ? [param, loop.index ?? "_k"] : loop.objectIteration === "keys" || loop.objectIteration === "values" || loop.iterationShape === "keys" ? [param] : supportableDestructure ? ["__bf_item", ...(loop.paramBindings ?? []).map((b) => b.name), loop.index ?? "_i"] : [param, loop.index ?? "_i"];
1439
+ const preambleDecls = loop.preamble?.declarations ?? [];
1440
+ for (const d of preambleDecls)
1441
+ loopBound.push(d.name);
1439
1442
  for (const n of loopBound) {
1440
1443
  this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
1441
1444
  }
1442
- const prevInLoop = this.inLoop;
1443
- this.inLoop = true;
1444
1445
  const prevLoopKeyDepth = this.currentLoopKeyDepth;
1445
1446
  this.currentLoopKeyDepth = loop.depth;
1446
1447
  const renderedChildren = this.renderChildren(loop.children);
1447
1448
  this.currentLoopKeyDepth = prevLoopKeyDepth;
1448
- this.inLoop = prevInLoop;
1449
1449
  const children = loop.bodyIsItemConditional && loop.key ? `<%== bf->comment("loop-i:" . ${this.convertExpressionToPerl(loop.key)}) %>
1450
1450
  ${renderedChildren}` : renderedChildren;
1451
1451
  const lines = [];
@@ -1505,6 +1505,7 @@ ${renderedChildren}` : renderedChildren;
1505
1505
  }
1506
1506
  }
1507
1507
  }
1508
+ const preambleLines = preambleDecls.map((d) => `% my $${d.name} = ${this.convertExpressionToPerl(d.raw, d.valueParsed)};`);
1508
1509
  if (loop.filterPredicate) {
1509
1510
  let filterCond;
1510
1511
  if (loop.filterPredicate.predicate) {
@@ -1516,9 +1517,11 @@ ${renderedChildren}` : renderedChildren;
1516
1517
  filterCond = filterCond.replace(new RegExp(`\\$${loop.filterPredicate.param}\\b`, "g"), `$${param}`);
1517
1518
  }
1518
1519
  lines.push(`% if (${filterCond}) {`);
1520
+ lines.push(...preambleLines);
1519
1521
  lines.push(children);
1520
1522
  lines.push(`% }`);
1521
1523
  } else {
1524
+ lines.push(...preambleLines);
1522
1525
  lines.push(children);
1523
1526
  }
1524
1527
  for (const n of loopBound) {
@@ -1562,10 +1565,7 @@ ${renderedChildren}` : renderedChildren;
1562
1565
  if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
1563
1566
  continue;
1564
1567
  if (p.value.kind === "jsx-children" && p.name !== "children") {
1565
- const prevInLoop = this.inLoop;
1566
- this.inLoop = false;
1567
1568
  const slotBody = this.renderChildren(p.value.children);
1568
- this.inLoop = prevInLoop;
1569
1569
  const varName = `$bf_prop_${this.childrenCaptureCounter++}`;
1570
1570
  namedSlotCaptures.push(`<% my ${varName} = begin %>${slotBody}<% end %>`);
1571
1571
  propParts.push(`${perlHashKey(p.name)} => ${varName}`);
@@ -1575,17 +1575,14 @@ ${renderedChildren}` : renderedChildren;
1575
1575
  if (lowered)
1576
1576
  propParts.push(lowered);
1577
1577
  }
1578
- if (comp.slotId && !this.inLoop) {
1578
+ if (derivesScopeFromSlot(comp)) {
1579
1579
  propParts.push(`_bf_slot => '${comp.slotId}'`);
1580
1580
  }
1581
1581
  const propsStr = propParts.length > 0 ? ", " + propParts.join(", ") : "";
1582
1582
  const tplName = this.toTemplateName(comp.name);
1583
1583
  const effectiveChildren = comp.children.length > 0 ? comp.children : resolveJsxChildrenProp(comp.props);
1584
1584
  if (effectiveChildren.length > 0) {
1585
- const prevInLoop = this.inLoop;
1586
- this.inLoop = false;
1587
1585
  const childrenBody = this.renderChildren(effectiveChildren);
1588
- this.inLoop = prevInLoop;
1589
1586
  const varName = `$bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`;
1590
1587
  return `${namedSlotCaptures.join("")}<% my ${varName} = begin %>${childrenBody}<% end %><%== bf->render_child('${tplName}'${propsStr}, children => ${varName}) %>`;
1591
1588
  }
@@ -1913,7 +1910,6 @@ var mojoAdapter = new MojoAdapter;
1913
1910
  // src/conformance-pins.ts
1914
1911
  var conformancePins = {
1915
1912
  "filter-typeof-predicate": [{ code: "BF021", severity: "error" }],
1916
- "map-preamble-branch-body": [{ code: "BF021", severity: "error" }],
1917
1913
  "map-array-builder-body": [{ code: "BF021", severity: "error" }],
1918
1914
  "map-array-builder-escaping": [{ code: "BF021", severity: "error" }],
1919
1915
  "fill-unsupported": [{ code: "BF101", severity: "error" }],
@@ -1938,7 +1934,10 @@ var conformancePins = {
1938
1934
  };
1939
1935
  // src/render-divergences.ts
1940
1936
  var renderDivergences = {
1941
- "composite-row-child-component": "a child component nested inside a dynamic loop row gets a random `Name_<id>` scope id from `render_child` instead of the parent-derived `<parent>_s0` the reference emits (https://github.com/piconic-ai/barefootjs/issues/2444)"
1937
+ "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)",
1938
+ "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)",
1939
+ "loop-param-shadows-bool-prop": 'a .map() param sharing a boolean prop\'s name is routed through the bool lowering in attribute position (renders "true"/"false" instead of the row string) — `collectBooleanTypedProps` lacks the loop-bound-name subtraction its sibling `collectStringValueNames` got in #2236 (https://github.com/piconic-ai/barefootjs/issues/2488)',
1940
+ "loop-param-shadows-record-template-span": "a dynamic-key element access on a loop row (`tone[k]`) diverges on real Mojolicious at render time (same silent-empty family as ERB/Go/Twig; the Perl-side mechanism needs a dig) (https://github.com/piconic-ai/barefootjs/issues/2491)"
1942
1941
  };
1943
1942
  export {
1944
1943
  renderDivergences,
@@ -1 +1 @@
1
- {"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBAe/B,CAAA"}
1
+ {"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBA2B/B,CAAA"}
@@ -1,5 +1,5 @@
1
1
  package BarefootJS::Backend::Mojo;
2
- our $VERSION = "0.28.1";
2
+ our $VERSION = "0.30.0";
3
3
  use Mojo::Base -base, -signatures;
4
4
 
5
5
  use Mojo::ByteStream qw(b);
@@ -1,5 +1,5 @@
1
1
  package Mojolicious::Plugin::BarefootJS::DevReload;
2
- our $VERSION = "0.28.1";
2
+ our $VERSION = "0.30.0";
3
3
  use Mojo::Base 'Mojolicious::Plugin', -signatures;
4
4
 
5
5
  =head1 NAME
@@ -1,5 +1,5 @@
1
1
  package Mojolicious::Plugin::BarefootJS;
2
- our $VERSION = "0.28.1";
2
+ our $VERSION = "0.30.0";
3
3
  use Mojo::Base 'Mojolicious::Plugin', -signatures;
4
4
 
5
5
  use Mojo::File qw(path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barefootjs/mojolicious",
3
- "version": "0.29.0",
3
+ "version": "0.30.2",
4
4
  "description": "Mojolicious EP template adapter for BarefootJS - generates .html.ep files from IR",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -52,7 +52,7 @@
52
52
  "directory": "packages/adapter-mojolicious"
53
53
  },
54
54
  "dependencies": {
55
- "@barefootjs/shared": "0.29.0"
55
+ "@barefootjs/shared": "0.30.2"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@barefootjs/jsx": ">=0.2.0",
@@ -60,6 +60,6 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@barefootjs/adapter-tests": "0.1.0",
63
- "@barefootjs/jsx": "0.29.0"
63
+ "@barefootjs/jsx": "0.30.2"
64
64
  }
65
65
  }
@@ -488,14 +488,14 @@ function C({ rows }: { rows?: number }) {
488
488
 
489
489
  test('leaves a defaulted attr unconditional (scope did not widen)', () => {
490
490
  const { template } = compileAndGenerate(`
491
- function C({ value = '' }: { value?: string }) {
492
- return <textarea value={value} />
491
+ function C({ placeholder = '' }: { placeholder?: string }) {
492
+ return <textarea placeholder={placeholder} />
493
493
  }
494
494
  `)
495
- // `value` has a destructure default → never undef → unconditional,
496
- // exactly like Hono's value="".
497
- expect(template).toContain('value="<%= $value %>"')
498
- expect(template).not.toContain('defined $value')
495
+ // `placeholder` has a destructure default → never undef → unconditional,
496
+ // exactly like Hono's placeholder="".
497
+ expect(template).toContain('placeholder="<%= $placeholder %>"')
498
+ expect(template).not.toContain('defined $placeholder')
499
499
  })
500
500
  })
501
501
 
@@ -64,6 +64,7 @@ import {
64
64
  dangerousInnerHtmlMetacharViolation,
65
65
  dangerousInnerHtmlDiagnostic,
66
66
  resolveStaticLoopSource,
67
+ derivesScopeFromSlot,
67
68
  } from '@barefootjs/jsx'
68
69
  import { isAriaBooleanAttr, isBooleanResultExpr } from './boolean-result.ts'
69
70
  import type { ParsedExpr, LoweringMatcher } from '@barefootjs/jsx'
@@ -170,7 +171,6 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
170
171
  private rootScopeNodes: Set<IRNode> = new Set()
171
172
  private options: Required<MojoAdapterOptions>
172
173
  private errors: CompilerError[] = []
173
- private inLoop: boolean = false
174
174
  /**
175
175
  * `IRLoop.depth` of the loop currently being rendered (save/restore
176
176
  * around `renderChildren(loop.children)`, mirroring `inLoop` above).
@@ -936,16 +936,19 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
936
936
  : supportableDestructure
937
937
  ? ['__bf_item', ...(loop.paramBindings ?? []).map(b => b.name), loop.index ?? '_i']
938
938
  : [param, loop.index ?? '_i']
939
+ // A `.map()` callback preamble lowers to one per-row `my` local per
940
+ // declaration (#2447). Loop-binding the names keeps a same-named module
941
+ // const from inlining over the local the loop just declared — the same
942
+ // hazard class `resolveModuleStringConst` already consults this map for.
943
+ const preambleDecls = loop.preamble?.declarations ?? []
944
+ for (const d of preambleDecls) loopBound.push(d.name)
939
945
  for (const n of loopBound) {
940
946
  this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1)
941
947
  }
942
- const prevInLoop = this.inLoop
943
- this.inLoop = true
944
948
  const prevLoopKeyDepth = this.currentLoopKeyDepth
945
949
  this.currentLoopKeyDepth = loop.depth
946
950
  const renderedChildren = this.renderChildren(loop.children)
947
951
  this.currentLoopKeyDepth = prevLoopKeyDepth
948
- this.inLoop = prevInLoop
949
952
 
950
953
  // Whole-item conditional (#1665): prepend an always-present
951
954
  // `<!--bf-loop-i:KEY-->` anchor before each item's (possibly empty)
@@ -1056,6 +1059,15 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
1056
1059
  }
1057
1060
  }
1058
1061
 
1062
+ // Per-row preamble locals (#2447), in source order so a later
1063
+ // initializer sees an earlier local — same as the source block. Emitted
1064
+ // INSIDE the filter guard below, matching JS evaluation order: a
1065
+ // `.filter(p).map(cb)` chain never runs `cb`'s body for a filtered-out
1066
+ // item.
1067
+ const preambleLines = preambleDecls.map(
1068
+ d => `% my $${d.name} = ${this.convertExpressionToPerl(d.raw, d.valueParsed)};`,
1069
+ )
1070
+
1059
1071
  // Handle filter().map() pattern by wrapping children in if-condition
1060
1072
  if (loop.filterPredicate) {
1061
1073
  let filterCond: string
@@ -1075,9 +1087,11 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
1075
1087
  )
1076
1088
  }
1077
1089
  lines.push(`% if (${filterCond}) {`)
1090
+ lines.push(...preambleLines)
1078
1091
  lines.push(children)
1079
1092
  lines.push(`% }`)
1080
1093
  } else {
1094
+ lines.push(...preambleLines)
1081
1095
  lines.push(children)
1082
1096
  }
1083
1097
 
@@ -1168,10 +1182,7 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
1168
1182
  // SSR (Hono renders neither; the client JS wires them at hydration).
1169
1183
  if ((p.name.match(/^on[A-Z]/) || p.name === 'ref') && p.value.kind === 'expression') continue
1170
1184
  if (p.value.kind === 'jsx-children' && p.name !== 'children') {
1171
- const prevInLoop = this.inLoop
1172
- this.inLoop = false
1173
1185
  const slotBody = this.renderChildren(p.value.children)
1174
- this.inLoop = prevInLoop
1175
1186
  // Purely counter-based — NOT derived from `p.name` or `comp.slotId`.
1176
1187
  // A JSX prop name can contain characters (`data-slot`) that aren't a
1177
1188
  // valid Perl variable token, and `comp.slotId` alone would collide
@@ -1186,9 +1197,10 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
1186
1197
  const lowered = emitAttrValue(p.value, this.componentPropEmitter, p.name)
1187
1198
  if (lowered) propParts.push(lowered)
1188
1199
  }
1189
- // Pass slot ID so the child renderer can set correct scope ID for hydration
1190
- // Skip for loop childrenthey use ComponentName_random pattern instead
1191
- if (comp.slotId && !this.inLoop) {
1200
+ // Pass slot ID so the child renderer can set correct scope ID for
1201
+ // hydration. Skipped for a loop item root it uses ComponentName_random
1202
+ // instead (#2444).
1203
+ if (derivesScopeFromSlot(comp)) {
1192
1204
  propParts.push(`_bf_slot => '${comp.slotId}'`)
1193
1205
  }
1194
1206
  const propsStr = propParts.length > 0 ? ', ' + propParts.join(', ') : ''
@@ -1215,10 +1227,7 @@ export class MojoAdapter extends BaseAdapter implements IRNodeEmitter<MojoRender
1215
1227
  // `render_child` would let the inner `%>` close the outer tag.
1216
1228
  // `render_child` materializes the resulting CODE ref into the
1217
1229
  // captured Mojo::ByteStream.
1218
- const prevInLoop = this.inLoop
1219
- this.inLoop = false
1220
1230
  const childrenBody = this.renderChildren(effectiveChildren)
1221
- this.inLoop = prevInLoop
1222
1231
  const varName = `$bf_children_${comp.slotId ?? 'c' + this.childrenCaptureCounter++}`
1223
1232
  return `${namedSlotCaptures.join('')}<% my ${varName} = begin %>${childrenBody}<% end %><%== bf->render_child('${tplName}'${propsStr}, children => ${varName}) %>`
1224
1233
  }
@@ -13,11 +13,6 @@ export const conformancePins: ConformancePins = {
13
13
  // JS-runtime target runs it, a DSL adapter surfaces BF021 + `/* @client */`.
14
14
  // See spec/callback-fidelity.md.
15
15
  'filter-typeof-predicate': [{ code: 'BF021', severity: 'error' }],
16
- // A `.map()` body with a `const`/`let` preamble before its branches:
17
- // a JS runtime folds it, a DSL adapter can't carry the loop-local into a
18
- // conditional branch template, so it refuses with BF021 + `/* @client */`.
19
- // See spec/callback-fidelity.md.
20
- 'map-preamble-branch-body': [{ code: 'BF021', severity: 'error' }],
21
16
  'map-array-builder-body': [{ code: 'BF021', severity: 'error' }],
22
17
  'map-array-builder-escaping': [{ code: 'BF021', severity: 'error' }],
23
18
  // `.fill(value)` mutates the receiver in place — no template lowering
@@ -20,13 +20,25 @@ export const renderDivergences: RenderDivergences = {
20
20
  // instead of a fixed regex-shape catalogue) now correctly seeds `todos`
21
21
  // from `(props.initialTodos ?? []).map(t => ({ ...t, editing: false }))`.
22
22
 
23
- // #2444: a child component nested inside a dynamic loop row whose root
24
- // is a plain element (`composite` loop plan + `nestedComponents`) is
25
- // rendered through the runtime's `render_child`, which mints its own
26
- // `Badge_<random>` scope id instead of deriving the parent-scope +
27
- // mount-slot id (`test_s0`) the Hono reference emits. Content is
28
- // correct; only `bf-s` diverges. Same class as the `grandchild-
29
- // composition` CSR skip.
30
- 'composite-row-child-component':
31
- 'a child component nested inside a dynamic loop row gets a random `Name_<id>` scope id from `render_child` instead of the parent-derived `<parent>_s0` the reference emits (https://github.com/piconic-ai/barefootjs/issues/2444)',
23
+ // Onboarding TSX-fidelity fixtures (PR #2461): `expectedHtml` is
24
+ // hand-authored to the CORRECT output because the emission bug lives in
25
+ // the shared compiler layer every adapter, including the Hono
26
+ // reference, currently emits the broken form (verified against this
27
+ // adapter's emitted template; see each fixture's docstring). Graduate
28
+ // by fixing the shared emission, regenerating `expectedHtml` from the
29
+ // fixed reference, and deleting these lines (and the matching hono
30
+ // `skipJsx` entries).
31
+ 'aliased-destructured-prop':
32
+ '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)',
33
+ 'composite-row-child-aliased-prop':
34
+ '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)',
35
+
36
+ // #2482 audit follow-up. Graduate by applying the loop-bound-name
37
+ // guard described in the issue and deleting the line. (The emitSpread
38
+ // sibling hole #2489 does NOT affect this adapter — its emitter
39
+ // consults the live `loopBoundNames` map on that path.)
40
+ 'loop-param-shadows-bool-prop':
41
+ 'a .map() param sharing a boolean prop\'s name is routed through the bool lowering in attribute position (renders "true"/"false" instead of the row string) — `collectBooleanTypedProps` lacks the loop-bound-name subtraction its sibling `collectStringValueNames` got in #2236 (https://github.com/piconic-ai/barefootjs/issues/2488)',
42
+ 'loop-param-shadows-record-template-span':
43
+ 'a dynamic-key element access on a loop row (`tone[k]`) diverges on real Mojolicious at render time (same silent-empty family as ERB/Go/Twig; the Perl-side mechanism needs a dig) (https://github.com/piconic-ai/barefootjs/issues/2491)',
32
44
  }