@barefootjs/go-template 0.33.4 → 0.34.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/vite.js CHANGED
@@ -8,10 +8,45 @@ import { devModuleUrl, loadManifest, resolveDevOrigin, resolveScriptAssets, toPo
8
8
  import ts25 from "typescript";
9
9
 
10
10
  // ../jsx/src/analyzer.ts
11
- import ts9 from "typescript";
11
+ import ts10 from "typescript";
12
12
 
13
13
  // ../jsx/src/expression-parser.ts
14
14
  import ts from "typescript";
15
+
16
+ // ../jsx/src/lowering-registry.ts
17
+ var plugins = [];
18
+ function registerLoweringPlugin(plugin) {
19
+ const existing = plugins.findIndex((p) => p.name === plugin.name);
20
+ if (existing >= 0)
21
+ plugins[existing] = plugin;
22
+ else
23
+ plugins.push(plugin);
24
+ }
25
+ function prepareLoweringMatchers(metadata) {
26
+ const matchers = [];
27
+ for (const plugin of plugins) {
28
+ const matcher = plugin.prepare(metadata);
29
+ if (matcher)
30
+ matchers.push(matcher);
31
+ }
32
+ return matchers;
33
+ }
34
+ function loweringNodeChildren(node) {
35
+ if (node.kind === "helper-call")
36
+ return [...node.args];
37
+ const children = [node.base];
38
+ for (const t of node.triples) {
39
+ if (t.guard)
40
+ children.push(t.guard);
41
+ children.push(t.value);
42
+ }
43
+ return children;
44
+ }
45
+ function isValidHelperId(helper) {
46
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
47
+ }
48
+
49
+ // ../jsx/src/expression-parser.ts
15
50
  var UNSUPPORTED_METHODS = new Set([
16
51
  "filter",
17
52
  "map",
@@ -209,7 +244,7 @@ function convertNode(node, raw) {
209
244
  }
210
245
  if (n === undefined || Number.isNaN(n)) {
211
246
  const parsedDepth = convertNode(depthNode, raw);
212
- if (checkSupport(parsedDepth, "rendered").supported) {
247
+ if (checkSupport(parsedDepth, "rendered", []).supported) {
213
248
  depthExpr = parsedDepth;
214
249
  flatDepth = 1;
215
250
  } else {
@@ -987,13 +1022,13 @@ function getUnaryOperatorString(op) {
987
1022
  return "unknown";
988
1023
  }
989
1024
  }
990
- function isSupported(expr) {
991
- return checkSupport(expr, "rendered");
1025
+ function isSupported(expr, opts) {
1026
+ return checkSupport(expr, "rendered", opts?.loweringMatchers ?? []);
992
1027
  }
993
- function isSupportedValue(expr) {
994
- return checkSupport(expr, "value");
1028
+ function isSupportedValue(expr, opts) {
1029
+ return checkSupport(expr, "value", opts?.loweringMatchers ?? []);
995
1030
  }
996
- function checkSupport(expr, pos) {
1031
+ function checkSupport(expr, pos, matchers) {
997
1032
  switch (expr.kind) {
998
1033
  case "unsupported":
999
1034
  return { supported: false, reason: expr.reason };
@@ -1002,7 +1037,7 @@ function checkSupport(expr, pos) {
1002
1037
  return { supported: false, reason: "Unsupported syntax: ObjectLiteralExpression" };
1003
1038
  }
1004
1039
  for (const prop of expr.properties) {
1005
- const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos);
1040
+ const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos, matchers);
1006
1041
  if (!propSupport.supported)
1007
1042
  return propSupport;
1008
1043
  }
@@ -1017,7 +1052,7 @@ function checkSupport(expr, pos) {
1017
1052
  return { supported: false, reason: "Standalone arrow functions / regex literals are not supported" };
1018
1053
  case "array-literal": {
1019
1054
  for (const el of expr.elements) {
1020
- const elSupport = checkSupport(el, pos);
1055
+ const elSupport = checkSupport(el, pos, matchers);
1021
1056
  if (!elSupport.supported)
1022
1057
  return elSupport;
1023
1058
  }
@@ -1030,28 +1065,39 @@ function checkSupport(expr, pos) {
1030
1065
  reason: `String.prototype.${expr.method} supports only a string pattern + string replacement (the regex form is deferred); use a string pattern or wrap the expression in /* @client */`
1031
1066
  };
1032
1067
  }
1033
- const objSupport = checkSupport(expr.object, pos);
1068
+ const objSupport = checkSupport(expr.object, pos, matchers);
1034
1069
  if (!objSupport.supported)
1035
1070
  return objSupport;
1036
1071
  for (const arg of expr.args) {
1037
- const argSupport = checkSupport(arg, pos);
1072
+ const argSupport = checkSupport(arg, pos, matchers);
1038
1073
  if (!argSupport.supported)
1039
1074
  return argSupport;
1040
1075
  }
1041
1076
  if (expr.method === "flat" && expr.depthExpr) {
1042
- const depthSupport = checkSupport(expr.depthExpr, pos);
1077
+ const depthSupport = checkSupport(expr.depthExpr, pos, matchers);
1043
1078
  if (!depthSupport.supported)
1044
1079
  return depthSupport;
1045
1080
  }
1046
1081
  return { supported: true, level: "L2" };
1047
1082
  }
1048
1083
  case "call": {
1084
+ for (const matcher of matchers) {
1085
+ const node = matcher(expr.callee, expr.args);
1086
+ if (!node)
1087
+ continue;
1088
+ for (const child of loweringNodeChildren(node)) {
1089
+ const childSupport = checkSupport(child, pos, matchers);
1090
+ if (!childSupport.supported)
1091
+ return childSupport;
1092
+ }
1093
+ return { supported: true, level: "L2" };
1094
+ }
1049
1095
  const cb = asCallbackMethodCall(expr);
1050
1096
  if (cb) {
1051
- const objSupport = checkSupport(cb.object, pos);
1097
+ const objSupport = checkSupport(cb.object, pos, matchers);
1052
1098
  if (!objSupport.supported)
1053
1099
  return objSupport;
1054
- const bodySupport = checkSupport(cb.arrow.body, pos);
1100
+ const bodySupport = checkSupport(cb.arrow.body, pos, matchers);
1055
1101
  if (!bodySupport.supported) {
1056
1102
  return {
1057
1103
  supported: false,
@@ -1060,13 +1106,13 @@ function checkSupport(expr, pos) {
1060
1106
  };
1061
1107
  }
1062
1108
  for (const rest of cb.args) {
1063
- const restSupport = checkSupport(rest, pos);
1109
+ const restSupport = checkSupport(rest, pos, matchers);
1064
1110
  if (!restSupport.supported)
1065
1111
  return restSupport;
1066
1112
  }
1067
1113
  return { supported: true, level: "L5" };
1068
1114
  }
1069
- const calleeSupport = checkSupport(expr.callee, pos);
1115
+ const calleeSupport = checkSupport(expr.callee, pos, matchers);
1070
1116
  if (!calleeSupport.supported) {
1071
1117
  return calleeSupport;
1072
1118
  }
@@ -1085,7 +1131,7 @@ function checkSupport(expr, pos) {
1085
1131
  return { supported: true, level: "L1" };
1086
1132
  }
1087
1133
  for (const arg of expr.args) {
1088
- const argSupport = checkSupport(arg, pos);
1134
+ const argSupport = checkSupport(arg, pos, matchers);
1089
1135
  if (!argSupport.supported) {
1090
1136
  return argSupport;
1091
1137
  }
@@ -1093,7 +1139,7 @@ function checkSupport(expr, pos) {
1093
1139
  return { supported: true, level: "L2" };
1094
1140
  }
1095
1141
  case "member": {
1096
- const objSupport = checkSupport(expr.object, pos);
1142
+ const objSupport = checkSupport(expr.object, pos, matchers);
1097
1143
  if (!objSupport.supported) {
1098
1144
  return objSupport;
1099
1145
  }
@@ -1103,19 +1149,19 @@ function checkSupport(expr, pos) {
1103
1149
  return { supported: true, level: "L2" };
1104
1150
  }
1105
1151
  case "index-access": {
1106
- const objSupport = checkSupport(expr.object, pos);
1152
+ const objSupport = checkSupport(expr.object, pos, matchers);
1107
1153
  if (!objSupport.supported)
1108
1154
  return objSupport;
1109
- const indexSupport = checkSupport(expr.index, pos);
1155
+ const indexSupport = checkSupport(expr.index, pos, matchers);
1110
1156
  if (!indexSupport.supported)
1111
1157
  return indexSupport;
1112
1158
  return { supported: true, level: "L2" };
1113
1159
  }
1114
1160
  case "binary": {
1115
- const leftSupport = checkSupport(expr.left, pos);
1161
+ const leftSupport = checkSupport(expr.left, pos, matchers);
1116
1162
  if (!leftSupport.supported)
1117
1163
  return leftSupport;
1118
- const rightSupport = checkSupport(expr.right, pos);
1164
+ const rightSupport = checkSupport(expr.right, pos, matchers);
1119
1165
  if (!rightSupport.supported)
1120
1166
  return rightSupport;
1121
1167
  if (["===", "==", "!==", "!=", ">", "<", ">=", "<="].includes(expr.op)) {
@@ -1127,7 +1173,7 @@ function checkSupport(expr, pos) {
1127
1173
  return { supported: false, reason: `Unknown operator: ${expr.op}` };
1128
1174
  }
1129
1175
  case "unary": {
1130
- const argSupport = checkSupport(expr.argument, pos);
1176
+ const argSupport = checkSupport(expr.argument, pos, matchers);
1131
1177
  if (!argSupport.supported)
1132
1178
  return argSupport;
1133
1179
  if (expr.op === "!") {
@@ -1139,25 +1185,25 @@ function checkSupport(expr, pos) {
1139
1185
  return { supported: false, reason: `Unsupported unary operator: ${expr.op}` };
1140
1186
  }
1141
1187
  case "logical": {
1142
- const leftSupport = checkSupport(expr.left, pos);
1188
+ const leftSupport = checkSupport(expr.left, pos, matchers);
1143
1189
  if (!leftSupport.supported)
1144
1190
  return leftSupport;
1145
1191
  if (expr.op === "??" && expr.right.kind === "object-literal" && expr.right.properties.length === 0) {
1146
1192
  return { supported: true, level: "L4" };
1147
1193
  }
1148
- const rightSupport = checkSupport(expr.right, pos);
1194
+ const rightSupport = checkSupport(expr.right, pos, matchers);
1149
1195
  if (!rightSupport.supported)
1150
1196
  return rightSupport;
1151
1197
  return { supported: true, level: "L4" };
1152
1198
  }
1153
1199
  case "conditional": {
1154
- const testSupport = checkSupport(expr.test, pos);
1200
+ const testSupport = checkSupport(expr.test, pos, matchers);
1155
1201
  if (!testSupport.supported)
1156
1202
  return testSupport;
1157
- const consSupport = checkSupport(expr.consequent, pos);
1203
+ const consSupport = checkSupport(expr.consequent, pos, matchers);
1158
1204
  if (!consSupport.supported)
1159
1205
  return consSupport;
1160
- const altSupport = checkSupport(expr.alternate, pos);
1206
+ const altSupport = checkSupport(expr.alternate, pos, matchers);
1161
1207
  if (!altSupport.supported)
1162
1208
  return altSupport;
1163
1209
  return { supported: true, level: "L4" };
@@ -1165,7 +1211,7 @@ function checkSupport(expr, pos) {
1165
1211
  case "template-literal": {
1166
1212
  for (const part of expr.parts) {
1167
1213
  if (part.type === "expression") {
1168
- const partSupport = checkSupport(part.expr, pos);
1214
+ const partSupport = checkSupport(part.expr, pos, matchers);
1169
1215
  if (!partSupport.supported)
1170
1216
  return partSupport;
1171
1217
  }
@@ -1939,7 +1985,7 @@ function identifierPath(callee) {
1939
1985
  }
1940
1986
 
1941
1987
  // ../jsx/src/prop-rewrite.ts
1942
- import ts5 from "typescript";
1988
+ import ts7 from "typescript";
1943
1989
 
1944
1990
  // ../jsx/src/ir-to-client-js/utils.ts
1945
1991
  import ts3 from "typescript";
@@ -2166,19 +2212,61 @@ function resolveJsxChildrenProp(props) {
2166
2212
  return [];
2167
2213
  return prop.value.children ?? [];
2168
2214
  }
2215
+ // ../jsx/src/ir-to-client-js/component-scope.ts
2216
+ function buildImportAliasMap(imports) {
2217
+ const aliases = new Map;
2218
+ for (const imp of imports) {
2219
+ if (imp.isTypeOnly)
2220
+ continue;
2221
+ for (const spec of imp.specifiers) {
2222
+ if (spec.isTypeOnly || spec.isDefault || spec.isNamespace || spec.alias === null)
2223
+ continue;
2224
+ aliases.set(spec.alias, spec.name);
2225
+ }
2226
+ }
2227
+ return aliases;
2228
+ }
2229
+
2169
2230
  // ../jsx/src/ir-to-client-js/csr-substitute.ts
2231
+ import ts5 from "typescript";
2232
+
2233
+ // ../jsx/src/props-binding.ts
2170
2234
  import ts4 from "typescript";
2235
+ function isIdentifierName(key) {
2236
+ if (key.length === 0)
2237
+ return false;
2238
+ for (let i = 0;i < key.length; ) {
2239
+ const cp = key.codePointAt(i);
2240
+ const ok = i === 0 ? ts4.isIdentifierStart(cp, ts4.ScriptTarget.Latest) : ts4.isIdentifierPart(cp, ts4.ScriptTarget.Latest);
2241
+ if (!ok)
2242
+ return false;
2243
+ i += cp > 65535 ? 2 : 1;
2244
+ }
2245
+ return true;
2246
+ }
2247
+ function propsDestructureBinding(p) {
2248
+ const callerKey = p.sourceName ?? p.name;
2249
+ const localName = p.name;
2250
+ const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
2251
+ return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
2252
+ }
2253
+ var EMPTY_SET = new Set;
2254
+
2255
+ // ../jsx/src/ir-to-client-js/csr-substitute.ts
2171
2256
  function extractFreeIdentifiersFromText(text) {
2172
2257
  if (!text || text.trim().length === 0)
2173
2258
  return new Set;
2174
- const sf = ts4.createSourceFile("__free_ids__.ts", `(${text});`, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
2259
+ const sf = ts5.createSourceFile("__free_ids__.ts", `(${text});`, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TS);
2175
2260
  const stmt = sf.statements[0];
2176
- if (!stmt || !ts4.isExpressionStatement(stmt))
2261
+ if (!stmt || !ts5.isExpressionStatement(stmt))
2177
2262
  return new Set;
2178
- const expr = ts4.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
2263
+ const expr = ts5.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
2179
2264
  return extractFreeIdentifiersFromNode(expr);
2180
2265
  }
2181
2266
 
2267
+ // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
2268
+ import ts6 from "typescript";
2269
+
2182
2270
  // ../jsx/src/scope/binding-scope.ts
2183
2271
  class BindingScope {
2184
2272
  frames;
@@ -2300,27 +2388,6 @@ var SKELETON_PATH_FORCE_CLOSE_GROUPS = [
2300
2388
  new Set(["li"])
2301
2389
  ];
2302
2390
 
2303
- // ../jsx/src/props-binding.ts
2304
- import ts6 from "typescript";
2305
- function isIdentifierName(key) {
2306
- if (key.length === 0)
2307
- return false;
2308
- for (let i = 0;i < key.length; ) {
2309
- const cp = key.codePointAt(i);
2310
- const ok = i === 0 ? ts6.isIdentifierStart(cp, ts6.ScriptTarget.Latest) : ts6.isIdentifierPart(cp, ts6.ScriptTarget.Latest);
2311
- if (!ok)
2312
- return false;
2313
- i += cp > 65535 ? 2 : 1;
2314
- }
2315
- return true;
2316
- }
2317
- function propsDestructureBinding(p) {
2318
- const callerKey = p.sourceName ?? p.name;
2319
- const localName = p.name;
2320
- const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
2321
- return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
2322
- }
2323
-
2324
2391
  // ../jsx/src/instrumentation.ts
2325
2392
  var _counters = freshCounters();
2326
2393
  function freshCounters() {
@@ -2334,20 +2401,21 @@ function freshCounters() {
2334
2401
  }
2335
2402
 
2336
2403
  // ../jsx/src/analyzer-context.ts
2337
- import ts8 from "typescript";
2404
+ import ts9 from "typescript";
2338
2405
 
2339
2406
  // ../jsx/src/strip-types.ts
2340
- import ts7 from "typescript";
2407
+ import ts8 from "typescript";
2341
2408
 
2342
2409
  // ../jsx/src/analyzer-context.ts
2343
- var _typePrinter = ts8.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
2344
- var _blankTypeSourceFile = ts8.createSourceFile("__bf_types__.ts", "", ts8.ScriptTarget.Latest);
2410
+ var _typePrinter = ts9.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
2411
+ var _blankTypeSourceFile = ts9.createSourceFile("__bf_types__.ts", "", ts9.ScriptTarget.Latest);
2345
2412
 
2346
2413
  // ../jsx/src/errors.ts
2347
2414
  var ErrorCodes = {
2348
2415
  MISSING_USE_CLIENT: "BF001",
2349
2416
  CLIENT_IMPORTING_SERVER: "BF003",
2350
2417
  SIGNAL_OUTSIDE_COMPONENT: "BF011",
2418
+ PRIMITIVE_VIA_NAMESPACE_IMPORT: "BF013",
2351
2419
  UNSUPPORTED_JSX_PATTERN: "BF021",
2352
2420
  MISSING_KEY_IN_LIST: "BF023",
2353
2421
  MISSING_KEY_IN_NESTED_LIST: "BF024",
@@ -2380,6 +2448,7 @@ var errorMessages = {
2380
2448
  [ErrorCodes.MISSING_USE_CLIENT]: "'use client' directive required for components with createSignal or event handlers",
2381
2449
  [ErrorCodes.CLIENT_IMPORTING_SERVER]: "Client component cannot import server component",
2382
2450
  [ErrorCodes.SIGNAL_OUTSIDE_COMPONENT]: "Module-level reactive declaration (createSignal / createMemo) is not allowed. " + "The downstream codegen drops the declaration silently and every reference becomes a ReferenceError at SSR and at hydrate. " + "Move the declaration inside a component function so each mount gets its own state.",
2451
+ [ErrorCodes.PRIMITIVE_VIA_NAMESPACE_IMPORT]: "Reactive primitive called through a namespace import of '@barefootjs/client' (import * as ns) is not recognized; " + "the declaration is dropped and its references throw ReferenceError at hydrate. Import the primitive by name instead.",
2383
2452
  [ErrorCodes.UNSUPPORTED_JSX_PATTERN]: "Unsupported JSX pattern",
2384
2453
  [ErrorCodes.MISSING_KEY_IN_LIST]: "Missing key attribute in list rendering. Add a key prop for efficient updates",
2385
2454
  [ErrorCodes.MISSING_KEY_IN_NESTED_LIST]: "Nested .map() loop requires key attribute for event delegation. Add a key prop to elements in the inner loop",
@@ -2571,46 +2640,46 @@ function extractFreeIdentifiersFromNode(node) {
2571
2640
  const ids = new Set;
2572
2641
  const boundNames = new Set;
2573
2642
  function addBindingNames(name, out) {
2574
- if (ts9.isIdentifier(name))
2643
+ if (ts10.isIdentifier(name))
2575
2644
  out.push(name.text);
2576
- else if (ts9.isObjectBindingPattern(name))
2645
+ else if (ts10.isObjectBindingPattern(name))
2577
2646
  name.elements.forEach((e) => addBindingNames(e.name, out));
2578
- else if (ts9.isArrayBindingPattern(name))
2647
+ else if (ts10.isArrayBindingPattern(name))
2579
2648
  name.elements.forEach((e) => {
2580
- if (!ts9.isOmittedExpression(e))
2649
+ if (!ts10.isOmittedExpression(e))
2581
2650
  addBindingNames(e.name, out);
2582
2651
  });
2583
2652
  }
2584
2653
  function visit(n) {
2585
- if (ts9.isTypeNode(n))
2654
+ if (ts10.isTypeNode(n))
2586
2655
  return;
2587
- if (ts9.isIdentifier(n)) {
2656
+ if (ts10.isIdentifier(n)) {
2588
2657
  const parent = n.parent;
2589
- if (parent && ts9.isPropertyAccessExpression(parent) && parent.name === n)
2658
+ if (parent && ts10.isPropertyAccessExpression(parent) && parent.name === n)
2590
2659
  return;
2591
- if (parent && ts9.isPropertyAssignment(parent) && parent.name === n)
2660
+ if (parent && ts10.isPropertyAssignment(parent) && parent.name === n)
2592
2661
  return;
2593
- if (parent && ts9.isParameter(parent) && parent.name === n)
2662
+ if (parent && ts10.isParameter(parent) && parent.name === n)
2594
2663
  return;
2595
- if (parent && ts9.isVariableDeclaration(parent) && parent.name === n)
2664
+ if (parent && ts10.isVariableDeclaration(parent) && parent.name === n)
2596
2665
  return;
2597
2666
  if (boundNames.has(n.text))
2598
2667
  return;
2599
2668
  ids.add(n.text);
2600
2669
  return;
2601
2670
  }
2602
- if (ts9.isArrowFunction(n)) {
2671
+ if (ts10.isArrowFunction(n)) {
2603
2672
  const params = [];
2604
2673
  for (const p of n.parameters)
2605
2674
  addBindingNames(p.name, params);
2606
2675
  for (const name of params)
2607
2676
  boundNames.add(name);
2608
- ts9.forEachChild(n, visit);
2677
+ ts10.forEachChild(n, visit);
2609
2678
  for (const name of params)
2610
2679
  boundNames.delete(name);
2611
2680
  return;
2612
2681
  }
2613
- ts9.forEachChild(n, visit);
2682
+ ts10.forEachChild(n, visit);
2614
2683
  }
2615
2684
  visit(node);
2616
2685
  return ids;
@@ -2633,7 +2702,7 @@ var REACTIVE_PRIMITIVES = new Set([
2633
2702
  ]);
2634
2703
 
2635
2704
  // ../jsx/src/jsx-to-ir.ts
2636
- import ts13 from "typescript";
2705
+ import ts14 from "typescript";
2637
2706
 
2638
2707
  // ../jsx/src/types.ts
2639
2708
  var SCOPE_FORBIDDEN = {
@@ -2683,7 +2752,7 @@ function preambleAnalysisTemplateText(p) {
2683
2752
  }
2684
2753
 
2685
2754
  // ../jsx/src/module-exports.ts
2686
- import ts10 from "typescript";
2755
+ import ts11 from "typescript";
2687
2756
  function formatParamWithType(p) {
2688
2757
  const rest = p.isRest ? "..." : "";
2689
2758
  const optional = p.optional ? "?" : "";
@@ -2718,21 +2787,21 @@ function findAssignedNames(bodyText, candidates) {
2718
2787
  const assigned = new Set;
2719
2788
  if (candidates.size === 0)
2720
2789
  return assigned;
2721
- const sf = ts10.createSourceFile("bf-assignment-scan.tsx", bodyText, ts10.ScriptTarget.Latest, false, ts10.ScriptKind.TSX);
2790
+ const sf = ts11.createSourceFile("bf-assignment-scan.tsx", bodyText, ts11.ScriptTarget.Latest, false, ts11.ScriptKind.TSX);
2722
2791
  const record = (target) => {
2723
- if (ts10.isIdentifier(target) && candidates.has(target.text)) {
2792
+ if (ts11.isIdentifier(target) && candidates.has(target.text)) {
2724
2793
  assigned.add(target.text);
2725
2794
  }
2726
2795
  };
2727
2796
  const visit = (node) => {
2728
- if (ts10.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
2797
+ if (ts11.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
2729
2798
  record(node.left);
2730
- } else if ((ts10.isPrefixUnaryExpression(node) || ts10.isPostfixUnaryExpression(node)) && (node.operator === ts10.SyntaxKind.PlusPlusToken || node.operator === ts10.SyntaxKind.MinusMinusToken)) {
2799
+ } else if ((ts11.isPrefixUnaryExpression(node) || ts11.isPostfixUnaryExpression(node)) && (node.operator === ts11.SyntaxKind.PlusPlusToken || node.operator === ts11.SyntaxKind.MinusMinusToken)) {
2731
2800
  record(node.operand);
2732
2801
  }
2733
- ts10.forEachChild(node, visit);
2802
+ ts11.forEachChild(node, visit);
2734
2803
  };
2735
- ts10.forEachChild(sf, visit);
2804
+ ts11.forEachChild(sf, visit);
2736
2805
  return assigned;
2737
2806
  }
2738
2807
  function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNames) {
@@ -2755,14 +2824,14 @@ function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNam
2755
2824
  return reachable;
2756
2825
  }
2757
2826
  function isAssignmentOperator(kind) {
2758
- return kind >= ts10.SyntaxKind.FirstAssignment && kind <= ts10.SyntaxKind.LastAssignment;
2827
+ return kind >= ts11.SyntaxKind.FirstAssignment && kind <= ts11.SyntaxKind.LastAssignment;
2759
2828
  }
2760
2829
 
2761
2830
  // ../jsx/src/reactivity-checker.ts
2762
- import ts11 from "typescript";
2831
+ import ts12 from "typescript";
2763
2832
 
2764
2833
  // ../jsx/src/free-refs.ts
2765
- import ts12 from "typescript";
2834
+ import ts13 from "typescript";
2766
2835
  var _bindingMapCache = new WeakMap;
2767
2836
 
2768
2837
  // ../jsx/src/to-locale-date-lowering.ts
@@ -3210,40 +3279,16 @@ var KEYWORDS_AND_GLOBALS = new Set([
3210
3279
  ]);
3211
3280
 
3212
3281
  // ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
3213
- import ts14 from "typescript";
3214
-
3215
- // ../jsx/src/ir-to-client-js/imports.ts
3216
- import ts16 from "typescript";
3217
-
3218
- // ../jsx/src/value-references.ts
3219
3282
  import ts15 from "typescript";
3220
3283
 
3221
- // ../jsx/src/relocate.ts
3284
+ // ../jsx/src/ir-to-client-js/imports.ts
3222
3285
  import ts17 from "typescript";
3223
3286
 
3224
- // ../jsx/src/lowering-registry.ts
3225
- var plugins = [];
3226
- function registerLoweringPlugin(plugin) {
3227
- const existing = plugins.findIndex((p) => p.name === plugin.name);
3228
- if (existing >= 0)
3229
- plugins[existing] = plugin;
3230
- else
3231
- plugins.push(plugin);
3232
- }
3233
- function prepareLoweringMatchers(metadata) {
3234
- const matchers = [];
3235
- for (const plugin of plugins) {
3236
- const matcher = plugin.prepare(metadata);
3237
- if (matcher)
3238
- matchers.push(matcher);
3239
- }
3240
- return matchers;
3241
- }
3242
- function isValidHelperId(helper) {
3243
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
3244
- }
3287
+ // ../jsx/src/value-references.ts
3288
+ import ts16 from "typescript";
3245
3289
 
3246
3290
  // ../jsx/src/relocate.ts
3291
+ import ts18 from "typescript";
3247
3292
  var REGISTRY_SAFE_BINDING_KINDS = new Set([
3248
3293
  "global",
3249
3294
  "module-import",
@@ -3415,10 +3460,10 @@ function formatDateLocalNames(metadata) {
3415
3460
  }
3416
3461
 
3417
3462
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3418
- import ts18 from "typescript";
3463
+ import ts19 from "typescript";
3419
3464
 
3420
3465
  // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3421
- import ts19 from "typescript";
3466
+ import ts20 from "typescript";
3422
3467
  var NO_PREAMBLE = {
3423
3468
  lazySafe: true,
3424
3469
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3468,7 +3513,7 @@ var INERT_BINDING_GLOBALS = new Set([
3468
3513
  ]);
3469
3514
 
3470
3515
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
3471
- import ts20 from "typescript";
3516
+ import ts21 from "typescript";
3472
3517
 
3473
3518
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3474
3519
  var NON_BUBBLING_EVENTS = new Set([
@@ -3482,9 +3527,6 @@ var NON_BUBBLING_EVENTS = new Set([
3482
3527
  "pointerleave"
3483
3528
  ]);
3484
3529
 
3485
- // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
3486
- import ts21 from "typescript";
3487
-
3488
3530
  // ../jsx/src/ir-to-client-js/source-map.ts
3489
3531
  var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3490
3532
  function encodeVLQ(value) {
@@ -4674,6 +4716,17 @@ function emitParsedExpr(expr, emitter) {
4674
4716
  case "literal":
4675
4717
  return emitter.literal(expr.value, expr.literalType);
4676
4718
  case "call": {
4719
+ if (emitter.lowering) {
4720
+ for (const matcher of emitter.lowering.matchers) {
4721
+ const node = matcher(expr.callee, expr.args);
4722
+ if (!node)
4723
+ continue;
4724
+ const rendered = emitter.lowering.render(node, emit);
4725
+ if (rendered !== null)
4726
+ return rendered;
4727
+ break;
4728
+ }
4729
+ }
4677
4730
  const cb = asCallbackMethodCall(expr);
4678
4731
  if (cb)
4679
4732
  return emitter.callbackMethod(cb.method, cb.object, cb.arrow, cb.args, emit);
@@ -5508,6 +5561,7 @@ class CompileState {
5508
5561
  componentName = "";
5509
5562
  errors = [];
5510
5563
  referencedDerivedConsts = new Set;
5564
+ templateReadRootFields = new Set;
5511
5565
  templateVarCounter = 0;
5512
5566
  pendingChildrenDefines = [];
5513
5567
  propsObjectName = null;
@@ -6082,9 +6136,22 @@ function lowerTernaryTest(ctx, test) {
6082
6136
  const isBoolShape = test.kind === "binary" && BOOL_COMPARISON_OPS.has(test.op) || test.kind === "unary" && test.op === "!" || test.kind === "literal" && test.literalType === "boolean";
6083
6137
  return isBoolShape ? go : `(bf_truthy ${go})`;
6084
6138
  }
6139
+ function matchRegisteredCall(ctx, callee, args) {
6140
+ for (const matcher of ctx.state.loweringMatchers) {
6141
+ const node = matcher(callee, args);
6142
+ if (node)
6143
+ return node;
6144
+ }
6145
+ return null;
6146
+ }
6147
+ function lowerRegisteredCallNode(ctx, callee, args) {
6148
+ if (ctx.state.loweringMatchers.length === 0)
6149
+ return null;
6150
+ const node = matchRegisteredCall(ctx, callee, args);
6151
+ return node ? renderLoweringNode(ctx, node) : null;
6152
+ }
6085
6153
  function lowerRegisteredCall(ctx, jsExpr, preParsed) {
6086
- const matchers = ctx.state.loweringMatchers;
6087
- if (matchers.length === 0)
6154
+ if (ctx.state.loweringMatchers.length === 0)
6088
6155
  return null;
6089
6156
  let call = preParsed?.kind === "call" ? preParsed : undefined;
6090
6157
  if (!call) {
@@ -6095,15 +6162,32 @@ function lowerRegisteredCall(ctx, jsExpr, preParsed) {
6095
6162
  return null;
6096
6163
  call = parsed;
6097
6164
  }
6098
- for (const matcher of matchers) {
6099
- const node = matcher(call.callee, call.args);
6100
- if (!node)
6101
- continue;
6102
- const rendered = renderLoweringNode(ctx, node);
6103
- if (rendered !== null)
6104
- return rendered;
6165
+ return lowerRegisteredCallNode(ctx, call.callee, call.args);
6166
+ }
6167
+ function lowerRegisteredAttrCall(ctx, attrName, parsed) {
6168
+ if (parsed.kind === "conditional") {
6169
+ if (!ternaryHasQueryBranch(ctx, parsed.consequent, parsed.alternate))
6170
+ return null;
6171
+ const rendered2 = lowerTernary(ctx, parsed.test, parsed.consequent, parsed.alternate);
6172
+ return `{{bf_attr ${JSON.stringify(attrName)} ${rendered2}}}`;
6105
6173
  }
6106
- return null;
6174
+ if (parsed.kind !== "call")
6175
+ return null;
6176
+ const node = matchRegisteredCall(ctx, parsed.callee, parsed.args);
6177
+ if (!node || node.kind !== "guard-list" || node.helper !== "query")
6178
+ return null;
6179
+ const rendered = renderLoweringNode(ctx, node);
6180
+ return rendered === null ? null : `{{bf_attr ${JSON.stringify(attrName)} (${rendered})}}`;
6181
+ }
6182
+ function isQueryGuardListCall(ctx, node) {
6183
+ if (node.kind !== "call")
6184
+ return false;
6185
+ const lowered = matchRegisteredCall(ctx, node.callee, node.args);
6186
+ return lowered?.kind === "guard-list" && lowered.helper === "query";
6187
+ }
6188
+ function ternaryHasQueryBranch(ctx, consequent, alternate) {
6189
+ const branchHasQuery = (n) => n.kind === "conditional" ? ternaryHasQueryBranch(ctx, n.consequent, n.alternate) : isQueryGuardListCall(ctx, n);
6190
+ return branchHasQuery(consequent) || branchHasQuery(alternate);
6107
6191
  }
6108
6192
  function renderLoweringNode(ctx, node) {
6109
6193
  const helper = goHelperName(node.helper);
@@ -6357,6 +6441,15 @@ function convertInitialValue(ctx, value, _typeInfo, propsParams, preParsed) {
6357
6441
  if (param2) {
6358
6442
  return propRef(param2);
6359
6443
  }
6444
+ const inlinedStr = ctx.resolveModuleStringConst(value);
6445
+ if (inlinedStr !== null)
6446
+ return inlinedStr;
6447
+ const inlinedNum = ctx.resolveModuleNumericConst(value);
6448
+ if (inlinedNum !== null)
6449
+ return inlinedNum;
6450
+ const inlinedBool = ctx.resolveModuleBooleanConst(value);
6451
+ if (inlinedBool !== null)
6452
+ return inlinedBool;
6360
6453
  }
6361
6454
  const propName = ctx.extractPropNameFromInitialValue(value, preParsed);
6362
6455
  const param = propName ? propsParams?.find((p) => p.name === propName) : undefined;
@@ -8064,7 +8157,9 @@ class GoTemplateAdapter extends BaseAdapter {
8064
8157
  extractPropNameFromInitialValue: (initialValue, preParsed) => this.extractPropNameFromInitialValue(initialValue, preParsed),
8065
8158
  extractPropFallback: (initialValue, preParsed) => this.extractPropFallback(initialValue, preParsed),
8066
8159
  extractCollisionDerivation: (parsed) => this.extractCollisionDerivation(parsed),
8067
- resolveModuleStringConst: (name) => this.resolveModuleStringConst(name)
8160
+ resolveModuleStringConst: (name) => this.resolveModuleStringConst(name),
8161
+ resolveModuleNumericConst: (name) => this.resolveModuleNumericConst(name),
8162
+ resolveModuleBooleanConst: (name) => this.resolveModuleBooleanConst(name)
8068
8163
  };
8069
8164
  get errors() {
8070
8165
  return this.state.errors;
@@ -8081,6 +8176,10 @@ class GoTemplateAdapter extends BaseAdapter {
8081
8176
  staticLoopBakeFailed = false;
8082
8177
  childComponentShapes = new Map;
8083
8178
  childContextConsumers = new Map;
8179
+ importAliases = new Map;
8180
+ resolveChildName(name) {
8181
+ return this.importAliases.get(name) ?? name;
8182
+ }
8084
8183
  constructor(options = {}) {
8085
8184
  super();
8086
8185
  this.options = {
@@ -8092,6 +8191,7 @@ class GoTemplateAdapter extends BaseAdapter {
8092
8191
  primeCompileState(ir) {
8093
8192
  this.state.propsObjectName = ir.metadata.propsObjectName;
8094
8193
  this.state.restPropsName = ir.metadata.restPropsName ?? null;
8194
+ this.importAliases = buildImportAliasMap(ir.metadata.imports ?? []);
8095
8195
  this.state.objectTypedPropNames = new Set((ir.metadata.propsParams ?? []).filter((p) => p.type.kind === "object").map((p) => p.name));
8096
8196
  this.state.moduleStringConsts = this.collectModuleStringConsts(ir.metadata.localConstants);
8097
8197
  this.state.localConstants = ir.metadata.localConstants ?? [];
@@ -8126,6 +8226,7 @@ class GoTemplateAdapter extends BaseAdapter {
8126
8226
  this.state.componentName = ir.metadata.componentName;
8127
8227
  this.state.errors = [];
8128
8228
  this.state.referencedDerivedConsts = new Set;
8229
+ this.state.templateReadRootFields = new Set;
8129
8230
  this.state.templateVarCounter = 0;
8130
8231
  this.state.pendingChildrenDefines = [];
8131
8232
  this.scope = BindingScope.EMPTY;
@@ -8154,7 +8255,7 @@ ${scriptRegistrations}${templateBody}
8154
8255
  template += `{{define "${d.name}"}}${d.content}{{end}}
8155
8256
  `;
8156
8257
  }
8157
- const types = this.generateTypes(ir);
8258
+ const types = this.generateTypes(ir, true);
8158
8259
  if (this.state.errors.length > 0) {
8159
8260
  ir.errors.push(...this.state.errors);
8160
8261
  }
@@ -8383,9 +8484,12 @@ ${scriptRegistrations}${templateBody}
8383
8484
  taken.add(desired);
8384
8485
  return desired;
8385
8486
  }
8386
- generateTypes(ir) {
8487
+ generateTypes(ir, preserveTemplateReadRootFields = false) {
8387
8488
  this.state.usesHtmlTemplate = false;
8388
8489
  this.state.usesFmt = false;
8490
+ if (!preserveTemplateReadRootFields) {
8491
+ this.state.templateReadRootFields = new Set;
8492
+ }
8389
8493
  this.primeCompileState(ir);
8390
8494
  const lines = [];
8391
8495
  const componentName = ir.metadata.componentName;
@@ -8529,10 +8633,17 @@ ${goFields.join(`
8529
8633
  const node = signal.parsed;
8530
8634
  if (!node || node.kind !== "array-literal" || node.elements.length === 0)
8531
8635
  return null;
8636
+ const name = `${componentName}${capitalizeFieldName(signal.getter)}Item`;
8637
+ return this.synthesizeStructsFromElements(node.elements, name);
8638
+ }
8639
+ synthesizeStructsFromElements(elements, name) {
8640
+ if (this.state.localTypeNames.has(name))
8641
+ return null;
8532
8642
  const order = [];
8533
- const goTypes = new Map;
8534
- for (let i = 0;i < node.elements.length; i++) {
8535
- const el = node.elements[i];
8643
+ const shapes = new Map;
8644
+ const nestedElements = new Map;
8645
+ for (let i = 0;i < elements.length; i++) {
8646
+ const el = elements[i];
8536
8647
  if (el.kind !== "object-literal")
8537
8648
  return null;
8538
8649
  const seen = new Set;
@@ -8544,37 +8655,93 @@ ${goFields.join(`
8544
8655
  const key = prop.key;
8545
8656
  if (!GO_IDENTIFIER.test(key))
8546
8657
  return null;
8658
+ seen.add(key);
8659
+ const isNestedArray = prop.value.kind === "array-literal" && prop.value.elements.every((e) => e.kind === "object-literal");
8660
+ if (isNestedArray) {
8661
+ const prevShape2 = shapes.get(key);
8662
+ if (prevShape2 === undefined) {
8663
+ if (i !== 0)
8664
+ return null;
8665
+ order.push(key);
8666
+ shapes.set(key, { kind: "nested-array" });
8667
+ nestedElements.set(key, []);
8668
+ } else if (prevShape2.kind !== "nested-array") {
8669
+ return null;
8670
+ }
8671
+ nestedElements.get(key).push(...prop.value.elements);
8672
+ continue;
8673
+ }
8547
8674
  const goType = this.scalarParsedGoType(prop.value);
8548
8675
  if (!goType)
8549
8676
  return null;
8550
- seen.add(key);
8551
- const prev = goTypes.get(key);
8552
- if (prev === undefined) {
8677
+ const prevShape = shapes.get(key);
8678
+ if (prevShape === undefined) {
8553
8679
  if (i !== 0)
8554
8680
  return null;
8555
8681
  order.push(key);
8556
- goTypes.set(key, goType);
8682
+ shapes.set(key, { kind: "scalar", goType });
8683
+ } else if (prevShape.kind !== "scalar") {
8684
+ return null;
8557
8685
  } else {
8558
- const merged = this.mergeScalarGoType(prev, goType);
8686
+ const merged = this.mergeScalarGoType(prevShape.goType, goType);
8559
8687
  if (!merged)
8560
8688
  return null;
8561
- goTypes.set(key, merged);
8689
+ shapes.set(key, { kind: "scalar", goType: merged });
8562
8690
  }
8563
8691
  }
8564
8692
  if (seen.size !== order.length)
8565
8693
  return null;
8566
8694
  }
8567
- const name = `${componentName}${capitalizeFieldName(signal.getter)}Item`;
8568
- if (this.state.localTypeNames.has(name))
8569
- return null;
8570
- return {
8695
+ const nestedStructs = [];
8696
+ const fields = [];
8697
+ const properties = [];
8698
+ for (const key of order) {
8699
+ const shape = shapes.get(key);
8700
+ if (shape.kind === "scalar") {
8701
+ fields.push({ tsName: key, goName: capitalizeFieldName(key), goType: shape.goType });
8702
+ properties.push({ name: key, type: this.scalarGoTypeToTypeInfo(shape.goType), optional: false, readonly: false });
8703
+ continue;
8704
+ }
8705
+ const nestedList = nestedElements.get(key);
8706
+ if (nestedList.length === 0)
8707
+ return null;
8708
+ const nestedName = `${name}${capitalizeFieldName(key)}Item`;
8709
+ const nested = this.synthesizeStructsFromElements(nestedList, nestedName);
8710
+ if (!nested)
8711
+ return null;
8712
+ nestedStructs.push(...nested);
8713
+ fields.push({ tsName: key, goName: capitalizeFieldName(key), goType: `[]${nestedName}` });
8714
+ properties.push({ name: key, type: this.synthSliceTypeInfo(nestedName), optional: false, readonly: false });
8715
+ }
8716
+ return [...nestedStructs, { name, fields, properties }];
8717
+ }
8718
+ scalarGoTypeToTypeInfo(goType) {
8719
+ if (goType === "string")
8720
+ return { kind: "primitive", raw: "string", primitive: "string" };
8721
+ if (goType === "bool")
8722
+ return { kind: "primitive", raw: "boolean", primitive: "boolean" };
8723
+ return { kind: "primitive", raw: "number", primitive: "number" };
8724
+ }
8725
+ synthSliceTypeInfo(name) {
8726
+ return { kind: "array", raw: `${name}[]`, elementType: { kind: "interface", raw: name } };
8727
+ }
8728
+ registerSynthStruct(lines, name, fields, properties, comment) {
8729
+ this.state.localTypeNames.add(name);
8730
+ this.state.localStructFields.set(name, new Map(fields.map((f) => [f.tsName, f.goName])));
8731
+ this.state.currentTypeDefinitions.push({
8732
+ kind: "type",
8571
8733
  name,
8572
- fields: order.map((key) => ({
8573
- tsName: key,
8574
- goName: capitalizeFieldName(key),
8575
- goType: goTypes.get(key)
8576
- }))
8577
- };
8734
+ definition: "",
8735
+ properties,
8736
+ loc: SYNTH_TYPE_LOC
8737
+ });
8738
+ const goFields = fields.map((f) => ` ${f.goName} ${f.goType} \`json:"${this.toJsonTag(f.tsName)}"\``);
8739
+ lines.push(comment);
8740
+ lines.push(`type ${name} struct {
8741
+ ${goFields.join(`
8742
+ `)}
8743
+ }`);
8744
+ lines.push("");
8578
8745
  }
8579
8746
  scalarParsedGoType(value) {
8580
8747
  if (value.kind === "unary" && value.op === "-" && value.argument.kind === "literal") {
@@ -8641,7 +8808,7 @@ ${goFields.join(`
8641
8808
  for (const nested of inputNested) {
8642
8809
  if (nested.loopMarkerId && this.getBakedStaticChildLoop(nested.loopMarkerId, nested, nested.loopArrayParsed, nested.loopParam, nested.loopKey))
8643
8810
  continue;
8644
- lines.push(` ${nested.name}s []${nested.name}Input`);
8811
+ lines.push(` ${nested.name}s []${this.resolveChildName(nested.name)}Input`);
8645
8812
  }
8646
8813
  const takenInput = new Set(this.propParamFieldNamesUnion(ir.metadata.propsParams));
8647
8814
  for (const c of this.nonCollidingContextConsumers(takenInput)) {
@@ -8677,10 +8844,11 @@ ${goFields.join(`
8677
8844
  const wrapperName = this.loopBodyWrapperName(parentComponentName, nested);
8678
8845
  const datumFields = this.resolveLoopDatumFields(nested.loopItemType);
8679
8846
  const bodyChildInstances = this.collectBodyChildInstances(nested.bodyChildren);
8680
- lines.push(`// ${wrapperName} wraps ${nested.name}Props with per-row loop datum`);
8847
+ const declaredName = this.resolveChildName(nested.name);
8848
+ lines.push(`// ${wrapperName} wraps ${declaredName}Props with per-row loop datum`);
8681
8849
  lines.push(`// fields and child component slots for the loop body children. (#1897)`);
8682
8850
  lines.push(`type ${wrapperName} struct {`);
8683
- lines.push(` ${nested.name}Props`);
8851
+ lines.push(` ${declaredName}Props`);
8684
8852
  for (const f of datumFields) {
8685
8853
  lines.push(` ${f.goName} ${f.goType} \`json:"-"\``);
8686
8854
  }
@@ -8689,7 +8857,7 @@ ${goFields.join(`
8689
8857
  lines.push(` BfLoopItem ${scalarLoopType} \`json:"-"\``);
8690
8858
  }
8691
8859
  for (const child of bodyChildInstances) {
8692
- lines.push(` ${child.fieldName} ${child.name}Props \`json:"-"\``);
8860
+ lines.push(` ${child.fieldName} ${this.resolveChildName(child.name)}Props \`json:"-"\``);
8693
8861
  }
8694
8862
  lines.push("}");
8695
8863
  lines.push("");
@@ -8773,12 +8941,13 @@ ${goFields.join(`
8773
8941
  const staticWithoutBody = staticNested.filter((n) => !n.bodyChildren || n.bodyChildren.length === 0);
8774
8942
  for (const nested of staticWithoutBody) {
8775
8943
  const varName = `${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`;
8944
+ const declaredName = this.resolveChildName(nested.name);
8776
8945
  const baked = nested.loopMarkerId ? this.getBakedStaticChildLoop(nested.loopMarkerId, nested, nested.loopArrayParsed, nested.loopParam, nested.loopKey) : null;
8777
8946
  if (baked) {
8778
- lines.push(` ${varName} := make([]${nested.name}Props, ${baked.items.length})`);
8947
+ lines.push(` ${varName} := make([]${declaredName}Props, ${baked.items.length})`);
8779
8948
  baked.items.forEach((item, i) => {
8780
8949
  const fields = item.inputFields.map((f) => `${f.goField}: ${f.goValue}`).join(", ");
8781
- lines.push(` ${varName}[${i}] = New${nested.name}Props(${nested.name}Input{${fields}})`);
8950
+ lines.push(` ${varName}[${i}] = New${declaredName}Props(${declaredName}Input{${fields}})`);
8782
8951
  lines.push(` ${varName}[${i}].BfParent = scopeID`);
8783
8952
  lines.push(` ${varName}[${i}].BfMount = "${nested.slotId}"`);
8784
8953
  if (item.dataKey !== null) {
@@ -8788,9 +8957,9 @@ ${goFields.join(`
8788
8957
  lines.push("");
8789
8958
  continue;
8790
8959
  }
8791
- lines.push(` ${varName} := make([]${nested.name}Props, len(in.${nested.name}s))`);
8960
+ lines.push(` ${varName} := make([]${declaredName}Props, len(in.${nested.name}s))`);
8792
8961
  lines.push(` for i, item := range in.${nested.name}s {`);
8793
- lines.push(` ${varName}[i] = New${nested.name}Props(item)`);
8962
+ lines.push(` ${varName}[i] = New${declaredName}Props(item)`);
8794
8963
  lines.push(` ${varName}[i].BfParent = scopeID`);
8795
8964
  lines.push(` ${varName}[i].BfMount = "${nested.slotId}"`);
8796
8965
  const keyField = loopKeyToGoFieldPath(nested.loopKey, nested.loopParam);
@@ -8905,8 +9074,14 @@ ${goFields.join(`
8905
9074
  lines.push(` ${fieldName}: ${hoisted.varName},`);
8906
9075
  } else {
8907
9076
  const bakeType = this.state.synthStructTypes.get(signal.getter) ?? signal.type;
9077
+ const resolvedParsed = this.resolvedSignalParsed(signal);
8908
9078
  const initialValue = convertInitialValue(this.emitCtx, signal.initialValue, bakeType, ir.metadata.propsParams, signal.parsed);
8909
9079
  lines.push(` ${fieldName}: ${initialValue},`);
9080
+ if (resolvedParsed?.kind === "object-literal" && jsLiteralToGo(this.emitCtx, bakeType, resolvedParsed) === null) {
9081
+ const step = this.state.ssrSeedPlan.steps.find((s) => s.kind === "derived" && s.origin === "signal" && s.name === signal.getter);
9082
+ if (step?.kind === "derived")
9083
+ this.refuseUnbakeableDerivedObjectLiteral(signal.getter, signal.loc, step.frees);
9084
+ }
8910
9085
  }
8911
9086
  }
8912
9087
  for (const nested of staticWithoutBody) {
@@ -9006,19 +9181,20 @@ ${goFields.join(`
9006
9181
  emitStaticChildInstances(lines, ir) {
9007
9182
  const staticChildren = this.collectStaticChildInstances(ir.root, ir.metadata.propsParams);
9008
9183
  for (const child of staticChildren) {
9009
- lines.push(` ${child.fieldName}: New${child.name}Props(${child.name}Input{`);
9184
+ const declaredName = this.resolveChildName(child.name);
9185
+ lines.push(` ${child.fieldName}: New${declaredName}Props(${declaredName}Input{`);
9010
9186
  lines.push(` ScopeID: scopeID + "_${child.slotId}",`);
9011
9187
  lines.push(` BfParent: scopeID,`);
9012
9188
  lines.push(` BfMount: "${child.slotId}",`);
9013
9189
  if (child.contextBindings) {
9014
- for (const consumer of this.childContextConsumers.get(child.name) ?? []) {
9190
+ for (const consumer of this.childContextConsumers.get(declaredName) ?? []) {
9015
9191
  const goVal = child.contextBindings.get(consumer.contextName);
9016
9192
  if (goVal !== undefined) {
9017
9193
  lines.push(` ${this.contextFieldName(consumer)}: ${goVal},`);
9018
9194
  }
9019
9195
  }
9020
9196
  }
9021
- const childShape = this.childComponentShapes.get(child.name);
9197
+ const childShape = this.childComponentShapes.get(declaredName);
9022
9198
  const restBagEntries = [];
9023
9199
  const emitChildField = (jsxName, goValue) => {
9024
9200
  if (childShape && childShape.restBagField && !childShape.paramNames.has(jsxName)) {
@@ -9115,6 +9291,7 @@ ${goFields.join(`
9115
9291
  lines.push(`// New${componentName}Props creates ${propsTypeName} from ${inputTypeName}.`);
9116
9292
  for (const nested of signalDynamicNested) {
9117
9293
  const arrayField = `${nested.name}s`;
9294
+ const declaredName = this.resolveChildName(nested.name);
9118
9295
  lines.push(`//`);
9119
9296
  lines.push(`// NOTE: \`${arrayField}\` is populated by the route handler, not by`);
9120
9297
  lines.push(`// New${componentName}Props — the SSR template iterates over it`);
@@ -9122,9 +9299,9 @@ ${goFields.join(`
9122
9299
  lines.push(`// assign it before passing the props to your renderer. Example:`);
9123
9300
  lines.push(`//`);
9124
9301
  lines.push(`// props := New${componentName}Props(${inputTypeName}{ /* ... */ })`);
9125
- lines.push(`// props.${arrayField} = make([]${nested.name}Props, len(items))`);
9302
+ lines.push(`// props.${arrayField} = make([]${declaredName}Props, len(items))`);
9126
9303
  lines.push(`// for i, item := range items {`);
9127
- lines.push(`// props.${arrayField}[i] = New${nested.name}Props(${nested.name}Input{ /* fields */ })`);
9304
+ lines.push(`// props.${arrayField}[i] = New${declaredName}Props(${declaredName}Input{ /* fields */ })`);
9128
9305
  lines.push(`// props.${arrayField}[i].BfParent = props.ScopeID`);
9129
9306
  lines.push(`// props.${arrayField}[i].BfMount = "${nested.slotId}"`);
9130
9307
  lines.push(`// }`);
@@ -9163,9 +9340,11 @@ ${goFields.join(`
9163
9340
  const wrapperType = this.loopBodyWrapperName(componentName, nested);
9164
9341
  const datumFields = this.resolveLoopDatumFields(nested.loopItemType);
9165
9342
  const bodyChildInstances = this.collectBodyChildInstances(nested.bodyChildren, ir.metadata.propsParams);
9343
+ const declaredName = this.resolveChildName(nested.name);
9166
9344
  for (const child of bodyChildInstances) {
9167
9345
  const childVar = `child_${child.fieldName}`;
9168
- lines.push(` ${childVar} := New${child.name}Props(${child.name}Input{`);
9346
+ const childDeclaredName = this.resolveChildName(child.name);
9347
+ lines.push(` ${childVar} := New${childDeclaredName}Props(${childDeclaredName}Input{`);
9169
9348
  lines.push(` ScopeID: scopeID + "_${child.slotId}",`);
9170
9349
  lines.push(` BfParent: scopeID,`);
9171
9350
  lines.push(` BfMount: "${child.slotId}",`);
@@ -9185,7 +9364,7 @@ ${goFields.join(`
9185
9364
  lines.push(` ${varName} := make([]${wrapperType}, len(${dataVar}))`);
9186
9365
  lines.push(` for i, item := range ${dataVar} {`);
9187
9366
  lines.push(` ${varName}[i] = ${wrapperType}{`);
9188
- lines.push(` ${nested.name}Props: New${nested.name}Props(${nested.name}Input{`);
9367
+ lines.push(` ${declaredName}Props: New${declaredName}Props(${declaredName}Input{`);
9189
9368
  lines.push(` BfParent: scopeID,`);
9190
9369
  lines.push(` BfMount: "${nested.slotId}",`);
9191
9370
  for (const prop of nested.props ?? []) {
@@ -9240,9 +9419,11 @@ ${goFields.join(`
9240
9419
  const varName = `${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`;
9241
9420
  const datumFields = this.resolveLoopDatumFields(nested.loopItemType);
9242
9421
  const bodyChildInstances = this.collectBodyChildInstances(nested.bodyChildren, ir.metadata.propsParams);
9422
+ const declaredName = this.resolveChildName(nested.name);
9243
9423
  for (const child of bodyChildInstances) {
9244
9424
  const childVar = `child_${child.fieldName}`;
9245
- lines.push(` ${childVar} := New${child.name}Props(${child.name}Input{`);
9425
+ const childDeclaredName = this.resolveChildName(child.name);
9426
+ lines.push(` ${childVar} := New${childDeclaredName}Props(${childDeclaredName}Input{`);
9246
9427
  lines.push(` ScopeID: scopeID + "_${child.slotId}",`);
9247
9428
  lines.push(` BfParent: scopeID,`);
9248
9429
  lines.push(` BfMount: "${child.slotId}",`);
@@ -9261,7 +9442,7 @@ ${goFields.join(`
9261
9442
  lines.push(` ${varName} := make([]${wrapperType}, len(bakedData))`);
9262
9443
  lines.push(` for i, item := range bakedData {`);
9263
9444
  lines.push(` ${varName}[i] = ${wrapperType}{`);
9264
- lines.push(` ${nested.name}Props: New${nested.name}Props(${nested.name}Input{`);
9445
+ lines.push(` ${declaredName}Props: New${declaredName}Props(${declaredName}Input{`);
9265
9446
  lines.push(` BfParent: scopeID,`);
9266
9447
  lines.push(` BfMount: "${nested.slotId}",`);
9267
9448
  lines.push(` }),`);
@@ -9316,21 +9497,7 @@ ${goFields.join(`
9316
9497
  visit(prop.type, desiredName, prop.name);
9317
9498
  }
9318
9499
  const fields = this.structFieldsFor(typeInfo);
9319
- this.state.localStructFields.set(desiredName, new Map(fields.map((f) => [f.tsName, f.goName])));
9320
- this.state.currentTypeDefinitions.push({
9321
- kind: "type",
9322
- name: desiredName,
9323
- definition: "",
9324
- properties: typeInfo.properties ?? [],
9325
- loc: SYNTH_TYPE_LOC
9326
- });
9327
- const goFields = fields.map((f) => ` ${f.goName} ${f.goType} \`json:"${this.toJsonTag(f.tsName)}"\``);
9328
- lines.push(`// ${desiredName} is a synthesised type for an anonymous object type (#2674).`);
9329
- lines.push(`type ${desiredName} struct {
9330
- ${goFields.join(`
9331
- `)}
9332
- }`);
9333
- lines.push("");
9500
+ this.registerSynthStruct(lines, desiredName, fields, typeInfo.properties ?? [], `// ${desiredName} is a synthesised type for an anonymous object type (#2674).`);
9334
9501
  };
9335
9502
  const visitArrayElem = (elemType, parentName, propName) => {
9336
9503
  if (!elemType)
@@ -9382,20 +9549,11 @@ ${goFields.join(`
9382
9549
  const synth = this.synthesizeStructFromSignal(signal, componentName);
9383
9550
  if (!synth)
9384
9551
  continue;
9385
- this.state.localTypeNames.add(synth.name);
9386
- this.state.localStructFields.set(synth.name, new Map(synth.fields.map((f) => [f.tsName, f.goName])));
9387
- this.state.synthStructTypes.set(signal.getter, {
9388
- kind: "array",
9389
- raw: `${synth.name}[]`,
9390
- elementType: { kind: "interface", raw: synth.name }
9391
- });
9392
- const goFields = synth.fields.map((f) => ` ${f.goName} ${f.goType} \`json:"${this.toJsonTag(f.tsName)}"\``);
9393
- lines.push(`// ${synth.name} is a synthesised element type for the ${signal.getter} signal.`);
9394
- lines.push(`type ${synth.name} struct {
9395
- ${goFields.join(`
9396
- `)}
9397
- }`);
9398
- lines.push("");
9552
+ for (const s of synth) {
9553
+ this.registerSynthStruct(lines, s.name, s.fields, s.properties, `// ${s.name} is a synthesised element type for the ${signal.getter} signal.`);
9554
+ }
9555
+ const top = synth[synth.length - 1];
9556
+ this.state.synthStructTypes.set(signal.getter, this.synthSliceTypeInfo(top.name));
9399
9557
  }
9400
9558
  }
9401
9559
  resolveNestedLoopItemTypes(ir, nestedComponents) {
@@ -9538,7 +9696,7 @@ ${goFields.join(`
9538
9696
  for (const nested of nestedComponents) {
9539
9697
  if (this.isOrphanedClientOnlyNested(nested))
9540
9698
  continue;
9541
- const elemType = nested.bodyChildren?.length ? this.loopBodyWrapperName(componentName, nested) : `${nested.name}Props`;
9699
+ const elemType = nested.bodyChildren?.length ? this.loopBodyWrapperName(componentName, nested) : `${this.resolveChildName(nested.name)}Props`;
9542
9700
  if (nested.isDynamic && !nested.isPropDerived) {
9543
9701
  lines.push(` ${nested.name}s []${elemType} \`json:"-"\``);
9544
9702
  } else if (nested.isDynamic && nested.isPropDerived && !propDrivingFieldNames.has(`${nested.name}s`)) {
@@ -9550,7 +9708,7 @@ ${goFields.join(`
9550
9708
  }
9551
9709
  const staticChildren = this.collectStaticChildInstances(ir.root, ir.metadata.propsParams);
9552
9710
  for (const child of staticChildren) {
9553
- lines.push(` ${child.fieldName} ${child.name}Props \`json:"-"\``);
9711
+ lines.push(` ${child.fieldName} ${this.resolveChildName(child.name)}Props \`json:"-"\``);
9554
9712
  }
9555
9713
  for (const slot of spreadSlots) {
9556
9714
  const jsonTag = "-";
@@ -9929,6 +10087,22 @@ ${goFields.join(`
9929
10087
  resolvedSignalParsed(signal) {
9930
10088
  return resolveSignalParsedThroughSeedPlan(this.state, signal);
9931
10089
  }
10090
+ refuseUnbakeableDerivedObjectLiteral(name, loc, frees) {
10091
+ if (frees.length === 0)
10092
+ return;
10093
+ if (!this.state.templateReadRootFields.has(name))
10094
+ return;
10095
+ this.state.errors.push({
10096
+ code: "BF101",
10097
+ severity: "error",
10098
+ message: `Signal '${name}' is seeded from an object literal that references live value(s) (${frees.join(", ")}) — the Go template adapter bakes object-typed signal values into Go source at New${this.state.componentName}Props time, and that baker is static-only (identifier/member/call operands defer), so the SSR template's read of it would see the Go zero value instead of the derived object.`,
10099
+ loc,
10100
+ suggestion: {
10101
+ message: `Wrap each SSR read of '${name}()' in /* @client */ so it renders on the client instead, or pass the already-derived object in as a prop.`,
10102
+ escape: [{ kind: "client-directive" }]
10103
+ }
10104
+ });
10105
+ }
9932
10106
  extractPropFallback(initialValue, preParsed) {
9933
10107
  const structural = preParsed ? this.extractPropFallbackFromParsed(preParsed) : null;
9934
10108
  if (structural)
@@ -10257,6 +10431,7 @@ ${goFields.join(`
10257
10431
  return hit !== null && hit.depth > 0 && hit.binding.source === "item";
10258
10432
  }
10259
10433
  rootFieldRef(name) {
10434
+ this.state.templateReadRootFields.add(name);
10260
10435
  const prefix = this.inLoop ? "$." : ".";
10261
10436
  return `${prefix}${capitalizeFieldName(name)}`;
10262
10437
  }
@@ -10278,6 +10453,9 @@ ${goFields.join(`
10278
10453
  return null;
10279
10454
  return `"${escapeGoString(value)}"`;
10280
10455
  }
10456
+ findModuleConst(name) {
10457
+ return this.state.localConstants.find((k) => k.name === name && k.isModule && !k.containsArrow);
10458
+ }
10281
10459
  resolveModuleNumericConst(name) {
10282
10460
  if (this.isCurrentLoopItem(name))
10283
10461
  return null;
@@ -10285,12 +10463,25 @@ ${goFields.join(`
10285
10463
  return null;
10286
10464
  if (this.isOuterLoopParam(name))
10287
10465
  return null;
10288
- const c = this.state.localConstants.find((k) => k.name === name && k.isModule && !k.containsArrow);
10466
+ const c = this.findModuleConst(name);
10289
10467
  if (!c || c.value === undefined)
10290
10468
  return null;
10291
10469
  const v = c.value.trim().replace(/(?<=\d)_(?=\d)/g, "");
10292
10470
  return /^-?\d+(\.\d+)?$/.test(v) ? v : null;
10293
10471
  }
10472
+ resolveModuleBooleanConst(name) {
10473
+ if (this.isCurrentLoopItem(name))
10474
+ return null;
10475
+ if (this.loopVarRefCount.has(name))
10476
+ return null;
10477
+ if (this.isOuterLoopParam(name))
10478
+ return null;
10479
+ const c = this.findModuleConst(name);
10480
+ if (!c || c.value === undefined)
10481
+ return null;
10482
+ const v = c.value.trim();
10483
+ return v === "true" || v === "false" ? v : null;
10484
+ }
10294
10485
  literal(value, literalType) {
10295
10486
  if (literalType === "string")
10296
10487
  return `"${value}"`;
@@ -10299,6 +10490,9 @@ ${goFields.join(`
10299
10490
  return String(value);
10300
10491
  }
10301
10492
  call(callee, args, emit) {
10493
+ const lowered = lowerRegisteredCallNode(this.emitCtx, callee, args);
10494
+ if (lowered !== null)
10495
+ return lowered;
10302
10496
  if (callee.kind === "identifier" && args.length === 0) {
10303
10497
  return this.searchParamsFieldRef(callee.name) ?? this.rootFieldRef(callee.name);
10304
10498
  }
@@ -10928,8 +11122,10 @@ ${goFields.join(`
10928
11122
  }
10929
11123
  const signal = localVarMap.get(expr.name);
10930
11124
  if (signal) {
11125
+ this.rootFieldRef(signal);
10931
11126
  return `$.${capitalizeFieldName(signal)}`;
10932
11127
  }
11128
+ this.rootFieldRef(expr.name);
10933
11129
  return `.${capitalizeFieldName(expr.name)}`;
10934
11130
  }
10935
11131
  case "literal":
@@ -10962,6 +11158,7 @@ ${goFields.join(`
10962
11158
  return `${paramPrefix}.${capitalizeFieldName(expr.callee.property)}`;
10963
11159
  }
10964
11160
  if (expr.callee.kind === "identifier" && expr.args.length === 0) {
11161
+ this.rootFieldRef(expr.callee.name);
10965
11162
  return `$.${capitalizeFieldName(expr.callee.name)}`;
10966
11163
  }
10967
11164
  if (asCallbackMethodCall(expr) !== null) {
@@ -11134,7 +11331,8 @@ ${goFields.join(`
11134
11331
  return this.scope.isBound(name) || this.loopVarRefCount.has(name);
11135
11332
  }
11136
11333
  loopRowChildPropOverrides(comp) {
11137
- const childShape = this.childComponentShapes.get(comp.name);
11334
+ const declaredName = this.resolveChildName(comp.name);
11335
+ const childShape = this.childComponentShapes.get(declaredName);
11138
11336
  const args = [];
11139
11337
  let needsRebuild = false;
11140
11338
  for (const prop of comp.props) {
@@ -11154,10 +11352,10 @@ ${goFields.join(`
11154
11352
  if (!free || ![...free].some((name) => this.isLoopShadowedName(name)))
11155
11353
  continue;
11156
11354
  {
11157
- const derived = this.childDerivedFieldDeps.get(comp.name);
11355
+ const derived = this.childDerivedFieldDeps.get(declaredName);
11158
11356
  const overriddenField = capitalizeFieldName(prop.name);
11159
11357
  const staleField = derived ? [...derived].find(([, deps]) => deps.has(overriddenField))?.[0] : undefined;
11160
- if (staleField && !this.childRepropsReady.has(comp.name)) {
11358
+ if (staleField && !this.childRepropsReady.has(declaredName)) {
11161
11359
  this.state.errors.push({
11162
11360
  code: "BF101",
11163
11361
  severity: "error",
@@ -11171,8 +11369,8 @@ ${goFields.join(`
11171
11369
  }
11172
11370
  if (staleField) {
11173
11371
  needsRebuild = true;
11174
- if (!this.repropsOwner.has(comp.name)) {
11175
- this.repropsOwner.set(comp.name, this.state.componentName);
11372
+ if (!this.repropsOwner.has(declaredName)) {
11373
+ this.repropsOwner.set(declaredName, this.state.componentName);
11176
11374
  }
11177
11375
  }
11178
11376
  }
@@ -11198,7 +11396,7 @@ ${goFields.join(`
11198
11396
  });
11199
11397
  continue;
11200
11398
  }
11201
- const fieldName = this.childPropFieldNames.get(comp.name)?.get(prop.name) ?? capitalizeFieldName(prop.name);
11399
+ const fieldName = this.childPropFieldNames.get(declaredName)?.get(prop.name) ?? capitalizeFieldName(prop.name);
11202
11400
  args.push(`${JSON.stringify(fieldName)} ${wrapIfMultiToken(go)}`);
11203
11401
  }
11204
11402
  if (args.length === 0)
@@ -11744,7 +11942,8 @@ ${goFields.join(`
11744
11942
  }
11745
11943
  queueDynamicPropDefine(comp) {
11746
11944
  const args = [];
11747
- const childShape = this.childComponentShapes.get(comp.name);
11945
+ const declaredName = this.resolveChildName(comp.name);
11946
+ const childShape = this.childComponentShapes.get(declaredName);
11748
11947
  for (const prop of comp.props) {
11749
11948
  if (prop.value.kind !== "jsx-children" || prop.name === "children")
11750
11949
  continue;
@@ -11771,7 +11970,7 @@ ${goFields.join(`
11771
11970
  content: this.renderChildren(children)
11772
11971
  });
11773
11972
  }
11774
- const fieldName = this.childPropFieldNames.get(comp.name)?.get(prop.name) ?? capitalizeFieldName(prop.name);
11973
+ const fieldName = this.childPropFieldNames.get(declaredName)?.get(prop.name) ?? capitalizeFieldName(prop.name);
11775
11974
  args.push(`${JSON.stringify(fieldName)} (bf_tmpl ${JSON.stringify(name)} .)`);
11776
11975
  }
11777
11976
  return args.length > 0 ? args.join(" ") : null;
@@ -11803,31 +12002,32 @@ ${goFields.join(`
11803
12002
  if (comp.dynamicTag) {
11804
12003
  return this.renderChildren(comp.children);
11805
12004
  }
12005
+ const declaredName = this.resolveChildName(comp.name);
11806
12006
  let templateCall;
11807
12007
  if (this.inLoop && (this.loopWrapperStack[this.loopWrapperStack.length - 1] ?? false)) {
11808
12008
  const loopBodyDefine = this.queueLoopBodyChildrenDefine(comp);
11809
12009
  if (loopBodyDefine) {
11810
12010
  const bodyData = this.loopScalarItemStack[this.loopScalarItemStack.length - 1] ? ".BfLoopItem" : ".";
11811
- templateCall = `{{template "${comp.name}" (bf_with_children . (bf_tmpl "${loopBodyDefine}" ${bodyData}))}}`;
12011
+ templateCall = `{{template "${declaredName}" (bf_with_children . (bf_tmpl "${loopBodyDefine}" ${bodyData}))}}`;
11812
12012
  } else {
11813
- templateCall = `{{template "${comp.name}" .}}`;
12013
+ templateCall = `{{template "${declaredName}" .}}`;
11814
12014
  }
11815
12015
  } else if (this.inLoop && comp.slotId) {
11816
12016
  const suffix = slotIdToFieldSuffix(comp.slotId);
11817
12017
  const overrides = this.loopRowChildPropOverrides(comp);
11818
12018
  const loopBodyDefine = this.queueLoopBodyChildrenDefine(comp);
11819
- const base = overrides ? overrides.helper === "bf_reprops" ? `(bf_reprops ${JSON.stringify(comp.name)} $.${comp.name}${suffix} ${overrides.args})` : `(bf_with_props $.${comp.name}${suffix} ${overrides.args})` : `$.${comp.name}${suffix}`;
11820
- templateCall = loopBodyDefine ? `{{template "${comp.name}" (bf_with_children ${base} (bf_tmpl "${loopBodyDefine}" .))}}` : `{{template "${comp.name}" ${base}}}`;
12019
+ const base = overrides ? overrides.helper === "bf_reprops" ? `(bf_reprops ${JSON.stringify(declaredName)} $.${comp.name}${suffix} ${overrides.args})` : `(bf_with_props $.${comp.name}${suffix} ${overrides.args})` : `$.${comp.name}${suffix}`;
12020
+ templateCall = loopBodyDefine ? `{{template "${declaredName}" (bf_with_children ${base} (bf_tmpl "${loopBodyDefine}" .))}}` : `{{template "${declaredName}" ${base}}}`;
11821
12021
  } else if (this.inLoop) {
11822
- templateCall = `{{template "${comp.name}" .}}`;
12022
+ templateCall = `{{template "${declaredName}" .}}`;
11823
12023
  } else if (comp.slotId) {
11824
12024
  const suffix = slotIdToFieldSuffix(comp.slotId);
11825
12025
  const childrenDefine = this.queueDynamicChildrenDefine(comp);
11826
12026
  const propArgs = this.queueDynamicPropDefine(comp);
11827
12027
  const base = propArgs ? `(bf_with_props .${comp.name}${suffix} ${propArgs})` : `.${comp.name}${suffix}`;
11828
- templateCall = childrenDefine ? `{{template "${comp.name}" (bf_with_children ${base} (bf_tmpl "${childrenDefine}" .))}}` : `{{template "${comp.name}" ${base}}}`;
12028
+ templateCall = childrenDefine ? `{{template "${declaredName}" (bf_with_children ${base} (bf_tmpl "${childrenDefine}" .))}}` : `{{template "${declaredName}" ${base}}}`;
11829
12029
  } else {
11830
- templateCall = `{{template "${comp.name}" .${comp.name}}}`;
12030
+ templateCall = `{{template "${declaredName}" .${comp.name}}}`;
11831
12031
  }
11832
12032
  if (ctx?.isRootOfClientComponent) {
11833
12033
  return `{{bfScopeComment .}}${templateCall}`;
@@ -11878,15 +12078,21 @@ ${children}`;
11878
12078
  const test = parsed.test;
11879
12079
  if (undef(parsed.alternate) && !undef(parsed.consequent)) {
11880
12080
  const { condition: goCond, preamble } = this.convertConditionToGo(this.isTemplateFragment(this.renderParsedExpr(test), test.kind) ? value.expr : value.expr.slice(0, value.expr.indexOf("?")).trim());
11881
- const valueExpr = this.renderParsedExpr(parsed.consequent);
11882
- const body = `${name}="{{${valueExpr}}}"`;
12081
+ const attrConsequent = lowerRegisteredAttrCall(this.emitCtx, name, parsed.consequent);
12082
+ const body = attrConsequent !== null ? attrConsequent : `${name}="{{${this.renderParsedExpr(parsed.consequent)}}}"`;
11883
12083
  return `${preamble}{{if ${goCond}}}${body}{{end}}`;
11884
12084
  }
12085
+ const attrTernary = lowerRegisteredAttrCall(this.emitCtx, name, parsed);
12086
+ if (attrTernary !== null)
12087
+ return attrTernary;
11885
12088
  return `${name}="{{${this.renderParsedExpr(parsed)}}}"`;
11886
12089
  }
11887
12090
  if (parsed.kind === "template-literal") {
11888
12091
  return `${name}="${this.renderParsedExpr(parsed)}"`;
11889
12092
  }
12093
+ const attrAction = lowerRegisteredAttrCall(this.emitCtx, name, parsed);
12094
+ if (attrAction !== null)
12095
+ return attrAction;
11890
12096
  const bareId = value.expr.trim();
11891
12097
  const propName = this.state.propsObjectName && bareId.startsWith(`${this.state.propsObjectName}.`) ? bareId.slice(this.state.propsObjectName.length + 1) : bareId;
11892
12098
  if (/^[A-Za-z_$][\w$]*$/.test(propName) && this.state.nillablePropNames.has(propName)) {