@barefootjs/mojolicious 0.31.4 → 0.31.6
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.
- package/dist/adapter/index.js +18 -36
- package/dist/adapter/mojo-adapter.d.ts +19 -12
- package/dist/adapter/mojo-adapter.d.ts.map +1 -1
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +29 -41
- package/dist/vite.js +149 -120
- package/lib/BarefootJS/Backend/Mojo.pm +1 -1
- package/lib/Mojolicious/Plugin/BarefootJS/DevReload.pm +1 -1
- package/lib/Mojolicious/Plugin/BarefootJS.pm +1 -1
- package/package.json +5 -5
- package/src/adapter/mojo-adapter.ts +57 -63
- package/src/conformance-pins.ts +14 -5
package/dist/adapter/index.js
CHANGED
|
@@ -25,7 +25,8 @@ import {
|
|
|
25
25
|
dangerousInnerHtmlMetacharViolation,
|
|
26
26
|
dangerousInnerHtmlDiagnostic,
|
|
27
27
|
resolveStaticLoopSource,
|
|
28
|
-
derivesScopeFromSlot
|
|
28
|
+
derivesScopeFromSlot,
|
|
29
|
+
BindingScope
|
|
29
30
|
} from "@barefootjs/jsx";
|
|
30
31
|
|
|
31
32
|
// src/adapter/boolean-result.ts
|
|
@@ -1054,7 +1055,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1054
1055
|
_loweringMatchers = [];
|
|
1055
1056
|
moduleStringConsts = new Map;
|
|
1056
1057
|
localConstants = [];
|
|
1057
|
-
|
|
1058
|
+
scope = BindingScope.EMPTY;
|
|
1058
1059
|
nullableOptionalProps = new Set;
|
|
1059
1060
|
constructor(options = {}) {
|
|
1060
1061
|
super();
|
|
@@ -1076,7 +1077,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1076
1077
|
this._searchParamsLocals = searchParamsLocalNames(ir.metadata);
|
|
1077
1078
|
this._loweringMatchers = prepareLoweringMatchers(ir.metadata);
|
|
1078
1079
|
this.localConstants = ir.metadata.localConstants ?? [];
|
|
1079
|
-
this.
|
|
1080
|
+
this.scope = BindingScope.EMPTY;
|
|
1080
1081
|
this.errors = [];
|
|
1081
1082
|
this.childrenCaptureCounter = 0;
|
|
1082
1083
|
if (!options?.siblingTemplatesRegistered) {
|
|
@@ -1111,7 +1112,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1111
1112
|
}
|
|
1112
1113
|
if (!/^[A-Za-z_$][\w$]*$/.test(bare))
|
|
1113
1114
|
return false;
|
|
1114
|
-
if (this.
|
|
1115
|
+
if (this.scope.isBound(bare))
|
|
1115
1116
|
return false;
|
|
1116
1117
|
return this.booleanTypedProps.has(bare);
|
|
1117
1118
|
}
|
|
@@ -1129,7 +1130,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1129
1130
|
};
|
|
1130
1131
|
}
|
|
1131
1132
|
resolveLiteralConst(name) {
|
|
1132
|
-
if (this.
|
|
1133
|
+
if (this.scope.isBound(name))
|
|
1133
1134
|
return null;
|
|
1134
1135
|
const c = (this.localConstants ?? []).find((lc) => lc.name === name);
|
|
1135
1136
|
if (c?.value === undefined)
|
|
@@ -1143,15 +1144,13 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1143
1144
|
return null;
|
|
1144
1145
|
}
|
|
1145
1146
|
resolveStaticRecordLiteral(objectName, key) {
|
|
1146
|
-
|
|
1147
|
-
return null;
|
|
1148
|
-
const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants);
|
|
1147
|
+
const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants, (name) => this.scope.isBound(name));
|
|
1149
1148
|
if (!hit)
|
|
1150
1149
|
return null;
|
|
1151
1150
|
return hit.kind === "number" ? hit.text : `'${hit.text.replace(/[\\']/g, (m) => `\\${m}`)}'`;
|
|
1152
1151
|
}
|
|
1153
1152
|
resolveModuleStringConst(name) {
|
|
1154
|
-
if (this.
|
|
1153
|
+
if (this.scope.isBound(name))
|
|
1155
1154
|
return null;
|
|
1156
1155
|
const value = this.moduleStringConsts.get(name);
|
|
1157
1156
|
if (value === undefined)
|
|
@@ -1416,7 +1415,7 @@ ${whenTrue}
|
|
|
1416
1415
|
});
|
|
1417
1416
|
}
|
|
1418
1417
|
const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
|
|
1419
|
-
isNameShadowed:
|
|
1418
|
+
isNameShadowed: this.scope.asShadowPredicate()
|
|
1420
1419
|
});
|
|
1421
1420
|
const staticArray = staticItems !== null ? staticValueToPerl(staticItems) : null;
|
|
1422
1421
|
const arrayName = loop.array.trim();
|
|
@@ -1429,7 +1428,8 @@ ${whenTrue}
|
|
|
1429
1428
|
message: `Loop array \`${arrayName}\` is a local computed value (\`${arrayConst.value}\`) that the Mojo adapter cannot bind as a template variable — only numeric/string-literal locals inline at their use site.`,
|
|
1430
1429
|
loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
1431
1430
|
suggestion: {
|
|
1432
|
-
message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client."
|
|
1431
|
+
message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client.",
|
|
1432
|
+
escape: [{ kind: "prop-precompute" }, { kind: "client-directive" }]
|
|
1433
1433
|
}
|
|
1434
1434
|
});
|
|
1435
1435
|
}
|
|
@@ -1443,13 +1443,9 @@ ${whenTrue}
|
|
|
1443
1443
|
}
|
|
1444
1444
|
const param = loop.param;
|
|
1445
1445
|
const indexVar = loop.iterationShape === "keys" ? `$${param}` : loop.index ? `$${loop.index}` : "$_i";
|
|
1446
|
-
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"];
|
|
1447
1446
|
const preambleDecls = loop.preamble?.declarations ?? [];
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
for (const n of loopBound) {
|
|
1451
|
-
this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
|
|
1452
|
-
}
|
|
1447
|
+
const prevScope = this.scope;
|
|
1448
|
+
this.scope = prevScope.enterLoopRow(loop);
|
|
1453
1449
|
const prevLoopKeyDepth = this.currentLoopKeyDepth;
|
|
1454
1450
|
this.currentLoopKeyDepth = loop.depth;
|
|
1455
1451
|
const renderedChildren = this.renderChildren(loop.children);
|
|
@@ -1459,13 +1455,7 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1459
1455
|
const lines = [];
|
|
1460
1456
|
lines.push(`<%== bf->comment("loop:${loop.markerId}") %>`);
|
|
1461
1457
|
if (sortedHoist && loop.sortComparator) {
|
|
1462
|
-
|
|
1463
|
-
const c = (this.loopBoundNames.get(n) ?? 1) - 1;
|
|
1464
|
-
if (c <= 0)
|
|
1465
|
-
this.loopBoundNames.delete(n);
|
|
1466
|
-
else
|
|
1467
|
-
this.loopBoundNames.set(n, c);
|
|
1468
|
-
}
|
|
1458
|
+
this.scope = prevScope;
|
|
1469
1459
|
const sortEmit = (e) => this.convertExpressionToPerl("", e);
|
|
1470
1460
|
const sortArrow = loop.sortComparator.arrow;
|
|
1471
1461
|
let sorted = null;
|
|
@@ -1481,9 +1471,7 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1481
1471
|
this._recordExprBF101(`.sort(...) loop comparator is not lowerable to a template sort`, `Pre-sort the array in the route handler, or mark the loop @client-only.`);
|
|
1482
1472
|
sorted = rawArray;
|
|
1483
1473
|
}
|
|
1484
|
-
|
|
1485
|
-
this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
|
|
1486
|
-
}
|
|
1474
|
+
this.scope = prevScope.enterLoopRow(loop);
|
|
1487
1475
|
lines.push(`% my $${sortedHoist} = ${sorted};`);
|
|
1488
1476
|
}
|
|
1489
1477
|
if (loop.objectIteration) {
|
|
@@ -1532,13 +1520,7 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1532
1520
|
lines.push(...preambleLines);
|
|
1533
1521
|
lines.push(children);
|
|
1534
1522
|
}
|
|
1535
|
-
|
|
1536
|
-
const c = (this.loopBoundNames.get(n) ?? 1) - 1;
|
|
1537
|
-
if (c <= 0)
|
|
1538
|
-
this.loopBoundNames.delete(n);
|
|
1539
|
-
else
|
|
1540
|
-
this.loopBoundNames.set(n, c);
|
|
1541
|
-
}
|
|
1523
|
+
this.scope = prevScope;
|
|
1542
1524
|
lines.push(`% }`);
|
|
1543
1525
|
lines.push(`<%== bf->comment("/loop:${loop.markerId}") %>`);
|
|
1544
1526
|
return lines.join(`
|
|
@@ -1651,7 +1633,7 @@ ${children}`;
|
|
|
1651
1633
|
}
|
|
1652
1634
|
const bareId = value.expr.trim();
|
|
1653
1635
|
const normalizedBareId = this.propsObjectName && bareId.startsWith(`${this.propsObjectName}.`) ? bareId.slice(this.propsObjectName.length + 1) : bareId;
|
|
1654
|
-
if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.
|
|
1636
|
+
if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.scope.isBound(normalizedBareId)) {
|
|
1655
1637
|
const perl2 = this.convertExpressionToPerl(value.expr);
|
|
1656
1638
|
const body = isBooleanResultExpr(value.expr) || isAriaBooleanAttr(name) || this.isBooleanTypedPropRef(value.expr) ? `${name}="<%= bf->bool_str(${perl2}) %>"` : `${name}="<%= ${perl2} %>"`;
|
|
1657
1639
|
return `<% if (defined ${perl2}) { %>${body}<% } %>`;
|
|
@@ -1694,7 +1676,7 @@ ${children}`;
|
|
|
1694
1676
|
if (ternaryHashref !== null) {
|
|
1695
1677
|
return `<%== bf->spread_attrs(${ternaryHashref}) %>`;
|
|
1696
1678
|
}
|
|
1697
|
-
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed) && !this.
|
|
1679
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed) && !this.scope.isBound(trimmed)) {
|
|
1698
1680
|
const localConst = this.localConstants.find((c) => c.name === trimmed && !c.isModule);
|
|
1699
1681
|
if (localConst?.value !== undefined) {
|
|
1700
1682
|
const initTrimmed = localConst.value.trim();
|
|
@@ -103,14 +103,22 @@ export declare class MojoAdapter extends BaseAdapter implements IRNodeEmitter<Mo
|
|
|
103
103
|
*/
|
|
104
104
|
private localConstants;
|
|
105
105
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
106
|
+
* The one canonical, position-accurate "names bound by an enclosing loop
|
|
107
|
+
* callback" service (#2482 Stage 2) — replaces the ref-counted
|
|
108
|
+
* `Map<string, number>` this adapter used to push/pop around
|
|
109
|
+
* `renderLoop`'s body (the `my $<param>` / `my $<index>` bindings it
|
|
110
|
+
* introduces). `resolveModuleStringConst` consults this so a loop
|
|
109
111
|
* variable whose name happens to match a module string const is NOT
|
|
110
112
|
* inlined as the const literal (mirrors the Go adapter's loop-param /
|
|
111
|
-
* loop-var shadowing guards). (#1749 review)
|
|
113
|
+
* loop-var shadowing guards). (#1749 review) Threaded via
|
|
114
|
+
* save/restore-by-reference around `renderChildren(loop.children)` in
|
|
115
|
+
* `renderLoop` (immutable — no ref-count bookkeeping), mirroring the
|
|
116
|
+
* Stage 1a/1b `ctx.scope` precedent in `jsx-to-ir.ts`. `IRLoop` already
|
|
117
|
+
* structurally satisfies `LoopBindingSource`
|
|
118
|
+
* (`param`/`index`/`paramBindings`/`preamble`), so `renderLoop` passes
|
|
119
|
+
* the loop node straight to `enterLoopRow`.
|
|
112
120
|
*/
|
|
113
|
-
private
|
|
121
|
+
private scope;
|
|
114
122
|
/**
|
|
115
123
|
* Prop names whose value is `undef` in the template body when the caller
|
|
116
124
|
* omits them — so a bare-reference attribute should be dropped rather
|
|
@@ -164,13 +172,12 @@ export declare class MojoAdapter extends BaseAdapter implements IRNodeEmitter<Mo
|
|
|
164
172
|
* function-scope consts never reach the per-render stash, so a bare
|
|
165
173
|
* `$totalPages` faults under strict mode.
|
|
166
174
|
*
|
|
167
|
-
* The
|
|
168
|
-
* callback's own param shadowing this outer const's name):
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
* no separate `staticLoopSourceBoundNames`-style field is needed here.
|
|
175
|
+
* The threaded scope's shadow guard also covers the #2221 hazard (a loop
|
|
176
|
+
* callback's own param shadowing this outer const's name): `this.scope`
|
|
177
|
+
* is position-accurate (#2482 Stage 2) — pushed/popped by reference as
|
|
178
|
+
* `renderLoop` descends/ascends into each loop body — so it's already
|
|
179
|
+
* scope-precise for this call site; no separate coarse whole-component
|
|
180
|
+
* field is needed here.
|
|
174
181
|
*/
|
|
175
182
|
private resolveLiteralConst;
|
|
176
183
|
private resolveStaticRecordLiteral;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mojo-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/mojo-adapter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,WAAW,EAEX,MAAM,EACN,SAAS,EACT,MAAM,EACN,YAAY,EACZ,aAAa,EACb,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,OAAO,EAMP,yBAAyB,EAE1B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAE3B,KAAK,aAAa,EAClB,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"mojo-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/mojo-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -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,
|
|
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,eA4L7B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,8 @@ import {
|
|
|
25
25
|
dangerousInnerHtmlMetacharViolation,
|
|
26
26
|
dangerousInnerHtmlDiagnostic,
|
|
27
27
|
resolveStaticLoopSource,
|
|
28
|
-
derivesScopeFromSlot
|
|
28
|
+
derivesScopeFromSlot,
|
|
29
|
+
BindingScope
|
|
29
30
|
} from "@barefootjs/jsx";
|
|
30
31
|
|
|
31
32
|
// src/adapter/boolean-result.ts
|
|
@@ -1054,7 +1055,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1054
1055
|
_loweringMatchers = [];
|
|
1055
1056
|
moduleStringConsts = new Map;
|
|
1056
1057
|
localConstants = [];
|
|
1057
|
-
|
|
1058
|
+
scope = BindingScope.EMPTY;
|
|
1058
1059
|
nullableOptionalProps = new Set;
|
|
1059
1060
|
constructor(options = {}) {
|
|
1060
1061
|
super();
|
|
@@ -1076,7 +1077,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1076
1077
|
this._searchParamsLocals = searchParamsLocalNames(ir.metadata);
|
|
1077
1078
|
this._loweringMatchers = prepareLoweringMatchers(ir.metadata);
|
|
1078
1079
|
this.localConstants = ir.metadata.localConstants ?? [];
|
|
1079
|
-
this.
|
|
1080
|
+
this.scope = BindingScope.EMPTY;
|
|
1080
1081
|
this.errors = [];
|
|
1081
1082
|
this.childrenCaptureCounter = 0;
|
|
1082
1083
|
if (!options?.siblingTemplatesRegistered) {
|
|
@@ -1111,7 +1112,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1111
1112
|
}
|
|
1112
1113
|
if (!/^[A-Za-z_$][\w$]*$/.test(bare))
|
|
1113
1114
|
return false;
|
|
1114
|
-
if (this.
|
|
1115
|
+
if (this.scope.isBound(bare))
|
|
1115
1116
|
return false;
|
|
1116
1117
|
return this.booleanTypedProps.has(bare);
|
|
1117
1118
|
}
|
|
@@ -1129,7 +1130,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1129
1130
|
};
|
|
1130
1131
|
}
|
|
1131
1132
|
resolveLiteralConst(name) {
|
|
1132
|
-
if (this.
|
|
1133
|
+
if (this.scope.isBound(name))
|
|
1133
1134
|
return null;
|
|
1134
1135
|
const c = (this.localConstants ?? []).find((lc) => lc.name === name);
|
|
1135
1136
|
if (c?.value === undefined)
|
|
@@ -1143,15 +1144,13 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1143
1144
|
return null;
|
|
1144
1145
|
}
|
|
1145
1146
|
resolveStaticRecordLiteral(objectName, key) {
|
|
1146
|
-
|
|
1147
|
-
return null;
|
|
1148
|
-
const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants);
|
|
1147
|
+
const hit = lookupStaticRecordLiteral(objectName, key, this.localConstants, (name) => this.scope.isBound(name));
|
|
1149
1148
|
if (!hit)
|
|
1150
1149
|
return null;
|
|
1151
1150
|
return hit.kind === "number" ? hit.text : `'${hit.text.replace(/[\\']/g, (m) => `\\${m}`)}'`;
|
|
1152
1151
|
}
|
|
1153
1152
|
resolveModuleStringConst(name) {
|
|
1154
|
-
if (this.
|
|
1153
|
+
if (this.scope.isBound(name))
|
|
1155
1154
|
return null;
|
|
1156
1155
|
const value = this.moduleStringConsts.get(name);
|
|
1157
1156
|
if (value === undefined)
|
|
@@ -1416,7 +1415,7 @@ ${whenTrue}
|
|
|
1416
1415
|
});
|
|
1417
1416
|
}
|
|
1418
1417
|
const staticItems = resolveStaticLoopSource(loop.arrayParsed, this.localConstants, {
|
|
1419
|
-
isNameShadowed:
|
|
1418
|
+
isNameShadowed: this.scope.asShadowPredicate()
|
|
1420
1419
|
});
|
|
1421
1420
|
const staticArray = staticItems !== null ? staticValueToPerl(staticItems) : null;
|
|
1422
1421
|
const arrayName = loop.array.trim();
|
|
@@ -1429,7 +1428,8 @@ ${whenTrue}
|
|
|
1429
1428
|
message: `Loop array \`${arrayName}\` is a local computed value (\`${arrayConst.value}\`) that the Mojo adapter cannot bind as a template variable — only numeric/string-literal locals inline at their use site.`,
|
|
1430
1429
|
loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
1431
1430
|
suggestion: {
|
|
1432
|
-
message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client."
|
|
1431
|
+
message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client.",
|
|
1432
|
+
escape: [{ kind: "prop-precompute" }, { kind: "client-directive" }]
|
|
1433
1433
|
}
|
|
1434
1434
|
});
|
|
1435
1435
|
}
|
|
@@ -1443,13 +1443,9 @@ ${whenTrue}
|
|
|
1443
1443
|
}
|
|
1444
1444
|
const param = loop.param;
|
|
1445
1445
|
const indexVar = loop.iterationShape === "keys" ? `$${param}` : loop.index ? `$${loop.index}` : "$_i";
|
|
1446
|
-
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"];
|
|
1447
1446
|
const preambleDecls = loop.preamble?.declarations ?? [];
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
for (const n of loopBound) {
|
|
1451
|
-
this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
|
|
1452
|
-
}
|
|
1447
|
+
const prevScope = this.scope;
|
|
1448
|
+
this.scope = prevScope.enterLoopRow(loop);
|
|
1453
1449
|
const prevLoopKeyDepth = this.currentLoopKeyDepth;
|
|
1454
1450
|
this.currentLoopKeyDepth = loop.depth;
|
|
1455
1451
|
const renderedChildren = this.renderChildren(loop.children);
|
|
@@ -1459,13 +1455,7 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1459
1455
|
const lines = [];
|
|
1460
1456
|
lines.push(`<%== bf->comment("loop:${loop.markerId}") %>`);
|
|
1461
1457
|
if (sortedHoist && loop.sortComparator) {
|
|
1462
|
-
|
|
1463
|
-
const c = (this.loopBoundNames.get(n) ?? 1) - 1;
|
|
1464
|
-
if (c <= 0)
|
|
1465
|
-
this.loopBoundNames.delete(n);
|
|
1466
|
-
else
|
|
1467
|
-
this.loopBoundNames.set(n, c);
|
|
1468
|
-
}
|
|
1458
|
+
this.scope = prevScope;
|
|
1469
1459
|
const sortEmit = (e) => this.convertExpressionToPerl("", e);
|
|
1470
1460
|
const sortArrow = loop.sortComparator.arrow;
|
|
1471
1461
|
let sorted = null;
|
|
@@ -1481,9 +1471,7 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1481
1471
|
this._recordExprBF101(`.sort(...) loop comparator is not lowerable to a template sort`, `Pre-sort the array in the route handler, or mark the loop @client-only.`);
|
|
1482
1472
|
sorted = rawArray;
|
|
1483
1473
|
}
|
|
1484
|
-
|
|
1485
|
-
this.loopBoundNames.set(n, (this.loopBoundNames.get(n) ?? 0) + 1);
|
|
1486
|
-
}
|
|
1474
|
+
this.scope = prevScope.enterLoopRow(loop);
|
|
1487
1475
|
lines.push(`% my $${sortedHoist} = ${sorted};`);
|
|
1488
1476
|
}
|
|
1489
1477
|
if (loop.objectIteration) {
|
|
@@ -1532,13 +1520,7 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1532
1520
|
lines.push(...preambleLines);
|
|
1533
1521
|
lines.push(children);
|
|
1534
1522
|
}
|
|
1535
|
-
|
|
1536
|
-
const c = (this.loopBoundNames.get(n) ?? 1) - 1;
|
|
1537
|
-
if (c <= 0)
|
|
1538
|
-
this.loopBoundNames.delete(n);
|
|
1539
|
-
else
|
|
1540
|
-
this.loopBoundNames.set(n, c);
|
|
1541
|
-
}
|
|
1523
|
+
this.scope = prevScope;
|
|
1542
1524
|
lines.push(`% }`);
|
|
1543
1525
|
lines.push(`<%== bf->comment("/loop:${loop.markerId}") %>`);
|
|
1544
1526
|
return lines.join(`
|
|
@@ -1651,7 +1633,7 @@ ${children}`;
|
|
|
1651
1633
|
}
|
|
1652
1634
|
const bareId = value.expr.trim();
|
|
1653
1635
|
const normalizedBareId = this.propsObjectName && bareId.startsWith(`${this.propsObjectName}.`) ? bareId.slice(this.propsObjectName.length + 1) : bareId;
|
|
1654
|
-
if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.
|
|
1636
|
+
if (!isBooleanAttr(name) && !value.presenceOrUndefined && /^[A-Za-z_$][\w$]*$/.test(normalizedBareId) && this.nullableOptionalProps.has(normalizedBareId) && !this.scope.isBound(normalizedBareId)) {
|
|
1655
1637
|
const perl2 = this.convertExpressionToPerl(value.expr);
|
|
1656
1638
|
const body = isBooleanResultExpr(value.expr) || isAriaBooleanAttr(name) || this.isBooleanTypedPropRef(value.expr) ? `${name}="<%= bf->bool_str(${perl2}) %>"` : `${name}="<%= ${perl2} %>"`;
|
|
1657
1639
|
return `<% if (defined ${perl2}) { %>${body}<% } %>`;
|
|
@@ -1694,7 +1676,7 @@ ${children}`;
|
|
|
1694
1676
|
if (ternaryHashref !== null) {
|
|
1695
1677
|
return `<%== bf->spread_attrs(${ternaryHashref}) %>`;
|
|
1696
1678
|
}
|
|
1697
|
-
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed) && !this.
|
|
1679
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed) && !this.scope.isBound(trimmed)) {
|
|
1698
1680
|
const localConst = this.localConstants.find((c) => c.name === trimmed && !c.isModule);
|
|
1699
1681
|
if (localConst?.value !== undefined) {
|
|
1700
1682
|
const initTrimmed = localConst.value.trim();
|
|
@@ -1930,14 +1912,20 @@ var conformancePins = {
|
|
|
1930
1912
|
"tag-cloud": [{ code: "BF021", severity: "error" }],
|
|
1931
1913
|
"preamble-cells": [{ code: "BF021", severity: "error" }],
|
|
1932
1914
|
"static-array-from-props": [
|
|
1933
|
-
{
|
|
1915
|
+
{
|
|
1916
|
+
code: "BF101",
|
|
1917
|
+
severity: "error",
|
|
1918
|
+
issue: "https://github.com/piconic-ai/barefootjs/issues/2321"
|
|
1919
|
+
}
|
|
1934
1920
|
],
|
|
1935
1921
|
"static-array-from-props-with-component": [
|
|
1936
|
-
{
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1922
|
+
{
|
|
1923
|
+
code: "BF101",
|
|
1924
|
+
severity: "error",
|
|
1925
|
+
issue: "https://github.com/piconic-ai/barefootjs/issues/2321"
|
|
1926
|
+
}
|
|
1940
1927
|
],
|
|
1928
|
+
"filter-nested-find-predicate": [{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2320" }],
|
|
1941
1929
|
"date-method-uncatalogued": [{ code: "BF021", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2356" }]
|
|
1942
1930
|
};
|
|
1943
1931
|
// src/render-divergences.ts
|