@barefootjs/go-template 0.31.0 → 0.31.2

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.
Files changed (35) hide show
  1. package/dist/adapter/go-template-adapter.d.ts +49 -41
  2. package/dist/adapter/go-template-adapter.d.ts.map +1 -1
  3. package/dist/adapter/index.js +167 -101
  4. package/dist/adapter/lib/types.d.ts +4 -1
  5. package/dist/adapter/lib/types.d.ts.map +1 -1
  6. package/dist/adapter/memo/memo-compute.d.ts +9 -0
  7. package/dist/adapter/memo/memo-compute.d.ts.map +1 -1
  8. package/dist/adapter/memo/memo-type.d.ts +2 -0
  9. package/dist/adapter/memo/memo-type.d.ts.map +1 -1
  10. package/dist/adapter/props/prop-types.d.ts +2 -1
  11. package/dist/adapter/props/prop-types.d.ts.map +1 -1
  12. package/dist/adapter/spread/spread-codegen.d.ts.map +1 -1
  13. package/dist/adapter/type/type-codegen.d.ts +22 -5
  14. package/dist/adapter/type/type-codegen.d.ts.map +1 -1
  15. package/dist/adapter/value/parsed-literal-to-go.d.ts +12 -0
  16. package/dist/adapter/value/parsed-literal-to-go.d.ts.map +1 -1
  17. package/dist/adapter/value/value-lowering.d.ts +3 -0
  18. package/dist/adapter/value/value-lowering.d.ts.map +1 -1
  19. package/dist/index.js +168 -104
  20. package/dist/render-divergences.d.ts +6 -0
  21. package/dist/render-divergences.d.ts.map +1 -1
  22. package/dist/vite.js +493 -192
  23. package/package.json +5 -5
  24. package/src/__tests__/go-template-adapter.test.ts +155 -10
  25. package/src/adapter/go-template-adapter.ts +213 -128
  26. package/src/adapter/lib/types.ts +4 -1
  27. package/src/adapter/memo/memo-compute.ts +21 -17
  28. package/src/adapter/memo/memo-type.ts +5 -5
  29. package/src/adapter/props/prop-types.ts +6 -5
  30. package/src/adapter/spread/spread-codegen.ts +12 -5
  31. package/src/adapter/type/type-codegen.ts +86 -25
  32. package/src/adapter/value/parsed-literal-to-go.ts +28 -10
  33. package/src/adapter/value/value-lowering.ts +65 -29
  34. package/src/render-divergences.ts +6 -15
  35. package/src/test-render.ts +6 -1
package/dist/vite.js CHANGED
@@ -4,8 +4,11 @@ import { resolve } from "node:path";
4
4
  import { barefoot as coreBarefoot } from "@barefootjs/vite";
5
5
  import { devModuleUrl, loadManifest, resolveDevOrigin, resolveScriptAssets, toPosixRelative } from "@barefootjs/vite";
6
6
 
7
+ // ../jsx/src/compiler.ts
8
+ import ts23 from "typescript";
9
+
7
10
  // ../jsx/src/analyzer.ts
8
- import ts8 from "typescript";
11
+ import ts9 from "typescript";
9
12
 
10
13
  // ../jsx/src/expression-parser.ts
11
14
  import ts from "typescript";
@@ -1920,6 +1923,29 @@ import ts5 from "typescript";
1920
1923
  // ../jsx/src/ir-to-client-js/utils.ts
1921
1924
  import ts3 from "typescript";
1922
1925
 
1926
+ // ../jsx/src/template-parts.ts
1927
+ function lookupPartToJsExpr(part, opts) {
1928
+ const key = opts?.useTemplate && part.templateKey ? part.templateKey : part.key;
1929
+ const obj = "{" + Object.entries(part.cases).map(([k, v]) => `${JSON.stringify(k)}: ${JSON.stringify(v)}`).join(", ") + "}";
1930
+ const typed = opts?.typed ? " as Record<string, string>" : "";
1931
+ return `(${obj}${typed})[${key}]`;
1932
+ }
1933
+ function templatePartsToJsExpr(parts, opts) {
1934
+ let result = "`";
1935
+ for (const part of parts) {
1936
+ if (part.type === "string") {
1937
+ result += opts?.useTemplate && part.templateValue ? part.templateValue : part.value;
1938
+ } else if (part.type === "ternary") {
1939
+ const cond = opts?.useTemplate && part.templateCondition ? part.templateCondition : part.condition;
1940
+ result += `\${${cond} ? '${part.whenTrue}' : '${part.whenFalse}'}`;
1941
+ } else if (part.type === "lookup") {
1942
+ result += `\${${lookupPartToJsExpr(part, opts)}}`;
1943
+ }
1944
+ }
1945
+ result += "`";
1946
+ return result;
1947
+ }
1948
+
1923
1949
  // ../jsx/src/scanner/js-scanner.ts
1924
1950
  import ts2 from "typescript";
