@barefootjs/go-template 0.31.9 → 0.32.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/emit-context.d.ts +16 -0
- package/dist/adapter/emit-context.d.ts.map +1 -1
- package/dist/adapter/go-template-adapter.d.ts +82 -0
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +119 -9
- package/dist/adapter/lib/compile-state.d.ts +28 -1
- package/dist/adapter/lib/compile-state.d.ts.map +1 -1
- package/dist/adapter/lib/types.d.ts +13 -0
- package/dist/adapter/lib/types.d.ts.map +1 -1
- package/dist/adapter/props/prop-types.d.ts.map +1 -1
- package/dist/index.js +119 -9
- package/dist/render-divergences.d.ts +3 -3
- package/dist/vite.js +154 -11
- package/package.json +5 -5
- package/src/__tests__/go-template-adapter.test.ts +345 -8
- package/src/adapter/emit-context.ts +14 -0
- package/src/adapter/go-template-adapter.ts +330 -10
- package/src/adapter/lib/compile-state.ts +34 -0
- package/src/adapter/lib/types.ts +10 -0
- package/src/adapter/props/prop-types.ts +32 -1
- package/src/render-divergences.ts +3 -3
- package/src/test-render.ts +18 -1
package/dist/index.js
CHANGED
|
@@ -361,6 +361,10 @@ class CompileState {
|
|
|
361
361
|
synthObjectStructNames = new Map;
|
|
362
362
|
needsStringsImport = false;
|
|
363
363
|
}
|
|
364
|
+
function resolveSignalParsedThroughSeedPlan(state, signal) {
|
|
365
|
+
const step = state.ssrSeedPlan.steps.find((s) => s.kind === "derived" && s.origin === "signal" && s.name === signal.getter);
|
|
366
|
+
return step?.kind === "derived" ? step.parsed : signal.parsed;
|
|
367
|
+
}
|
|
364
368
|
|
|
365
369
|
// src/adapter/analysis/component-tree.ts
|
|
366
370
|
function hasClientInteractivity(ir) {
|
|
@@ -2673,7 +2677,18 @@ function collectNullishConsumedPropNames(ctx, ir) {
|
|
|
2673
2677
|
};
|
|
2674
2678
|
walk(ir.root);
|
|
2675
2679
|
for (const signal of ir.metadata.signals) {
|
|
2676
|
-
const
|
|
2680
|
+
const resolvedParsed = resolveSignalParsedThroughSeedPlan(ctx.state, signal);
|
|
2681
|
+
let match = ctx.extractPropFallback(signal.initialValue, resolvedParsed);
|
|
2682
|
+
if (!match) {
|
|
2683
|
+
const collision = ctx.extractCollisionDerivation(resolvedParsed);
|
|
2684
|
+
if (collision) {
|
|
2685
|
+
const collisionParam = ir.metadata.propsParams.find((p) => p.name === collision.propName);
|
|
2686
|
+
const collisionField = collisionParam ? capitalizeFieldName(collisionParam.sourceName ?? collision.propName) : null;
|
|
2687
|
+
if (collisionField && capitalizeFieldName(signal.getter) === collisionField) {
|
|
2688
|
+
match = { propName: collision.propName, goFallback: collision.goFallback };
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2677
2692
|
if (!match || !optionalParams.has(match.propName))
|
|
2678
2693
|
continue;
|
|
2679
2694
|
const f = match.goFallback;
|
|
@@ -2859,6 +2874,7 @@ class GoTemplateAdapter extends BaseAdapter {
|
|
|
2859
2874
|
convertConditionToGo: (jsCondition, preParsed) => this.convertConditionToGo(jsCondition, preParsed),
|
|
2860
2875
|
extractPropNameFromInitialValue: (initialValue, preParsed) => this.extractPropNameFromInitialValue(initialValue, preParsed),
|
|
2861
2876
|
extractPropFallback: (initialValue, preParsed) => this.extractPropFallback(initialValue, preParsed),
|
|
2877
|
+
extractCollisionDerivation: (parsed) => this.extractCollisionDerivation(parsed),
|
|
2862
2878
|
resolveModuleStringConst: (name) => this.resolveModuleStringConst(name)
|
|
2863
2879
|
};
|
|
2864
2880
|
get errors() {
|
|
@@ -3637,6 +3653,7 @@ ${goFields.join(`
|
|
|
3637
3653
|
}
|
|
3638
3654
|
lines.push("");
|
|
3639
3655
|
}
|
|
3656
|
+
this.emitCallerPropsInit(lines, ir, nestedComponents, staticWithoutBody, staticWithBody, dynamicWithBody, emittedWrapperVars, propTypeOverrides);
|
|
3640
3657
|
lines.push(` return ${propsTypeName}{`);
|
|
3641
3658
|
lines.push("\t\tScopeID: scopeID,");
|
|
3642
3659
|
lines.push("\t\tBfParent: in.BfParent,");
|
|
@@ -3644,6 +3661,7 @@ ${goFields.join(`
|
|
|
3644
3661
|
if (this.usesSearchParams(ir)) {
|
|
3645
3662
|
lines.push("\t\tSearchParams: in.SearchParams,");
|
|
3646
3663
|
}
|
|
3664
|
+
lines.push("\t\tBfCallerProps: bfCallerProps,");
|
|
3647
3665
|
const nestedArrayFields = this.propDerivedNestedArrayFields(nestedComponents);
|
|
3648
3666
|
const memoFallbacks = new Map;
|
|
3649
3667
|
for (const memo of ir.metadata.memos) {
|
|
@@ -3669,7 +3687,8 @@ ${goFields.join(`
|
|
|
3669
3687
|
continue;
|
|
3670
3688
|
const hoisted = propFallbackVars.get(param.name);
|
|
3671
3689
|
if (hoisted) {
|
|
3672
|
-
|
|
3690
|
+
const value = hoisted.collisionWrap ? `${hoisted.varName} ${hoisted.collisionWrap.operator} ${hoisted.collisionWrap.operand}` : hoisted.varName;
|
|
3691
|
+
lines.push(` ${fieldName}: ${value},`);
|
|
3673
3692
|
} else {
|
|
3674
3693
|
const paramDefault = goPropDefault(param.defaultValue);
|
|
3675
3694
|
const memoFold = memoFallbacks.get(fieldName);
|
|
@@ -3691,7 +3710,7 @@ ${goFields.join(`
|
|
|
3691
3710
|
const fieldName = capitalizeFieldName(signal.getter);
|
|
3692
3711
|
if (propFieldNames.has(fieldName))
|
|
3693
3712
|
continue;
|
|
3694
|
-
const fallbackMatch = this.extractPropFallback(signal.initialValue, signal
|
|
3713
|
+
const fallbackMatch = this.extractPropFallback(signal.initialValue, this.resolvedSignalParsed(signal));
|
|
3695
3714
|
const hoisted = fallbackMatch ? propFallbackVars.get(fallbackMatch.propName) : undefined;
|
|
3696
3715
|
if (hoisted) {
|
|
3697
3716
|
lines.push(` ${fieldName}: ${hoisted.varName},`);
|
|
@@ -3748,6 +3767,53 @@ ${goFields.join(`
|
|
|
3748
3767
|
lines.push("\t}");
|
|
3749
3768
|
lines.push("}");
|
|
3750
3769
|
}
|
|
3770
|
+
emitCallerPropsInit(lines, ir, nestedComponents, staticWithoutBody, staticWithBody, dynamicWithBody, emittedWrapperVars, propTypeOverrides) {
|
|
3771
|
+
lines.push("\tbfCallerProps := map[string]interface{}{}");
|
|
3772
|
+
const bfCallerPropsTakenTags = new Set;
|
|
3773
|
+
const nestedArrayFields = this.propDerivedNestedArrayFields(nestedComponents);
|
|
3774
|
+
for (const param of ir.metadata.propsParams) {
|
|
3775
|
+
if (param.name === "children")
|
|
3776
|
+
continue;
|
|
3777
|
+
if (this.isNestedArrayShadowed(param, nestedArrayFields))
|
|
3778
|
+
continue;
|
|
3779
|
+
const callerKey = this.claimJsonTag(this.toJsonTag(param.sourceName ?? param.name), bfCallerPropsTakenTags);
|
|
3780
|
+
if (callerKey === "-")
|
|
3781
|
+
continue;
|
|
3782
|
+
const inputField = `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
|
|
3783
|
+
const goType = resolvePropGoType(this.emitCtx, param, propTypeOverrides);
|
|
3784
|
+
const isNillable = goType === "interface{}" || goType === "map[string]interface{}" || goType.startsWith("[]");
|
|
3785
|
+
if (param.optional && isNillable) {
|
|
3786
|
+
lines.push(` if ${inputField} != nil {`);
|
|
3787
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${inputField}`);
|
|
3788
|
+
lines.push(` }`);
|
|
3789
|
+
} else {
|
|
3790
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${inputField}`);
|
|
3791
|
+
}
|
|
3792
|
+
}
|
|
3793
|
+
for (const nested of [...staticWithoutBody, ...staticWithBody, ...dynamicWithBody]) {
|
|
3794
|
+
if (!nested.isPropDerived)
|
|
3795
|
+
continue;
|
|
3796
|
+
const varName = `${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`;
|
|
3797
|
+
const isBuilt = staticWithoutBody.includes(nested) || emittedWrapperVars.has(varName);
|
|
3798
|
+
if (!isBuilt)
|
|
3799
|
+
continue;
|
|
3800
|
+
const arrayFieldName = capitalizeFieldName(`${nested.name}s`);
|
|
3801
|
+
const param = ir.metadata.propsParams.find((p) => capitalizeFieldName(p.name) === arrayFieldName || capitalizeFieldName(p.sourceName ?? p.name) === arrayFieldName);
|
|
3802
|
+
if (!param || !this.isNestedArrayShadowed(param, nestedArrayFields))
|
|
3803
|
+
continue;
|
|
3804
|
+
const callerKey = this.claimJsonTag(this.toJsonTag(param.sourceName ?? param.name), bfCallerPropsTakenTags);
|
|
3805
|
+
if (callerKey === "-")
|
|
3806
|
+
continue;
|
|
3807
|
+
if (param.optional) {
|
|
3808
|
+
lines.push(` if in.${nested.name}s != nil {`);
|
|
3809
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${varName}`);
|
|
3810
|
+
lines.push(` }`);
|
|
3811
|
+
} else {
|
|
3812
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${varName}`);
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
lines.push("");
|
|
3816
|
+
}
|
|
3751
3817
|
emitStaticChildInstances(lines, ir) {
|
|
3752
3818
|
const staticChildren = this.collectStaticChildInstances(ir.root, ir.metadata.propsParams);
|
|
3753
3819
|
for (const child of staticChildren) {
|
|
@@ -4199,6 +4265,7 @@ ${goFields.join(`
|
|
|
4199
4265
|
if (this.usesSearchParams(ir)) {
|
|
4200
4266
|
lines.push('\tSearchParams bf.SearchParams `json:"-"`');
|
|
4201
4267
|
}
|
|
4268
|
+
lines.push('\tBfCallerProps map[string]interface{} `json:"-"`');
|
|
4202
4269
|
}
|
|
4203
4270
|
emitPropsDataFields(lines, ir, nestedComponents, propTypeOverrides, takenJsonTags) {
|
|
4204
4271
|
const nestedArrayFields = this.propDerivedNestedArrayFields(nestedComponents);
|
|
@@ -4219,7 +4286,7 @@ ${goFields.join(`
|
|
|
4219
4286
|
const fieldName = capitalizeFieldName(signal.getter);
|
|
4220
4287
|
if (propFieldNames.has(fieldName))
|
|
4221
4288
|
continue;
|
|
4222
|
-
const jsonTag =
|
|
4289
|
+
const jsonTag = "-";
|
|
4223
4290
|
const synthType = this.state.synthStructTypes.get(signal.getter);
|
|
4224
4291
|
if (synthType) {
|
|
4225
4292
|
lines.push(` ${fieldName} ${typeInfoToGo(this.emitCtx, synthType)} \`json:"${jsonTag}"\``);
|
|
@@ -4251,7 +4318,7 @@ ${goFields.join(`
|
|
|
4251
4318
|
const fieldName = capitalizeFieldName(memo.name);
|
|
4252
4319
|
if (propFieldNames.has(fieldName))
|
|
4253
4320
|
continue;
|
|
4254
|
-
const jsonTag =
|
|
4321
|
+
const jsonTag = "-";
|
|
4255
4322
|
const goType = this.inferMemoType(memo, ir.metadata.signals, propsParamMap);
|
|
4256
4323
|
lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
|
|
4257
4324
|
}
|
|
@@ -4271,15 +4338,22 @@ ${goFields.join(`
|
|
|
4271
4338
|
...ir.metadata.memos.map((m) => capitalizeFieldName(m.name))
|
|
4272
4339
|
]);
|
|
4273
4340
|
for (const c of this.nonCollidingContextConsumers(takenProps)) {
|
|
4274
|
-
const jsonTag =
|
|
4341
|
+
const jsonTag = "-";
|
|
4275
4342
|
lines.push(` ${this.contextFieldName(c)} ${this.contextConsumerGoType(c)} \`json:"${jsonTag}"\``);
|
|
4276
4343
|
}
|
|
4344
|
+
const propDrivingFieldNames = new Set;
|
|
4345
|
+
for (const p of ir.metadata.propsParams) {
|
|
4346
|
+
propDrivingFieldNames.add(capitalizeFieldName(p.name));
|
|
4347
|
+
propDrivingFieldNames.add(capitalizeFieldName(p.sourceName ?? p.name));
|
|
4348
|
+
}
|
|
4277
4349
|
for (const nested of nestedComponents) {
|
|
4278
4350
|
if (this.isOrphanedClientOnlyNested(nested))
|
|
4279
4351
|
continue;
|
|
4280
4352
|
const elemType = nested.bodyChildren?.length ? this.loopBodyWrapperName(componentName, nested) : `${nested.name}Props`;
|
|
4281
4353
|
if (nested.isDynamic && !nested.isPropDerived) {
|
|
4282
4354
|
lines.push(` ${nested.name}s []${elemType} \`json:"-"\``);
|
|
4355
|
+
} else if (nested.isDynamic && nested.isPropDerived && !propDrivingFieldNames.has(`${nested.name}s`)) {
|
|
4356
|
+
lines.push(` ${nested.name}s []${elemType} \`json:"-"\``);
|
|
4283
4357
|
} else {
|
|
4284
4358
|
const jsonTag = this.claimJsonTag(this.toJsonTag(`${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`), takenJsonTags);
|
|
4285
4359
|
lines.push(` ${nested.name}s []${elemType} \`json:"${jsonTag}"\``);
|
|
@@ -4290,7 +4364,7 @@ ${goFields.join(`
|
|
|
4290
4364
|
lines.push(` ${child.fieldName} ${child.name}Props \`json:"-"\``);
|
|
4291
4365
|
}
|
|
4292
4366
|
for (const slot of spreadSlots) {
|
|
4293
|
-
const jsonTag =
|
|
4367
|
+
const jsonTag = "-";
|
|
4294
4368
|
lines.push(` ${slot.slotId} map[string]any \`json:"${jsonTag}"\``);
|
|
4295
4369
|
}
|
|
4296
4370
|
}
|
|
@@ -4603,7 +4677,19 @@ ${goFields.join(`
|
|
|
4603
4677
|
}
|
|
4604
4678
|
const propTypeOverrides = buildPropTypeOverrides(this.emitCtx, ir);
|
|
4605
4679
|
for (const signal of ir.metadata.signals) {
|
|
4606
|
-
|
|
4680
|
+
let match = this.extractPropFallback(signal.initialValue, this.resolvedSignalParsed(signal));
|
|
4681
|
+
let collisionWrap;
|
|
4682
|
+
if (!match) {
|
|
4683
|
+
const collision = this.extractCollisionDerivation(this.resolvedSignalParsed(signal));
|
|
4684
|
+
if (collision) {
|
|
4685
|
+
const collisionParam = ir.metadata.propsParams.find((p) => p.name === collision.propName);
|
|
4686
|
+
const collisionField = collisionParam ? capitalizeFieldName(collisionParam.sourceName ?? collision.propName) : null;
|
|
4687
|
+
if (collisionField && capitalizeFieldName(signal.getter) === collisionField) {
|
|
4688
|
+
match = { propName: collision.propName, goFallback: collision.goFallback };
|
|
4689
|
+
collisionWrap = { operator: collision.operator, operand: collision.operand };
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
}
|
|
4607
4693
|
if (!match)
|
|
4608
4694
|
continue;
|
|
4609
4695
|
if (result.has(match.propName))
|
|
@@ -4642,11 +4728,15 @@ ${goFields.join(`
|
|
|
4642
4728
|
fieldName,
|
|
4643
4729
|
goFallback: match.goFallback,
|
|
4644
4730
|
zeroLiteral,
|
|
4645
|
-
...nullishLowered ? { assertType: concreteType } : {}
|
|
4731
|
+
...nullishLowered ? { assertType: concreteType } : {},
|
|
4732
|
+
...collisionWrap ? { collisionWrap } : {}
|
|
4646
4733
|
});
|
|
4647
4734
|
}
|
|
4648
4735
|
return result;
|
|
4649
4736
|
}
|
|
4737
|
+
resolvedSignalParsed(signal) {
|
|
4738
|
+
return resolveSignalParsedThroughSeedPlan(this.state, signal);
|
|
4739
|
+
}
|
|
4650
4740
|
extractPropFallback(initialValue, preParsed) {
|
|
4651
4741
|
const structural = preParsed ? this.extractPropFallbackFromParsed(preParsed) : null;
|
|
4652
4742
|
if (structural)
|
|
@@ -4689,6 +4779,26 @@ ${goFields.join(`
|
|
|
4689
4779
|
return null;
|
|
4690
4780
|
return { propName, goFallback };
|
|
4691
4781
|
}
|
|
4782
|
+
extractCollisionDerivation(parsed) {
|
|
4783
|
+
if (!parsed || parsed.kind !== "binary")
|
|
4784
|
+
return null;
|
|
4785
|
+
if (!["*", "+", "-", "/"].includes(parsed.op))
|
|
4786
|
+
return null;
|
|
4787
|
+
const { right } = parsed;
|
|
4788
|
+
if (right.kind !== "literal" || right.literalType !== "number" || typeof right.value !== "number" || !Number.isInteger(right.value) || right.value < 0) {
|
|
4789
|
+
return null;
|
|
4790
|
+
}
|
|
4791
|
+
if (parsed.op === "/" && right.value === 0)
|
|
4792
|
+
return null;
|
|
4793
|
+
const coalesce = parsed.left;
|
|
4794
|
+
if (coalesce.kind !== "logical" || coalesce.op !== "??" || coalesce.right.kind !== "literal" || coalesce.right.literalType !== "number") {
|
|
4795
|
+
return null;
|
|
4796
|
+
}
|
|
4797
|
+
const inner = this.extractPropFallbackFromParsed(parsed.left);
|
|
4798
|
+
if (!inner)
|
|
4799
|
+
return null;
|
|
4800
|
+
return { ...inner, operator: parsed.op, operand: String(right.value) };
|
|
4801
|
+
}
|
|
4692
4802
|
extractPropNameFromInitialValue(initialValue, preParsed) {
|
|
4693
4803
|
if (!this.state.propsObjectName) {
|
|
4694
4804
|
if (preParsed?.kind === "logical" && (preParsed.op === "??" || preParsed.op === "||") && preParsed.left.kind === "identifier") {
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
* file even when the set is empty — the next divergence lands here, not in
|
|
7
7
|
* a re-created file.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* (#2630's `static-array-from-props-with-component-precomputed` divergence
|
|
10
|
+
* graduated once the harness (`test-render.ts`'s
|
|
11
11
|
* `buildDynamicChildLoopSeeding`, despite the name — see its doc comment)
|
|
12
12
|
* learned to seed a prop-backed static child-component loop's Props slice
|
|
13
13
|
* the same way it already seeded a signal-backed dynamic one: the adapter's
|
|
14
14
|
* own `emission` was never the bug, only this harness's route-handler
|
|
15
|
-
* stand-in was missing the prop-derived case.
|
|
15
|
+
* stand-in was missing the prop-derived case.)
|
|
16
16
|
*/
|
|
17
17
|
import type { RenderDivergences } from '@barefootjs/jsx';
|
|
18
18
|
export declare const renderDivergences: RenderDivergences;
|
package/dist/vite.js
CHANGED
|
@@ -3929,6 +3929,38 @@ function classify(name, origin, expr, parsed, available) {
|
|
|
3929
3929
|
}
|
|
3930
3930
|
return { kind: "derived", name, origin, expr, parsed, frees: [...frees] };
|
|
3931
3931
|
}
|
|
3932
|
+
function localConstExprsByName(metadata) {
|
|
3933
|
+
const out = new Map;
|
|
3934
|
+
for (const c of metadata.localConstants ?? []) {
|
|
3935
|
+
if (c.isModule || c.declarationKind !== "const" || c.value === undefined)
|
|
3936
|
+
continue;
|
|
3937
|
+
out.set(c.name, c.parsed ?? parseExpression(c.value.trim()));
|
|
3938
|
+
}
|
|
3939
|
+
return out;
|
|
3940
|
+
}
|
|
3941
|
+
function resolveThroughLocalConsts(parsed, localConsts) {
|
|
3942
|
+
let current = parsed;
|
|
3943
|
+
const maxIter = localConsts.size + 1;
|
|
3944
|
+
for (let i = 0;i < maxIter; i++) {
|
|
3945
|
+
const frees = freeIdentifiers(current);
|
|
3946
|
+
if (frees === null)
|
|
3947
|
+
break;
|
|
3948
|
+
let changed = false;
|
|
3949
|
+
for (const name of frees) {
|
|
3950
|
+
const value = localConsts.get(name);
|
|
3951
|
+
if (!value)
|
|
3952
|
+
continue;
|
|
3953
|
+
const inlined = inlineBinding(current, name, value);
|
|
3954
|
+
if (inlined === null)
|
|
3955
|
+
continue;
|
|
3956
|
+
current = inlined;
|
|
3957
|
+
changed = true;
|
|
3958
|
+
}
|
|
3959
|
+
if (!changed)
|
|
3960
|
+
break;
|
|
3961
|
+
}
|
|
3962
|
+
return current;
|
|
3963
|
+
}
|
|
3932
3964
|
function computeSsrSeedPlan(metadata) {
|
|
3933
3965
|
const baseScope = metadata.propsParams.map((p) => p.name);
|
|
3934
3966
|
if (metadata.propsObjectName)
|
|
@@ -3937,6 +3969,7 @@ function computeSsrSeedPlan(metadata) {
|
|
|
3937
3969
|
baseScope.push(name);
|
|
3938
3970
|
}
|
|
3939
3971
|
const available = new Set(baseScope);
|
|
3972
|
+
const localConsts = localConstExprsByName(metadata);
|
|
3940
3973
|
const steps = [];
|
|
3941
3974
|
for (const signal of metadata.signals) {
|
|
3942
3975
|
if (signal.envReader) {
|
|
@@ -3948,13 +3981,13 @@ function computeSsrSeedPlan(metadata) {
|
|
|
3948
3981
|
}
|
|
3949
3982
|
}
|
|
3950
3983
|
const expr = signal.initialValue.trim();
|
|
3951
|
-
steps.push(expr === "" ? { kind: "opaque", name: signal.getter, origin: "signal" } : classify(signal.getter, "signal", expr, parseExpression(expr), available));
|
|
3984
|
+
steps.push(expr === "" ? { kind: "opaque", name: signal.getter, origin: "signal" } : classify(signal.getter, "signal", expr, resolveThroughLocalConsts(parseExpression(expr), localConsts), available));
|
|
3952
3985
|
available.add(signal.getter);
|
|
3953
3986
|
}
|
|
3954
3987
|
for (const memo of metadata.memos) {
|
|
3955
3988
|
const body = extractArrowBodyExpression(memo.computation);
|
|
3956
3989
|
const expr = body?.trim() ?? "";
|
|
3957
|
-
steps.push(expr === "" ? { kind: "opaque", name: memo.name, origin: "memo" } : classify(memo.name, "memo", expr, memo.parsed ?? parseExpression(expr), available));
|
|
3990
|
+
steps.push(expr === "" ? { kind: "opaque", name: memo.name, origin: "memo" } : classify(memo.name, "memo", expr, resolveThroughLocalConsts(memo.parsed ?? parseExpression(expr), localConsts), available));
|
|
3958
3991
|
available.add(memo.name);
|
|
3959
3992
|
}
|
|
3960
3993
|
return { baseScope, steps };
|
|
@@ -5458,6 +5491,10 @@ class CompileState {
|
|
|
5458
5491
|
synthObjectStructNames = new Map;
|
|
5459
5492
|
needsStringsImport = false;
|
|
5460
5493
|
}
|
|
5494
|
+
function resolveSignalParsedThroughSeedPlan(state, signal) {
|
|
5495
|
+
const step = state.ssrSeedPlan.steps.find((s) => s.kind === "derived" && s.origin === "signal" && s.name === signal.getter);
|
|
5496
|
+
return step?.kind === "derived" ? step.parsed : signal.parsed;
|
|
5497
|
+
}
|
|
5461
5498
|
|
|
5462
5499
|
// src/adapter/analysis/component-tree.ts
|
|
5463
5500
|
function hasClientInteractivity(ir) {
|
|
@@ -7740,7 +7777,18 @@ function collectNullishConsumedPropNames(ctx, ir) {
|
|
|
7740
7777
|
};
|
|
7741
7778
|
walk(ir.root);
|
|
7742
7779
|
for (const signal of ir.metadata.signals) {
|
|
7743
|
-
const
|
|
7780
|
+
const resolvedParsed = resolveSignalParsedThroughSeedPlan(ctx.state, signal);
|
|
7781
|
+
let match = ctx.extractPropFallback(signal.initialValue, resolvedParsed);
|
|
7782
|
+
if (!match) {
|
|
7783
|
+
const collision = ctx.extractCollisionDerivation(resolvedParsed);
|
|
7784
|
+
if (collision) {
|
|
7785
|
+
const collisionParam = ir.metadata.propsParams.find((p) => p.name === collision.propName);
|
|
7786
|
+
const collisionField = collisionParam ? capitalizeFieldName(collisionParam.sourceName ?? collision.propName) : null;
|
|
7787
|
+
if (collisionField && capitalizeFieldName(signal.getter) === collisionField) {
|
|
7788
|
+
match = { propName: collision.propName, goFallback: collision.goFallback };
|
|
7789
|
+
}
|
|
7790
|
+
}
|
|
7791
|
+
}
|
|
7744
7792
|
if (!match || !optionalParams.has(match.propName))
|
|
7745
7793
|
continue;
|
|
7746
7794
|
const f = match.goFallback;
|
|
@@ -7925,6 +7973,7 @@ class GoTemplateAdapter extends BaseAdapter {
|
|
|
7925
7973
|
convertConditionToGo: (jsCondition, preParsed) => this.convertConditionToGo(jsCondition, preParsed),
|
|
7926
7974
|
extractPropNameFromInitialValue: (initialValue, preParsed) => this.extractPropNameFromInitialValue(initialValue, preParsed),
|
|
7927
7975
|
extractPropFallback: (initialValue, preParsed) => this.extractPropFallback(initialValue, preParsed),
|
|
7976
|
+
extractCollisionDerivation: (parsed) => this.extractCollisionDerivation(parsed),
|
|
7928
7977
|
resolveModuleStringConst: (name) => this.resolveModuleStringConst(name)
|
|
7929
7978
|
};
|
|
7930
7979
|
get errors() {
|
|
@@ -8703,6 +8752,7 @@ ${goFields.join(`
|
|
|
8703
8752
|
}
|
|
8704
8753
|
lines.push("");
|
|
8705
8754
|
}
|
|
8755
|
+
this.emitCallerPropsInit(lines, ir, nestedComponents, staticWithoutBody, staticWithBody, dynamicWithBody, emittedWrapperVars, propTypeOverrides);
|
|
8706
8756
|
lines.push(` return ${propsTypeName}{`);
|
|
8707
8757
|
lines.push("\t\tScopeID: scopeID,");
|
|
8708
8758
|
lines.push("\t\tBfParent: in.BfParent,");
|
|
@@ -8710,6 +8760,7 @@ ${goFields.join(`
|
|
|
8710
8760
|
if (this.usesSearchParams(ir)) {
|
|
8711
8761
|
lines.push("\t\tSearchParams: in.SearchParams,");
|
|
8712
8762
|
}
|
|
8763
|
+
lines.push("\t\tBfCallerProps: bfCallerProps,");
|
|
8713
8764
|
const nestedArrayFields = this.propDerivedNestedArrayFields(nestedComponents);
|
|
8714
8765
|
const memoFallbacks = new Map;
|
|
8715
8766
|
for (const memo of ir.metadata.memos) {
|
|
@@ -8735,7 +8786,8 @@ ${goFields.join(`
|
|
|
8735
8786
|
continue;
|
|
8736
8787
|
const hoisted = propFallbackVars.get(param.name);
|
|
8737
8788
|
if (hoisted) {
|
|
8738
|
-
|
|
8789
|
+
const value = hoisted.collisionWrap ? `${hoisted.varName} ${hoisted.collisionWrap.operator} ${hoisted.collisionWrap.operand}` : hoisted.varName;
|
|
8790
|
+
lines.push(` ${fieldName}: ${value},`);
|
|
8739
8791
|
} else {
|
|
8740
8792
|
const paramDefault = goPropDefault(param.defaultValue);
|
|
8741
8793
|
const memoFold = memoFallbacks.get(fieldName);
|
|
@@ -8757,7 +8809,7 @@ ${goFields.join(`
|
|
|
8757
8809
|
const fieldName = capitalizeFieldName(signal.getter);
|
|
8758
8810
|
if (propFieldNames.has(fieldName))
|
|
8759
8811
|
continue;
|
|
8760
|
-
const fallbackMatch = this.extractPropFallback(signal.initialValue, signal
|
|
8812
|
+
const fallbackMatch = this.extractPropFallback(signal.initialValue, this.resolvedSignalParsed(signal));
|
|
8761
8813
|
const hoisted = fallbackMatch ? propFallbackVars.get(fallbackMatch.propName) : undefined;
|
|
8762
8814
|
if (hoisted) {
|
|
8763
8815
|
lines.push(` ${fieldName}: ${hoisted.varName},`);
|
|
@@ -8814,6 +8866,53 @@ ${goFields.join(`
|
|
|
8814
8866
|
lines.push("\t}");
|
|
8815
8867
|
lines.push("}");
|
|
8816
8868
|
}
|
|
8869
|
+
emitCallerPropsInit(lines, ir, nestedComponents, staticWithoutBody, staticWithBody, dynamicWithBody, emittedWrapperVars, propTypeOverrides) {
|
|
8870
|
+
lines.push("\tbfCallerProps := map[string]interface{}{}");
|
|
8871
|
+
const bfCallerPropsTakenTags = new Set;
|
|
8872
|
+
const nestedArrayFields = this.propDerivedNestedArrayFields(nestedComponents);
|
|
8873
|
+
for (const param of ir.metadata.propsParams) {
|
|
8874
|
+
if (param.name === "children")
|
|
8875
|
+
continue;
|
|
8876
|
+
if (this.isNestedArrayShadowed(param, nestedArrayFields))
|
|
8877
|
+
continue;
|
|
8878
|
+
const callerKey = this.claimJsonTag(this.toJsonTag(param.sourceName ?? param.name), bfCallerPropsTakenTags);
|
|
8879
|
+
if (callerKey === "-")
|
|
8880
|
+
continue;
|
|
8881
|
+
const inputField = `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
|
|
8882
|
+
const goType = resolvePropGoType(this.emitCtx, param, propTypeOverrides);
|
|
8883
|
+
const isNillable = goType === "interface{}" || goType === "map[string]interface{}" || goType.startsWith("[]");
|
|
8884
|
+
if (param.optional && isNillable) {
|
|
8885
|
+
lines.push(` if ${inputField} != nil {`);
|
|
8886
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${inputField}`);
|
|
8887
|
+
lines.push(` }`);
|
|
8888
|
+
} else {
|
|
8889
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${inputField}`);
|
|
8890
|
+
}
|
|
8891
|
+
}
|
|
8892
|
+
for (const nested of [...staticWithoutBody, ...staticWithBody, ...dynamicWithBody]) {
|
|
8893
|
+
if (!nested.isPropDerived)
|
|
8894
|
+
continue;
|
|
8895
|
+
const varName = `${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`;
|
|
8896
|
+
const isBuilt = staticWithoutBody.includes(nested) || emittedWrapperVars.has(varName);
|
|
8897
|
+
if (!isBuilt)
|
|
8898
|
+
continue;
|
|
8899
|
+
const arrayFieldName = capitalizeFieldName(`${nested.name}s`);
|
|
8900
|
+
const param = ir.metadata.propsParams.find((p) => capitalizeFieldName(p.name) === arrayFieldName || capitalizeFieldName(p.sourceName ?? p.name) === arrayFieldName);
|
|
8901
|
+
if (!param || !this.isNestedArrayShadowed(param, nestedArrayFields))
|
|
8902
|
+
continue;
|
|
8903
|
+
const callerKey = this.claimJsonTag(this.toJsonTag(param.sourceName ?? param.name), bfCallerPropsTakenTags);
|
|
8904
|
+
if (callerKey === "-")
|
|
8905
|
+
continue;
|
|
8906
|
+
if (param.optional) {
|
|
8907
|
+
lines.push(` if in.${nested.name}s != nil {`);
|
|
8908
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${varName}`);
|
|
8909
|
+
lines.push(` }`);
|
|
8910
|
+
} else {
|
|
8911
|
+
lines.push(` bfCallerProps["${callerKey}"] = ${varName}`);
|
|
8912
|
+
}
|
|
8913
|
+
}
|
|
8914
|
+
lines.push("");
|
|
8915
|
+
}
|
|
8817
8916
|
emitStaticChildInstances(lines, ir) {
|
|
8818
8917
|
const staticChildren = this.collectStaticChildInstances(ir.root, ir.metadata.propsParams);
|
|
8819
8918
|
for (const child of staticChildren) {
|
|
@@ -9265,6 +9364,7 @@ ${goFields.join(`
|
|
|
9265
9364
|
if (this.usesSearchParams(ir)) {
|
|
9266
9365
|
lines.push('\tSearchParams bf.SearchParams `json:"-"`');
|
|
9267
9366
|
}
|
|
9367
|
+
lines.push('\tBfCallerProps map[string]interface{} `json:"-"`');
|
|
9268
9368
|
}
|
|
9269
9369
|
emitPropsDataFields(lines, ir, nestedComponents, propTypeOverrides, takenJsonTags) {
|
|
9270
9370
|
const nestedArrayFields = this.propDerivedNestedArrayFields(nestedComponents);
|
|
@@ -9285,7 +9385,7 @@ ${goFields.join(`
|
|
|
9285
9385
|
const fieldName = capitalizeFieldName(signal.getter);
|
|
9286
9386
|
if (propFieldNames.has(fieldName))
|
|
9287
9387
|
continue;
|
|
9288
|
-
const jsonTag =
|
|
9388
|
+
const jsonTag = "-";
|
|
9289
9389
|
const synthType = this.state.synthStructTypes.get(signal.getter);
|
|
9290
9390
|
if (synthType) {
|
|
9291
9391
|
lines.push(` ${fieldName} ${typeInfoToGo(this.emitCtx, synthType)} \`json:"${jsonTag}"\``);
|
|
@@ -9317,7 +9417,7 @@ ${goFields.join(`
|
|
|
9317
9417
|
const fieldName = capitalizeFieldName(memo.name);
|
|
9318
9418
|
if (propFieldNames.has(fieldName))
|
|
9319
9419
|
continue;
|
|
9320
|
-
const jsonTag =
|
|
9420
|
+
const jsonTag = "-";
|
|
9321
9421
|
const goType = this.inferMemoType(memo, ir.metadata.signals, propsParamMap);
|
|
9322
9422
|
lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
|
|
9323
9423
|
}
|
|
@@ -9337,15 +9437,22 @@ ${goFields.join(`
|
|
|
9337
9437
|
...ir.metadata.memos.map((m) => capitalizeFieldName(m.name))
|
|
9338
9438
|
]);
|
|
9339
9439
|
for (const c of this.nonCollidingContextConsumers(takenProps)) {
|
|
9340
|
-
const jsonTag =
|
|
9440
|
+
const jsonTag = "-";
|
|
9341
9441
|
lines.push(` ${this.contextFieldName(c)} ${this.contextConsumerGoType(c)} \`json:"${jsonTag}"\``);
|
|
9342
9442
|
}
|
|
9443
|
+
const propDrivingFieldNames = new Set;
|
|
9444
|
+
for (const p of ir.metadata.propsParams) {
|
|
9445
|
+
propDrivingFieldNames.add(capitalizeFieldName(p.name));
|
|
9446
|
+
propDrivingFieldNames.add(capitalizeFieldName(p.sourceName ?? p.name));
|
|
9447
|
+
}
|
|
9343
9448
|
for (const nested of nestedComponents) {
|
|
9344
9449
|
if (this.isOrphanedClientOnlyNested(nested))
|
|
9345
9450
|
continue;
|
|
9346
9451
|
const elemType = nested.bodyChildren?.length ? this.loopBodyWrapperName(componentName, nested) : `${nested.name}Props`;
|
|
9347
9452
|
if (nested.isDynamic && !nested.isPropDerived) {
|
|
9348
9453
|
lines.push(` ${nested.name}s []${elemType} \`json:"-"\``);
|
|
9454
|
+
} else if (nested.isDynamic && nested.isPropDerived && !propDrivingFieldNames.has(`${nested.name}s`)) {
|
|
9455
|
+
lines.push(` ${nested.name}s []${elemType} \`json:"-"\``);
|
|
9349
9456
|
} else {
|
|
9350
9457
|
const jsonTag = this.claimJsonTag(this.toJsonTag(`${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`), takenJsonTags);
|
|
9351
9458
|
lines.push(` ${nested.name}s []${elemType} \`json:"${jsonTag}"\``);
|
|
@@ -9356,7 +9463,7 @@ ${goFields.join(`
|
|
|
9356
9463
|
lines.push(` ${child.fieldName} ${child.name}Props \`json:"-"\``);
|
|
9357
9464
|
}
|
|
9358
9465
|
for (const slot of spreadSlots) {
|
|
9359
|
-
const jsonTag =
|
|
9466
|
+
const jsonTag = "-";
|
|
9360
9467
|
lines.push(` ${slot.slotId} map[string]any \`json:"${jsonTag}"\``);
|
|
9361
9468
|
}
|
|
9362
9469
|
}
|
|
@@ -9669,7 +9776,19 @@ ${goFields.join(`
|
|
|
9669
9776
|
}
|
|
9670
9777
|
const propTypeOverrides = buildPropTypeOverrides(this.emitCtx, ir);
|
|
9671
9778
|
for (const signal of ir.metadata.signals) {
|
|
9672
|
-
|
|
9779
|
+
let match = this.extractPropFallback(signal.initialValue, this.resolvedSignalParsed(signal));
|
|
9780
|
+
let collisionWrap;
|
|
9781
|
+
if (!match) {
|
|
9782
|
+
const collision = this.extractCollisionDerivation(this.resolvedSignalParsed(signal));
|
|
9783
|
+
if (collision) {
|
|
9784
|
+
const collisionParam = ir.metadata.propsParams.find((p) => p.name === collision.propName);
|
|
9785
|
+
const collisionField = collisionParam ? capitalizeFieldName(collisionParam.sourceName ?? collision.propName) : null;
|
|
9786
|
+
if (collisionField && capitalizeFieldName(signal.getter) === collisionField) {
|
|
9787
|
+
match = { propName: collision.propName, goFallback: collision.goFallback };
|
|
9788
|
+
collisionWrap = { operator: collision.operator, operand: collision.operand };
|
|
9789
|
+
}
|
|
9790
|
+
}
|
|
9791
|
+
}
|
|
9673
9792
|
if (!match)
|
|
9674
9793
|
continue;
|
|
9675
9794
|
if (result.has(match.propName))
|
|
@@ -9708,11 +9827,15 @@ ${goFields.join(`
|
|
|
9708
9827
|
fieldName,
|
|
9709
9828
|
goFallback: match.goFallback,
|
|
9710
9829
|
zeroLiteral,
|
|
9711
|
-
...nullishLowered ? { assertType: concreteType } : {}
|
|
9830
|
+
...nullishLowered ? { assertType: concreteType } : {},
|
|
9831
|
+
...collisionWrap ? { collisionWrap } : {}
|
|
9712
9832
|
});
|
|
9713
9833
|
}
|
|
9714
9834
|
return result;
|
|
9715
9835
|
}
|
|
9836
|
+
resolvedSignalParsed(signal) {
|
|
9837
|
+
return resolveSignalParsedThroughSeedPlan(this.state, signal);
|
|
9838
|
+
}
|
|
9716
9839
|
extractPropFallback(initialValue, preParsed) {
|
|
9717
9840
|
const structural = preParsed ? this.extractPropFallbackFromParsed(preParsed) : null;
|
|
9718
9841
|
if (structural)
|
|
@@ -9755,6 +9878,26 @@ ${goFields.join(`
|
|
|
9755
9878
|
return null;
|
|
9756
9879
|
return { propName, goFallback };
|
|
9757
9880
|
}
|
|
9881
|
+
extractCollisionDerivation(parsed) {
|
|
9882
|
+
if (!parsed || parsed.kind !== "binary")
|
|
9883
|
+
return null;
|
|
9884
|
+
if (!["*", "+", "-", "/"].includes(parsed.op))
|
|
9885
|
+
return null;
|
|
9886
|
+
const { right } = parsed;
|
|
9887
|
+
if (right.kind !== "literal" || right.literalType !== "number" || typeof right.value !== "number" || !Number.isInteger(right.value) || right.value < 0) {
|
|
9888
|
+
return null;
|
|
9889
|
+
}
|
|
9890
|
+
if (parsed.op === "/" && right.value === 0)
|
|
9891
|
+
return null;
|
|
9892
|
+
const coalesce = parsed.left;
|
|
9893
|
+
if (coalesce.kind !== "logical" || coalesce.op !== "??" || coalesce.right.kind !== "literal" || coalesce.right.literalType !== "number") {
|
|
9894
|
+
return null;
|
|
9895
|
+
}
|
|
9896
|
+
const inner = this.extractPropFallbackFromParsed(parsed.left);
|
|
9897
|
+
if (!inner)
|
|
9898
|
+
return null;
|
|
9899
|
+
return { ...inner, operator: parsed.op, operand: String(right.value) };
|
|
9900
|
+
}
|
|
9758
9901
|
extractPropNameFromInitialValue(initialValue, preParsed) {
|
|
9759
9902
|
if (!this.state.propsObjectName) {
|
|
9760
9903
|
if (preParsed?.kind === "logical" && (preParsed.op === "??" || preParsed.op === "||") && preParsed.left.kind === "identifier") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/go-template",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Go html/template adapter for BarefootJS - generates Go template files from IR",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"directory": "packages/adapter-go-template"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@barefootjs/shared": "0.
|
|
52
|
+
"@barefootjs/shared": "0.32.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@barefootjs/jsx": ">=0.2.0",
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
70
|
-
"@barefootjs/client": "0.
|
|
71
|
-
"@barefootjs/jsx": "0.
|
|
72
|
-
"@barefootjs/vite": "0.
|
|
70
|
+
"@barefootjs/client": "0.32.0",
|
|
71
|
+
"@barefootjs/jsx": "0.32.0",
|
|
72
|
+
"@barefootjs/vite": "0.32.0",
|
|
73
73
|
"vite": "^6.0.0"
|
|
74
74
|
}
|
|
75
75
|
}
|