@barefootjs/mojolicious 0.17.0 → 0.18.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 +13 -1
- package/dist/adapter/expr/array-method.d.ts.map +1 -1
- package/dist/adapter/expr/emitters.d.ts +9 -4
- package/dist/adapter/expr/emitters.d.ts.map +1 -1
- package/dist/adapter/index.js +100 -68
- package/dist/adapter/lib/ir-scope.d.ts +0 -7
- package/dist/adapter/lib/ir-scope.d.ts.map +1 -1
- package/dist/adapter/memo/seed.d.ts +10 -19
- package/dist/adapter/memo/seed.d.ts.map +1 -1
- package/dist/adapter/mojo-adapter.d.ts.map +1 -1
- package/dist/build.js +100 -68
- package/dist/conformance-pins.d.ts +10 -0
- package/dist/conformance-pins.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +116 -68
- package/dist/test-render.d.ts.map +1 -1
- package/lib/BarefootJS/Backend/Mojo.pm +14 -5
- package/lib/Mojolicious/Plugin/BarefootJS/DevReload.pm +1 -1
- package/lib/Mojolicious/Plugin/BarefootJS.pm +55 -33
- package/package.json +3 -3
- package/src/__tests__/mojo-adapter.test.ts +180 -135
- package/src/__tests__/multi-component-registry.test.ts +215 -0
- package/src/__tests__/stock-route.test.ts +203 -0
- package/src/adapter/expr/array-method.ts +43 -1
- package/src/adapter/expr/emitters.ts +59 -15
- package/src/adapter/lib/ir-scope.ts +0 -13
- package/src/adapter/memo/seed.ts +20 -73
- package/src/adapter/mojo-adapter.ts +154 -34
- package/src/conformance-pins.ts +138 -0
- package/src/index.ts +1 -0
- package/src/test-render.ts +8 -0
package/dist/build.js
CHANGED
|
@@ -2,23 +2,24 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BaseAdapter,
|
|
4
4
|
isBooleanAttr,
|
|
5
|
-
parseExpression as
|
|
5
|
+
parseExpression as parseExpression2,
|
|
6
6
|
stringifyParsedExpr as stringifyParsedExpr2,
|
|
7
7
|
parseStyleObjectEntries,
|
|
8
|
-
isSupported
|
|
8
|
+
isSupported,
|
|
9
9
|
exprToString,
|
|
10
10
|
parseProviderObjectLiteral,
|
|
11
11
|
emitParsedExpr as emitParsedExpr2,
|
|
12
12
|
emitIRNode,
|
|
13
13
|
emitAttrValue,
|
|
14
14
|
augmentInheritedPropAccesses,
|
|
15
|
-
isLowerableObjectRestDestructure,
|
|
16
15
|
collectModuleStringConsts,
|
|
17
16
|
lookupStaticRecordLiteral,
|
|
18
17
|
searchParamsLocalNames,
|
|
19
18
|
prepareLoweringMatchers,
|
|
20
19
|
queryHrefArgs,
|
|
21
|
-
|
|
20
|
+
isValidHelperId,
|
|
21
|
+
sortComparatorFromArrow as sortComparatorFromArrow2,
|
|
22
|
+
isLowerableLoopDestructure
|
|
22
23
|
} from "@barefootjs/jsx";
|
|
23
24
|
|
|
24
25
|
// src/adapter/boolean-result.ts
|
|
@@ -128,13 +129,6 @@ function collectRootScopeNodes(node) {
|
|
|
128
129
|
visit(node);
|
|
129
130
|
return out;
|
|
130
131
|
}
|
|
131
|
-
function referencedVarsAreAvailable(expr, available) {
|
|
132
|
-
for (const m of expr.matchAll(/\$([A-Za-z_]\w*)/g)) {
|
|
133
|
-
if (!available.has(m[1]))
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
132
|
|
|
139
133
|
// src/adapter/expr/array-method.ts
|
|
140
134
|
import {
|
|
@@ -307,6 +301,13 @@ function renderFlatMapEval(recv, body, param, emit) {
|
|
|
307
301
|
const env = emitEvalEnvArg(body, [param], emit);
|
|
308
302
|
return `bf->flat_map_eval(${recv}, '${escapePerlSingleQuote(json)}', '${param}', ${env})`;
|
|
309
303
|
}
|
|
304
|
+
function renderMapEval(recv, body, param, emit) {
|
|
305
|
+
const json = serializeParsedExpr(body);
|
|
306
|
+
if (json === null)
|
|
307
|
+
return null;
|
|
308
|
+
const env = emitEvalEnvArg(body, [param], emit);
|
|
309
|
+
return `bf->map_eval(${recv}, '${escapePerlSingleQuote(json)}', '${param}', ${env})`;
|
|
310
|
+
}
|
|
310
311
|
function renderSortMethod(recv, c) {
|
|
311
312
|
const keyHashes = c.keys.map((k) => {
|
|
312
313
|
const keyEntry = k.key.kind === "self" ? `key_kind => 'self'` : `key_kind => 'field', key => '${k.key.field}'`;
|
|
@@ -314,7 +315,10 @@ function renderSortMethod(recv, c) {
|
|
|
314
315
|
});
|
|
315
316
|
return `bf->sort(${recv}, { keys => [${keyHashes.join(", ")}] })`;
|
|
316
317
|
}
|
|
317
|
-
function renderFlatMethod(recv, depth) {
|
|
318
|
+
function renderFlatMethod(recv, depth, emit) {
|
|
319
|
+
if (typeof depth === "object") {
|
|
320
|
+
return `bf->flat_dynamic(${recv}, ${emit(depth.expr)})`;
|
|
321
|
+
}
|
|
318
322
|
const d = depth === "infinity" ? -1 : depth;
|
|
319
323
|
return `bf->flat(${recv}, ${d})`;
|
|
320
324
|
}
|
|
@@ -360,10 +364,12 @@ class MojoFilterEmitter {
|
|
|
360
364
|
param;
|
|
361
365
|
localVarMap;
|
|
362
366
|
isStringName;
|
|
363
|
-
|
|
367
|
+
onUnsupported;
|
|
368
|
+
constructor(param, localVarMap, isStringName = () => false, onUnsupported) {
|
|
364
369
|
this.param = param;
|
|
365
370
|
this.localVarMap = localVarMap;
|
|
366
371
|
this.isStringName = isStringName;
|
|
372
|
+
this.onUnsupported = onUnsupported;
|
|
367
373
|
}
|
|
368
374
|
identifier(name) {
|
|
369
375
|
if (name === this.param)
|
|
@@ -442,12 +448,14 @@ class MojoFilterEmitter {
|
|
|
442
448
|
return `(${l} // ${r})`;
|
|
443
449
|
}
|
|
444
450
|
callbackMethod(method, object, arrow, _restArgs, emit) {
|
|
445
|
-
if (!PREDICATE_METHODS.has(method))
|
|
451
|
+
if (!PREDICATE_METHODS.has(method)) {
|
|
452
|
+
this.onUnsupported?.(`Filter predicate contains a nested '.${method}(...)' callback, which has no Perl scalar form`, `Rewrite the predicate without a nested callback method, or add /* @client */ for client-only evaluation (no SSR).`);
|
|
446
453
|
return "1";
|
|
454
|
+
}
|
|
447
455
|
const param = arrow.params[0];
|
|
448
456
|
const predicate = arrow.body;
|
|
449
457
|
const arrayExpr = emit(object);
|
|
450
|
-
const predBody = emitParsedExpr(predicate, new MojoFilterEmitter(param, this.localVarMap, this.isStringName));
|
|
458
|
+
const predBody = emitParsedExpr(predicate, new MojoFilterEmitter(param, this.localVarMap, this.isStringName, this.onUnsupported));
|
|
451
459
|
const grepBody = predBody.replace(new RegExp(`\\$${param}\\b`, "g"), "$_");
|
|
452
460
|
if (method === "filter")
|
|
453
461
|
return `[grep { ${grepBody} } @{${arrayExpr}}]`;
|
|
@@ -455,6 +463,7 @@ class MojoFilterEmitter {
|
|
|
455
463
|
return `!(grep { !(${grepBody}) } @{${arrayExpr}})`;
|
|
456
464
|
if (method === "some")
|
|
457
465
|
return `!!(grep { ${grepBody} } @{${arrayExpr}})`;
|
|
466
|
+
this.onUnsupported?.(`Filter predicate contains a nested '.${method}(...)' callback, which has no Perl scalar form`, `Rewrite the predicate without a nested callback method, or add /* @client */ for client-only evaluation (no SSR).`);
|
|
458
467
|
return arrayExpr;
|
|
459
468
|
}
|
|
460
469
|
arrayLiteral(elements, emit) {
|
|
@@ -464,7 +473,7 @@ class MojoFilterEmitter {
|
|
|
464
473
|
return renderArrayMethod(method, object, args, emit);
|
|
465
474
|
}
|
|
466
475
|
flatMethod(object, depth, emit) {
|
|
467
|
-
return renderFlatMethod(emit(object), depth);
|
|
476
|
+
return renderFlatMethod(emit(object), depth, emit);
|
|
468
477
|
}
|
|
469
478
|
conditional(_test, _consequent, _alternate) {
|
|
470
479
|
return "1";
|
|
@@ -620,6 +629,13 @@ class MojoTopLevelEmitter {
|
|
|
620
629
|
this.ctx._recordExprBF101(`.flatMap(...) projection is not lowerable to a template flat-map`, `Pre-compute the projection in the route handler, or mark the loop @client-only.`);
|
|
621
630
|
return "''";
|
|
622
631
|
}
|
|
632
|
+
if (method === "map") {
|
|
633
|
+
const evalForm = renderMapEval(recv, body, params[0], emit);
|
|
634
|
+
if (evalForm !== null)
|
|
635
|
+
return evalForm;
|
|
636
|
+
this.ctx._recordExprBF101(`.map(...) projection is not lowerable to a template map`, `Pre-compute the projection in the route handler, or mark the position @client-only.`);
|
|
637
|
+
return "''";
|
|
638
|
+
}
|
|
623
639
|
const cb = {
|
|
624
640
|
method,
|
|
625
641
|
object,
|
|
@@ -672,7 +688,7 @@ class MojoTopLevelEmitter {
|
|
|
672
688
|
return renderArrayMethod(method, object, args, emit);
|
|
673
689
|
}
|
|
674
690
|
flatMethod(object, depth, emit) {
|
|
675
|
-
return renderFlatMethod(emit(object), depth);
|
|
691
|
+
return renderFlatMethod(emit(object), depth, emit);
|
|
676
692
|
}
|
|
677
693
|
conditional(test, consequent, alternate, emit) {
|
|
678
694
|
return `(${emit(test)} ? ${emit(consequent)} : ${emit(alternate)})`;
|
|
@@ -703,8 +719,8 @@ class MojoTopLevelEmitter {
|
|
|
703
719
|
unsupported(_raw, _reason) {
|
|
704
720
|
return "''";
|
|
705
721
|
}
|
|
706
|
-
objectLiteral(
|
|
707
|
-
return "''";
|
|
722
|
+
objectLiteral(properties, _raw, _emit) {
|
|
723
|
+
return properties.length === 0 ? "{}" : "''";
|
|
708
724
|
}
|
|
709
725
|
}
|
|
710
726
|
|
|
@@ -863,9 +879,7 @@ function recordIndexAccessToPerl(ctx, val) {
|
|
|
863
879
|
// src/adapter/memo/seed.ts
|
|
864
880
|
import {
|
|
865
881
|
collectContextConsumers,
|
|
866
|
-
|
|
867
|
-
isSupported,
|
|
868
|
-
parseExpression as parseExpression2
|
|
882
|
+
computeSsrSeedPlan
|
|
869
883
|
} from "@barefootjs/jsx";
|
|
870
884
|
function contextDefaultPerl(c) {
|
|
871
885
|
const d = c.defaultValue;
|
|
@@ -886,42 +900,20 @@ function generateContextConsumerSeed(ir) {
|
|
|
886
900
|
`;
|
|
887
901
|
}
|
|
888
902
|
function generateDerivedMemoSeed(ctx, ir) {
|
|
889
|
-
const
|
|
890
|
-
const signals = ir.metadata.signals ?? [];
|
|
891
|
-
if (memos.length === 0 && signals.length === 0)
|
|
892
|
-
return "";
|
|
893
|
-
const available = new Set(ir.metadata.propsParams.map((p) => p.name));
|
|
903
|
+
const plan = ir.metadata.ssrSeedPlan ?? computeSsrSeedPlan(ir.metadata);
|
|
894
904
|
const lines = [];
|
|
895
|
-
for (const
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
const body = extractArrowBodyExpression(memo.computation);
|
|
903
|
-
if (body !== null) {
|
|
904
|
-
const perl = tryLowerToPerl(ctx, body, available);
|
|
905
|
-
if (perl !== null)
|
|
906
|
-
lines.push(`% my $${memo.name} = ${perl};`);
|
|
907
|
-
}
|
|
908
|
-
available.add(memo.name);
|
|
905
|
+
for (const step of plan.steps) {
|
|
906
|
+
if (step.kind !== "derived")
|
|
907
|
+
continue;
|
|
908
|
+
const perl = ctx.convertExpressionToPerl(step.expr, step.parsed);
|
|
909
|
+
if (perl === "" || !/\$[A-Za-z_]\w*/.test(perl))
|
|
910
|
+
continue;
|
|
911
|
+
lines.push(`% my $${step.name} = ${perl};`);
|
|
909
912
|
}
|
|
910
913
|
return lines.length > 0 ? lines.join(`
|
|
911
914
|
`) + `
|
|
912
915
|
` : "";
|
|
913
916
|
}
|
|
914
|
-
function tryLowerToPerl(ctx, expr, available) {
|
|
915
|
-
const trimmed = expr.trim();
|
|
916
|
-
if (!trimmed)
|
|
917
|
-
return null;
|
|
918
|
-
if (!isSupported(parseExpression2(trimmed)).supported)
|
|
919
|
-
return null;
|
|
920
|
-
const perl = ctx.convertExpressionToPerl(trimmed);
|
|
921
|
-
if (perl === "" || !/\$[A-Za-z_]\w*/.test(perl))
|
|
922
|
-
return null;
|
|
923
|
-
return referencedVarsAreAvailable(perl, available) ? perl : null;
|
|
924
|
-
}
|
|
925
917
|
|
|
926
918
|
// src/adapter/value/parsed-literal.ts
|
|
927
919
|
function isStringTypeInfo(type) {
|
|
@@ -963,6 +955,17 @@ function collectStringValueNames(ir) {
|
|
|
963
955
|
}
|
|
964
956
|
|
|
965
957
|
// src/adapter/mojo-adapter.ts
|
|
958
|
+
function perlSegmentAccessor(base, segments) {
|
|
959
|
+
let expr = base;
|
|
960
|
+
for (const seg of segments) {
|
|
961
|
+
expr += seg.kind === "field" ? `->{${seg.isIdent ? seg.key : perlHashKey(seg.key)}}` : `->[${seg.index}]`;
|
|
962
|
+
}
|
|
963
|
+
return expr;
|
|
964
|
+
}
|
|
965
|
+
function perlStringLiteral(s) {
|
|
966
|
+
return `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
967
|
+
}
|
|
968
|
+
|
|
966
969
|
class MojoAdapter extends BaseAdapter {
|
|
967
970
|
name = "mojolicious";
|
|
968
971
|
extension = ".html.ep";
|
|
@@ -1043,7 +1046,7 @@ class MojoAdapter extends BaseAdapter {
|
|
|
1043
1046
|
return this.booleanTypedProps.has(bare);
|
|
1044
1047
|
}
|
|
1045
1048
|
parseUndefinedAlternateTernary(expr) {
|
|
1046
|
-
const parsed =
|
|
1049
|
+
const parsed = parseExpression2(expr.trim());
|
|
1047
1050
|
if (parsed?.kind !== "conditional")
|
|
1048
1051
|
return null;
|
|
1049
1052
|
const alt = parsed.alternate;
|
|
@@ -1291,24 +1294,41 @@ ${whenTrue}
|
|
|
1291
1294
|
return `<%== bf->comment("cond-start:${condId}") %>${content}<%== bf->comment("cond-end:${condId}") %>`;
|
|
1292
1295
|
}
|
|
1293
1296
|
renderLoop(loop) {
|
|
1294
|
-
if (loop.clientOnly)
|
|
1295
|
-
return ""
|
|
1297
|
+
if (loop.clientOnly) {
|
|
1298
|
+
return `<%== bf->comment("loop:${loop.markerId}") %><%== bf->comment("/loop:${loop.markerId}") %>`;
|
|
1299
|
+
}
|
|
1296
1300
|
const destructure = !!(loop.paramBindings && loop.paramBindings.length > 0);
|
|
1297
|
-
const supportableDestructure = destructure &&
|
|
1301
|
+
const supportableDestructure = destructure && isLowerableLoopDestructure(loop);
|
|
1298
1302
|
if (destructure && !supportableDestructure) {
|
|
1299
1303
|
this.errors.push({
|
|
1300
1304
|
code: "BF104",
|
|
1301
1305
|
severity: "error",
|
|
1302
|
-
message: `Loop callback uses
|
|
1306
|
+
message: `Loop callback uses a destructure pattern (\`${loop.param}\`) that the Mojo adapter cannot lower — see the diagnostic detail for the specific shape.`,
|
|
1303
1307
|
loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
1304
1308
|
suggestion: {
|
|
1305
1309
|
message: `Options:
|
|
1306
|
-
` + ` 1.
|
|
1307
|
-
` + ` 2.
|
|
1308
|
-
` + ` 3.
|
|
1310
|
+
` + ` 1. If this is an object-rest binding (\`{ ...rest }\`), only reading \`rest.field\` or spreading \`{...rest}\` onto an intrinsic element lowers — other uses (passing \`rest\` to a function, rendering it as text) need the client runtime.
|
|
1311
|
+
` + ` 2. If this is chained \`.filter().map(({ ... }) => ...)\`, hoist the destructure into a variable inside the callback body instead.
|
|
1312
|
+
` + ` 3. Mark the loop position as @client-only so the destructure runs in JS on the client.
|
|
1313
|
+
` + ` 4. Move the loop into a primitive that the adapter registers explicitly.`
|
|
1309
1314
|
}
|
|
1310
1315
|
});
|
|
1311
1316
|
}
|
|
1317
|
+
const arrayName = loop.array.trim();
|
|
1318
|
+
if (/^[A-Za-z_$][\w$]*$/.test(arrayName)) {
|
|
1319
|
+
const arrayConst = (this.localConstants ?? []).find((c) => c.name === arrayName);
|
|
1320
|
+
if (arrayConst && !arrayConst.isModule && this.resolveLiteralConst(arrayName) === null) {
|
|
1321
|
+
this.errors.push({
|
|
1322
|
+
code: "BF101",
|
|
1323
|
+
severity: "error",
|
|
1324
|
+
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.`,
|
|
1325
|
+
loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
1326
|
+
suggestion: {
|
|
1327
|
+
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."
|
|
1328
|
+
}
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1312
1332
|
const rawArray = this.convertExpressionToPerl(loop.array);
|
|
1313
1333
|
let sortedHoist = null;
|
|
1314
1334
|
let array = rawArray;
|
|
@@ -1363,7 +1383,15 @@ ${renderedChildren}` : renderedChildren;
|
|
|
1363
1383
|
if (supportableDestructure) {
|
|
1364
1384
|
lines.push(`% my $__bf_item = ${array}->[${indexVar}];`);
|
|
1365
1385
|
for (const b of loop.paramBindings ?? []) {
|
|
1366
|
-
|
|
1386
|
+
const parent = perlSegmentAccessor("$__bf_item", b.segments ?? []);
|
|
1387
|
+
if (b.rest?.kind === "object") {
|
|
1388
|
+
const exclude = b.rest.exclude.map((k) => perlStringLiteral(k.key)).join(", ");
|
|
1389
|
+
lines.push(`% my $${b.name} = bf->omit(${parent}, [${exclude}]);`);
|
|
1390
|
+
} else if (b.rest?.kind === "array") {
|
|
1391
|
+
lines.push(`% my $${b.name} = bf->slice(${parent}, ${b.rest.from}, undef);`);
|
|
1392
|
+
} else {
|
|
1393
|
+
lines.push(`% my $${b.name} = ${perlSegmentAccessor("$__bf_item", b.segments ?? [])};`);
|
|
1394
|
+
}
|
|
1367
1395
|
}
|
|
1368
1396
|
} else {
|
|
1369
1397
|
lines.push(`% my $${param} = ${array}->[${indexVar}];`);
|
|
@@ -1547,7 +1575,7 @@ ${children}`;
|
|
|
1547
1575
|
if (localConst?.value !== undefined) {
|
|
1548
1576
|
const initTrimmed = localConst.value.trim();
|
|
1549
1577
|
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(initTrimmed)) {
|
|
1550
|
-
const resolved = conditionalSpreadToPerl(this.spreadCtx,
|
|
1578
|
+
const resolved = conditionalSpreadToPerl(this.spreadCtx, parseExpression2(initTrimmed));
|
|
1551
1579
|
if (resolved !== null) {
|
|
1552
1580
|
return `<%== bf->spread_attrs(${resolved}) %>`;
|
|
1553
1581
|
}
|
|
@@ -1565,7 +1593,7 @@ ${children}`;
|
|
|
1565
1593
|
if (!entries)
|
|
1566
1594
|
return null;
|
|
1567
1595
|
for (const e of entries) {
|
|
1568
|
-
if (e.kind === "expr" && !
|
|
1596
|
+
if (e.kind === "expr" && !isSupported(parseExpression2(e.expr)).supported)
|
|
1569
1597
|
return null;
|
|
1570
1598
|
}
|
|
1571
1599
|
return entries.map((e) => e.kind === "literal" ? `${this.escapeAttrText(e.cssKey)}:${this.escapeAttrText(e.value)}` : `${this.escapeAttrText(e.cssKey)}:<%= ${this.convertExpressionToPerl(e.expr)} %>`).join(";");
|
|
@@ -1601,7 +1629,7 @@ ${children}`;
|
|
|
1601
1629
|
return `${BF_COND}="${condId}"`;
|
|
1602
1630
|
}
|
|
1603
1631
|
renderPerlFilterExpr(expr, param, localVarMap = new Map) {
|
|
1604
|
-
return emitParsedExpr2(expr, new MojoFilterEmitter(param, localVarMap, (n) => this._isStringValueName(n)));
|
|
1632
|
+
return emitParsedExpr2(expr, new MojoFilterEmitter(param, localVarMap, (n) => this._isStringValueName(n), (message, reason) => this._recordExprBF101(message, reason)));
|
|
1605
1633
|
}
|
|
1606
1634
|
convertTemplateLiteralPartsToPerl(literalParts) {
|
|
1607
1635
|
const parts = [];
|
|
@@ -1646,8 +1674,8 @@ ${children}`;
|
|
|
1646
1674
|
const hasTaggedTemplate = /[A-Za-z_$][\w$]*\s*`/.test(probe);
|
|
1647
1675
|
if (!startsAsObjectLiteral && !hasTaggedTemplate)
|
|
1648
1676
|
return false;
|
|
1649
|
-
const parsed =
|
|
1650
|
-
const support =
|
|
1677
|
+
const parsed = parseExpression2(expr.trim());
|
|
1678
|
+
const support = isSupported(parsed);
|
|
1651
1679
|
if (parsed.kind !== "unsupported" && support.supported)
|
|
1652
1680
|
return false;
|
|
1653
1681
|
const reason = support.reason ?? (parsed.kind === "unsupported" ? parsed.reason : undefined);
|
|
@@ -1695,7 +1723,7 @@ ${reason}` : "";
|
|
|
1695
1723
|
const trimmed = expr.trim();
|
|
1696
1724
|
if (trimmed === "")
|
|
1697
1725
|
return "''";
|
|
1698
|
-
parsed =
|
|
1726
|
+
parsed = parseExpression2(trimmed);
|
|
1699
1727
|
}
|
|
1700
1728
|
if (parsed.kind === "call") {
|
|
1701
1729
|
for (const matcher of this._loweringMatchers) {
|
|
@@ -1704,9 +1732,13 @@ ${reason}` : "";
|
|
|
1704
1732
|
const argsGo = queryHrefArgs(node, (n) => this.renderParsedExprToPerl(n));
|
|
1705
1733
|
return `bf->query(${argsGo.join(", ")})`;
|
|
1706
1734
|
}
|
|
1735
|
+
if (node?.kind === "helper-call" && isValidHelperId(node.helper)) {
|
|
1736
|
+
const argsX = node.args.map((a) => this.renderParsedExprToPerl(a));
|
|
1737
|
+
return `bf->${node.helper}(${argsX.join(", ")})`;
|
|
1738
|
+
}
|
|
1707
1739
|
}
|
|
1708
1740
|
}
|
|
1709
|
-
const support =
|
|
1741
|
+
const support = isSupported(parsed);
|
|
1710
1742
|
if (!support.supported) {
|
|
1711
1743
|
this.errors.push({
|
|
1712
1744
|
code: "BF101",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-fixture build-time contracts for shapes the Mojo adapter
|
|
3
|
+
* intentionally refuses to lower. Owned by this module (not by the
|
|
4
|
+
* shared fixtures) so adding a new adapter doesn't require touching any
|
|
5
|
+
* cross-adapter file. Consumed by this package's own conformance test
|
|
6
|
+
* (as `expectedDiagnostics`) and by `bf compat` (issue-URL attribution).
|
|
7
|
+
*/
|
|
8
|
+
import type { ConformancePins } from '@barefootjs/jsx';
|
|
9
|
+
export declare const conformancePins: ConformancePins;
|
|
10
|
+
//# sourceMappingURL=conformance-pins.d.ts.map
|
|
@@ -0,0 +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,eA+H7B,CAAA"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAC7D,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA"}
|