@barefootjs/go-template 0.19.0 → 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/go-template-adapter.d.ts +8 -2
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +156 -22
- package/dist/adapter/lib/compile-state.d.ts +16 -0
- package/dist/adapter/lib/compile-state.d.ts.map +1 -1
- package/dist/adapter/memo/memo-compute.d.ts +8 -0
- package/dist/adapter/memo/memo-compute.d.ts.map +1 -1
- package/dist/adapter/props/prop-types.d.ts +52 -0
- package/dist/adapter/props/prop-types.d.ts.map +1 -1
- package/dist/adapter/value/value-lowering.d.ts +9 -1
- package/dist/adapter/value/value-lowering.d.ts.map +1 -1
- package/dist/build.js +156 -22
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +158 -23
- package/package.json +3 -3
- package/src/__tests__/derived-state-memo.test.ts +10 -3
- package/src/__tests__/go-template-adapter.test.ts +144 -36
- package/src/adapter/go-template-adapter.ts +114 -38
- package/src/adapter/lib/compile-state.ts +18 -0
- package/src/adapter/memo/memo-compute.ts +123 -9
- package/src/adapter/props/prop-types.ts +141 -9
- package/src/adapter/value/value-lowering.ts +57 -4
- package/src/conformance-pins.ts +6 -0
package/dist/build.js
CHANGED
|
@@ -708,6 +708,8 @@ class CompileState {
|
|
|
708
708
|
nillablePropNames = new Set;
|
|
709
709
|
nullishConsumedPropNames = new Set;
|
|
710
710
|
omittableAttrConsumedPropNames = new Set;
|
|
711
|
+
textConsumedPropNames = new Set;
|
|
712
|
+
presenceCheckedPropNames = new Set;
|
|
711
713
|
stringValueNames = new Set;
|
|
712
714
|
rootScopeNodes = new Set;
|
|
713
715
|
memoBackedLoopSlice = new Map;
|
|
@@ -1451,15 +1453,28 @@ function parsedLiteralToGo(ctx, expr, typeInfo) {
|
|
|
1451
1453
|
|
|
1452
1454
|
// src/adapter/value/value-lowering.ts
|
|
1453
1455
|
var EMPTY_PROP_FALLBACK_VARS = new Map;
|
|
1456
|
+
function nillableAwarePropRef(ctx, propName, expectedType) {
|
|
1457
|
+
const fieldRef = `in.${capitalizeFieldName(propName)}`;
|
|
1458
|
+
const scalar = expectedType.kind === "primitive" ? expectedType : expectedType.kind === "union" && expectedType.unionTypes?.length === 2 ? expectedType.unionTypes.find((t) => t.primitive !== "undefined" && t.primitive !== "null") : undefined;
|
|
1459
|
+
if (ctx.state.nillablePropNames.has(propName) && scalar?.kind === "primitive") {
|
|
1460
|
+
const goType = scalar.primitive === "boolean" ? "bool" : scalar.primitive === "number" ? "float64" : scalar.primitive === "string" ? "string" : null;
|
|
1461
|
+
if (goType) {
|
|
1462
|
+
const zero = goType === "bool" ? "false" : goType === "string" ? '""' : "0";
|
|
1463
|
+
return `func() ${goType} { if v, ok := ${fieldRef}.(${goType}); ok { return v }; return ${zero} }()`;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
return fieldRef;
|
|
1467
|
+
}
|
|
1454
1468
|
function convertInitialValue(ctx, value, typeInfo, propsParams, preParsed) {
|
|
1469
|
+
const propRef = (propName2) => nillableAwarePropRef(ctx, propName2, typeInfo);
|
|
1455
1470
|
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
|
|
1456
1471
|
if (propsParams?.some((p) => p.name === value)) {
|
|
1457
|
-
return
|
|
1472
|
+
return propRef(value);
|
|
1458
1473
|
}
|
|
1459
1474
|
}
|
|
1460
1475
|
const propName = ctx.extractPropNameFromInitialValue(value, preParsed);
|
|
1461
1476
|
if (propName && propsParams?.some((p) => p.name === propName)) {
|
|
1462
|
-
return
|
|
1477
|
+
return propRef(propName);
|
|
1463
1478
|
}
|
|
1464
1479
|
if (typeInfo.kind === "primitive") {
|
|
1465
1480
|
if (typeInfo.primitive === "boolean") {
|
|
@@ -1526,19 +1541,20 @@ function objectLiteralToGoMap(ctx, expr) {
|
|
|
1526
1541
|
return null;
|
|
1527
1542
|
return `map[string]interface{}{${entries.join(", ")}}`;
|
|
1528
1543
|
}
|
|
1529
|
-
function getSignalInitialValueAsGo(ctx, initialValue, propsParams, propFallbackVars = EMPTY_PROP_FALLBACK_VARS) {
|
|
1544
|
+
function getSignalInitialValueAsGo(ctx, initialValue, propsParams, propFallbackVars = EMPTY_PROP_FALLBACK_VARS, signalType) {
|
|
1545
|
+
const propRef = (propName2) => signalType ? nillableAwarePropRef(ctx, propName2, signalType) : `in.${capitalizeFieldName(propName2)}`;
|
|
1530
1546
|
if (propsParams.some((p) => p.name === initialValue)) {
|
|
1531
1547
|
const hoisted = propFallbackVars.get(initialValue);
|
|
1532
1548
|
if (hoisted)
|
|
1533
1549
|
return hoisted.varName;
|
|
1534
|
-
return
|
|
1550
|
+
return propRef(initialValue);
|
|
1535
1551
|
}
|
|
1536
1552
|
const propName = ctx.extractPropNameFromInitialValue(initialValue);
|
|
1537
1553
|
if (propName && propsParams.some((p) => p.name === propName)) {
|
|
1538
1554
|
const hoisted = propFallbackVars.get(propName);
|
|
1539
1555
|
if (hoisted)
|
|
1540
1556
|
return hoisted.varName;
|
|
1541
|
-
return
|
|
1557
|
+
return propRef(propName);
|
|
1542
1558
|
}
|
|
1543
1559
|
if (/^-?\d+$/.test(initialValue)) {
|
|
1544
1560
|
return initialValue;
|
|
@@ -2008,9 +2024,34 @@ var EMPTY_PROP_FALLBACK_VARS2 = new Map;
|
|
|
2008
2024
|
function getterCallName(e) {
|
|
2009
2025
|
return e.kind === "call" && e.callee.kind === "identifier" && e.args.length === 0 ? e.callee.name : null;
|
|
2010
2026
|
}
|
|
2027
|
+
function isBooleanTypeInfo(t) {
|
|
2028
|
+
if (t.kind === "primitive")
|
|
2029
|
+
return t.primitive === "boolean";
|
|
2030
|
+
if (t.kind === "union" && t.unionTypes?.length === 2) {
|
|
2031
|
+
const scalar = t.unionTypes.find((u) => u.primitive !== "undefined" && u.primitive !== "null");
|
|
2032
|
+
return scalar?.kind === "primitive" && scalar.primitive === "boolean";
|
|
2033
|
+
}
|
|
2034
|
+
return false;
|
|
2035
|
+
}
|
|
2036
|
+
function isBooleanTypedGetter(ctx, name, signals) {
|
|
2037
|
+
const signal = signals.find((s) => s.getter === name);
|
|
2038
|
+
if (signal)
|
|
2039
|
+
return signal.type !== undefined && isBooleanTypeInfo(signal.type);
|
|
2040
|
+
const memo = (ctx.state.currentMemos ?? []).find((m) => m.name === name);
|
|
2041
|
+
return memo?.type !== undefined && isBooleanTypeInfo(memo.type);
|
|
2042
|
+
}
|
|
2011
2043
|
function propsMemberName(e) {
|
|
2012
2044
|
return e.kind === "member" && !e.computed && e.object.kind === "identifier" && e.object.name === "props" ? e.property : null;
|
|
2013
2045
|
}
|
|
2046
|
+
function propNameForPropsBinding(ctx, e) {
|
|
2047
|
+
const propsObject = ctx.state.propsObjectName;
|
|
2048
|
+
if (e.kind === "member" && !e.computed && e.object.kind === "identifier" && e.object.name === propsObject) {
|
|
2049
|
+
return e.property;
|
|
2050
|
+
}
|
|
2051
|
+
if (!propsObject && e.kind === "identifier")
|
|
2052
|
+
return e.name;
|
|
2053
|
+
return null;
|
|
2054
|
+
}
|
|
2014
2055
|
function matchFilterArmMemo(ctx, body, signals, propsParams) {
|
|
2015
2056
|
const cb = asCallbackMethodCall2(body);
|
|
2016
2057
|
if (!cb || cb.method !== "filter")
|
|
@@ -2149,6 +2190,17 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
|
|
|
2149
2190
|
if (propName)
|
|
2150
2191
|
return propRef(propName);
|
|
2151
2192
|
}
|
|
2193
|
+
if (body.kind === "binary" && (body.op === "!==" || body.op === "!=" || body.op === "===" || body.op === "==")) {
|
|
2194
|
+
const other = body.right.kind === "identifier" && body.right.name === "undefined" ? body.left : body.left.kind === "identifier" && body.left.name === "undefined" ? body.right : null;
|
|
2195
|
+
const propName = other ? propNameForPropsBinding(ctx, other) : null;
|
|
2196
|
+
if (propName) {
|
|
2197
|
+
const param = propsParams.find((p) => p.name === propName);
|
|
2198
|
+
if (param && ctx.state.nillablePropNames.has(propName)) {
|
|
2199
|
+
const isNe = body.op === "!==" || body.op === "!=";
|
|
2200
|
+
return `in.${capitalizeFieldName(propName)} ${isNe ? "!=" : "=="} nil`;
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2152
2204
|
if (body.kind === "conditional") {
|
|
2153
2205
|
const condName = getterCallName(body.test);
|
|
2154
2206
|
if (condName) {
|
|
@@ -2183,6 +2235,18 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
|
|
|
2183
2235
|
}
|
|
2184
2236
|
}
|
|
2185
2237
|
}
|
|
2238
|
+
if (condName) {
|
|
2239
|
+
const tName = getterCallName(body.consequent);
|
|
2240
|
+
const fName = getterCallName(body.alternate);
|
|
2241
|
+
if (tName && fName && isBooleanTypedGetter(ctx, tName, signals) && isBooleanTypedGetter(ctx, fName, signals)) {
|
|
2242
|
+
const condGo = resolveGetterValueAsGo(ctx, condName, signals, propsParams, propFallbackVars, resolving);
|
|
2243
|
+
const tGo = resolveGetterValueAsGo(ctx, tName, signals, propsParams, propFallbackVars, resolving);
|
|
2244
|
+
const fGo = resolveGetterValueAsGo(ctx, fName, signals, propsParams, propFallbackVars, resolving);
|
|
2245
|
+
if (condGo !== null && tGo !== null && fGo !== null) {
|
|
2246
|
+
return `func() bool { if ${condGo} { return ${tGo} }; return ${fGo} }()`;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2186
2250
|
}
|
|
2187
2251
|
if (body.kind === "binary" && ["*", "+", "-", "/"].includes(body.op) && body.right.kind === "literal" && body.right.literalType === "number" && typeof body.right.value === "number" && Number.isInteger(body.right.value) && body.right.value >= 0) {
|
|
2188
2252
|
const operator = body.op;
|
|
@@ -2271,7 +2335,7 @@ function computeMemoInitialValueOrNull(ctx, memo, signals, propsParams, propFall
|
|
|
2271
2335
|
function resolveGetterValueAsGo(ctx, name, signals, propsParams, propFallbackVars, resolving = new Set) {
|
|
2272
2336
|
const signal = signals.find((s) => s.getter === name);
|
|
2273
2337
|
if (signal) {
|
|
2274
|
-
return getSignalInitialValueAsGo(ctx, signal.initialValue, propsParams, propFallbackVars);
|
|
2338
|
+
return getSignalInitialValueAsGo(ctx, signal.initialValue, propsParams, propFallbackVars, signal.type);
|
|
2275
2339
|
}
|
|
2276
2340
|
const memo = (ctx.state.currentMemos ?? []).find((m) => m.name === name);
|
|
2277
2341
|
if (memo) {
|
|
@@ -2673,8 +2737,10 @@ function collectNullishConsumedPropNames(ctx, ir) {
|
|
|
2673
2737
|
const propNameOfLeft = (left) => {
|
|
2674
2738
|
if (left.kind === "identifier")
|
|
2675
2739
|
return left.name;
|
|
2676
|
-
if (left.kind === "member" && !left.computed && left.object.kind === "identifier"
|
|
2677
|
-
|
|
2740
|
+
if (left.kind === "member" && !left.computed && left.object.kind === "identifier") {
|
|
2741
|
+
if (left.object.name === propsObject)
|
|
2742
|
+
return left.property;
|
|
2743
|
+
return left.object.name;
|
|
2678
2744
|
}
|
|
2679
2745
|
return null;
|
|
2680
2746
|
};
|
|
@@ -2745,12 +2811,60 @@ function collectOmittableAttrConsumedPropNames(ctx, ir) {
|
|
|
2745
2811
|
walk(ir.root);
|
|
2746
2812
|
return names;
|
|
2747
2813
|
}
|
|
2814
|
+
function collectTextConsumedPropNames(ctx, ir) {
|
|
2815
|
+
const names = new Set;
|
|
2816
|
+
const optionalParams = new Set(ir.metadata.propsParams.filter((p) => p.optional && p.defaultValue == null && p.type.kind === "primitive").map((p) => p.name));
|
|
2817
|
+
if (optionalParams.size === 0)
|
|
2818
|
+
return names;
|
|
2819
|
+
const propsObject = ctx.state.propsObjectName;
|
|
2820
|
+
const walk = (node) => {
|
|
2821
|
+
if (!node || typeof node !== "object")
|
|
2822
|
+
return;
|
|
2823
|
+
if (Array.isArray(node)) {
|
|
2824
|
+
for (const item of node)
|
|
2825
|
+
walk(item);
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2828
|
+
const rec = node;
|
|
2829
|
+
if (rec.type === "expression") {
|
|
2830
|
+
const bareId = String(rec.expr ?? "").trim();
|
|
2831
|
+
const propName = propsObject && bareId.startsWith(`${propsObject}.`) ? bareId.slice(propsObject.length + 1) : bareId;
|
|
2832
|
+
if (/^[A-Za-z_$][\w$]*$/.test(propName) && optionalParams.has(propName)) {
|
|
2833
|
+
names.add(propName);
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
for (const value of Object.values(rec))
|
|
2837
|
+
walk(value);
|
|
2838
|
+
};
|
|
2839
|
+
walk(ir.root);
|
|
2840
|
+
return names;
|
|
2841
|
+
}
|
|
2842
|
+
function collectPresenceCheckedPropNames(ctx, ir) {
|
|
2843
|
+
const names = new Set;
|
|
2844
|
+
const optionalParams = new Set(ir.metadata.propsParams.filter((p) => p.optional && p.defaultValue == null && p.type.kind === "primitive").map((p) => p.name));
|
|
2845
|
+
if (optionalParams.size === 0)
|
|
2846
|
+
return names;
|
|
2847
|
+
const propsObject = ctx.state.propsObjectName;
|
|
2848
|
+
const isUndefinedCheck = (op) => op === "!==" || op === "!=" || op === "===" || op === "==";
|
|
2849
|
+
for (const memo of ir.metadata.memos) {
|
|
2850
|
+
const body = memo.parsed;
|
|
2851
|
+
if (!body || body.kind !== "binary" || !isUndefinedCheck(body.op))
|
|
2852
|
+
continue;
|
|
2853
|
+
const other = body.right.kind === "identifier" && body.right.name === "undefined" ? body.left : body.left.kind === "identifier" && body.left.name === "undefined" ? body.right : null;
|
|
2854
|
+
if (!other)
|
|
2855
|
+
continue;
|
|
2856
|
+
const propName = other.kind === "member" && !other.computed && other.object.kind === "identifier" && other.object.name === propsObject ? other.property : !propsObject && other.kind === "identifier" ? other.name : null;
|
|
2857
|
+
if (propName && optionalParams.has(propName))
|
|
2858
|
+
names.add(propName);
|
|
2859
|
+
}
|
|
2860
|
+
return names;
|
|
2861
|
+
}
|
|
2748
2862
|
function resolvePropGoType(ctx, param, propTypeOverrides) {
|
|
2749
2863
|
const base = propTypeOverrides.get(param.name) ?? typeInfoToGo(ctx, param.type, param.defaultValue);
|
|
2750
2864
|
if (param.optional && ctx.state.localStructFields.has(base)) {
|
|
2751
2865
|
return "map[string]interface{}";
|
|
2752
2866
|
}
|
|
2753
|
-
if (param.optional && param.type.kind === "primitive" && (ctx.state.nullishConsumedPropNames.has(param.name) || ctx.state.omittableAttrConsumedPropNames.has(param.name)) && NULLISH_SCALAR_GO_TYPES.has(base)) {
|
|
2867
|
+
if (param.optional && param.type.kind === "primitive" && (ctx.state.nullishConsumedPropNames.has(param.name) || ctx.state.omittableAttrConsumedPropNames.has(param.name) || ctx.state.textConsumedPropNames.has(param.name) || ctx.state.presenceCheckedPropNames.has(param.name)) && NULLISH_SCALAR_GO_TYPES.has(base)) {
|
|
2754
2868
|
return "interface{}";
|
|
2755
2869
|
}
|
|
2756
2870
|
return base;
|
|
@@ -2887,6 +3001,8 @@ class GoTemplateAdapter extends BaseAdapter {
|
|
|
2887
3001
|
this.buildLocalTypeTables(ir, ir.metadata.componentName);
|
|
2888
3002
|
this.state.nullishConsumedPropNames = collectNullishConsumedPropNames(this.emitCtx, ir);
|
|
2889
3003
|
this.state.omittableAttrConsumedPropNames = collectOmittableAttrConsumedPropNames(this.emitCtx, ir);
|
|
3004
|
+
this.state.textConsumedPropNames = collectTextConsumedPropNames(this.emitCtx, ir);
|
|
3005
|
+
this.state.presenceCheckedPropNames = collectPresenceCheckedPropNames(this.emitCtx, ir);
|
|
2890
3006
|
this.state.nillablePropNames = collectNillablePropNames(this.emitCtx, ir);
|
|
2891
3007
|
}
|
|
2892
3008
|
generate(ir, options) {
|
|
@@ -4569,10 +4685,22 @@ ${goFields.join(`
|
|
|
4569
4685
|
}
|
|
4570
4686
|
return goExpr;
|
|
4571
4687
|
}
|
|
4688
|
+
const finalExpr = this.textNillablePropNameOf(classify.parsed) !== null ? `bf_string ${wrapIfMultiToken(goExpr)}` : goExpr;
|
|
4572
4689
|
if (expr.slotId) {
|
|
4573
|
-
return `{{bfTextStart "${expr.slotId}"}}{{${
|
|
4690
|
+
return `{{bfTextStart "${expr.slotId}"}}{{${finalExpr}}}{{bfTextEnd}}`;
|
|
4574
4691
|
}
|
|
4575
|
-
return `{{${
|
|
4692
|
+
return `{{${finalExpr}}}`;
|
|
4693
|
+
}
|
|
4694
|
+
textNillablePropNameOf(expr) {
|
|
4695
|
+
if (!expr)
|
|
4696
|
+
return null;
|
|
4697
|
+
let name = null;
|
|
4698
|
+
if (expr.kind === "identifier") {
|
|
4699
|
+
name = expr.name;
|
|
4700
|
+
} else if (expr.kind === "member" && !expr.computed && expr.object.kind === "identifier" && expr.object.name === this.state.propsObjectName) {
|
|
4701
|
+
name = expr.property;
|
|
4702
|
+
}
|
|
4703
|
+
return name !== null && this.state.textConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
4576
4704
|
}
|
|
4577
4705
|
isTemplateFragment(go, kind) {
|
|
4578
4706
|
return go.startsWith("{{") || kind === "template-literal";
|
|
@@ -4788,7 +4916,7 @@ ${goFields.join(`
|
|
|
4788
4916
|
}
|
|
4789
4917
|
const obj = emit(object);
|
|
4790
4918
|
if (property === "length")
|
|
4791
|
-
return `
|
|
4919
|
+
return `bf_length ${wrapIfMultiToken(obj)}`;
|
|
4792
4920
|
if (optional) {
|
|
4793
4921
|
return `bf_get ${wrapIfMultiToken(obj)} ${JSON.stringify(goFieldNameForKey(property))}`;
|
|
4794
4922
|
}
|
|
@@ -4866,8 +4994,12 @@ ${goFields.join(`
|
|
|
4866
4994
|
let name = null;
|
|
4867
4995
|
if (expr.kind === "identifier") {
|
|
4868
4996
|
name = expr.name;
|
|
4869
|
-
} else if (expr.kind === "member" && !expr.computed && expr.object.kind === "identifier"
|
|
4870
|
-
name
|
|
4997
|
+
} else if (expr.kind === "member" && !expr.computed && expr.object.kind === "identifier") {
|
|
4998
|
+
if (expr.object.name === this.state.propsObjectName) {
|
|
4999
|
+
name = expr.property;
|
|
5000
|
+
} else {
|
|
5001
|
+
name = expr.object.name;
|
|
5002
|
+
}
|
|
4871
5003
|
}
|
|
4872
5004
|
return name !== null && this.state.nullishConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
4873
5005
|
}
|
|
@@ -5302,9 +5434,6 @@ ${goFields.join(`
|
|
|
5302
5434
|
renderPredicateCondition(pred, param, datumField) {
|
|
5303
5435
|
return this.renderFilterExpr(pred, param, new Map, datumField ?? undefined);
|
|
5304
5436
|
}
|
|
5305
|
-
needsParens(expr) {
|
|
5306
|
-
return expr.kind === "logical" || expr.kind === "unary" || expr.kind === "conditional";
|
|
5307
|
-
}
|
|
5308
5437
|
splitPreamble(rendered) {
|
|
5309
5438
|
if (!rendered.includes("{{"))
|
|
5310
5439
|
return null;
|
|
@@ -5717,7 +5846,8 @@ ${goFields.join(`
|
|
|
5717
5846
|
return plain(this.rootFieldRef(expr.callee.name));
|
|
5718
5847
|
}
|
|
5719
5848
|
if (expr.callee.kind === "identifier" && (identifierPath(expr.callee) ?? expr.callee.name) === "isValidElement" && expr.args.length === 1) {
|
|
5720
|
-
|
|
5849
|
+
const inner = this.renderConditionExpr(expr.args[0]);
|
|
5850
|
+
return { preamble: inner.preamble, expr: `(bf_is_element ${wrapIfMultiToken(inner.expr)})` };
|
|
5721
5851
|
}
|
|
5722
5852
|
if (expr.callee.kind === "identifier" && !this.templatePrimitives[identifierPath(expr.callee) ?? ""]) {
|
|
5723
5853
|
const path = identifierPath(expr.callee) ?? expr.callee.name;
|
|
@@ -5834,9 +5964,9 @@ ${goFields.join(`
|
|
|
5834
5964
|
const leftResult = this.renderConditionExpr(expr.left);
|
|
5835
5965
|
const rightResult = this.renderConditionExpr(expr.right);
|
|
5836
5966
|
const preamble = leftResult.preamble + rightResult.preamble;
|
|
5837
|
-
const wrapLeft =
|
|
5838
|
-
const wrapRight =
|
|
5839
|
-
const result = expr.op === "&&" ? `and ${wrapLeft} ${wrapRight}` : `or ${wrapLeft} ${wrapRight}`;
|
|
5967
|
+
const wrapLeft = wrapIfMultiToken(leftResult.expr);
|
|
5968
|
+
const wrapRight = wrapIfMultiToken(rightResult.expr);
|
|
5969
|
+
const result = expr.op === "&&" ? `and ${wrapLeft} ${wrapRight}` : expr.op === "??" && this.nillablePropNameOf(expr.left) !== null ? `bf_nullish ${wrapLeft} ${wrapRight}` : `or ${wrapLeft} ${wrapRight}`;
|
|
5840
5970
|
return { preamble, expr: result };
|
|
5841
5971
|
}
|
|
5842
5972
|
case "conditional": {
|
|
@@ -6249,7 +6379,11 @@ ${children}`;
|
|
|
6249
6379
|
if (e.kind === "expr" && !isSupported(parseExpression4(e.expr)).supported)
|
|
6250
6380
|
return null;
|
|
6251
6381
|
}
|
|
6252
|
-
|
|
6382
|
+
const args = entries.flatMap((e) => [
|
|
6383
|
+
JSON.stringify(e.cssKey),
|
|
6384
|
+
e.kind === "literal" ? JSON.stringify(e.value) : wrapIfMultiToken(this.convertExpressionToGo(e.expr))
|
|
6385
|
+
]);
|
|
6386
|
+
return `{{bf_style_object ${args.join(" ")}}}`;
|
|
6253
6387
|
}
|
|
6254
6388
|
renderAttributes(element) {
|
|
6255
6389
|
const parts = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;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;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eAqI7B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -368,6 +368,8 @@ class CompileState {
|
|
|
368
368
|
nillablePropNames = new Set;
|
|
369
369
|
nullishConsumedPropNames = new Set;
|
|
370
370
|
omittableAttrConsumedPropNames = new Set;
|
|
371
|
+
textConsumedPropNames = new Set;
|
|
372
|
+
presenceCheckedPropNames = new Set;
|
|
371
373
|
stringValueNames = new Set;
|
|
372
374
|
rootScopeNodes = new Set;
|
|
373
375
|
memoBackedLoopSlice = new Map;
|
|
@@ -1111,15 +1113,28 @@ function parsedLiteralToGo(ctx, expr, typeInfo) {
|
|
|
1111
1113
|
|
|
1112
1114
|
// src/adapter/value/value-lowering.ts
|
|
1113
1115
|
var EMPTY_PROP_FALLBACK_VARS = new Map;
|
|
1116
|
+
function nillableAwarePropRef(ctx, propName, expectedType) {
|
|
1117
|
+
const fieldRef = `in.${capitalizeFieldName(propName)}`;
|
|
1118
|
+
const scalar = expectedType.kind === "primitive" ? expectedType : expectedType.kind === "union" && expectedType.unionTypes?.length === 2 ? expectedType.unionTypes.find((t) => t.primitive !== "undefined" && t.primitive !== "null") : undefined;
|
|
1119
|
+
if (ctx.state.nillablePropNames.has(propName) && scalar?.kind === "primitive") {
|
|
1120
|
+
const goType = scalar.primitive === "boolean" ? "bool" : scalar.primitive === "number" ? "float64" : scalar.primitive === "string" ? "string" : null;
|
|
1121
|
+
if (goType) {
|
|
1122
|
+
const zero = goType === "bool" ? "false" : goType === "string" ? '""' : "0";
|
|
1123
|
+
return `func() ${goType} { if v, ok := ${fieldRef}.(${goType}); ok { return v }; return ${zero} }()`;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return fieldRef;
|
|
1127
|
+
}
|
|
1114
1128
|
function convertInitialValue(ctx, value, typeInfo, propsParams, preParsed) {
|
|
1129
|
+
const propRef = (propName2) => nillableAwarePropRef(ctx, propName2, typeInfo);
|
|
1115
1130
|
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
|
|
1116
1131
|
if (propsParams?.some((p) => p.name === value)) {
|
|
1117
|
-
return
|
|
1132
|
+
return propRef(value);
|
|
1118
1133
|
}
|
|
1119
1134
|
}
|
|
1120
1135
|
const propName = ctx.extractPropNameFromInitialValue(value, preParsed);
|
|
1121
1136
|
if (propName && propsParams?.some((p) => p.name === propName)) {
|
|
1122
|
-
return
|
|
1137
|
+
return propRef(propName);
|
|
1123
1138
|
}
|
|
1124
1139
|
if (typeInfo.kind === "primitive") {
|
|
1125
1140
|
if (typeInfo.primitive === "boolean") {
|
|
@@ -1186,19 +1201,20 @@ function objectLiteralToGoMap(ctx, expr) {
|
|
|
1186
1201
|
return null;
|
|
1187
1202
|
return `map[string]interface{}{${entries.join(", ")}}`;
|
|
1188
1203
|
}
|
|
1189
|
-
function getSignalInitialValueAsGo(ctx, initialValue, propsParams, propFallbackVars = EMPTY_PROP_FALLBACK_VARS) {
|
|
1204
|
+
function getSignalInitialValueAsGo(ctx, initialValue, propsParams, propFallbackVars = EMPTY_PROP_FALLBACK_VARS, signalType) {
|
|
1205
|
+
const propRef = (propName2) => signalType ? nillableAwarePropRef(ctx, propName2, signalType) : `in.${capitalizeFieldName(propName2)}`;
|
|
1190
1206
|
if (propsParams.some((p) => p.name === initialValue)) {
|
|
1191
1207
|
const hoisted = propFallbackVars.get(initialValue);
|
|
1192
1208
|
if (hoisted)
|
|
1193
1209
|
return hoisted.varName;
|
|
1194
|
-
return
|
|
1210
|
+
return propRef(initialValue);
|
|
1195
1211
|
}
|
|
1196
1212
|
const propName = ctx.extractPropNameFromInitialValue(initialValue);
|
|
1197
1213
|
if (propName && propsParams.some((p) => p.name === propName)) {
|
|
1198
1214
|
const hoisted = propFallbackVars.get(propName);
|
|
1199
1215
|
if (hoisted)
|
|
1200
1216
|
return hoisted.varName;
|
|
1201
|
-
return
|
|
1217
|
+
return propRef(propName);
|
|
1202
1218
|
}
|
|
1203
1219
|
if (/^-?\d+$/.test(initialValue)) {
|
|
1204
1220
|
return initialValue;
|
|
@@ -1668,9 +1684,34 @@ var EMPTY_PROP_FALLBACK_VARS2 = new Map;
|
|
|
1668
1684
|
function getterCallName(e) {
|
|
1669
1685
|
return e.kind === "call" && e.callee.kind === "identifier" && e.args.length === 0 ? e.callee.name : null;
|
|
1670
1686
|
}
|
|
1687
|
+
function isBooleanTypeInfo(t) {
|
|
1688
|
+
if (t.kind === "primitive")
|
|
1689
|
+
return t.primitive === "boolean";
|
|
1690
|
+
if (t.kind === "union" && t.unionTypes?.length === 2) {
|
|
1691
|
+
const scalar = t.unionTypes.find((u) => u.primitive !== "undefined" && u.primitive !== "null");
|
|
1692
|
+
return scalar?.kind === "primitive" && scalar.primitive === "boolean";
|
|
1693
|
+
}
|
|
1694
|
+
return false;
|
|
1695
|
+
}
|
|
1696
|
+
function isBooleanTypedGetter(ctx, name, signals) {
|
|
1697
|
+
const signal = signals.find((s) => s.getter === name);
|
|
1698
|
+
if (signal)
|
|
1699
|
+
return signal.type !== undefined && isBooleanTypeInfo(signal.type);
|
|
1700
|
+
const memo = (ctx.state.currentMemos ?? []).find((m) => m.name === name);
|
|
1701
|
+
return memo?.type !== undefined && isBooleanTypeInfo(memo.type);
|
|
1702
|
+
}
|
|
1671
1703
|
function propsMemberName(e) {
|
|
1672
1704
|
return e.kind === "member" && !e.computed && e.object.kind === "identifier" && e.object.name === "props" ? e.property : null;
|
|
1673
1705
|
}
|
|
1706
|
+
function propNameForPropsBinding(ctx, e) {
|
|
1707
|
+
const propsObject = ctx.state.propsObjectName;
|
|
1708
|
+
if (e.kind === "member" && !e.computed && e.object.kind === "identifier" && e.object.name === propsObject) {
|
|
1709
|
+
return e.property;
|
|
1710
|
+
}
|
|
1711
|
+
if (!propsObject && e.kind === "identifier")
|
|
1712
|
+
return e.name;
|
|
1713
|
+
return null;
|
|
1714
|
+
}
|
|
1674
1715
|
function matchFilterArmMemo(ctx, body, signals, propsParams) {
|
|
1675
1716
|
const cb = asCallbackMethodCall2(body);
|
|
1676
1717
|
if (!cb || cb.method !== "filter")
|
|
@@ -1809,6 +1850,17 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
|
|
|
1809
1850
|
if (propName)
|
|
1810
1851
|
return propRef(propName);
|
|
1811
1852
|
}
|
|
1853
|
+
if (body.kind === "binary" && (body.op === "!==" || body.op === "!=" || body.op === "===" || body.op === "==")) {
|
|
1854
|
+
const other = body.right.kind === "identifier" && body.right.name === "undefined" ? body.left : body.left.kind === "identifier" && body.left.name === "undefined" ? body.right : null;
|
|
1855
|
+
const propName = other ? propNameForPropsBinding(ctx, other) : null;
|
|
1856
|
+
if (propName) {
|
|
1857
|
+
const param = propsParams.find((p) => p.name === propName);
|
|
1858
|
+
if (param && ctx.state.nillablePropNames.has(propName)) {
|
|
1859
|
+
const isNe = body.op === "!==" || body.op === "!=";
|
|
1860
|
+
return `in.${capitalizeFieldName(propName)} ${isNe ? "!=" : "=="} nil`;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1812
1864
|
if (body.kind === "conditional") {
|
|
1813
1865
|
const condName = getterCallName(body.test);
|
|
1814
1866
|
if (condName) {
|
|
@@ -1843,6 +1895,18 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
|
|
|
1843
1895
|
}
|
|
1844
1896
|
}
|
|
1845
1897
|
}
|
|
1898
|
+
if (condName) {
|
|
1899
|
+
const tName = getterCallName(body.consequent);
|
|
1900
|
+
const fName = getterCallName(body.alternate);
|
|
1901
|
+
if (tName && fName && isBooleanTypedGetter(ctx, tName, signals) && isBooleanTypedGetter(ctx, fName, signals)) {
|
|
1902
|
+
const condGo = resolveGetterValueAsGo(ctx, condName, signals, propsParams, propFallbackVars, resolving);
|
|
1903
|
+
const tGo = resolveGetterValueAsGo(ctx, tName, signals, propsParams, propFallbackVars, resolving);
|
|
1904
|
+
const fGo = resolveGetterValueAsGo(ctx, fName, signals, propsParams, propFallbackVars, resolving);
|
|
1905
|
+
if (condGo !== null && tGo !== null && fGo !== null) {
|
|
1906
|
+
return `func() bool { if ${condGo} { return ${tGo} }; return ${fGo} }()`;
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1846
1910
|
}
|
|
1847
1911
|
if (body.kind === "binary" && ["*", "+", "-", "/"].includes(body.op) && body.right.kind === "literal" && body.right.literalType === "number" && typeof body.right.value === "number" && Number.isInteger(body.right.value) && body.right.value >= 0) {
|
|
1848
1912
|
const operator = body.op;
|
|
@@ -1931,7 +1995,7 @@ function computeMemoInitialValueOrNull(ctx, memo, signals, propsParams, propFall
|
|
|
1931
1995
|
function resolveGetterValueAsGo(ctx, name, signals, propsParams, propFallbackVars, resolving = new Set) {
|
|
1932
1996
|
const signal = signals.find((s) => s.getter === name);
|
|
1933
1997
|
if (signal) {
|
|
1934
|
-
return getSignalInitialValueAsGo(ctx, signal.initialValue, propsParams, propFallbackVars);
|
|
1998
|
+
return getSignalInitialValueAsGo(ctx, signal.initialValue, propsParams, propFallbackVars, signal.type);
|
|
1935
1999
|
}
|
|
1936
2000
|
const memo = (ctx.state.currentMemos ?? []).find((m) => m.name === name);
|
|
1937
2001
|
if (memo) {
|
|
@@ -2333,8 +2397,10 @@ function collectNullishConsumedPropNames(ctx, ir) {
|
|
|
2333
2397
|
const propNameOfLeft = (left) => {
|
|
2334
2398
|
if (left.kind === "identifier")
|
|
2335
2399
|
return left.name;
|
|
2336
|
-
if (left.kind === "member" && !left.computed && left.object.kind === "identifier"
|
|
2337
|
-
|
|
2400
|
+
if (left.kind === "member" && !left.computed && left.object.kind === "identifier") {
|
|
2401
|
+
if (left.object.name === propsObject)
|
|
2402
|
+
return left.property;
|
|
2403
|
+
return left.object.name;
|
|
2338
2404
|
}
|
|
2339
2405
|
return null;
|
|
2340
2406
|
};
|
|
@@ -2405,12 +2471,60 @@ function collectOmittableAttrConsumedPropNames(ctx, ir) {
|
|
|
2405
2471
|
walk(ir.root);
|
|
2406
2472
|
return names;
|
|
2407
2473
|
}
|
|
2474
|
+
function collectTextConsumedPropNames(ctx, ir) {
|
|
2475
|
+
const names = new Set;
|
|
2476
|
+
const optionalParams = new Set(ir.metadata.propsParams.filter((p) => p.optional && p.defaultValue == null && p.type.kind === "primitive").map((p) => p.name));
|
|
2477
|
+
if (optionalParams.size === 0)
|
|
2478
|
+
return names;
|
|
2479
|
+
const propsObject = ctx.state.propsObjectName;
|
|
2480
|
+
const walk = (node) => {
|
|
2481
|
+
if (!node || typeof node !== "object")
|
|
2482
|
+
return;
|
|
2483
|
+
if (Array.isArray(node)) {
|
|
2484
|
+
for (const item of node)
|
|
2485
|
+
walk(item);
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
const rec = node;
|
|
2489
|
+
if (rec.type === "expression") {
|
|
2490
|
+
const bareId = String(rec.expr ?? "").trim();
|
|
2491
|
+
const propName = propsObject && bareId.startsWith(`${propsObject}.`) ? bareId.slice(propsObject.length + 1) : bareId;
|
|
2492
|
+
if (/^[A-Za-z_$][\w$]*$/.test(propName) && optionalParams.has(propName)) {
|
|
2493
|
+
names.add(propName);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
for (const value of Object.values(rec))
|
|
2497
|
+
walk(value);
|
|
2498
|
+
};
|
|
2499
|
+
walk(ir.root);
|
|
2500
|
+
return names;
|
|
2501
|
+
}
|
|
2502
|
+
function collectPresenceCheckedPropNames(ctx, ir) {
|
|
2503
|
+
const names = new Set;
|
|
2504
|
+
const optionalParams = new Set(ir.metadata.propsParams.filter((p) => p.optional && p.defaultValue == null && p.type.kind === "primitive").map((p) => p.name));
|
|
2505
|
+
if (optionalParams.size === 0)
|
|
2506
|
+
return names;
|
|
2507
|
+
const propsObject = ctx.state.propsObjectName;
|
|
2508
|
+
const isUndefinedCheck = (op) => op === "!==" || op === "!=" || op === "===" || op === "==";
|
|
2509
|
+
for (const memo of ir.metadata.memos) {
|
|
2510
|
+
const body = memo.parsed;
|
|
2511
|
+
if (!body || body.kind !== "binary" || !isUndefinedCheck(body.op))
|
|
2512
|
+
continue;
|
|
2513
|
+
const other = body.right.kind === "identifier" && body.right.name === "undefined" ? body.left : body.left.kind === "identifier" && body.left.name === "undefined" ? body.right : null;
|
|
2514
|
+
if (!other)
|
|
2515
|
+
continue;
|
|
2516
|
+
const propName = other.kind === "member" && !other.computed && other.object.kind === "identifier" && other.object.name === propsObject ? other.property : !propsObject && other.kind === "identifier" ? other.name : null;
|
|
2517
|
+
if (propName && optionalParams.has(propName))
|
|
2518
|
+
names.add(propName);
|
|
2519
|
+
}
|
|
2520
|
+
return names;
|
|
2521
|
+
}
|
|
2408
2522
|
function resolvePropGoType(ctx, param, propTypeOverrides) {
|
|
2409
2523
|
const base = propTypeOverrides.get(param.name) ?? typeInfoToGo(ctx, param.type, param.defaultValue);
|
|
2410
2524
|
if (param.optional && ctx.state.localStructFields.has(base)) {
|
|
2411
2525
|
return "map[string]interface{}";
|
|
2412
2526
|
}
|
|
2413
|
-
if (param.optional && param.type.kind === "primitive" && (ctx.state.nullishConsumedPropNames.has(param.name) || ctx.state.omittableAttrConsumedPropNames.has(param.name)) && NULLISH_SCALAR_GO_TYPES.has(base)) {
|
|
2527
|
+
if (param.optional && param.type.kind === "primitive" && (ctx.state.nullishConsumedPropNames.has(param.name) || ctx.state.omittableAttrConsumedPropNames.has(param.name) || ctx.state.textConsumedPropNames.has(param.name) || ctx.state.presenceCheckedPropNames.has(param.name)) && NULLISH_SCALAR_GO_TYPES.has(base)) {
|
|
2414
2528
|
return "interface{}";
|
|
2415
2529
|
}
|
|
2416
2530
|
return base;
|
|
@@ -2547,6 +2661,8 @@ class GoTemplateAdapter extends BaseAdapter {
|
|
|
2547
2661
|
this.buildLocalTypeTables(ir, ir.metadata.componentName);
|
|
2548
2662
|
this.state.nullishConsumedPropNames = collectNullishConsumedPropNames(this.emitCtx, ir);
|
|
2549
2663
|
this.state.omittableAttrConsumedPropNames = collectOmittableAttrConsumedPropNames(this.emitCtx, ir);
|
|
2664
|
+
this.state.textConsumedPropNames = collectTextConsumedPropNames(this.emitCtx, ir);
|
|
2665
|
+
this.state.presenceCheckedPropNames = collectPresenceCheckedPropNames(this.emitCtx, ir);
|
|
2550
2666
|
this.state.nillablePropNames = collectNillablePropNames(this.emitCtx, ir);
|
|
2551
2667
|
}
|
|
2552
2668
|
generate(ir, options) {
|
|
@@ -4229,10 +4345,22 @@ ${goFields.join(`
|
|
|
4229
4345
|
}
|
|
4230
4346
|
return goExpr;
|
|
4231
4347
|
}
|
|
4348
|
+
const finalExpr = this.textNillablePropNameOf(classify.parsed) !== null ? `bf_string ${wrapIfMultiToken(goExpr)}` : goExpr;
|
|
4232
4349
|
if (expr.slotId) {
|
|
4233
|
-
return `{{bfTextStart "${expr.slotId}"}}{{${
|
|
4350
|
+
return `{{bfTextStart "${expr.slotId}"}}{{${finalExpr}}}{{bfTextEnd}}`;
|
|
4234
4351
|
}
|
|
4235
|
-
return `{{${
|
|
4352
|
+
return `{{${finalExpr}}}`;
|
|
4353
|
+
}
|
|
4354
|
+
textNillablePropNameOf(expr) {
|
|
4355
|
+
if (!expr)
|
|
4356
|
+
return null;
|
|
4357
|
+
let name = null;
|
|
4358
|
+
if (expr.kind === "identifier") {
|
|
4359
|
+
name = expr.name;
|
|
4360
|
+
} else if (expr.kind === "member" && !expr.computed && expr.object.kind === "identifier" && expr.object.name === this.state.propsObjectName) {
|
|
4361
|
+
name = expr.property;
|
|
4362
|
+
}
|
|
4363
|
+
return name !== null && this.state.textConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
4236
4364
|
}
|
|
4237
4365
|
isTemplateFragment(go, kind) {
|
|
4238
4366
|
return go.startsWith("{{") || kind === "template-literal";
|
|
@@ -4448,7 +4576,7 @@ ${goFields.join(`
|
|
|
4448
4576
|
}
|
|
4449
4577
|
const obj = emit(object);
|
|
4450
4578
|
if (property === "length")
|
|
4451
|
-
return `
|
|
4579
|
+
return `bf_length ${wrapIfMultiToken(obj)}`;
|
|
4452
4580
|
if (optional) {
|
|
4453
4581
|
return `bf_get ${wrapIfMultiToken(obj)} ${JSON.stringify(goFieldNameForKey(property))}`;
|
|
4454
4582
|
}
|
|
@@ -4526,8 +4654,12 @@ ${goFields.join(`
|
|
|
4526
4654
|
let name = null;
|
|
4527
4655
|
if (expr.kind === "identifier") {
|
|
4528
4656
|
name = expr.name;
|
|
4529
|
-
} else if (expr.kind === "member" && !expr.computed && expr.object.kind === "identifier"
|
|
4530
|
-
name
|
|
4657
|
+
} else if (expr.kind === "member" && !expr.computed && expr.object.kind === "identifier") {
|
|
4658
|
+
if (expr.object.name === this.state.propsObjectName) {
|
|
4659
|
+
name = expr.property;
|
|
4660
|
+
} else {
|
|
4661
|
+
name = expr.object.name;
|
|
4662
|
+
}
|
|
4531
4663
|
}
|
|
4532
4664
|
return name !== null && this.state.nullishConsumedPropNames.has(name) && this.state.nillablePropNames.has(name) ? name : null;
|
|
4533
4665
|
}
|
|
@@ -4962,9 +5094,6 @@ ${goFields.join(`
|
|
|
4962
5094
|
renderPredicateCondition(pred, param, datumField) {
|
|
4963
5095
|
return this.renderFilterExpr(pred, param, new Map, datumField ?? undefined);
|
|
4964
5096
|
}
|
|
4965
|
-
needsParens(expr) {
|
|
4966
|
-
return expr.kind === "logical" || expr.kind === "unary" || expr.kind === "conditional";
|
|
4967
|
-
}
|
|
4968
5097
|
splitPreamble(rendered) {
|
|
4969
5098
|
if (!rendered.includes("{{"))
|
|
4970
5099
|
return null;
|
|
@@ -5377,7 +5506,8 @@ ${goFields.join(`
|
|
|
5377
5506
|
return plain(this.rootFieldRef(expr.callee.name));
|
|
5378
5507
|
}
|
|
5379
5508
|
if (expr.callee.kind === "identifier" && (identifierPath(expr.callee) ?? expr.callee.name) === "isValidElement" && expr.args.length === 1) {
|
|
5380
|
-
|
|
5509
|
+
const inner = this.renderConditionExpr(expr.args[0]);
|
|
5510
|
+
return { preamble: inner.preamble, expr: `(bf_is_element ${wrapIfMultiToken(inner.expr)})` };
|
|
5381
5511
|
}
|
|
5382
5512
|
if (expr.callee.kind === "identifier" && !this.templatePrimitives[identifierPath(expr.callee) ?? ""]) {
|
|
5383
5513
|
const path = identifierPath(expr.callee) ?? expr.callee.name;
|
|
@@ -5494,9 +5624,9 @@ ${goFields.join(`
|
|
|
5494
5624
|
const leftResult = this.renderConditionExpr(expr.left);
|
|
5495
5625
|
const rightResult = this.renderConditionExpr(expr.right);
|
|
5496
5626
|
const preamble = leftResult.preamble + rightResult.preamble;
|
|
5497
|
-
const wrapLeft =
|
|
5498
|
-
const wrapRight =
|
|
5499
|
-
const result = expr.op === "&&" ? `and ${wrapLeft} ${wrapRight}` : `or ${wrapLeft} ${wrapRight}`;
|
|
5627
|
+
const wrapLeft = wrapIfMultiToken(leftResult.expr);
|
|
5628
|
+
const wrapRight = wrapIfMultiToken(rightResult.expr);
|
|
5629
|
+
const result = expr.op === "&&" ? `and ${wrapLeft} ${wrapRight}` : expr.op === "??" && this.nillablePropNameOf(expr.left) !== null ? `bf_nullish ${wrapLeft} ${wrapRight}` : `or ${wrapLeft} ${wrapRight}`;
|
|
5500
5630
|
return { preamble, expr: result };
|
|
5501
5631
|
}
|
|
5502
5632
|
case "conditional": {
|
|
@@ -5909,7 +6039,11 @@ ${children}`;
|
|
|
5909
6039
|
if (e.kind === "expr" && !isSupported(parseExpression4(e.expr)).supported)
|
|
5910
6040
|
return null;
|
|
5911
6041
|
}
|
|
5912
|
-
|
|
6042
|
+
const args = entries.flatMap((e) => [
|
|
6043
|
+
JSON.stringify(e.cssKey),
|
|
6044
|
+
e.kind === "literal" ? JSON.stringify(e.value) : wrapIfMultiToken(this.convertExpressionToGo(e.expr))
|
|
6045
|
+
]);
|
|
6046
|
+
return `{{bf_style_object ${args.join(" ")}}}`;
|
|
5913
6047
|
}
|
|
5914
6048
|
renderAttributes(element) {
|
|
5915
6049
|
const parts = [];
|
|
@@ -6032,7 +6166,8 @@ var conformancePins = {
|
|
|
6032
6166
|
"filter-nested-find-predicate": [
|
|
6033
6167
|
{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2038" }
|
|
6034
6168
|
],
|
|
6035
|
-
"dangerous-inner-html-dynamic": [{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2215" }]
|
|
6169
|
+
"dangerous-inner-html-dynamic": [{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2215" }],
|
|
6170
|
+
"date-method-uncatalogued": [{ code: "BF021", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2274" }]
|
|
6036
6171
|
};
|
|
6037
6172
|
// src/render-divergences.ts
|
|
6038
6173
|
var renderDivergences = {};
|