1925
1951
  function* iterateJsTokens(text, start = 0, end = text.length) {
@@ -2098,6 +2124,16 @@ function escapeHtml(text) {
2098
2124
  }
2099
2125
  // ../jsx/src/ir-to-client-js/csr-substitute.ts
2100
2126
  import ts4 from "typescript";
2127
+ function extractFreeIdentifiersFromText(text) {
2128
+ if (!text || text.trim().length === 0)
2129
+ return new Set;
2130
+ const sf = ts4.createSourceFile("__free_ids__.ts", `(${text});`, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
2131
+ const stmt = sf.statements[0];
2132
+ if (!stmt || !ts4.isExpressionStatement(stmt))
2133
+ return new Set;
2134
+ const expr = ts4.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
2135
+ return extractFreeIdentifiersFromNode(expr);
2136
+ }
2101
2137
 
2102
2138
  // ../jsx/src/ir-to-client-js/html-template.ts
2103
2139
  var VOID_ELEMENTS = new Set([
@@ -2143,6 +2179,27 @@ var SKELETON_PATH_FORCE_CLOSE_GROUPS = [
2143
2179
  new Set(["li"])
2144
2180
  ];
2145
2181
 
2182
+ // ../jsx/src/props-binding.ts
2183
+ import ts6 from "typescript";
2184
+ function isIdentifierName(key) {
2185
+ if (key.length === 0)
2186
+ return false;
2187
+ for (let i = 0;i < key.length; ) {
2188
+ const cp = key.codePointAt(i);
2189
+ const ok = i === 0 ? ts6.isIdentifierStart(cp, ts6.ScriptTarget.Latest) : ts6.isIdentifierPart(cp, ts6.ScriptTarget.Latest);
2190
+ if (!ok)
2191
+ return false;
2192
+ i += cp > 65535 ? 2 : 1;
2193
+ }
2194
+ return true;
2195
+ }
2196
+ function propsDestructureBinding(p) {
2197
+ const callerKey = p.sourceName ?? p.name;
2198
+ const localName = p.name;
2199
+ const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
2200
+ return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
2201
+ }
2202
+
2146
2203
  // ../jsx/src/instrumentation.ts
2147
2204
  var _counters = freshCounters();
2148
2205
  function freshCounters() {
@@ -2156,14 +2213,14 @@ function freshCounters() {
2156
2213
  }
2157
2214
 
2158
2215
  // ../jsx/src/analyzer-context.ts
2159
- import ts7 from "typescript";
2216
+ import ts8 from "typescript";
2160
2217
 
2161
2218
  // ../jsx/src/strip-types.ts
2162
- import ts6 from "typescript";
2219
+ import ts7 from "typescript";
2163
2220
 
2164
2221
  // ../jsx/src/analyzer-context.ts
2165
- var _typePrinter = ts7.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
2166
- var _blankTypeSourceFile = ts7.createSourceFile("__bf_types__.ts", "", ts7.ScriptTarget.Latest);
2222
+ var _typePrinter = ts8.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
2223
+ var _blankTypeSourceFile = ts8.createSourceFile("__bf_types__.ts", "", ts8.ScriptTarget.Latest);
2167
2224
 
2168
2225
  // ../jsx/src/errors.ts
2169
2226
  var ErrorCodes = {
@@ -2179,6 +2236,7 @@ var ErrorCodes = {
2179
2236
  JSX_IN_LOCAL_FUNCTION: "BF045",
2180
2237
  COMPONENT_REQUIRED_PROP_MISSING: "BF046",
2181
2238
  JSX_BRANCH_LOCAL_IN_CALLBACK: "BF047",
2239
+ SIBLING_COMPONENT_NOT_COMPILED: "BF048",
2182
2240
  SHARED_PROGRAM_REQUIRED: "BF050",
2183
2241
  WRONG_PACKAGE_IMPORT: "BF051",
2184
2242
  BUILTIN_REQUIRES_IMPORT: "BF054",
@@ -2208,6 +2266,7 @@ var errorMessages = {
2208
2266
  [ErrorCodes.JSX_IN_LOCAL_FUNCTION]: "Local function returns JSX but cannot be inlined. Extract it as a top-level PascalCase component or use a single return statement.",
2209
2267
  [ErrorCodes.COMPONENT_REQUIRED_PROP_MISSING]: "Built-in component is missing a required prop.",
2210
2268
  [ErrorCodes.JSX_BRANCH_LOCAL_IN_CALLBACK]: "JSX-typed local declared inside an `if`-block cannot be referenced from a callback body (ref / event handler). " + "Render it as a child instead: `<div ref={...}>{local}</div>`.",
2269
+ [ErrorCodes.SIBLING_COMPONENT_NOT_COMPILED]: "Referenced component did not compile to a template, so this reference would throw " + "`ReferenceError` at render time. Multi-return JSX dispatch (a `switch` or `if`/`else` " + "chain across multiple JSX-returning branches) cannot compile as a component in a " + `'use client' file. Extract it to a separate non-"use client" file (where it is preserved ` + "verbatim, see #932), or rewrite it as a single-return ternary/conditional chain so the " + "component pipeline can compile it.",
2211
2270
  [ErrorCodes.SHARED_PROGRAM_REQUIRED]: "Shared ts.Program required for type-based reactivity classification. This source imports a Reactive<T>-branded library (e.g. @barefootjs/form) whose getters cannot be classified by regex alone. Pass `options.program` (built via `createProgramForCorpus`) so the analyzer can resolve the brand through the TypeChecker.",
2212
2271
  [ErrorCodes.WRONG_PACKAGE_IMPORT]: "Import from wrong package.",
2213
2272
  [ErrorCodes.BUILTIN_REQUIRES_IMPORT]: "Built-in <Async> / <Region> must be imported from '@barefootjs/client'. " + "The compiler recognises these tags by their import (not by tag name), " + "so an unimported tag with this name is treated as an undeclared component.",
@@ -2381,6 +2440,54 @@ var CLIENT_EXPORTS = new Set([
2381
2440
  "Async",
2382
2441
  "Region"
2383
2442
  ]);
2443
+ function extractFreeIdentifiersFromNode(node) {
2444
+ const ids = new Set;
2445
+ const boundNames = new Set;
2446
+ function addBindingNames(name, out) {
2447
+ if (ts9.isIdentifier(name))
2448
+ out.push(name.text);
2449
+ else if (ts9.isObjectBindingPattern(name))
2450
+ name.elements.forEach((e) => addBindingNames(e.name, out));
2451
+ else if (ts9.isArrayBindingPattern(name))
2452
+ name.elements.forEach((e) => {
2453
+ if (!ts9.isOmittedExpression(e))
2454
+ addBindingNames(e.name, out);
2455
+ });
2456
+ }
2457
+ function visit(n) {
2458
+ if (ts9.isTypeNode(n))
2459
+ return;
2460
+ if (ts9.isIdentifier(n)) {
2461
+ const parent = n.parent;
2462
+ if (parent && ts9.isPropertyAccessExpression(parent) && parent.name === n)
2463
+ return;
2464
+ if (parent && ts9.isPropertyAssignment(parent) && parent.name === n)
2465
+ return;
2466
+ if (parent && ts9.isParameter(parent) && parent.name === n)
2467
+ return;
2468
+ if (parent && ts9.isVariableDeclaration(parent) && parent.name === n)
2469
+ return;
2470
+ if (boundNames.has(n.text))
2471
+ return;
2472
+ ids.add(n.text);
2473
+ return;
2474
+ }
2475
+ if (ts9.isArrowFunction(n)) {
2476
+ const params = [];
2477
+ for (const p of n.parameters)
2478
+ addBindingNames(p.name, params);
2479
+ for (const name of params)
2480
+ boundNames.add(name);
2481
+ ts9.forEachChild(n, visit);
2482
+ for (const name of params)
2483
+ boundNames.delete(name);
2484
+ return;
2485
+ }
2486
+ ts9.forEachChild(n, visit);
2487
+ }
2488
+ visit(node);
2489
+ return ids;
2490
+ }
2384
2491
  var BROWSER_ONLY_CLIENT_APIS = new Set([
2385
2492
  "useContext",
2386
2493
  "provideContext",
@@ -2399,7 +2506,7 @@ var REACTIVE_PRIMITIVES = new Set([
2399
2506
  ]);
2400
2507
 
2401
2508
  // ../jsx/src/jsx-to-ir.ts
2402
- import ts11 from "typescript";
2509
+ import ts12 from "typescript";
2403
2510
 
2404
2511
  // ../jsx/src/types.ts
2405
2512
  var SCOPE_FORBIDDEN = {
@@ -2481,10 +2588,10 @@ function findReachableNames(primaryRefs, declarations) {
2481
2588
  }
2482
2589
 
2483
2590
  // ../jsx/src/reactivity-checker.ts
2484
- import ts9 from "typescript";
2591
+ import ts10 from "typescript";
2485
2592
 
2486
2593
  // ../jsx/src/free-refs.ts
2487
- import ts10 from "typescript";
2594
+ import ts11 from "typescript";
2488
2595
  var _bindingMapCache = new WeakMap;
2489
2596
 
2490
2597
  // ../jsx/src/to-locale-date-lowering.ts
@@ -2898,13 +3005,13 @@ var KEYWORDS_AND_GLOBALS = new Set([
2898
3005
  ]);
2899
3006
 
2900
3007
  // ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
2901
- import ts12 from "typescript";
3008
+ import ts13 from "typescript";
2902
3009
 
2903
3010
  // ../jsx/src/value-references.ts
2904
- import ts13 from "typescript";
3011
+ import ts14 from "typescript";
2905
3012
 
2906
3013
  // ../jsx/src/relocate.ts
2907
- import ts14 from "typescript";
3014
+ import ts15 from "typescript";
2908
3015
 
2909
3016
  // ../jsx/src/lowering-registry.ts
2910
3017
  var plugins = [];
@@ -3100,10 +3207,10 @@ function formatDateLocalNames(metadata) {
3100
3207
  }
3101
3208
 
3102
3209
  // ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
3103
- import ts15 from "typescript";
3210
+ import ts16 from "typescript";
3104
3211
 
3105
3212
  // ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
3106
- import ts16 from "typescript";
3213
+ import ts17 from "typescript";
3107
3214
  var NO_PREAMBLE = {
3108
3215
  lazySafe: true,
3109
3216
  facts: { declaredNames: new Set, freeNames: new Set }
@@ -3153,7 +3260,7 @@ var INERT_BINDING_GLOBALS = new Set([
3153
3260
  ]);
3154
3261
 
3155
3262
  // ../jsx/src/ir-to-client-js/emit-reactive.ts
3156
- import ts17 from "typescript";
3263
+ import ts18 from "typescript";
3157
3264
 
3158
3265
  // ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
3159
3266
  var NON_BUBBLING_EVENTS = new Set([
@@ -3168,7 +3275,7 @@ var NON_BUBBLING_EVENTS = new Set([
3168
3275
  ]);
3169
3276
 
3170
3277
  // ../jsx/src/ir-to-client-js/rewrite-props-object.ts
3171
- import ts18 from "typescript";
3278
+ import ts19 from "typescript";
3172
3279
 
3173
3280
  // ../jsx/src/ir-to-client-js/source-map.ts
3174
3281
  var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -3259,15 +3366,15 @@ class SourceMapGenerator {
3259
3366
  }
3260
3367
 
3261
3368
  // ../jsx/src/preprocess-inline-jsx-callbacks.ts
3262
- import ts19 from "typescript";
3369
+ import ts20 from "typescript";
3263
3370
 
3264
3371
  // ../jsx/src/ssr-defaults.ts
3265
- import ts20 from "typescript";
3372
+ import ts21 from "typescript";
3266
3373
  var UNRESOLVED = Symbol("unresolved");
3267
3374
  var NO_RETURN = Symbol("no-return");
3268
3375
 
3269
3376
  // ../jsx/src/augment-inherited-props.ts
3270
- import ts21 from "typescript";
3377
+ import ts22 from "typescript";
3271
3378
  function collectContextConsumers(metadata) {
3272
3379
  const constants = metadata.localConstants ?? [];
3273
3380
  const contextDefaults = new Map;
@@ -3299,47 +3406,47 @@ function collectContextConsumers(metadata) {
3299
3406
  }
3300
3407
  function parseUseContextArg(source) {
3301
3408
  const expr = parseSingleExpression(source);
3302
- if (!expr || !ts21.isCallExpression(expr))
3409
+ if (!expr || !ts22.isCallExpression(expr))
3303
3410
  return null;
3304
- if (!ts21.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3411
+ if (!ts22.isIdentifier(expr.expression) || expr.expression.text !== "useContext")
3305
3412
  return null;
3306
3413
  if (expr.arguments.length !== 1)
3307
3414
  return null;
3308
3415
  const arg = expr.arguments[0];
3309
- return ts21.isIdentifier(arg) ? arg.text : null;
3416
+ return ts22.isIdentifier(arg) ? arg.text : null;
3310
3417
  }
3311
3418
  function parseCreateContextDefault(source) {
3312
3419
  const expr = parseSingleExpression(source);
3313
- if (!expr || !ts21.isCallExpression(expr))
3420
+ if (!expr || !ts22.isCallExpression(expr))
3314
3421
  return null;
3315
3422
  if (expr.arguments.length === 0)
3316
3423
  return null;
3317
3424
  const arg = expr.arguments[0];
3318
- if (ts21.isStringLiteral(arg) || ts21.isNoSubstitutionTemplateLiteral(arg))
3425
+ if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3319
3426
  return arg.text;
3320
- if (ts21.isNumericLiteral(arg))
3427
+ if (ts22.isNumericLiteral(arg))
3321
3428
  return Number(arg.text);
3322
- if (arg.kind === ts21.SyntaxKind.TrueKeyword)
3429
+ if (arg.kind === ts22.SyntaxKind.TrueKeyword)
3323
3430
  return true;
3324
- if (arg.kind === ts21.SyntaxKind.FalseKeyword)
3431
+ if (arg.kind === ts22.SyntaxKind.FalseKeyword)
3325
3432
  return false;
3326
3433
  return null;
3327
3434
  }
3328
3435
  function isObjectLiteralCreateContextDefault(source) {
3329
3436
  const expr = parseSingleExpression(source);
3330
- if (!expr || !ts21.isCallExpression(expr))
3437
+ if (!expr || !ts22.isCallExpression(expr))
3331
3438
  return false;
3332
3439
  if (expr.arguments.length === 0)
3333
3440
  return false;
3334
- return ts21.isObjectLiteralExpression(expr.arguments[0]);
3441
+ return ts22.isObjectLiteralExpression(expr.arguments[0]);
3335
3442
  }
3336
3443
  function parseSingleExpression(source) {
3337
- const sf = ts21.createSourceFile("__ctx.ts", `(${source})`, ts21.ScriptTarget.Latest, false);
3444
+ const sf = ts22.createSourceFile("__ctx.ts", `(${source})`, ts22.ScriptTarget.Latest, false);
3338
3445
  const stmt = sf.statements[0];
3339
- if (!stmt || !ts21.isExpressionStatement(stmt))
3446
+ if (!stmt || !ts22.isExpressionStatement(stmt))
3340
3447
  return null;
3341
3448
  let e = stmt.expression;
3342
- while (ts21.isParenthesizedExpression(e))
3449
+ while (ts22.isParenthesizedExpression(e))
3343
3450
  e = e.expression;
3344
3451
  return e;
3345
3452
  }
@@ -3364,25 +3471,25 @@ function augmentInheritedPropAccesses(ir) {
3364
3471
  const pinCoalesceLiterals = (s) => {
3365
3472
  if (!s || !s.includes(propsObj))
3366
3473
  return;
3367
- const sf = ts21.createSourceFile("__aug.ts", `(${s})`, ts21.ScriptTarget.Latest, false);
3474
+ const sf = ts22.createSourceFile("__aug.ts", `(${s})`, ts22.ScriptTarget.Latest, false);
3368
3475
  const visit = (n) => {
3369
- if (ts21.isBinaryExpression(n) && (n.operatorToken.kind === ts21.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts21.SyntaxKind.BarBarToken)) {
3476
+ if (ts22.isBinaryExpression(n) && (n.operatorToken.kind === ts22.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts22.SyntaxKind.BarBarToken)) {
3370
3477
  let left = n.left;
3371
- while (ts21.isParenthesizedExpression(left))
3478
+ while (ts22.isParenthesizedExpression(left))
3372
3479
  left = left.expression;
3373
- if (ts21.isPropertyAccessExpression(left) && ts21.isIdentifier(left.expression) && left.expression.text === propsObj) {
3480
+ if (ts22.isPropertyAccessExpression(left) && ts22.isIdentifier(left.expression) && left.expression.text === propsObj) {
3374
3481
  const name = left.name.text;
3375
3482
  let right = n.right;
3376
- while (ts21.isParenthesizedExpression(right))
3483
+ while (ts22.isParenthesizedExpression(right))
3377
3484
  right = right.expression;
3378
- if (ts21.isPrefixUnaryExpression(right))
3485
+ if (ts22.isPrefixUnaryExpression(right))
3379
3486
  right = right.operand;
3380
- const kind = ts21.isNumericLiteral(right) ? "number" : right.kind === ts21.SyntaxKind.TrueKeyword || right.kind === ts21.SyntaxKind.FalseKeyword ? "boolean" : ts21.isStringLiteralLike(right) ? "string" : null;
3487
+ const kind = ts22.isNumericLiteral(right) ? "number" : right.kind === ts22.SyntaxKind.TrueKeyword || right.kind === ts22.SyntaxKind.FalseKeyword ? "boolean" : ts22.isStringLiteralLike(right) ? "string" : null;
3381
3488
  if (kind && !coalesceLiteralTypes.has(name))
3382
3489
  coalesceLiteralTypes.set(name, kind);
3383
3490
  }
3384
3491
  }
3385
- ts21.forEachChild(n, visit);
3492
+ ts22.forEachChild(n, visit);
3386
3493
  };
3387
3494
  visit(sf);
3388
3495
  };
@@ -3493,33 +3600,33 @@ function augmentInheritedPropAccesses(ir) {
3493
3600
  }
3494
3601
  }
3495
3602
  function parseStaticStringConst(source) {
3496
- const sf = ts21.createSourceFile("__const.ts", `const __x = (${source});`, ts21.ScriptTarget.Latest, false);
3603
+ const sf = ts22.createSourceFile("__const.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3497
3604
  const stmt = sf.statements[0];
3498
- if (!stmt || !ts21.isVariableStatement(stmt))
3605
+ if (!stmt || !ts22.isVariableStatement(stmt))
3499
3606
  return null;
3500
3607
  let init = stmt.declarationList.declarations[0]?.initializer;
3501
- while (init && ts21.isParenthesizedExpression(init))
3608
+ while (init && ts22.isParenthesizedExpression(init))
3502
3609
  init = init.expression;
3503
3610
  if (!init)
3504
3611
  return null;
3505
- if (ts21.isStringLiteral(init) || ts21.isNoSubstitutionTemplateLiteral(init)) {
3612
+ if (ts22.isStringLiteral(init) || ts22.isNoSubstitutionTemplateLiteral(init)) {
3506
3613
  return init.text;
3507
3614
  }
3508
3615
  return evalStringArrayJoin(source);
3509
3616
  }
3510
3617
  function evalTemplateOfStringConsts(source, resolved) {
3511
- const sf = ts21.createSourceFile("__const.ts", `const __x = (${source});`, ts21.ScriptTarget.Latest, false);
3618
+ const sf = ts22.createSourceFile("__const.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3512
3619
  const stmt = sf.statements[0];
3513
- if (!stmt || !ts21.isVariableStatement(stmt))
3620
+ if (!stmt || !ts22.isVariableStatement(stmt))
3514
3621
  return null;
3515
3622
  let init = stmt.declarationList.declarations[0]?.initializer;
3516
- while (init && ts21.isParenthesizedExpression(init))
3623
+ while (init && ts22.isParenthesizedExpression(init))
3517
3624
  init = init.expression;
3518
- if (!init || !ts21.isTemplateExpression(init))
3625
+ if (!init || !ts22.isTemplateExpression(init))
3519
3626
  return null;
3520
3627
  let out = init.head.text;
3521
3628
  for (const span of init.templateSpans) {
3522
- if (!ts21.isIdentifier(span.expression))
3629
+ if (!ts22.isIdentifier(span.expression))
3523
3630
  return null;
3524
3631
  const value = resolved.get(span.expression.text);
3525
3632
  if (value === undefined)
@@ -3547,28 +3654,28 @@ function collectModuleStringConsts(constants) {
3547
3654
  return map;
3548
3655
  }
3549
3656
  function evalStringArrayJoin(source) {
3550
- const sf = ts21.createSourceFile("__join.ts", `const __x = (${source});`, ts21.ScriptTarget.Latest, false);
3657
+ const sf = ts22.createSourceFile("__join.ts", `const __x = (${source});`, ts22.ScriptTarget.Latest, false);
3551
3658
  const stmt = sf.statements[0];
3552
- if (!stmt || !ts21.isVariableStatement(stmt))
3659
+ if (!stmt || !ts22.isVariableStatement(stmt))
3553
3660
  return null;
3554
3661
  let node = stmt.declarationList.declarations[0]?.initializer;
3555
- while (node && ts21.isParenthesizedExpression(node))
3662
+ while (node && ts22.isParenthesizedExpression(node))
3556
3663
  node = node.expression;
3557
- if (!node || !ts21.isCallExpression(node))
3664
+ if (!node || !ts22.isCallExpression(node))
3558
3665
  return null;
3559
3666
  const callee = node.expression;
3560
- if (!ts21.isPropertyAccessExpression(callee))
3667
+ if (!ts22.isPropertyAccessExpression(callee))
3561
3668
  return null;
3562
3669
  if (callee.name.text !== "join")
3563
3670
  return null;
3564
3671
  let recv = callee.expression;
3565
- while (ts21.isParenthesizedExpression(recv))
3672
+ while (ts22.isParenthesizedExpression(recv))
3566
3673
  recv = recv.expression;
3567
- if (!ts21.isArrayLiteralExpression(recv))
3674
+ if (!ts22.isArrayLiteralExpression(recv))
3568
3675
  return null;
3569
3676
  const parts = [];
3570
3677
  for (const el of recv.elements) {
3571
- if (ts21.isStringLiteral(el) || ts21.isNoSubstitutionTemplateLiteral(el)) {
3678
+ if (ts22.isStringLiteral(el) || ts22.isNoSubstitutionTemplateLiteral(el)) {
3572
3679
  parts.push(el.text);
3573
3680
  } else {
3574
3681
  return null;
@@ -3577,7 +3684,7 @@ function evalStringArrayJoin(source) {
3577
3684
  let sep = ",";
3578
3685
  if (node.arguments.length >= 1) {
3579
3686
  const arg = node.arguments[0];
3580
- if (ts21.isStringLiteral(arg) || ts21.isNoSubstitutionTemplateLiteral(arg))
3687
+ if (ts22.isStringLiteral(arg) || ts22.isNoSubstitutionTemplateLiteral(arg))
3581
3688
  sep = arg.text;
3582
3689
  else
3583
3690
  return null;
@@ -3585,11 +3692,11 @@ function evalStringArrayJoin(source) {
3585
3692
  return parts.join(sep);
3586
3693
  }
3587
3694
  function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3588
- if (!ts21.isElementAccessExpression(val))
3695
+ if (!ts22.isElementAccessExpression(val))
3589
3696
  return null;
3590
3697
  const obj = val.expression;
3591
3698
  const arg = val.argumentExpression;
3592
- if (!ts21.isIdentifier(obj) || !ts21.isIdentifier(arg))
3699
+ if (!ts22.isIdentifier(obj) || !ts22.isIdentifier(arg))
3593
3700
  return null;
3594
3701
  let indexPropName;
3595
3702
  let defaultKey;
@@ -3605,35 +3712,35 @@ function parseRecordIndexAccess(val, localConstants, propsParams, resolveKey) {
3605
3712
  const constInfo = localConstants.find((c) => c.name === obj.text && c.isModule);
3606
3713
  if (constInfo?.value === undefined)
3607
3714
  return null;
3608
- const sf = ts21.createSourceFile("__rec.ts", `(${constInfo.value})`, ts21.ScriptTarget.Latest, true);
3715
+ const sf = ts22.createSourceFile("__rec.ts", `(${constInfo.value})`, ts22.ScriptTarget.Latest, true);
3609
3716
  if (sf.statements.length !== 1)
3610
3717
  return null;
3611
3718
  const stmt = sf.statements[0];
3612
- if (!ts21.isExpressionStatement(stmt))
3719
+ if (!ts22.isExpressionStatement(stmt))
3613
3720
  return null;
3614
3721
  let parsed = stmt.expression;
3615
- while (ts21.isParenthesizedExpression(parsed))
3722
+ while (ts22.isParenthesizedExpression(parsed))
3616
3723
  parsed = parsed.expression;
3617
- if (!ts21.isObjectLiteralExpression(parsed))
3724
+ if (!ts22.isObjectLiteralExpression(parsed))
3618
3725
  return null;
3619
3726
  const entries = [];
3620
3727
  for (const prop of parsed.properties) {
3621
- if (!ts21.isPropertyAssignment(prop))
3728
+ if (!ts22.isPropertyAssignment(prop))
3622
3729
  return null;
3623
3730
  let key;
3624
- if (ts21.isIdentifier(prop.name)) {
3731
+ if (ts22.isIdentifier(prop.name)) {
3625
3732
  key = prop.name.text;
3626
- } else if (ts21.isStringLiteral(prop.name) || ts21.isNoSubstitutionTemplateLiteral(prop.name)) {
3733
+ } else if (ts22.isStringLiteral(prop.name) || ts22.isNoSubstitutionTemplateLiteral(prop.name)) {
3627
3734
  key = prop.name.text;
3628
3735
  } else {
3629
3736
  return null;
3630
3737
  }
3631
3738
  let v = prop.initializer;
3632
- while (ts21.isParenthesizedExpression(v))
3739
+ while (ts22.isParenthesizedExpression(v))
3633
3740
  v = v.expression;
3634
- if (ts21.isNumericLiteral(v)) {
3741
+ if (ts22.isNumericLiteral(v)) {
3635
3742
  entries.push({ key, value: { kind: "number", text: v.text } });
3636
- } else if (ts21.isStringLiteral(v) || ts21.isNoSubstitutionTemplateLiteral(v)) {
3743
+ } else if (ts22.isStringLiteral(v) || ts22.isNoSubstitutionTemplateLiteral(v)) {
3637
3744
  entries.push({ key, value: { kind: "string", text: v.text } });
3638
3745
  } else {
3639
3746
  return null;
@@ -3689,7 +3796,7 @@ function computeSsrSeedPlan(metadata) {
3689
3796
  // ../jsx/src/rich-type-refusal.ts
3690
3797
  var EMPTY_BINDINGS2 = new Map;
3691
3798
  // ../jsx/src/shared-program.ts
3692
- import ts22 from "typescript";
3799
+ import ts24 from "typescript";
3693
3800
  // ../jsx/src/adapters/interface.ts
3694
3801
  class BaseAdapter {
3695
3802
  renderChildren(children) {
@@ -3765,7 +3872,7 @@ class JsxAdapter extends BaseAdapter {
3765
3872
  }
3766
3873
  const rawInitialValue = preserveTypes ? signal.typedInitialValue ?? signal.initialValue : signal.initialValue;
3767
3874
  const initialValue = rawInitialValue.trim().startsWith("{") ? `(${rawInitialValue})` : rawInitialValue;
3768
- const needsTypeAssertion = preserveTypes && !signal.typedInitialValue && signal.type.kind !== "unknown" && signal.type.kind !== "primitive";
3875
+ const needsTypeAssertion = preserveTypes && !signal.typedInitialValue && signal.type.kind !== "unknown" && signal.type.kind !== "primitive" && signal.type.raw !== "object";
3769
3876
  if (needsTypeAssertion) {
3770
3877
  lines.push(` const ${signal.getter} = () => ${initialValue} as ${signal.type.raw}`);
3771
3878
  } else {
@@ -3784,12 +3891,16 @@ class JsxAdapter extends BaseAdapter {
3784
3891
  const computation = preserveTypes ? memo.typedComputation ?? memo.computation : memo.computation;
3785
3892
  lines.push(` const ${memo.name} = ${computation}`);
3786
3893
  }
3894
+ const moduleScopeNames = this.moduleScopeDeclarationNames(ir);
3787
3895
  for (const constant of ir.metadata.localConstants) {
3788
3896
  if (constant.isExported)
3789
3897
  continue;
3898
+ if (moduleScopeNames.has(constant.name))
3899
+ continue;
3790
3900
  const keyword = constant.declarationKind ?? "const";
3791
3901
  if (!constant.value) {
3792
- lines.push(` ${keyword} ${constant.name}`);
3902
+ const typeAnnotation = preserveTypes && constant.type ? `: ${constant.type.raw}` : "";
3903
+ lines.push(` ${keyword} ${constant.name}${typeAnnotation}`);
3793
3904
  continue;
3794
3905
  }
3795
3906
  const value = constant.value.trim();
@@ -3801,6 +3912,8 @@ class JsxAdapter extends BaseAdapter {
3801
3912
  lines.push(` ${keyword} ${constant.name} = ${constValue}`);
3802
3913
  }
3803
3914
  for (const func of localFunctions) {
3915
+ if (moduleScopeNames.has(func.name))
3916
+ continue;
3804
3917
  if (!reachable.has(func.name))
3805
3918
  continue;
3806
3919
  const params = preserveTypes && func.typedParams !== undefined ? func.typedParams : func.params.map(formatParamWithType).join(", ");
@@ -3810,6 +3923,125 @@ class JsxAdapter extends BaseAdapter {
3810
3923
  lines.push(` ${asyncKw}function ${func.name}(${params})${returnAnnotation} ${body}`);
3811
3924
  }
3812
3925
  return lines.join(`
3926
+ `);
3927
+ }
3928
+ moduleScopeNamesCache = new WeakMap;
3929
+ moduleScopeDeclarationNames(ir) {
3930
+ const cached = this.moduleScopeNamesCache.get(ir);
3931
+ if (cached)
3932
+ return cached;
3933
+ const componentScope = new Set;
3934
+ for (const sig of ir.metadata.signals) {
3935
+ if (sig.isModule)
3936
+ continue;
3937
+ componentScope.add(sig.getter);
3938
+ if (sig.setter)
3939
+ componentScope.add(sig.setter);
3940
+ }
3941
+ for (const memo of ir.metadata.memos) {
3942
+ if (!memo.isModule)
3943
+ componentScope.add(memo.name);
3944
+ }
3945
+ for (const p of ir.metadata.propsParams)
3946
+ componentScope.add(p.name);
3947
+ if (ir.metadata.propsObjectName)
3948
+ componentScope.add(ir.metadata.propsObjectName);
3949
+ if (ir.metadata.restPropsName)
3950
+ componentScope.add(ir.metadata.restPropsName);
3951
+ for (const c of ir.metadata.localConstants) {
3952
+ if (!c.isModule)
3953
+ componentScope.add(c.name);
3954
+ }
3955
+ for (const f of ir.metadata.localFunctions) {
3956
+ if (!f.isModule)
3957
+ componentScope.add(f.name);
3958
+ }
3959
+ const exported = new Set;
3960
+ const candidates = new Map;
3961
+ for (const c of ir.metadata.localConstants) {
3962
+ if (!c.isModule)
3963
+ continue;
3964
+ if (c.isJsx || c.isJsxFunction)
3965
+ continue;
3966
+ if (c.isExported) {
3967
+ exported.add(c.name);
3968
+ continue;
3969
+ }
3970
+ candidates.set(c.name, c.freeIdentifiers ?? extractFreeIdentifiersFromText(c.value ?? ""));
3971
+ }
3972
+ for (const f of ir.metadata.localFunctions) {
3973
+ if (!f.isModule)
3974
+ continue;
3975
+ if (f.isJsxFunction || f.isMultiReturnJsxHelper)
3976
+ continue;
3977
+ if (f.isExported) {
3978
+ exported.add(f.name);
3979
+ continue;
3980
+ }
3981
+ const params = f.typedParams !== undefined ? f.typedParams : f.params.map(formatParamWithType).join(", ");
3982
+ candidates.set(f.name, extractFreeIdentifiersFromText(`(${params}) => ${f.body}`));
3983
+ }
3984
+ const referencesAny = (refs, names) => {
3985
+ for (const ref of refs) {
3986
+ if (names.has(ref))
3987
+ return true;
3988
+ }
3989
+ return false;
3990
+ };
3991
+ let changed = true;
3992
+ while (changed) {
3993
+ changed = false;
3994
+ for (const [name, refs] of candidates) {
3995
+ if (referencesAny(refs, componentScope)) {
3996
+ candidates.delete(name);
3997
+ componentScope.add(name);
3998
+ changed = true;
3999
+ }
4000
+ }
4001
+ }
4002
+ const result = new Set([...exported, ...candidates.keys()]);
4003
+ this.moduleScopeNamesCache.set(ir, result);
4004
+ return result;
4005
+ }
4006
+ generateModuleScopeDeclarations(ir) {
4007
+ const { preserveTypes } = this.jsxConfig;
4008
+ const moduleNames = this.moduleScopeDeclarationNames(ir);
4009
+ const entries = [];
4010
+ for (const t of ir.metadata.typeDefinitions) {
4011
+ entries.push({ line: t.loc.start.line, text: t.definition });
4012
+ }
4013
+ for (const c of ir.metadata.localConstants) {
4014
+ if (!c.isModule || !moduleNames.has(c.name))
4015
+ continue;
4016
+ const keyword = c.declarationKind ?? "const";
4017
+ const exportKw = c.isExported ? "export " : "";
4018
+ if (!c.value) {
4019
+ entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name}` });
4020
+ continue;
4021
+ }
4022
+ const trimmed = c.value.trim();
4023
+ if (/^new WeakMap\b/.test(trimmed))
4024
+ continue;
4025
+ if (c.isExported && /^createContext\b/.test(trimmed))
4026
+ continue;
4027
+ const value = preserveTypes ? c.typedValue ?? c.value : c.value;
4028
+ entries.push({ line: c.loc.start.line, text: `${exportKw}${keyword} ${c.name} = ${value}` });
4029
+ }
4030
+ for (const f of ir.metadata.localFunctions) {
4031
+ if (!f.isModule || !moduleNames.has(f.name))
4032
+ continue;
4033
+ const params = preserveTypes && f.typedParams !== undefined ? f.typedParams : f.params.map(formatParamWithType).join(", ");
4034
+ const returnAnnotation = preserveTypes && f.typedReturnType ? `: ${f.typedReturnType}` : "";
4035
+ const body = preserveTypes ? f.typedBody ?? f.body : f.body;
4036
+ const asyncKw = f.isAsync ? "async " : "";
4037
+ const exportKw = f.isExported ? "export " : "";
4038
+ entries.push({
4039
+ line: f.loc.start.line,
4040
+ text: `${exportKw}${asyncKw}function ${f.name}(${params})${returnAnnotation} ${body}`
4041
+ });
4042
+ }
4043
+ entries.sort((a, b) => a.line - b.line);
4044
+ return entries.map((e) => e.text).join(`
3813
4045
  `);
3814
4046
  }
3815
4047
  renderNodeRaw(node) {
@@ -3821,6 +4053,15 @@ class JsxAdapter extends BaseAdapter {
3821
4053
  }
3822
4054
  return this.renderNode(node);
3823
4055
  }
4056
+ renderTemplatePartsAsJs(parts) {
4057
+ return templatePartsToJsExpr(parts, { typed: this.jsxConfig.preserveTypes });
4058
+ }
4059
+ expressionValueToJs(value) {
4060
+ if (this.jsxConfig.preserveTypes && value.parts && value.expr === templatePartsToJsExpr(value.parts)) {
4061
+ return this.renderTemplatePartsAsJs(value.parts);
4062
+ }
4063
+ return value.expr;
4064
+ }
3824
4065
  renderScopeMarker(instanceIdExpr) {
3825
4066
  return `${BF_SCOPE}={${instanceIdExpr}}`;
3826
4067
  }
@@ -3888,6 +4129,7 @@ class TestAdapter extends JsxAdapter {
3888
4129
  generate(ir) {
3889
4130
  this.componentName = ir.metadata.componentName;
3890
4131
  const imports = this.generateImports(ir);
4132
+ const moduleConstants = this.generateModuleScopeDeclarations(ir);
3891
4133
  const types = this.generateTypes(ir);
3892
4134
  const component = this.generateComponent(ir);
3893
4135
  const defaultExport = ir.metadata.hasDefaultExport ? `
@@ -3896,9 +4138,11 @@ export default ${this.componentName}` : "";
3896
4138
  imports,
3897
4139
  types: types || "",
3898
4140
  component,
3899
- defaultExport
4141
+ defaultExport,
4142
+ moduleConstants,
4143
+ moduleConstantsIncludeExports: true
3900
4144
  };
3901
- const template = [imports, types, component].filter(Boolean).join(`
4145
+ const template = [imports, moduleConstants, types, component].filter(Boolean).join(`
3902
4146
 
3903
4147
  `) + defaultExport;
3904
4148
  return {
@@ -3929,9 +4173,6 @@ export default ${this.componentName}` : "";
3929
4173
  }
3930
4174
  generateTypes(ir) {
3931
4175
  const lines = [];
3932
- for (const typeDef of ir.metadata.typeDefinitions) {
3933
- lines.push(typeDef.definition);
3934
- }
3935
4176
  const propsTypeName = ir.metadata.propsType?.raw;
3936
4177
  if (propsTypeName && !ir.metadata.propsObjectName) {
3937
4178
  lines.push("");
@@ -3954,7 +4195,7 @@ export default ${this.componentName}` : "";
3954
4195
  const bodyRefText = [jsxBody, signalInits, scopeIdLine].join(`
3955
4196
  `);
3956
4197
  const bfScopeAlias = /\b__bfScope\b/.test(bodyRefText) ? "__bfScope" : "__bfScope: _bfScope";
3957
- const propsParams = ir.metadata.propsParams.map((p) => p.defaultValue ? `${p.name} = ${p.defaultValue}` : p.name).join(", ");
4198
+ const propsParams = ir.metadata.propsParams.map((p) => propsDestructureBinding(p)).join(", ");
3958
4199
  const restPropsName = ir.metadata.restPropsName;
3959
4200
  const hydrationProps = `__instanceId, ${bfScopeAlias}`;
3960
4201
  const parts = [];
@@ -4101,13 +4342,7 @@ export default ${this.componentName}` : "";
4101
4342
  }
4102
4343
  flattenTemplate(value) {
4103
4344
  const v = value;
4104
- return "`" + v.parts.map((p) => {
4105
- if (p.type === "string")
4106
- return p.value;
4107
- if (p.type === "ternary")
4108
- return `\${${p.condition} ? '${p.whenTrue}' : '${p.whenFalse}'}`;
4109
- return `\${(${JSON.stringify(p.cases)})[${p.key}]}`;
4110
- }).join("") + "`";
4345
+ return this.renderTemplatePartsAsJs(v.parts);
4111
4346
  }
4112
4347
  renderComponentProps(comp) {
4113
4348
  const parts = [];
@@ -4575,7 +4810,7 @@ function dangerousInnerHtmlDiagnostic(expr, loc, reason) {
4575
4810
  };
4576
4811
  }
4577
4812
  // ../jsx/src/combine-client-js.ts
4578
- import ts23 from "typescript";
4813
+ import ts25 from "typescript";
4579
4814
  // ../jsx/src/loop-destructure.ts
4580
4815
  function isLowerableLoopDestructure(loop) {
4581
4816
  const bindings = loop.paramBindings;
@@ -4715,9 +4950,9 @@ function escapeRe(s) {
4715
4950
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4716
4951
  }
4717
4952
  // ../jsx/src/debug.ts
4718
- import ts24 from "typescript";
4953
+ import ts26 from "typescript";
4719
4954
  // ../jsx/src/profiler.ts
4720
- import ts25 from "typescript";
4955
+ import ts27 from "typescript";
4721
4956
 
4722
4957
  // ../jsx/src/index.ts
4723
4958
  registerBuiltinLoweringPlugins();
@@ -5647,15 +5882,43 @@ function collapseLiteralUnion(typeInfo) {
5647
5882
  }
5648
5883
  return { kind: "primitive", raw: typeInfo.raw, primitive: first };
5649
5884
  }
5650
- function typeInfoToGo(ctx, _typeInfo, defaultValue) {
5885
+ function literalNumberValue(expr) {
5886
+ if (expr.kind === "literal" && expr.literalType === "number" && typeof expr.value === "number") {
5887
+ return expr.value;
5888
+ }
5889
+ if (expr.kind === "unary" && expr.op === "-" && expr.argument.kind === "literal" && expr.argument.literalType === "number" && typeof expr.argument.value === "number") {
5890
+ return -expr.argument.value;
5891
+ }
5892
+ return null;
5893
+ }
5894
+ function inferGoTypeFromParsed(expr) {
5895
+ const n = literalNumberValue(expr);
5896
+ if (n !== null)
5897
+ return Number.isInteger(n) ? "int" : "float64";
5898
+ if (expr.kind === "literal") {
5899
+ if (expr.literalType === "boolean")
5900
+ return "bool";
5901
+ if (expr.literalType === "string")
5902
+ return "string";
5903
+ return null;
5904
+ }
5905
+ if (expr.kind === "array-literal")
5906
+ return "[]interface{}";
5907
+ return null;
5908
+ }
5909
+ function typeInfoToGo(ctx, _typeInfo, defaultValue, preParsed) {
5651
5910
  const typeInfo = collapseLiteralUnion(_typeInfo);
5652
5911
  switch (typeInfo.kind) {
5653
5912
  case "primitive":
5654
5913
  switch (typeInfo.primitive) {
5655
5914
  case "string":
5656
5915
  return "string";
5657
- case "number":
5916
+ case "number": {
5917
+ const n = preParsed ? literalNumberValue(preParsed) : null;
5918
+ if (n !== null)
5919
+ return Number.isInteger(n) ? "int" : "float64";
5658
5920
  return defaultValue !== undefined ? numberPrimitiveGoType(defaultValue) : "int";
5921
+ }
5659
5922
  case "boolean":
5660
5923
  return "bool";
5661
5924
  default:
@@ -5678,30 +5941,21 @@ function typeInfoToGo(ctx, _typeInfo, defaultValue) {
5678
5941
  return resolved;
5679
5942
  }
5680
5943
  return "interface{}";
5681
- case "unknown":
5944
+ case "unknown": {
5945
+ const inferred = preParsed ? inferGoTypeFromParsed(preParsed) : null;
5946
+ if (inferred)
5947
+ return inferred;
5682
5948
  if (defaultValue !== undefined) {
5683
5949
  return inferTypeFromValue(defaultValue);
5684
5950
  }
5685
5951
  return "interface{}";
5952
+ }
5686
5953
  default:
5687
5954
  return "interface{}";
5688
5955
  }
5689
5956
  }
5690
5957
  function tsTypeStringToGo(ctx, tsType) {
5691
5958
  const t = tsType.trim();
5692
- if (t === "number")
5693
- return "int";
5694
- if (t === "string")
5695
- return "string";
5696
- if (t === "boolean" || t === "bool")
5697
- return "bool";
5698
- if (t.endsWith("[]")) {
5699
- const elem = t.slice(0, -2);
5700
- return `[]${tsTypeStringToGo(ctx, elem)}`;
5701
- }
5702
- const arrayMatch = t.match(/^Array<(.+)>$/);
5703
- if (arrayMatch)
5704
- return `[]${tsTypeStringToGo(ctx, arrayMatch[1])}`;
5705
5959
  if (ctx.state.localStructFields.has(t) || ctx.state.localTypeAliases.has(t))
5706
5960
  return t;
5707
5961
  return "interface{}";
@@ -5745,16 +5999,25 @@ function bakeInlineObjectAsGoMap(ctx, expr) {
5745
5999
  }
5746
6000
  return `map[string]interface{}{${entries.join(", ")}}`;
5747
6001
  }
5748
- function parsedLiteralToGo(ctx, expr, typeInfo) {
6002
+ function numberLiteralRawGo(expr) {
5749
6003
  if (expr.kind === "unary" && expr.op === "-" && expr.argument.kind === "literal" && expr.argument.literalType === "number") {
5750
6004
  return expr.argument.raw !== undefined ? `-${expr.argument.raw}` : null;
5751
6005
  }
6006
+ if (expr.kind === "literal" && expr.literalType === "number") {
6007
+ return expr.raw ?? null;
6008
+ }
6009
+ return null;
6010
+ }
6011
+ function parsedLiteralToGo(ctx, expr, typeInfo) {
6012
+ const numberGo = numberLiteralRawGo(expr);
6013
+ if (numberGo !== null)
6014
+ return numberGo;
5752
6015
  if (expr.kind === "literal") {
5753
6016
  switch (expr.literalType) {
5754
6017
  case "string":
5755
6018
  return JSON.stringify(expr.value);
5756
6019
  case "number":
5757
- return expr.raw ?? null;
6020
+ return null;
5758
6021
  case "boolean":
5759
6022
  return expr.value ? "true" : "false";
5760
6023
  case "null":
@@ -5806,10 +6069,10 @@ function parsedLiteralToGo(ctx, expr, typeInfo) {
5806
6069
 
5807
6070
  // src/adapter/value/value-lowering.ts
5808
6071
  var EMPTY_PROP_FALLBACK_VARS = new Map;
5809
- function nillableAwarePropRef(ctx, propName, expectedType) {
5810
- const fieldRef = `in.${capitalizeFieldName(propName)}`;
6072
+ function nillableAwarePropRef(ctx, param, expectedType) {
6073
+ const fieldRef = `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
5811
6074
  const scalar = expectedType.kind === "primitive" ? expectedType : expectedType.kind === "union" && expectedType.unionTypes?.length === 2 ? expectedType.unionTypes.find((t) => t.primitive !== "undefined" && t.primitive !== "null") : undefined;
5812
- if (ctx.state.nillablePropNames.has(propName) && scalar?.kind === "primitive") {
6075
+ if (ctx.state.nillablePropNames.has(param.name) && scalar?.kind === "primitive") {
5813
6076
  const goType = scalar.primitive === "boolean" ? "bool" : scalar.primitive === "number" ? "float64" : scalar.primitive === "string" ? "string" : null;
5814
6077
  if (goType) {
5815
6078
  const zero = goType === "bool" ? "false" : goType === "string" ? '""' : "0";
@@ -5820,21 +6083,29 @@ function nillableAwarePropRef(ctx, propName, expectedType) {
5820
6083
  }
5821
6084
  function convertInitialValue(ctx, value, _typeInfo, propsParams, preParsed) {
5822
6085
  const typeInfo = collapseLiteralUnion(_typeInfo);
5823
- const propRef = (propName2) => nillableAwarePropRef(ctx, propName2, typeInfo);
6086
+ const propRef = (param2) => nillableAwarePropRef(ctx, param2, typeInfo);
5824
6087
  if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(value)) {
5825
- if (propsParams?.some((p) => p.name === value)) {
5826
- return propRef(value);
6088
+ const param2 = propsParams?.find((p) => p.name === value);
6089
+ if (param2) {
6090
+ return propRef(param2);
5827
6091
  }
5828
6092
  }
5829
6093
  const propName = ctx.extractPropNameFromInitialValue(value, preParsed);
5830
- if (propName && propsParams?.some((p) => p.name === propName)) {
5831
- return propRef(propName);
6094
+ const param = propName ? propsParams?.find((p) => p.name === propName) : undefined;
6095
+ if (param) {
6096
+ return propRef(param);
5832
6097
  }
5833
6098
  if (typeInfo.kind === "primitive") {
5834
6099
  if (typeInfo.primitive === "boolean") {
6100
+ if (preParsed?.kind === "literal" && preParsed.literalType === "boolean" && typeof preParsed.value === "boolean") {
6101
+ return preParsed.value ? "true" : "false";
6102
+ }
5835
6103
  return value === "true" ? "true" : "false";
5836
6104
  }
5837
6105
  if (typeInfo.primitive === "number") {
6106
+ const numGo = preParsed ? numberLiteralRawGo(preParsed) : null;
6107
+ if (numGo !== null)
6108
+ return numGo;
5838
6109
  if (/^-?\d+$/.test(value))
5839
6110
  return value;
5840
6111
  if (/^-?\d+\.\d+$/.test(value))
@@ -5842,7 +6113,10 @@ function convertInitialValue(ctx, value, _typeInfo, propsParams, preParsed) {
5842
6113
  return "0";
5843
6114
  }
5844
6115
  if (typeInfo.primitive === "string") {
5845
- if (value.startsWith("'") || value.endsWith("'")) {
6116
+ if (preParsed?.kind === "literal" && preParsed.literalType === "string" && typeof preParsed.value === "string") {
6117
+ return JSON.stringify(preParsed.value);
6118
+ }
6119
+ if (value.startsWith("'") && value.endsWith("'")) {
5846
6120
  return value.replace(/'/g, '"');
5847
6121
  }
5848
6122
  if (value.startsWith('"') && value.endsWith('"')) {
@@ -5904,19 +6178,21 @@ function objectLiteralToGoMap(ctx, expr) {
5904
6178
  return `map[string]interface{}{${entries.join(", ")}}`;
5905
6179
  }
5906
6180
  function getSignalInitialValueAsGo(ctx, initialValue, propsParams, propFallbackVars = EMPTY_PROP_FALLBACK_VARS, signalType) {
5907
- const propRef = (propName2) => signalType ? nillableAwarePropRef(ctx, propName2, signalType) : `in.${capitalizeFieldName(propName2)}`;
5908
- if (propsParams.some((p) => p.name === initialValue)) {
6181
+ const propRef = (param2) => signalType ? nillableAwarePropRef(ctx, param2, signalType) : `in.${capitalizeFieldName(param2.sourceName ?? param2.name)}`;
6182
+ const directParam = propsParams.find((p) => p.name === initialValue);
6183
+ if (directParam) {
5909
6184
  const hoisted = propFallbackVars.get(initialValue);
5910
6185
  if (hoisted)
5911
6186
  return hoisted.varName;
5912
- return propRef(initialValue);
6187
+ return propRef(directParam);
5913
6188
  }
5914
6189
  const propName = ctx.extractPropNameFromInitialValue(initialValue);
5915
- if (propName && propsParams.some((p) => p.name === propName)) {
6190
+ const param = propName ? propsParams.find((p) => p.name === propName) : undefined;
6191
+ if (param) {
5916
6192
  const hoisted = propFallbackVars.get(propName);
5917
6193
  if (hoisted)
5918
6194
  return hoisted.varName;
5919
- return propRef(propName);
6195
+ return propRef(param);
5920
6196
  }
5921
6197
  if (/^-?\d+$/.test(initialValue)) {
5922
6198
  return initialValue;
@@ -5950,8 +6226,9 @@ function resolveMapJoinBaseAsGo(ctx, object, signals, propsParams) {
5950
6226
  }
5951
6227
  }
5952
6228
  const propName = object.kind === "member" && !object.computed && object.object.kind === "identifier" && object.object.name === "props" ? object.property : object.kind === "identifier" ? object.name : null;
5953
- if (propName && propsParams.some((p) => p.name === propName)) {
5954
- return `in.${capitalizeFieldName(propName)}`;
6229
+ const param = propName ? propsParams.find((p) => p.name === propName) : undefined;
6230
+ if (param) {
6231
+ return `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
5955
6232
  }
5956
6233
  if (object.kind === "array-literal") {
5957
6234
  if (object.elements.length === 0)
@@ -5982,11 +6259,12 @@ function mapJoinChainToGo(ctx, chain, signals, propsParams, propFallbackVars) {
5982
6259
  for (const name of freeVars) {
5983
6260
  const sig = signals.find((s) => s.getter === name);
5984
6261
  let goExpr = null;
6262
+ const freeVarParam = propsParams.find((p) => p.name === name);
5985
6263
  if (sig) {
5986
6264
  goExpr = getSignalInitialValueAsGo(ctx, sig.initialValue, propsParams, propFallbackVars, sig.type);
5987
- } else if (propsParams.some((p) => p.name === name)) {
6265
+ } else if (freeVarParam) {
5988
6266
  const hoisted = propFallbackVars.get(name);
5989
- goExpr = hoisted ? hoisted.varName : `in.${capitalizeFieldName(name)}`;
6267
+ goExpr = hoisted ? hoisted.varName : `in.${capitalizeFieldName(freeVarParam.sourceName ?? name)}`;
5990
6268
  }
5991
6269
  if (goExpr === null)
5992
6270
  return null;
@@ -6028,14 +6306,14 @@ function isBooleanMemo(ctx, memo, signals, propsParamMap) {
6028
6306
  return true;
6029
6307
  if (/\?\?\s*(true|false)\b/.test(sig.initialValue))
6030
6308
  return true;
6031
- const propName = ctx.extractPropNameFromInitialValue(sig.initialValue) ?? sig.initialValue;
6309
+ const propName = ctx.extractPropNameFromInitialValue(sig.initialValue, sig.parsed) ?? sig.initialValue;
6032
6310
  const prop2 = propsParamMap.get(propName);
6033
- if (prop2 && typeInfoToGo(ctx, prop2.type, prop2.defaultValue) === "bool")
6311
+ if (prop2 && typeInfoToGo(ctx, prop2.type, prop2.defaultValue, prop2.parsed) === "bool")
6034
6312
  return true;
6035
6313
  return false;
6036
6314
  }
6037
6315
  const prop = propsParamMap.get(name);
6038
- return !!prop && typeInfoToGo(ctx, prop.type, prop.defaultValue) === "bool";
6316
+ return !!prop && typeInfoToGo(ctx, prop.type, prop.defaultValue, prop.parsed) === "bool";
6039
6317
  };
6040
6318
  const ternary = c.match(/=>\s*\w+\(\)\s*\?\s*(\w+)\(\)\s*:\s*(\w+)\(\)/);
6041
6319
  if (ternary) {
@@ -6305,7 +6583,7 @@ function computeObjectMemoInitialValue(ctx, memo) {
6305
6583
  }
6306
6584
 
6307
6585
  // src/adapter/memo/template-interp.ts
6308
- import ts26 from "typescript";
6586
+ import ts28 from "typescript";
6309
6587
  function computeTemplateLiteralMemoInitialValue(ctx, memo, propsParams) {
6310
6588
  const localKeyBindings = new Map;
6311
6589
  let templateValue;
@@ -6528,7 +6806,8 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
6528
6806
  const hoisted = propFallbackVars.get(propName);
6529
6807
  if (hoisted)
6530
6808
  return hoisted.varName;
6531
- return `in.${capitalizeFieldName(propName)}`;
6809
+ const param = propsParams.find((p) => p.name === propName);
6810
+ return `in.${capitalizeFieldName(param?.sourceName ?? propName)}`;
6532
6811
  };
6533
6812
  const envGetKey = (e) => {
6534
6813
  if (e.kind !== "call" || e.callee.kind !== "member" || e.callee.computed)
@@ -6620,7 +6899,7 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
6620
6899
  const param = propsParams.find((p) => p.name === propName);
6621
6900
  if (param && ctx.state.nillablePropNames.has(propName)) {
6622
6901
  const isNe = body.op === "!==" || body.op === "!=";
6623
- return `in.${capitalizeFieldName(propName)} ${isNe ? "!=" : "=="} nil`;
6902
+ return `in.${capitalizeFieldName(param.sourceName ?? propName)} ${isNe ? "!=" : "=="} nil`;
6624
6903
  }
6625
6904
  }
6626
6905
  }
@@ -6692,7 +6971,7 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
6692
6971
  return `${hoisted.varName} ${operator} ${operand}`;
6693
6972
  const fieldName = capitalizeFieldName(propName);
6694
6973
  if (param.type) {
6695
- const goType = typeInfoToGo(ctx, param.type, param.defaultValue);
6974
+ const goType = typeInfoToGo(ctx, param.type, param.defaultValue, param.parsed);
6696
6975
  if (goType === "interface{}")
6697
6976
  return `in.${fieldName}.(int) ${operator} ${operand}`;
6698
6977
  }
@@ -6703,9 +6982,9 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
6703
6982
  const varName = body.left.name;
6704
6983
  const param = propsParams.find((p) => p.name === varName);
6705
6984
  if (param) {
6706
- const fieldName = capitalizeFieldName(varName);
6985
+ const fieldName = capitalizeFieldName(param.sourceName ?? varName);
6707
6986
  if (param.type) {
6708
- const goType = typeInfoToGo(ctx, param.type, param.defaultValue);
6987
+ const goType = typeInfoToGo(ctx, param.type, param.defaultValue, param.parsed);
6709
6988
  if (goType === "interface{}")
6710
6989
  return `in.${fieldName}.(int) ${operator} ${operand}`;
6711
6990
  }
@@ -6729,7 +7008,7 @@ function memoInitialFromParsedBody(ctx, body, signals, propsParams, propFallback
6729
7008
  if (body.kind === "identifier") {
6730
7009
  const param = propsParams.find((p) => p.name === body.name);
6731
7010
  if (param)
6732
- return `in.${capitalizeFieldName(body.name)}`;
7011
+ return `in.${capitalizeFieldName(param.sourceName ?? body.name)}`;
6733
7012
  }
6734
7013
  if (body.kind === "binary" && body.op === "+") {
6735
7014
  const concatGo = resolveStringConcatChainGo(ctx, body, signals, propsParams, propFallbackVars, propRef);
@@ -6791,7 +7070,8 @@ function resolveGetterValueAsGo(ctx, name, signals, propsParams, propFallbackVar
6791
7070
  const stripped = memo.computation.replace(/^\(\)\s*=>\s*/, "");
6792
7071
  const fb = ctx.extractPropFallback(stripped);
6793
7072
  if (fb && capitalizeFieldName(fb.propName) === capitalizeFieldName(memo.name)) {
6794
- const field = `in.${capitalizeFieldName(fb.propName)}`;
7073
+ const fbParam = propsParams.find((p) => p.name === fb.propName);
7074
+ const field = `in.${capitalizeFieldName(fbParam?.sourceName ?? fb.propName)}`;
6795
7075
  return `func() interface{} { v := interface{}(${field}); if v == nil || v == "" { return ${fb.goFallback} }; return v }()`;
6796
7076
  }
6797
7077
  return computeMemoInitialValueOrNull(ctx, memo, signals, propsParams, propFallbackVars, new Set([...resolving, memo.name]));
@@ -6799,7 +7079,7 @@ function resolveGetterValueAsGo(ctx, name, signals, propsParams, propFallbackVar
6799
7079
  const param = propsParams.find((p) => p.name === name);
6800
7080
  if (param) {
6801
7081
  const hoisted = propFallbackVars.get(name);
6802
- return hoisted ? hoisted.varName : `in.${capitalizeFieldName(name)}`;
7082
+ return hoisted ? hoisted.varName : `in.${capitalizeFieldName(param.sourceName ?? name)}`;
6803
7083
  }
6804
7084
  return null;
6805
7085
  }
@@ -6934,7 +7214,7 @@ function collectPropsReadByCtorInit(body, propsObjectName, propNames) {
6934
7214
  }
6935
7215
 
6936
7216
  // src/adapter/spread/spread-codegen.ts
6937
- import ts27 from "typescript";
7217
+ import ts29 from "typescript";
6938
7218
  function collectSpreadSlots(ctx, node) {
6939
7219
  const result = [];
6940
7220
  collectSpreadSlotsRecursive(ctx, node, result);
@@ -7059,10 +7339,10 @@ function buildSpreadInitializer(ctx, spreadExpr, ir, parsed) {
7059
7339
  if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(trimmed)) {
7060
7340
  const param = ir.metadata.propsParams.find((p) => p.name === trimmed);
7061
7341
  if (param) {
7062
- return `in.${capitalizeFieldName(param.name)}`;
7342
+ return `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
7063
7343
  }
7064
7344
  if (ir.metadata.propsObjectName === trimmed) {
7065
- const entries = ir.metadata.propsParams.map((p) => `${JSON.stringify(p.name)}: in.${capitalizeFieldName(p.name)}`);
7345
+ const entries = ir.metadata.propsParams.map((p) => `${JSON.stringify(p.sourceName ?? p.name)}: in.${capitalizeFieldName(p.sourceName ?? p.name)}`);
7066
7346
  return `map[string]any{${entries.join(", ")}}`;
7067
7347
  }
7068
7348
  if (ir.metadata.restPropsName === trimmed) {
@@ -7116,7 +7396,7 @@ function conditionToGoBool(condition, ir) {
7116
7396
  const param = ir.metadata.propsParams.find((p) => p.name === node.name);
7117
7397
  if (!param)
7118
7398
  return null;
7119
- const field = `in.${capitalizeFieldName(param.name)}`;
7399
+ const field = `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
7120
7400
  const prim = param.type.kind === "primitive" ? param.type.primitive : undefined;
7121
7401
  let truthy;
7122
7402
  if (prim === "boolean") {
@@ -7154,7 +7434,7 @@ function objectLiteralToGoSpreadMap(ctx, obj, ir) {
7154
7434
  const param = ir.metadata.propsParams.find((p) => p.name === val.name);
7155
7435
  if (!param)
7156
7436
  return null;
7157
- goVal = `in.${capitalizeFieldName(param.name)}`;
7437
+ goVal = `in.${capitalizeFieldName(param.sourceName ?? param.name)}`;
7158
7438
  } else {
7159
7439
  const indexed = recordIndexAccessToGoMap(ctx, val, ir);
7160
7440
  if (indexed === null)
@@ -7169,7 +7449,7 @@ function recordIndexAccessToGoMap(ctx, val, ir) {
7169
7449
  if (val.kind !== "index-access" || val.object.kind !== "identifier" || val.index.kind !== "identifier") {
7170
7450
  return null;
7171
7451
  }
7172
- const tsVal = ts27.factory.createElementAccessExpression(ts27.factory.createIdentifier(val.object.name), ts27.factory.createIdentifier(val.index.name));
7452
+ const tsVal = ts29.factory.createElementAccessExpression(ts29.factory.createIdentifier(val.object.name), ts29.factory.createIdentifier(val.index.name));
7173
7453
  const parsed = parseRecordIndexAccess(tsVal, ir.metadata.localConstants ?? [], ir.metadata.propsParams);
7174
7454
  if (!parsed)
7175
7455
  return null;
@@ -7178,7 +7458,8 @@ function recordIndexAccessToGoMap(ctx, val, ir) {
7178
7458
  return `${JSON.stringify(e.key)}: ${mapVal}`;
7179
7459
  });
7180
7460
  ctx.state.usesFmt = true;
7181
- const field = `in.${capitalizeFieldName(parsed.indexPropName)}`;
7461
+ const indexParam = ir.metadata.propsParams.find((p) => p.name === parsed.indexPropName);
7462
+ const field = `in.${capitalizeFieldName(indexParam?.sourceName ?? parsed.indexPropName)}`;
7182
7463
  return `map[string]any{${entries.join(", ")}}[fmt.Sprint(${field})]`;
7183
7464
  }
7184
7465
 
@@ -7194,9 +7475,9 @@ function buildPropTypeOverrides(ctx, ir) {
7194
7475
  const param = ir.metadata.propsParams.find((p) => p.name === propName);
7195
7476
  if (!param)
7196
7477
  continue;
7197
- const propGoType = typeInfoToGo(ctx, param.type, param.defaultValue);
7478
+ const propGoType = typeInfoToGo(ctx, param.type, param.defaultValue, param.parsed);
7198
7479
  if (propGoType.includes("interface{}")) {
7199
- const signalGoType = typeInfoToGo(ctx, signal.type, signal.initialValue);
7480
+ const signalGoType = typeInfoToGo(ctx, signal.type, signal.initialValue, signal.parsed);
7200
7481
  if (!signalGoType.includes("interface{}")) {
7201
7482
  overrides.set(propName, signalGoType);
7202
7483
  }
@@ -7207,7 +7488,7 @@ function buildPropTypeOverrides(ctx, ir) {
7207
7488
  const param = ir.metadata.propsParams.find((p) => p.name === propName);
7208
7489
  if (!param)
7209
7490
  continue;
7210
- const resolved = overrides.get(propName) ?? typeInfoToGo(ctx, param.type, param.defaultValue);
7491
+ const resolved = overrides.get(propName) ?? typeInfoToGo(ctx, param.type, param.defaultValue, param.parsed);
7211
7492
  if (resolved === "int") {
7212
7493
  overrides.set(propName, "float64");
7213
7494
  }
@@ -7377,7 +7658,7 @@ function collectPresenceCheckedPropNames(ctx, ir) {
7377
7658
  return names;
7378
7659
  }
7379
7660
  function resolvePropGoType(ctx, param, propTypeOverrides) {
7380
- const base = propTypeOverrides.get(param.name) ?? typeInfoToGo(ctx, param.type, param.defaultValue);
7661
+ const base = propTypeOverrides.get(param.name) ?? typeInfoToGo(ctx, param.type, param.defaultValue, param.parsed);
7381
7662
  if (param.optional && ctx.state.localStructFields.has(base)) {
7382
7663
  return "map[string]interface{}";
7383
7664
  }
@@ -7764,6 +8045,18 @@ ${scriptRegistrations}${templateBody}
7764
8045
  nonCollidingContextConsumers(taken) {
7765
8046
  return this.state.contextConsumers.filter((c) => !taken.has(this.contextFieldName(c)));
7766
8047
  }
8048
+ isNestedArrayShadowed(param, nestedArrayFields) {
8049
+ return nestedArrayFields.has(capitalizeFieldName(param.name)) || nestedArrayFields.has(capitalizeFieldName(param.sourceName ?? param.name));
8050
+ }
8051
+ propParamFieldNamesUnion(params) {
8052
+ return params.flatMap((p) => [capitalizeFieldName(p.name), capitalizeFieldName(p.sourceName ?? p.name)]);
8053
+ }
8054
+ claimJsonTag(desired, taken) {
8055
+ if (taken.has(desired))
8056
+ return "-";
8057
+ taken.add(desired);
8058
+ return desired;
8059
+ }
7767
8060
  generateTypes(ir) {
7768
8061
  this.state.usesHtmlTemplate = false;
7769
8062
  this.state.usesFmt = false;
@@ -7794,13 +8087,16 @@ ${scriptRegistrations}${templateBody}
7794
8087
  if (!this.childDerivedFieldDeps.has(componentName))
7795
8088
  return;
7796
8089
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
7797
- const params = (ir.metadata.propsParams ?? []).filter((p) => !nestedArrayFields.has(capitalizeFieldName(p.name)));
7798
- const takenInput = new Set((ir.metadata.propsParams ?? []).map((p) => capitalizeFieldName(p.name)));
8090
+ const params = (ir.metadata.propsParams ?? []).filter((p) => !this.isNestedArrayShadowed(p, nestedArrayFields));
8091
+ const takenInput = new Set(this.propParamFieldNamesUnion(ir.metadata.propsParams ?? []));
7799
8092
  const eligible = nestedComponents.every((n) => n.isDynamic && !n.isPropDerived) && spreadSlots.length === 0 && !ir.metadata.restPropsName && this.nonCollidingContextConsumers(takenInput).length === 0;
7800
8093
  if (!eligible)
7801
8094
  return;
7802
8095
  this.childRepropsReady.set(componentName, {
7803
- params: params.map((p) => capitalizeFieldName(p.name)),
8096
+ params: params.map((p) => ({
8097
+ propsField: capitalizeFieldName(p.name),
8098
+ inputField: capitalizeFieldName(p.sourceName ?? p.name)
8099
+ })),
7804
8100
  usesSearchParams: this.usesSearchParams(ir)
7805
8101
  });
7806
8102
  }
@@ -7836,17 +8132,17 @@ ${scriptRegistrations}${templateBody}
7836
8132
  lines.push("\t\t\tBfMount: b.BfMount,");
7837
8133
  if (usesSearchParams)
7838
8134
  lines.push("\t\t\tSearchParams: b.SearchParams,");
7839
- for (const field of params) {
7840
- lines.push(` ${field}: b.${field},`);
8135
+ for (const { propsField, inputField } of params) {
8136
+ lines.push(` ${inputField}: b.${propsField},`);
7841
8137
  }
7842
8138
  lines.push("\t\t}");
7843
8139
  lines.push("\t\tfor i := 0; i < len(kv); i += 2 {");
7844
8140
  lines.push("\t\t\tname, _ := kv[i].(string)");
7845
8141
  lines.push("\t\t\tvar err error");
7846
8142
  lines.push("\t\t\tswitch name {");
7847
- for (const field of params) {
7848
- lines.push(` case ${JSON.stringify(field)}:`);
7849
- lines.push(` err = bf.RepropsAssign(${q}, ${JSON.stringify(field)}, &in.${field}, kv[i+1])`);
8143
+ for (const { propsField, inputField } of params) {
8144
+ lines.push(` case ${JSON.stringify(propsField)}:`);
8145
+ lines.push(` err = bf.RepropsAssign(${q}, ${JSON.stringify(propsField)}, &in.${inputField}, kv[i+1])`);
7850
8146
  }
7851
8147
  lines.push("\t\t\tdefault:");
7852
8148
  lines.push(` err = bf.RepropsUnknownFieldError(${q}, name)`);
@@ -7984,6 +8280,7 @@ ${goFields.join(`
7984
8280
  return false;
7985
8281
  const taken = new Set([
7986
8282
  ...ir.metadata.propsParams.map((p) => capitalizeFieldName(p.name)),
8283
+ ...ir.metadata.propsParams.map((p) => capitalizeFieldName(p.sourceName ?? p.name)),
7987
8284
  ...ir.metadata.signals.filter((s) => !s.envReader).map((s) => capitalizeFieldName(s.getter)),
7988
8285
  ...ir.metadata.memos.map((m) => capitalizeFieldName(m.name)),
7989
8286
  ...this.state.contextConsumers.map((c) => this.contextFieldName(c))
@@ -8006,8 +8303,8 @@ ${goFields.join(`
8006
8303
  const inputNested = nestedComponents.filter((n) => !n.isDynamic || n.isPropDerived);
8007
8304
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
8008
8305
  for (const param of ir.metadata.propsParams) {
8009
- const fieldName = capitalizeFieldName(param.name);
8010
- if (nestedArrayFields.has(fieldName))
8306
+ const fieldName = capitalizeFieldName(param.sourceName ?? param.name);
8307
+ if (this.isNestedArrayShadowed(param, nestedArrayFields))
8011
8308
  continue;
8012
8309
  const goType = resolvePropGoType(this.emitCtx, param, propTypeOverrides);
8013
8310
  lines.push(` ${fieldName} ${goType}`);
@@ -8017,7 +8314,7 @@ ${goFields.join(`
8017
8314
  continue;
8018
8315
  lines.push(` ${nested.name}s []${nested.name}Input`);
8019
8316
  }
8020
- const takenInput = new Set(ir.metadata.propsParams.map((p) => capitalizeFieldName(p.name)));
8317
+ const takenInput = new Set(this.propParamFieldNamesUnion(ir.metadata.propsParams));
8021
8318
  for (const c of this.nonCollidingContextConsumers(takenInput)) {
8022
8319
  lines.push(` ${this.contextFieldName(c)} ${this.contextConsumerGoType(c)}`);
8023
8320
  }
@@ -8041,8 +8338,9 @@ ${goFields.join(`
8041
8338
  generatePropsStruct(lines, ir, componentName, nestedComponents, propTypeOverrides, spreadSlots) {
8042
8339
  const propsTypeName = `${componentName}Props`;
8043
8340
  this.emitPropsStructHeader(lines, ir, propsTypeName, componentName);
8044
- this.emitPropsDataFields(lines, ir, nestedComponents, propTypeOverrides);
8045
- this.emitPropsAuxFields(lines, ir, componentName, nestedComponents, spreadSlots);
8341
+ const takenJsonTags = new Set;
8342
+ this.emitPropsDataFields(lines, ir, nestedComponents, propTypeOverrides, takenJsonTags);
8343
+ this.emitPropsAuxFields(lines, ir, componentName, nestedComponents, spreadSlots, takenJsonTags);
8046
8344
  lines.push("}");
8047
8345
  lines.push("");
8048
8346
  }
@@ -8079,7 +8377,7 @@ ${goFields.join(`
8079
8377
  resolveLoopDatumFields(itemType) {
8080
8378
  if (!itemType)
8081
8379
  return [];
8082
- const typeName = itemType.raw?.replace(/\[\]$/, "") ?? itemType.raw;
8380
+ const typeName = itemType.kind === "array" ? itemType.elementType?.raw ?? itemType.raw : itemType.raw;
8083
8381
  if (!typeName)
8084
8382
  return [];
8085
8383
  for (const td of this.state.currentTypeDefinitions) {
@@ -8242,7 +8540,8 @@ ${goFields.join(`
8242
8540
  const propFieldNames = new Set;
8243
8541
  for (const param of ir.metadata.propsParams) {
8244
8542
  const fieldName = capitalizeFieldName(param.name);
8245
- if (nestedArrayFields.has(fieldName))
8543
+ const inputField = capitalizeFieldName(param.sourceName ?? param.name);
8544
+ if (this.isNestedArrayShadowed(param, nestedArrayFields))
8246
8545
  continue;
8247
8546
  const hoisted = propFallbackVars.get(param.name);
8248
8547
  if (hoisted) {
@@ -8251,13 +8550,13 @@ ${goFields.join(`
8251
8550
  const paramDefault = goPropDefault(param.defaultValue);
8252
8551
  const memoFold = memoFallbacks.get(fieldName);
8253
8552
  if (paramDefault !== null) {
8254
- lines.push(` ${fieldName}: ${applyGoFallback(`in.${fieldName}`, paramDefault)},`);
8553
+ lines.push(` ${fieldName}: ${applyGoFallback(`in.${inputField}`, paramDefault)},`);
8255
8554
  } else if (memoFold !== undefined && memoFold.goType === "string") {
8256
- lines.push(` ${fieldName}: ${applyGoFallback(`in.${fieldName}`, memoFold.goFallback)},`);
8555
+ lines.push(` ${fieldName}: ${applyGoFallback(`in.${inputField}`, memoFold.goFallback)},`);
8257
8556
  } else if (memoFold !== undefined) {
8258
- lines.push(` ${fieldName}: func() interface{} { v := interface{}(in.${fieldName}); if v == nil || v == "" { return ${memoFold.goFallback} }; return v }(),`);
8557
+ lines.push(` ${fieldName}: func() interface{} { v := interface{}(in.${inputField}); if v == nil || v == "" { return ${memoFold.goFallback} }; return v }(),`);
8259
8558
  } else {
8260
- lines.push(` ${fieldName}: in.${fieldName},`);
8559
+ lines.push(` ${fieldName}: in.${inputField},`);
8261
8560
  }
8262
8561
  }
8263
8562
  propFieldNames.add(fieldName);
@@ -8310,7 +8609,7 @@ ${goFields.join(`
8310
8609
  lines.push(` ${f.name}: ${f.init},`);
8311
8610
  }
8312
8611
  const takenInit = new Set([
8313
- ...ir.metadata.propsParams.map((p) => capitalizeFieldName(p.name)),
8612
+ ...this.propParamFieldNamesUnion(ir.metadata.propsParams),
8314
8613
  ...ir.metadata.signals.map((s) => capitalizeFieldName(s.getter)),
8315
8614
  ...ir.metadata.memos.map((m) => capitalizeFieldName(m.name))
8316
8615
  ]);
@@ -8349,7 +8648,7 @@ ${goFields.join(`
8349
8648
  }
8350
8649
  if (jsxName.includes("-"))
8351
8650
  return;
8352
- const fieldName = this.childPropFieldNames.get(child.name)?.get(jsxName) ?? capitalizeFieldName(jsxName);
8651
+ const fieldName = capitalizeFieldName(jsxName);
8353
8652
  lines.push(` ${fieldName}: ${goValue},`);
8354
8653
  };
8355
8654
  for (const prop of child.props) {
@@ -8718,15 +9017,15 @@ ${goFields.join(`
8718
9017
  lines.push('\tSearchParams bf.SearchParams `json:"-"`');
8719
9018
  }
8720
9019
  }
8721
- emitPropsDataFields(lines, ir, nestedComponents, propTypeOverrides) {
9020
+ emitPropsDataFields(lines, ir, nestedComponents, propTypeOverrides, takenJsonTags) {
8722
9021
  const nestedArrayFields = new Set(nestedComponents.map((n) => `${n.name}s`));
8723
9022
  const propFieldNames = new Set;
8724
9023
  for (const param of ir.metadata.propsParams) {
8725
9024
  const fieldName = capitalizeFieldName(param.name);
8726
- if (nestedArrayFields.has(fieldName))
9025
+ if (this.isNestedArrayShadowed(param, nestedArrayFields))
8727
9026
  continue;
8728
9027
  const goType = resolvePropGoType(this.emitCtx, param, propTypeOverrides);
8729
- const jsonTag = param.name === "children" ? "-" : this.toJsonTag(param.name);
9028
+ const jsonTag = param.name === "children" ? "-" : this.claimJsonTag(this.toJsonTag(param.sourceName ?? param.name), takenJsonTags);
8730
9029
  lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
8731
9030
  propFieldNames.add(fieldName);
8732
9031
  }
@@ -8737,7 +9036,7 @@ ${goFields.join(`
8737
9036
  const fieldName = capitalizeFieldName(signal.getter);
8738
9037
  if (propFieldNames.has(fieldName))
8739
9038
  continue;
8740
- const jsonTag = this.toJsonTag(signal.getter);
9039
+ const jsonTag = this.claimJsonTag(this.toJsonTag(signal.getter), takenJsonTags);
8741
9040
  const synthType = this.state.synthStructTypes.get(signal.getter);
8742
9041
  if (synthType) {
8743
9042
  lines.push(` ${fieldName} ${typeInfoToGo(this.emitCtx, synthType)} \`json:"${jsonTag}"\``);
@@ -8746,13 +9045,13 @@ ${goFields.join(`
8746
9045
  let goType;
8747
9046
  let referencedProp = propsParamMap.get(signal.initialValue);
8748
9047
  if (!referencedProp) {
8749
- const propName = this.extractPropNameFromInitialValue(signal.initialValue);
9048
+ const propName = this.extractPropNameFromInitialValue(signal.initialValue, signal.parsed);
8750
9049
  if (propName)
8751
9050
  referencedProp = propsParamMap.get(propName);
8752
9051
  }
8753
9052
  if (referencedProp) {
8754
- const propGoType = typeInfoToGo(this.emitCtx, referencedProp.type, referencedProp.defaultValue);
8755
- const signalGoType = typeInfoToGo(this.emitCtx, signal.type, signal.initialValue);
9053
+ const propGoType = typeInfoToGo(this.emitCtx, referencedProp.type, referencedProp.defaultValue, referencedProp.parsed);
9054
+ const signalGoType = typeInfoToGo(this.emitCtx, signal.type, signal.initialValue, signal.parsed);
8756
9055
  if (propGoType.includes("interface{}")) {
8757
9056
  goType = signalGoType;
8758
9057
  } else if (!signalGoType.includes("interface{}") && signalGoType !== propGoType) {
@@ -8761,7 +9060,7 @@ ${goFields.join(`
8761
9060
  goType = propGoType;
8762
9061
  }
8763
9062
  } else {
8764
- goType = typeInfoToGo(this.emitCtx, signal.type, signal.initialValue);
9063
+ goType = typeInfoToGo(this.emitCtx, signal.type, signal.initialValue, signal.parsed);
8765
9064
  }
8766
9065
  lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
8767
9066
  }
@@ -8769,12 +9068,12 @@ ${goFields.join(`
8769
9068
  const fieldName = capitalizeFieldName(memo.name);
8770
9069
  if (propFieldNames.has(fieldName))
8771
9070
  continue;
8772
- const jsonTag = this.toJsonTag(memo.name);
9071
+ const jsonTag = this.claimJsonTag(this.toJsonTag(memo.name), takenJsonTags);
8773
9072
  const goType = this.inferMemoType(memo, ir.metadata.signals, propsParamMap);
8774
9073
  lines.push(` ${fieldName} ${goType} \`json:"${jsonTag}"\``);
8775
9074
  }
8776
9075
  }
8777
- emitPropsAuxFields(lines, ir, componentName, nestedComponents, spreadSlots) {
9076
+ emitPropsAuxFields(lines, ir, componentName, nestedComponents, spreadSlots, takenJsonTags) {
8778
9077
  const takenForDerivedConsts = new Set([
8779
9078
  ...ir.metadata.propsParams.map((p) => capitalizeFieldName(p.name)),
8780
9079
  ...ir.metadata.signals.map((s) => capitalizeFieldName(s.getter)),
@@ -8784,12 +9083,12 @@ ${goFields.join(`
8784
9083
  lines.push(` ${f.name} string \`json:"-"\``);
8785
9084
  }
8786
9085
  const takenProps = new Set([
8787
- ...ir.metadata.propsParams.map((p) => capitalizeFieldName(p.name)),
9086
+ ...this.propParamFieldNamesUnion(ir.metadata.propsParams),
8788
9087
  ...ir.metadata.signals.map((s) => capitalizeFieldName(s.getter)),
8789
9088
  ...ir.metadata.memos.map((m) => capitalizeFieldName(m.name))
8790
9089
  ]);
8791
9090
  for (const c of this.nonCollidingContextConsumers(takenProps)) {
8792
- const jsonTag = this.toJsonTag(c.localName);
9091
+ const jsonTag = this.claimJsonTag(this.toJsonTag(c.localName), takenJsonTags);
8793
9092
  lines.push(` ${this.contextFieldName(c)} ${this.contextConsumerGoType(c)} \`json:"${jsonTag}"\``);
8794
9093
  }
8795
9094
  for (const nested of nestedComponents) {
@@ -8797,7 +9096,7 @@ ${goFields.join(`
8797
9096
  if (nested.isDynamic && !nested.isPropDerived) {
8798
9097
  lines.push(` ${nested.name}s []${elemType} \`json:"-"\``);
8799
9098
  } else {
8800
- const jsonTag = this.toJsonTag(`${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`);
9099
+ const jsonTag = this.claimJsonTag(this.toJsonTag(`${nested.name.charAt(0).toLowerCase()}${nested.name.slice(1)}s`), takenJsonTags);
8801
9100
  lines.push(` ${nested.name}s []${elemType} \`json:"${jsonTag}"\``);
8802
9101
  }
8803
9102
  }
@@ -8806,7 +9105,7 @@ ${goFields.join(`
8806
9105
  lines.push(` ${child.fieldName} ${child.name}Props \`json:"-"\``);
8807
9106
  }
8808
9107
  for (const slot of spreadSlots) {
8809
- const jsonTag = this.toJsonTag(slot.slotId);
9108
+ const jsonTag = this.claimJsonTag(this.toJsonTag(slot.slotId), takenJsonTags);
8810
9109
  lines.push(` ${slot.slotId} map[string]any \`json:"${jsonTag}"\``);
8811
9110
  }
8812
9111
  }
@@ -8982,8 +9281,9 @@ ${goFields.join(`
8982
9281
  return literal;
8983
9282
  if (node.kind === "logical" && node.op === "??" && node.right.kind === "object-literal" && node.right.properties.length === 0 && node.left.kind === "member" && !node.left.computed && node.left.object.kind === "identifier" && node.left.object.name === this.state.propsObjectName) {
8984
9283
  const propName = node.left.property;
8985
- if (propsParams.some((param) => param.name === propName)) {
8986
- const fieldRef = `in.${capitalizeFieldName(propName)}`;
9284
+ const matchedParam = propsParams.find((param) => param.name === propName);
9285
+ if (matchedParam) {
9286
+ const fieldRef = `in.${capitalizeFieldName(matchedParam.sourceName ?? matchedParam.name)}`;
8987
9287
  return `func() map[string]interface{} { ` + `if m := bf.AsMap(${fieldRef}); m != nil { return m }; ` + `return map[string]interface{}{} }()`;
8988
9288
  }
8989
9289
  }
@@ -9001,7 +9301,7 @@ ${goFields.join(`
9001
9301
  const param = propsParams.find((p) => p.name === keyExpr);
9002
9302
  if (!param)
9003
9303
  return null;
9004
- const fieldName = capitalizeFieldName(keyExpr);
9304
+ const fieldName = capitalizeFieldName(param.sourceName ?? keyExpr);
9005
9305
  const caseEntries = Object.entries(part.cases);
9006
9306
  if (caseEntries.length === 0) {
9007
9307
  segments.push('""');
@@ -9064,8 +9364,9 @@ ${goFields.join(`
9064
9364
  const localConst = this.state.localConstants.find((c) => c.name === passthroughName);
9065
9365
  const isPropsDestructureAlias = localConst !== undefined && propsObjectName !== null && localConst.value === `${propsObjectName}.${passthroughName}`;
9066
9366
  const shadowedByLocal = passthroughName !== null && (localConst !== undefined && !isPropsDestructureAlias || this.state.localHelperNames.has(passthroughName));
9067
- if (passthroughName && !shadowedByLocal && propsParams.some((p) => p.name === passthroughName)) {
9068
- return `in.${capitalizeFieldName(passthroughName)}`;
9367
+ const passthroughParam = passthroughName && !shadowedByLocal ? propsParams.find((p) => p.name === passthroughName) : undefined;
9368
+ if (passthroughParam) {
9369
+ return `in.${capitalizeFieldName(passthroughParam.sourceName ?? passthroughParam.name)}`;
9069
9370
  }
9070
9371
  return null;
9071
9372
  }
@@ -9080,17 +9381,17 @@ ${goFields.join(`
9080
9381
  if (signal) {
9081
9382
  let referencedProp = propsParamMap.get(signal.initialValue);
9082
9383
  if (!referencedProp) {
9083
- const propName = this.extractPropNameFromInitialValue(signal.initialValue);
9384
+ const propName = this.extractPropNameFromInitialValue(signal.initialValue, signal.parsed);
9084
9385
  if (propName)
9085
9386
  referencedProp = propsParamMap.get(propName);
9086
9387
  }
9087
9388
  if (referencedProp) {
9088
- const propType = typeInfoToGo(this.emitCtx, referencedProp.type, referencedProp.defaultValue);
9389
+ const propType = typeInfoToGo(this.emitCtx, referencedProp.type, referencedProp.defaultValue, referencedProp.parsed);
9089
9390
  if (propType === "int" || propType === "float64") {
9090
9391
  return "int";
9091
9392
  }
9092
9393
  }
9093
- const signalType = typeInfoToGo(this.emitCtx, signal.type, signal.initialValue);
9394
+ const signalType = typeInfoToGo(this.emitCtx, signal.type, signal.initialValue, signal.parsed);
9094
9395
  if (signalType === "int" || signalType === "float64") {
9095
9396
  return "int";
9096
9397
  }
@@ -9127,8 +9428,8 @@ ${goFields.join(`
9127
9428
  continue;
9128
9429
  if (goPropDefault(param.defaultValue) !== null)
9129
9430
  continue;
9130
- const fieldName = capitalizeFieldName(match.propName);
9131
- const concreteType = propTypeOverrides.get(param.name) ?? typeInfoToGo(this.emitCtx, param.type, param.defaultValue);
9431
+ const fieldName = capitalizeFieldName(param.sourceName ?? match.propName);
9432
+ const concreteType = propTypeOverrides.get(param.name) ?? typeInfoToGo(this.emitCtx, param.type, param.defaultValue, param.parsed);
9132
9433
  const nullishLowered = NULLISH_SCALAR_GO_TYPES.has(concreteType) && resolvePropGoType(this.emitCtx, param, propTypeOverrides) === "interface{}";
9133
9434
  let zeroLiteral;
9134
9435
  if (match.goFallback === "true" || match.goFallback === "false") {