@barefootjs/mojolicious 0.19.1 → 0.20.0
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/expr/array-method.d.ts.map +1 -1
- package/dist/adapter/index.js +1 -1
- package/dist/build.js +1 -1
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +3 -2
- 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 +3 -3
- package/src/__tests__/mojo-adapter.test.ts +12 -22
- package/src/adapter/expr/array-method.ts +12 -6
- package/src/conformance-pins.ts +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAExB;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,
|
|
1
|
+
{"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAExB;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAsOR;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAOf;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAmBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,EAC/B,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CAaxE;AAKD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,EACvC,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAoBR"}
|
package/dist/adapter/index.js
CHANGED
|
@@ -149,7 +149,7 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
149
149
|
case "join": {
|
|
150
150
|
const obj = emit(object);
|
|
151
151
|
const sep = args.length >= 1 ? emit(args[0]) : `','`;
|
|
152
|
-
return `join(${
|
|
152
|
+
return `bf->join(${obj}, ${sep})`;
|
|
153
153
|
}
|
|
154
154
|
case "includes": {
|
|
155
155
|
const obj = emit(object);
|
package/dist/build.js
CHANGED
|
@@ -149,7 +149,7 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
149
149
|
case "join": {
|
|
150
150
|
const obj = emit(object);
|
|
151
151
|
const sep = args.length >= 1 ? emit(args[0]) : `','`;
|
|
152
|
-
return `join(${
|
|
152
|
+
return `bf->join(${obj}, ${sep})`;
|
|
153
153
|
}
|
|
154
154
|
case "includes": {
|
|
155
155
|
const obj = emit(object);
|
|
@@ -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,eAyI7B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -149,7 +149,7 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
149
149
|
case "join": {
|
|
150
150
|
const obj = emit(object);
|
|
151
151
|
const sep = args.length >= 1 ? emit(args[0]) : `','`;
|
|
152
|
-
return `join(${
|
|
152
|
+
return `bf->join(${obj}, ${sep})`;
|
|
153
153
|
}
|
|
154
154
|
case "includes": {
|
|
155
155
|
const obj = emit(object);
|
|
@@ -1912,7 +1912,8 @@ var conformancePins = {
|
|
|
1912
1912
|
"filter-nested-find-predicate": [
|
|
1913
1913
|
{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2038" }
|
|
1914
1914
|
],
|
|
1915
|
-
"dangerous-inner-html-dynamic": [{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2215" }]
|
|
1915
|
+
"dangerous-inner-html-dynamic": [{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2215" }],
|
|
1916
|
+
"date-method-uncatalogued": [{ code: "BF021", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2274" }]
|
|
1916
1917
|
};
|
|
1917
1918
|
// src/render-divergences.ts
|
|
1918
1919
|
var renderDivergences = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/mojolicious",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
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.
|
|
55
|
+
"@barefootjs/shared": "0.20.0"
|
|
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.
|
|
63
|
+
"@barefootjs/jsx": "0.20.0"
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -59,17 +59,7 @@ runAdapterConformanceTests({
|
|
|
59
59
|
// #1467 Phase 2e: same `/* @client */` keyed-map elision (data-table).
|
|
60
60
|
'data-table',
|
|
61
61
|
]),
|
|
62
|
-
skipDataPoints: new Set<string>(
|
|
63
|
-
// #2260 — controlled boolean props: the SSR seed evaluates only the
|
|
64
|
-
// static fallback of `props.X ?? internal()` chains.
|
|
65
|
-
'toggle:gen:pressed:true',
|
|
66
|
-
'switch:gen:checked:true',
|
|
67
|
-
'checkbox:gen:checked:true',
|
|
68
|
-
// #2262 — dynamic `.flat` depth 0/negative violates the documented
|
|
69
|
-
// shallow-copy contract.
|
|
70
|
-
'array-flat-dynamic-depth:gen:depth:zero',
|
|
71
|
-
'array-flat-dynamic-depth:gen:depth:negative',
|
|
72
|
-
]),
|
|
62
|
+
skipDataPoints: new Set<string>(),
|
|
73
63
|
onRenderError: (err, id) => {
|
|
74
64
|
if (err instanceof PerlNotAvailableError) {
|
|
75
65
|
console.log(`Skipping [${id}]: ${err.message}`)
|
|
@@ -915,7 +905,7 @@ export function C() {
|
|
|
915
905
|
// filter, `.join`) hit a separate refusal gate and the chain
|
|
916
906
|
// emitted BF101 — making the scaffold `<Button>` / `<Card>`
|
|
917
907
|
// unusable on Mojo. The fix lowers all three to Embedded Perl
|
|
918
|
-
// (`join(
|
|
908
|
+
// (`bf->join([grep { $_ } @{[...]}], ' ')`), unblocking the
|
|
919
909
|
// registry surface. The #1421 recursion guard stays in place
|
|
920
910
|
// as defence in depth for other unsupported shapes, but this
|
|
921
911
|
// specific chain no longer reaches the loop because the parser
|
|
@@ -938,7 +928,7 @@ export { Slot }
|
|
|
938
928
|
)
|
|
939
929
|
expect(result.errors?.filter(e => e.code === 'BF101') ?? []).toEqual([])
|
|
940
930
|
const template = result.files.find(f => f.path.endsWith('.html.ep'))?.content ?? ''
|
|
941
|
-
expect(template).toContain(`join(
|
|
931
|
+
expect(template).toContain(`bf->join([grep { $_ } @{[$className]}], ' ')`)
|
|
942
932
|
})
|
|
943
933
|
|
|
944
934
|
test('lowers .includes(x) on an array prop via bf->includes(...) (#1448 Tier A)', () => {
|
|
@@ -1168,7 +1158,7 @@ export { A }`, 'A.tsx', { adapter })
|
|
|
1168
1158
|
export { A }`, 'A.tsx', { adapter })
|
|
1169
1159
|
expect(result.errors?.filter(e => e.code === 'BF101') ?? []).toEqual([])
|
|
1170
1160
|
const template = result.files.find(f => f.path.endsWith('.html.ep'))?.content ?? ''
|
|
1171
|
-
expect(template).toContain("join(
|
|
1161
|
+
expect(template).toContain("bf->join(bf->reverse($items), ' ')")
|
|
1172
1162
|
expect(template).not.toContain('$bf->reverse')
|
|
1173
1163
|
})
|
|
1174
1164
|
|
|
@@ -1180,7 +1170,7 @@ export { A }`, 'A.tsx', { adapter })
|
|
|
1180
1170
|
export { A }`, 'A.tsx', { adapter })
|
|
1181
1171
|
expect(result.errors?.filter(e => e.code === 'BF101') ?? []).toEqual([])
|
|
1182
1172
|
const template = result.files.find(f => f.path.endsWith('.html.ep'))?.content ?? ''
|
|
1183
|
-
expect(template).toContain("join(
|
|
1173
|
+
expect(template).toContain("bf->join(bf->reverse($items), ' ')")
|
|
1184
1174
|
})
|
|
1185
1175
|
|
|
1186
1176
|
test('lowers .slice(start, end).join(\' \') via bf->slice + join (#1448 Tier A)', () => {
|
|
@@ -1192,7 +1182,7 @@ export { A }`, 'A.tsx', { adapter })
|
|
|
1192
1182
|
export { A }`, 'A.tsx', { adapter })
|
|
1193
1183
|
expect(result.errors?.filter(e => e.code === 'BF101') ?? []).toEqual([])
|
|
1194
1184
|
const template = result.files.find(f => f.path.endsWith('.html.ep'))?.content ?? ''
|
|
1195
|
-
expect(template).toContain("join(
|
|
1185
|
+
expect(template).toContain("bf->join(bf->slice($items, 1, 3), ' ')")
|
|
1196
1186
|
expect(template).not.toContain('$bf->slice')
|
|
1197
1187
|
})
|
|
1198
1188
|
|
|
@@ -1206,7 +1196,7 @@ export { A }`, 'A.tsx', { adapter })
|
|
|
1206
1196
|
export { A }`, 'A.tsx', { adapter })
|
|
1207
1197
|
expect(result.errors?.filter(e => e.code === 'BF101') ?? []).toEqual([])
|
|
1208
1198
|
const template = result.files.find(f => f.path.endsWith('.html.ep'))?.content ?? ''
|
|
1209
|
-
expect(template).toContain("join(
|
|
1199
|
+
expect(template).toContain("bf->join(bf->slice($items, 2, undef), ' ')")
|
|
1210
1200
|
})
|
|
1211
1201
|
|
|
1212
1202
|
test('lowers .concat(other).join(\' \') via bf->concat + join (#1448 Tier A)', () => {
|
|
@@ -1222,7 +1212,7 @@ export { A }`, 'A.tsx', { adapter })
|
|
|
1222
1212
|
export { A }`, 'A.tsx', { adapter })
|
|
1223
1213
|
expect(result.errors?.filter(e => e.code === 'BF101') ?? []).toEqual([])
|
|
1224
1214
|
const template = result.files.find(f => f.path.endsWith('.html.ep'))?.content ?? ''
|
|
1225
|
-
expect(template).toContain("join(
|
|
1215
|
+
expect(template).toContain("bf->join(bf->concat($left, $right), ' ')")
|
|
1226
1216
|
expect(template).not.toContain('$bf->concat')
|
|
1227
1217
|
})
|
|
1228
1218
|
|
|
@@ -1484,10 +1474,10 @@ describe('MojoAdapter - #1448 Tier A/B fixture-driven lowering pins', () => {
|
|
|
1484
1474
|
{ fixture: arraySliceFixture, expect: 'bf->slice($items, 1, 3)' },
|
|
1485
1475
|
// #1448 full-arity — zero-arg defaults.
|
|
1486
1476
|
{ fixture: arraySliceCopyFixture, expect: 'bf->slice($items, 0, undef)' },
|
|
1487
|
-
{ fixture: arrayJoinDefaultFixture, expect: `join(','
|
|
1477
|
+
{ fixture: arrayJoinDefaultFixture, expect: `bf->join($items, ',')` },
|
|
1488
1478
|
// `.at()` → index 0; `.concat()` → the receiver (shallow copy).
|
|
1489
1479
|
{ fixture: arrayAtDefaultFixture, expect: 'bf->at($items, 0)' },
|
|
1490
|
-
{ fixture: arrayConcatCopyFixture, expect: `join('|'
|
|
1480
|
+
{ fixture: arrayConcatCopyFixture, expect: `bf->join($items, '|')` },
|
|
1491
1481
|
{ fixture: arrayReverseFixture, expect: 'bf->reverse($items)' },
|
|
1492
1482
|
// .toReversed shares the helper with .reverse — pinning both
|
|
1493
1483
|
// routings catches a future divergence between them.
|
|
@@ -1497,7 +1487,7 @@ describe('MojoAdapter - #1448 Tier A/B fixture-driven lowering pins', () => {
|
|
|
1497
1487
|
{ fixture: stringTrimFixture, expect: 'bf->trim($value)' },
|
|
1498
1488
|
// #1448 Tier B — string → array. `.split(',')` lowers to
|
|
1499
1489
|
// `bf->split`, here chained into `.join('|')` so the array ref is
|
|
1500
|
-
// observable (`join(
|
|
1490
|
+
// observable (`bf->join(bf->split($value, ','), '|')`).
|
|
1501
1491
|
{ fixture: stringSplitFixture, expect: `bf->split($value, ',')` },
|
|
1502
1492
|
{ fixture: stringSplitLimitFixture, expect: `bf->split($value, ',', 2)` },
|
|
1503
1493
|
// #1448 Tier B — string → boolean at condition position (`% if`).
|
|
@@ -1687,7 +1677,7 @@ export { C }
|
|
|
1687
1677
|
// projects each element (no flatten) and composes through `.join`.
|
|
1688
1678
|
test('.map(t => `#${t}`).join(" ") emits bf->map_eval composed into join', () => {
|
|
1689
1679
|
const t = emitMap("tags.map(t => `#${t}`).join(' ')")
|
|
1690
|
-
expect(t).toContain(`join(
|
|
1680
|
+
expect(t).toContain(`bf->join(bf->map_eval($tags,`)
|
|
1691
1681
|
expect(t).toContain(`"kind":"template-literal"`)
|
|
1692
1682
|
})
|
|
1693
1683
|
|
|
@@ -35,14 +35,20 @@ export function renderArrayMethod(
|
|
|
35
35
|
): string {
|
|
36
36
|
switch (method) {
|
|
37
37
|
case 'join': {
|
|
38
|
-
// arr.join(sep) → join(
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
38
|
+
// arr.join(sep) → bf->join(arr, sep), NOT Perl's native `join`
|
|
39
|
+
// builtin directly on `@{arr}` — a nested-array element (e.g.
|
|
40
|
+
// `.flat(0)`'s shallow copy) would stringify to its Perl memory
|
|
41
|
+
// address ("ARRAY(0x...)") under native `join`'s scalar coercion
|
|
42
|
+
// instead of JS's recursive comma-join (#2262/#2272). `bf->join`
|
|
43
|
+
// (BarefootJS.pm) routes each element through `string()` first.
|
|
44
|
+
// The default `${obj}->{join}` hash-lookup fallback would emit
|
|
45
|
+
// invalid Perl, which is why the IR carves out a dedicated method
|
|
46
|
+
// node instead of routing through the generic call dispatcher.
|
|
47
|
+
// `.join()` defaults the separator to `,` (JS) and ignores any
|
|
48
|
+
// extra argument.
|
|
43
49
|
const obj = emit(object)
|
|
44
50
|
const sep = args.length >= 1 ? emit(args[0]) : `','`
|
|
45
|
-
return `join(${
|
|
51
|
+
return `bf->join(${obj}, ${sep})`
|
|
46
52
|
}
|
|
47
53
|
case 'includes': {
|
|
48
54
|
// Both `arr.includes(x)` and `str.includes(sub)` route here —
|
package/src/conformance-pins.ts
CHANGED
|
@@ -88,7 +88,7 @@ export const conformancePins: ConformancePins = {
|
|
|
88
88
|
// below for the shared `/* @client */` keyed-map slot-id elision
|
|
89
89
|
// contract (same as `todo-app`), not a render or BF101 gap.
|
|
90
90
|
// #1443: `[a, b].filter(Boolean).join(' ')` (the registry Slot's
|
|
91
|
-
// shape) now lowers to `join(
|
|
91
|
+
// shape) now lowers to `bf->join([grep { $_ } @{[$a, $b]}], ' ')`.
|
|
92
92
|
// No BF101 expected — pinned positively via the
|
|
93
93
|
// `branch-local-filter-join` template-output test below.
|
|
94
94
|
//
|
|
@@ -139,4 +139,10 @@ export const conformancePins: ConformancePins = {
|
|
|
139
139
|
// A dynamic/signal-derived value still refuses with BF101 — see the
|
|
140
140
|
// `dangerous-inner-html-dynamic` fixture/pin below (tracked: #2215).
|
|
141
141
|
'dangerous-inner-html-dynamic': [{ code: 'BF101', severity: 'error', issue: 'https://github.com/piconic-ai/barefootjs/issues/2215' }],
|
|
142
|
+
// #2273: a method call on a prop typed as a built-in host rich type
|
|
143
|
+
// (Date, Map, …) has no catalogued lowering in any adapter — this is a
|
|
144
|
+
// compiler-level refusal (`checkRichTypeMethodCalls`, wired ahead of
|
|
145
|
+
// `adapter.generate()`), not an adapter-specific gap, so it is pinned
|
|
146
|
+
// identically across every adapter package including Hono.
|
|
147
|
+
'date-method-uncatalogued': [{ code: 'BF021', severity: 'error', issue: 'https://github.com/piconic-ai/barefootjs/issues/2274' }],
|
|
142
148
|
}
|