@barefootjs/mojolicious 0.35.2 → 0.35.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.
- package/dist/adapter/index.js +5 -1
- package/dist/adapter/props/prop-classes.d.ts +16 -0
- package/dist/adapter/props/prop-classes.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/render-divergences.d.ts.map +1 -1
- package/dist/vite.js +22 -4
- 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/__tests__/mojo-adapter.test.ts +34 -0
- package/src/adapter/props/prop-classes.ts +23 -1
- package/src/render-divergences.ts +1 -12
package/dist/adapter/index.js
CHANGED
|
@@ -977,7 +977,7 @@ function generateDerivedMemoSeed(ctx, ir) {
|
|
|
977
977
|
}
|
|
978
978
|
|
|
979
979
|
// src/adapter/props/prop-classes.ts
|
|
980
|
-
import { collectLoopBoundNames } from "@barefootjs/jsx";
|
|
980
|
+
import { collectLoopBoundNames, resolveBodyDestructuredPropAliases } from "@barefootjs/jsx";
|
|
981
981
|
|
|
982
982
|
// src/adapter/value/parsed-literal.ts
|
|
983
983
|
function isStringTypeInfo(type) {
|
|
@@ -1015,6 +1015,10 @@ function collectStringValueNames(ir) {
|
|
|
1015
1015
|
if (isStringTypeInfo(p.type))
|
|
1016
1016
|
names.add(p.name);
|
|
1017
1017
|
}
|
|
1018
|
+
for (const [local, callerKey] of resolveBodyDestructuredPropAliases(ir.metadata.localConstants ?? [], ir.metadata.propsObjectName)) {
|
|
1019
|
+
if (names.has(callerKey))
|
|
1020
|
+
names.add(local);
|
|
1021
|
+
}
|
|
1018
1022
|
for (const c of ir.metadata.localConstants) {
|
|
1019
1023
|
if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value))
|
|
1020
1024
|
names.add(c.name);
|
|
@@ -59,6 +59,22 @@ export declare function collectNullableOptionalProps(ir: ComponentIR): Set<strin
|
|
|
59
59
|
* elsewhere in the component) but safe: the suppressed case just falls
|
|
60
60
|
* back to today's numeric `+` — the same, already-accepted residual as an
|
|
61
61
|
* unresolvable operand — never silently-wrong output.
|
|
62
|
+
*
|
|
63
|
+
* A bare-props-form component's BODY-destructured, RENAMED prop
|
|
64
|
+
* (`const { fallbackLabel: skipLabel } = props`, the #2788 alias family)
|
|
65
|
+
* has no `propsParams` entry of its own — `propsParams` only carries the
|
|
66
|
+
* TYPE-level, caller-facing names, and the local alias never appears
|
|
67
|
+
* there. Without the alias resolved here too, a string-typed prop
|
|
68
|
+
* referenced only under its local rename inside a filter predicate
|
|
69
|
+
* (`t => t.label !== skipLabel`) is invisible to this witness, so its
|
|
70
|
+
* equality lowers to numeric `!=` instead of `ne` — every row is
|
|
71
|
+
* dropped, since `'Alpha' != 'Alpha'` and `'Beta' != 'Alpha'` both
|
|
72
|
+
* numify to `0 != 0` (#2883). `resolveBodyDestructuredPropAliases`
|
|
73
|
+
* already recognizes this exact destructuring shape (built for #2788's
|
|
74
|
+
* top-level splice path); reusing it here keeps this one witness the
|
|
75
|
+
* single source of truth `MojoFilterEmitter`/`MojoTopLevelEmitter` both
|
|
76
|
+
* read via `_isStringValueName`, rather than growing a second, adapter-
|
|
77
|
+
* emitter-local alias lookup.
|
|
62
78
|
*/
|
|
63
79
|
export declare function collectStringValueNames(ir: ComponentIR): Set<string>;
|
|
64
80
|
//# sourceMappingURL=prop-classes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"prop-classes.d.ts","sourceRoot":"","sources":["../../../src/adapter/props/prop-classes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAA6D,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG7G;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAMrE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAWzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,WAAW,GAAG,GAAG,CAAC,MAAM,CAAC,CAqBpE"}
|
package/dist/index.js
CHANGED
|
@@ -977,7 +977,7 @@ function generateDerivedMemoSeed(ctx, ir) {
|
|
|
977
977
|
}
|
|
978
978
|
|
|
979
979
|
// src/adapter/props/prop-classes.ts
|
|
980
|
-
import { collectLoopBoundNames } from "@barefootjs/jsx";
|
|
980
|
+
import { collectLoopBoundNames, resolveBodyDestructuredPropAliases } from "@barefootjs/jsx";
|
|
981
981
|
|
|
982
982
|
// src/adapter/value/parsed-literal.ts
|
|
983
983
|
function isStringTypeInfo(type) {
|
|
@@ -1015,6 +1015,10 @@ function collectStringValueNames(ir) {
|
|
|
1015
1015
|
if (isStringTypeInfo(p.type))
|
|
1016
1016
|
names.add(p.name);
|
|
1017
1017
|
}
|
|
1018
|
+
for (const [local, callerKey] of resolveBodyDestructuredPropAliases(ir.metadata.localConstants ?? [], ir.metadata.propsObjectName)) {
|
|
1019
|
+
if (names.has(callerKey))
|
|
1020
|
+
names.add(local);
|
|
1021
|
+
}
|
|
1018
1022
|
for (const c of ir.metadata.localConstants) {
|
|
1019
1023
|
if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value))
|
|
1020
1024
|
names.add(c.name);
|
|
@@ -1922,9 +1926,7 @@ var conformancePins = {
|
|
|
1922
1926
|
"namespace-import-primitive": [{ code: "BF013", severity: "error" }]
|
|
1923
1927
|
};
|
|
1924
1928
|
// src/render-divergences.ts
|
|
1925
|
-
var renderDivergences = {
|
|
1926
|
-
"filter-predicate-renamed-prop": "https://github.com/piconic-ai/barefootjs/issues/2883"
|
|
1927
|
-
};
|
|
1929
|
+
var renderDivergences = {};
|
|
1928
1930
|
export {
|
|
1929
1931
|
renderDivergences,
|
|
1930
1932
|
mojoAdapter,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAQxD,eAAO,MAAM,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAQxD,eAAO,MAAM,iBAAiB,EAAE,iBAAsB,CAAA"}
|
package/dist/vite.js
CHANGED
|
@@ -2175,6 +2175,20 @@ function propsDestructureBinding(p) {
|
|
|
2175
2175
|
const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
|
|
2176
2176
|
return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
|
|
2177
2177
|
}
|
|
2178
|
+
function resolveBodyDestructuredPropAliases(localConstants, propsObjectName) {
|
|
2179
|
+
const aliases = new Map;
|
|
2180
|
+
if (propsObjectName === null)
|
|
2181
|
+
return aliases;
|
|
2182
|
+
for (const c of localConstants) {
|
|
2183
|
+
if (c.isModule)
|
|
2184
|
+
continue;
|
|
2185
|
+
const m = c.parsed;
|
|
2186
|
+
if (m?.kind === "member" && !m.computed && m.object.kind === "identifier" && m.object.name === propsObjectName) {
|
|
2187
|
+
aliases.set(c.name, m.property);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
return aliases;
|
|
2191
|
+
}
|
|
2178
2192
|
var EMPTY_SET = new Set;
|
|
2179
2193
|
|
|
2180
2194
|
// ../jsx/src/ir-to-client-js/csr-substitute.ts
|
|
@@ -3421,8 +3435,11 @@ function matchSearchParamsMethodCall(callee, args, localNames) {
|
|
|
3421
3435
|
// ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
|
|
3422
3436
|
import ts19 from "typescript";
|
|
3423
3437
|
|
|
3424
|
-
// ../jsx/src/ir-to-client-js/
|
|
3438
|
+
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
3425
3439
|
import ts20 from "typescript";
|
|
3440
|
+
|
|
3441
|
+
// ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
|
|
3442
|
+
import ts21 from "typescript";
|
|
3426
3443
|
var NO_PREAMBLE = {
|
|
3427
3444
|
lazySafe: true,
|
|
3428
3445
|
facts: { declaredNames: new Set, freeNames: new Set }
|
|
@@ -3471,9 +3488,6 @@ var INERT_BINDING_GLOBALS = new Set([
|
|
|
3471
3488
|
"decodeURI"
|
|
3472
3489
|
]);
|
|
3473
3490
|
|
|
3474
|
-
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
3475
|
-
import ts21 from "typescript";
|
|
3476
|
-
|
|
3477
3491
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
|
|
3478
3492
|
var NON_BUBBLING_EVENTS = new Set([
|
|
3479
3493
|
"blur",
|
|
@@ -6250,6 +6264,10 @@ function collectStringValueNames(ir) {
|
|
|
6250
6264
|
if (isStringTypeInfo(p.type))
|
|
6251
6265
|
names.add(p.name);
|
|
6252
6266
|
}
|
|
6267
|
+
for (const [local, callerKey] of resolveBodyDestructuredPropAliases(ir.metadata.localConstants ?? [], ir.metadata.propsObjectName)) {
|
|
6268
|
+
if (names.has(callerKey))
|
|
6269
|
+
names.add(local);
|
|
6270
|
+
}
|
|
6253
6271
|
for (const c of ir.metadata.localConstants) {
|
|
6254
6272
|
if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value))
|
|
6255
6273
|
names.add(c.name);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/mojolicious",
|
|
3
|
-
"version": "0.35.
|
|
3
|
+
"version": "0.35.3",
|
|
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.35.
|
|
55
|
+
"@barefootjs/shared": "0.35.3"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
58
|
"@barefootjs/jsx": ">=0.2.0",
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
73
|
-
"@barefootjs/jsx": "0.35.
|
|
74
|
-
"@barefootjs/vite": "0.35.
|
|
75
|
-
"@barefootjs/client": "0.35.
|
|
73
|
+
"@barefootjs/jsx": "0.35.3",
|
|
74
|
+
"@barefootjs/vite": "0.35.3",
|
|
75
|
+
"@barefootjs/client": "0.35.3",
|
|
76
76
|
"vite": "^6.0.0"
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -733,6 +733,40 @@ export function L() {
|
|
|
733
733
|
expect(result.template).not.toContain('$sel eq $t->{n}')
|
|
734
734
|
})
|
|
735
735
|
|
|
736
|
+
test('compares a filter predicate against a renamed body-destructured prop with Perl `ne`, not numeric `!=` (#2883)', () => {
|
|
737
|
+
// `MojoFilterEmitter.identifier()` correctly resolves `skipLabel` to
|
|
738
|
+
// `$skipLabel` (Mojo seeds/derives that stash key for the #2788 alias
|
|
739
|
+
// family, same as the top-level splice path) — the actual bug was
|
|
740
|
+
// `collectStringValueNames`'s witness for `eq`/`ne` vs `==`/`!=` not
|
|
741
|
+
// knowing about body-destructured RENAMED props, so this comparison
|
|
742
|
+
// fell through to numeric `!=`. `'Alpha' != 'Alpha'` and
|
|
743
|
+
// `'Beta' != 'Alpha'` both numify to `0 != 0` — every row was
|
|
744
|
+
// filtered out regardless of the real string value.
|
|
745
|
+
const result = compileAndGenerate(`
|
|
746
|
+
"use client"
|
|
747
|
+
import { createSignal } from "@barefootjs/client"
|
|
748
|
+
|
|
749
|
+
type Todo = { id: number; label: string }
|
|
750
|
+
|
|
751
|
+
export function FilterPredicateRenamedProp(props: { fallbackLabel: string }) {
|
|
752
|
+
const { fallbackLabel: skipLabel } = props
|
|
753
|
+
const [todos] = createSignal<Todo[]>([
|
|
754
|
+
{ id: 1, label: 'Alpha' },
|
|
755
|
+
{ id: 2, label: 'Beta' },
|
|
756
|
+
])
|
|
757
|
+
return (
|
|
758
|
+
<ul>
|
|
759
|
+
{todos().filter(t => t.label !== skipLabel).map(t => (
|
|
760
|
+
<li key={t.id}>{t.label}</li>
|
|
761
|
+
))}
|
|
762
|
+
</ul>
|
|
763
|
+
)
|
|
764
|
+
}
|
|
765
|
+
`)
|
|
766
|
+
expect(result.template).toContain('$t->{label} ne $skipLabel')
|
|
767
|
+
expect(result.template).not.toContain('$t->{label} != $skipLabel')
|
|
768
|
+
})
|
|
769
|
+
|
|
736
770
|
test('generates script registration for client components', () => {
|
|
737
771
|
const result = compileAndGenerate(`
|
|
738
772
|
"use client"
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* adapter's `props/prop-types.ts`. No adapter instance state.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { collectLoopBoundNames, type ComponentIR } from '@barefootjs/jsx'
|
|
10
|
+
import { collectLoopBoundNames, resolveBodyDestructuredPropAliases, type ComponentIR } from '@barefootjs/jsx'
|
|
11
11
|
import { isStringTypeInfo, isBareStringLiteral } from '../value/parsed-literal.ts'
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -88,6 +88,22 @@ export function collectNullableOptionalProps(ir: ComponentIR): Set<string> {
|
|
|
88
88
|
* elsewhere in the component) but safe: the suppressed case just falls
|
|
89
89
|
* back to today's numeric `+` — the same, already-accepted residual as an
|
|
90
90
|
* unresolvable operand — never silently-wrong output.
|
|
91
|
+
*
|
|
92
|
+
* A bare-props-form component's BODY-destructured, RENAMED prop
|
|
93
|
+
* (`const { fallbackLabel: skipLabel } = props`, the #2788 alias family)
|
|
94
|
+
* has no `propsParams` entry of its own — `propsParams` only carries the
|
|
95
|
+
* TYPE-level, caller-facing names, and the local alias never appears
|
|
96
|
+
* there. Without the alias resolved here too, a string-typed prop
|
|
97
|
+
* referenced only under its local rename inside a filter predicate
|
|
98
|
+
* (`t => t.label !== skipLabel`) is invisible to this witness, so its
|
|
99
|
+
* equality lowers to numeric `!=` instead of `ne` — every row is
|
|
100
|
+
* dropped, since `'Alpha' != 'Alpha'` and `'Beta' != 'Alpha'` both
|
|
101
|
+
* numify to `0 != 0` (#2883). `resolveBodyDestructuredPropAliases`
|
|
102
|
+
* already recognizes this exact destructuring shape (built for #2788's
|
|
103
|
+
* top-level splice path); reusing it here keeps this one witness the
|
|
104
|
+
* single source of truth `MojoFilterEmitter`/`MojoTopLevelEmitter` both
|
|
105
|
+
* read via `_isStringValueName`, rather than growing a second, adapter-
|
|
106
|
+
* emitter-local alias lookup.
|
|
91
107
|
*/
|
|
92
108
|
export function collectStringValueNames(ir: ComponentIR): Set<string> {
|
|
93
109
|
const names = new Set<string>()
|
|
@@ -99,6 +115,12 @@ export function collectStringValueNames(ir: ComponentIR): Set<string> {
|
|
|
99
115
|
for (const p of ir.metadata.propsParams) {
|
|
100
116
|
if (isStringTypeInfo(p.type)) names.add(p.name)
|
|
101
117
|
}
|
|
118
|
+
for (const [local, callerKey] of resolveBodyDestructuredPropAliases(
|
|
119
|
+
ir.metadata.localConstants ?? [],
|
|
120
|
+
ir.metadata.propsObjectName,
|
|
121
|
+
)) {
|
|
122
|
+
if (names.has(callerKey)) names.add(local)
|
|
123
|
+
}
|
|
102
124
|
for (const c of ir.metadata.localConstants) {
|
|
103
125
|
if (isStringTypeInfo(c.type ?? undefined) || isBareStringLiteral(c.value)) names.add(c.name)
|
|
104
126
|
}
|
|
@@ -15,15 +15,4 @@ import type { RenderDivergences } from '@barefootjs/jsx'
|
|
|
15
15
|
// at value position and the runtime evaluator's `object-literal` case
|
|
16
16
|
// now merges it, so the seed classifies `derived` and SSRs identically
|
|
17
17
|
// to Hono.
|
|
18
|
-
export const renderDivergences: RenderDivergences = {
|
|
19
|
-
// #2883: `MojoFilterEmitter.identifier()` (expr/emitters.ts) resolves a
|
|
20
|
-
// `.filter()` predicate identifier against only the loop param and
|
|
21
|
-
// `localVarMap` — a bare-props-form renamed prop destructure (`const {
|
|
22
|
-
// fallbackLabel: skipLabel } = props`, the #2788 alias family) falls
|
|
23
|
-
// through to a bare `$skipLabel`, a Perl variable never declared in the
|
|
24
|
-
// generated `.html.ep`. Every row is filtered out (the fixture's
|
|
25
|
-
// reference expects only the non-matching row to survive). Unrelated to
|
|
26
|
-
// #2857's Go Template adapter fix that this fixture was added for — this
|
|
27
|
-
// fixture is a shared cross-adapter conformance fixture, not Go-specific.
|
|
28
|
-
'filter-predicate-renamed-prop': 'https://github.com/piconic-ai/barefootjs/issues/2883',
|
|
29
|
-
}
|
|
18
|
+
export const renderDivergences: RenderDivergences = {}
|