@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/adapter/emit-context.d.ts +12 -0
- package/dist/adapter/emit-context.d.ts.map +1 -1
- package/dist/adapter/expr/url-builder.d.ts +53 -1
- package/dist/adapter/expr/url-builder.d.ts.map +1 -1
- package/dist/adapter/go-template-adapter.d.ts +153 -7
- package/dist/adapter/go-template-adapter.d.ts.map +1 -1
- package/dist/adapter/index.js +253 -99
- package/dist/adapter/lib/compile-state.d.ts +17 -0
- package/dist/adapter/lib/compile-state.d.ts.map +1 -1
- package/dist/adapter/value/parsed-literal-to-go.d.ts.map +1 -1
- package/dist/adapter/value/value-lowering.d.ts.map +1 -1
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +261 -103
- package/dist/render-divergences.d.ts +10 -0
- package/dist/render-divergences.d.ts.map +1 -1
- package/dist/vite.js +420 -214
- package/package.json +5 -5
- package/src/__tests__/go-template-adapter.test.ts +333 -9
- package/src/__tests__/lowering-plugin.test.ts +38 -0
- package/src/__tests__/query-href.test.ts +126 -0
- package/src/adapter/emit-context.ts +14 -0
- package/src/adapter/expr/url-builder.ts +114 -8
- package/src/adapter/go-template-adapter.ts +514 -107
- package/src/adapter/lib/compile-state.ts +18 -0
- package/src/adapter/value/parsed-literal-to-go.ts +11 -7
- package/src/adapter/value/value-lowering.ts +17 -0
- package/src/conformance-pins.ts +19 -0
- package/src/render-divergences.ts +12 -6
- package/src/test-render.ts +32 -15
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
|
|
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
|
|
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 =
|
|
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 || !
|
|
2261
|
+
if (!stmt || !ts5.isExpressionStatement(stmt))
|
|
2177
2262
|
return new Set;
|
|
2178
|
-
const expr =
|
|
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
|
|
2404
|
+
import ts9 from "typescript";
|
|
2338
2405
|
|
|
2339
2406
|
// ../jsx/src/strip-types.ts
|
|
2340
|
-
import
|
|
2407
|
+
import ts8 from "typescript";
|
|
2341
2408
|
|
|
2342
2409
|
// ../jsx/src/analyzer-context.ts
|
|
2343
|
-
var _typePrinter =
|
|
2344
|
-
var _blankTypeSourceFile =
|
|
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 (
|
|
2643
|
+
if (ts10.isIdentifier(name))
|
|
2575
2644
|
out.push(name.text);
|
|
2576
|
-
else if (
|
|
2645
|
+
else if (ts10.isObjectBindingPattern(name))
|
|
2577
2646
|
name.elements.forEach((e) => addBindingNames(e.name, out));
|
|
2578
|
-
else if (
|
|
2647
|
+
else if (ts10.isArrayBindingPattern(name))
|
|
2579
2648
|
name.elements.forEach((e) => {
|
|
2580
|
-
if (!
|
|
2649
|
+
if (!ts10.isOmittedExpression(e))
|
|
2581
2650
|
addBindingNames(e.name, out);
|
|
2582
2651
|
});
|
|
2583
2652
|
}
|
|
2584
2653
|
function visit(n) {
|
|
2585
|
-
if (
|
|
2654
|
+
if (ts10.isTypeNode(n))
|
|
2586
2655
|
return;
|
|
2587
|
-
if (
|
|
2656
|
+
if (ts10.isIdentifier(n)) {
|
|
2588
2657
|
const parent = n.parent;
|
|
2589
|
-
if (parent &&
|
|
2658
|
+
if (parent && ts10.isPropertyAccessExpression(parent) && parent.name === n)
|
|
2590
2659
|
return;
|
|
2591
|
-
if (parent &&
|
|
2660
|
+
if (parent && ts10.isPropertyAssignment(parent) && parent.name === n)
|
|
2592
2661
|
return;
|
|
2593
|
-
if (parent &&
|
|
2662
|
+
if (parent && ts10.isParameter(parent) && parent.name === n)
|
|
2594
2663
|
return;
|
|
2595
|
-
if (parent &&
|
|
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 (
|
|
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
|
-
|
|
2677
|
+
ts10.forEachChild(n, visit);
|
|
2609
2678
|
for (const name of params)
|
|
2610
2679
|
boundNames.delete(name);
|
|
2611
2680
|
return;
|
|
2612
2681
|
}
|
|
2613
|
-
|
|
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
|
|
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
|
|
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 =
|
|
2790
|
+
const sf = ts11.createSourceFile("bf-assignment-scan.tsx", bodyText, ts11.ScriptTarget.Latest, false, ts11.ScriptKind.TSX);
|
|
2722
2791
|
const record = (target) => {
|
|
2723
|
-
if (
|
|
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 (
|
|
2797
|
+
if (ts11.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
|
|
2729
2798
|
record(node.left);
|
|
2730
|
-
} else if ((
|
|
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
|
-
|
|
2802
|
+
ts11.forEachChild(node, visit);
|
|
2734
2803
|
};
|
|
2735
|
-
|
|
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 >=
|
|
2827
|
+
return kind >= ts11.SyntaxKind.FirstAssignment && kind <= ts11.SyntaxKind.LastAssignment;
|
|
2759
2828
|
}
|
|
2760
2829
|
|
|
2761
2830
|
// ../jsx/src/reactivity-checker.ts
|
|
2762
|
-
import
|
|
2831
|
+
import ts12 from "typescript";
|
|
2763
2832
|
|
|
2764
2833
|
// ../jsx/src/free-refs.ts
|
|
2765
|
-
import
|
|
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/
|
|
3284
|
+
// ../jsx/src/ir-to-client-js/imports.ts
|
|
3222
3285
|
import ts17 from "typescript";
|
|
3223
3286
|
|
|
3224
|
-
// ../jsx/src/
|
|
3225
|
-
|
|
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
|
|
3463
|
+
import ts19 from "typescript";
|
|
3419
3464
|
|
|
3420
3465
|
// ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
|
|
3421
|
-
import
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
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
|
-
|
|
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
|
|
8534
|
-
|
|
8535
|
-
|
|
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
|
-
|
|
8551
|
-
|
|
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
|
-
|
|
8682
|
+
shapes.set(key, { kind: "scalar", goType });
|
|
8683
|
+
} else if (prevShape.kind !== "scalar") {
|
|
8684
|
+
return null;
|
|
8557
8685
|
} else {
|
|
8558
|
-
const merged = this.mergeScalarGoType(
|
|
8686
|
+
const merged = this.mergeScalarGoType(prevShape.goType, goType);
|
|
8559
8687
|
if (!merged)
|
|
8560
8688
|
return null;
|
|
8561
|
-
|
|
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
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
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
|
-
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
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
|
-
|
|
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(` ${
|
|
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([]${
|
|
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${
|
|
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([]${
|
|
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${
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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([]${
|
|
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${
|
|
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
|
-
|
|
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(` ${
|
|
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
|
-
|
|
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(` ${
|
|
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.
|
|
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
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
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.
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
11175
|
-
this.repropsOwner.set(
|
|
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(
|
|
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
|
|
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(
|
|
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 "${
|
|
12011
|
+
templateCall = `{{template "${declaredName}" (bf_with_children . (bf_tmpl "${loopBodyDefine}" ${bodyData}))}}`;
|
|
11812
12012
|
} else {
|
|
11813
|
-
templateCall = `{{template "${
|
|
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(
|
|
11820
|
-
templateCall = loopBodyDefine ? `{{template "${
|
|
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 "${
|
|
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 "${
|
|
12028
|
+
templateCall = childrenDefine ? `{{template "${declaredName}" (bf_with_children ${base} (bf_tmpl "${childrenDefine}" .))}}` : `{{template "${declaredName}" ${base}}}`;
|
|
11829
12029
|
} else {
|
|
11830
|
-
templateCall = `{{template "${
|
|
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
|
|
11882
|
-
const body = `${name}="{{${
|
|
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)) {
|