@barefootjs/erb 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 +11 -1
- package/dist/adapter/emit-context.d.ts.map +1 -1
- package/dist/adapter/erb-adapter.d.ts +14 -0
- package/dist/adapter/erb-adapter.d.ts.map +1 -1
- package/dist/adapter/expr/emitters.d.ts +11 -1
- package/dist/adapter/expr/emitters.d.ts.map +1 -1
- package/dist/adapter/index.js +33 -23
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +38 -25
- package/dist/render-divergences.d.ts.map +1 -1
- package/dist/vite.js +197 -135
- package/package.json +5 -5
- package/src/adapter/emit-context.ts +12 -1
- package/src/adapter/erb-adapter.ts +36 -43
- package/src/adapter/expr/emitters.ts +33 -0
- package/src/conformance-pins.ts +11 -0
- package/src/render-divergences.ts +4 -1
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",
|
|
@@ -263,7 +298,7 @@ function convertNode(node, raw) {
|
|
|
263
298
|
}
|
|
264
299
|
if (n === undefined || Number.isNaN(n)) {
|
|
265
300
|
const parsedDepth = convertNode(depthNode, raw);
|
|
266
|
-
if (checkSupport(parsedDepth, "rendered").supported) {
|
|
301
|
+
if (checkSupport(parsedDepth, "rendered", []).supported) {
|
|
267
302
|
depthExpr = parsedDepth;
|
|
268
303
|
flatDepth = 1;
|
|
269
304
|
} else {
|
|
@@ -1041,13 +1076,13 @@ function getUnaryOperatorString(op) {
|
|
|
1041
1076
|
return "unknown";
|
|
1042
1077
|
}
|
|
1043
1078
|
}
|
|
1044
|
-
function isSupported(expr) {
|
|
1045
|
-
return checkSupport(expr, "rendered");
|
|
1079
|
+
function isSupported(expr, opts) {
|
|
1080
|
+
return checkSupport(expr, "rendered", opts?.loweringMatchers ?? []);
|
|
1046
1081
|
}
|
|
1047
|
-
function isSupportedValue(expr) {
|
|
1048
|
-
return checkSupport(expr, "value");
|
|
1082
|
+
function isSupportedValue(expr, opts) {
|
|
1083
|
+
return checkSupport(expr, "value", opts?.loweringMatchers ?? []);
|
|
1049
1084
|
}
|
|
1050
|
-
function checkSupport(expr, pos) {
|
|
1085
|
+
function checkSupport(expr, pos, matchers) {
|
|
1051
1086
|
switch (expr.kind) {
|
|
1052
1087
|
case "unsupported":
|
|
1053
1088
|
return { supported: false, reason: expr.reason };
|
|
@@ -1056,7 +1091,7 @@ function checkSupport(expr, pos) {
|
|
|
1056
1091
|
return { supported: false, reason: "Unsupported syntax: ObjectLiteralExpression" };
|
|
1057
1092
|
}
|
|
1058
1093
|
for (const prop of expr.properties) {
|
|
1059
|
-
const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos);
|
|
1094
|
+
const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos, matchers);
|
|
1060
1095
|
if (!propSupport.supported)
|
|
1061
1096
|
return propSupport;
|
|
1062
1097
|
}
|
|
@@ -1071,7 +1106,7 @@ function checkSupport(expr, pos) {
|
|
|
1071
1106
|
return { supported: false, reason: "Standalone arrow functions / regex literals are not supported" };
|
|
1072
1107
|
case "array-literal": {
|
|
1073
1108
|
for (const el of expr.elements) {
|
|
1074
|
-
const elSupport = checkSupport(el, pos);
|
|
1109
|
+
const elSupport = checkSupport(el, pos, matchers);
|
|
1075
1110
|
if (!elSupport.supported)
|
|
1076
1111
|
return elSupport;
|
|
1077
1112
|
}
|
|
@@ -1084,28 +1119,39 @@ function checkSupport(expr, pos) {
|
|
|
1084
1119
|
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 */`
|
|
1085
1120
|
};
|
|
1086
1121
|
}
|
|
1087
|
-
const objSupport = checkSupport(expr.object, pos);
|
|
1122
|
+
const objSupport = checkSupport(expr.object, pos, matchers);
|
|
1088
1123
|
if (!objSupport.supported)
|
|
1089
1124
|
return objSupport;
|
|
1090
1125
|
for (const arg of expr.args) {
|
|
1091
|
-
const argSupport = checkSupport(arg, pos);
|
|
1126
|
+
const argSupport = checkSupport(arg, pos, matchers);
|
|
1092
1127
|
if (!argSupport.supported)
|
|
1093
1128
|
return argSupport;
|
|
1094
1129
|
}
|
|
1095
1130
|
if (expr.method === "flat" && expr.depthExpr) {
|
|
1096
|
-
const depthSupport = checkSupport(expr.depthExpr, pos);
|
|
1131
|
+
const depthSupport = checkSupport(expr.depthExpr, pos, matchers);
|
|
1097
1132
|
if (!depthSupport.supported)
|
|
1098
1133
|
return depthSupport;
|
|
1099
1134
|
}
|
|
1100
1135
|
return { supported: true, level: "L2" };
|
|
1101
1136
|
}
|
|
1102
1137
|
case "call": {
|
|
1138
|
+
for (const matcher of matchers) {
|
|
1139
|
+
const node = matcher(expr.callee, expr.args);
|
|
1140
|
+
if (!node)
|
|
1141
|
+
continue;
|
|
1142
|
+
for (const child of loweringNodeChildren(node)) {
|
|
1143
|
+
const childSupport = checkSupport(child, pos, matchers);
|
|
1144
|
+
if (!childSupport.supported)
|
|
1145
|
+
return childSupport;
|
|
1146
|
+
}
|
|
1147
|
+
return { supported: true, level: "L2" };
|
|
1148
|
+
}
|
|
1103
1149
|
const cb = asCallbackMethodCall(expr);
|
|
1104
1150
|
if (cb) {
|
|
1105
|
-
const objSupport = checkSupport(cb.object, pos);
|
|
1151
|
+
const objSupport = checkSupport(cb.object, pos, matchers);
|
|
1106
1152
|
if (!objSupport.supported)
|
|
1107
1153
|
return objSupport;
|
|
1108
|
-
const bodySupport = checkSupport(cb.arrow.body, pos);
|
|
1154
|
+
const bodySupport = checkSupport(cb.arrow.body, pos, matchers);
|
|
1109
1155
|
if (!bodySupport.supported) {
|
|
1110
1156
|
return {
|
|
1111
1157
|
supported: false,
|
|
@@ -1114,13 +1160,13 @@ function checkSupport(expr, pos) {
|
|
|
1114
1160
|
};
|
|
1115
1161
|
}
|
|
1116
1162
|
for (const rest of cb.args) {
|
|
1117
|
-
const restSupport = checkSupport(rest, pos);
|
|
1163
|
+
const restSupport = checkSupport(rest, pos, matchers);
|
|
1118
1164
|
if (!restSupport.supported)
|
|
1119
1165
|
return restSupport;
|
|
1120
1166
|
}
|
|
1121
1167
|
return { supported: true, level: "L5" };
|
|
1122
1168
|
}
|
|
1123
|
-
const calleeSupport = checkSupport(expr.callee, pos);
|
|
1169
|
+
const calleeSupport = checkSupport(expr.callee, pos, matchers);
|
|
1124
1170
|
if (!calleeSupport.supported) {
|
|
1125
1171
|
return calleeSupport;
|
|
1126
1172
|
}
|
|
@@ -1139,7 +1185,7 @@ function checkSupport(expr, pos) {
|
|
|
1139
1185
|
return { supported: true, level: "L1" };
|
|
1140
1186
|
}
|
|
1141
1187
|
for (const arg of expr.args) {
|
|
1142
|
-
const argSupport = checkSupport(arg, pos);
|
|
1188
|
+
const argSupport = checkSupport(arg, pos, matchers);
|
|
1143
1189
|
if (!argSupport.supported) {
|
|
1144
1190
|
return argSupport;
|
|
1145
1191
|
}
|
|
@@ -1147,7 +1193,7 @@ function checkSupport(expr, pos) {
|
|
|
1147
1193
|
return { supported: true, level: "L2" };
|
|
1148
1194
|
}
|
|
1149
1195
|
case "member": {
|
|
1150
|
-
const objSupport = checkSupport(expr.object, pos);
|
|
1196
|
+
const objSupport = checkSupport(expr.object, pos, matchers);
|
|
1151
1197
|
if (!objSupport.supported) {
|
|
1152
1198
|
return objSupport;
|
|
1153
1199
|
}
|
|
@@ -1157,19 +1203,19 @@ function checkSupport(expr, pos) {
|
|
|
1157
1203
|
return { supported: true, level: "L2" };
|
|
1158
1204
|
}
|
|
1159
1205
|
case "index-access": {
|
|
1160
|
-
const objSupport = checkSupport(expr.object, pos);
|
|
1206
|
+
const objSupport = checkSupport(expr.object, pos, matchers);
|
|
1161
1207
|
if (!objSupport.supported)
|
|
1162
1208
|
return objSupport;
|
|
1163
|
-
const indexSupport = checkSupport(expr.index, pos);
|
|
1209
|
+
const indexSupport = checkSupport(expr.index, pos, matchers);
|
|
1164
1210
|
if (!indexSupport.supported)
|
|
1165
1211
|
return indexSupport;
|
|
1166
1212
|
return { supported: true, level: "L2" };
|
|
1167
1213
|
}
|
|
1168
1214
|
case "binary": {
|
|
1169
|
-
const leftSupport = checkSupport(expr.left, pos);
|
|
1215
|
+
const leftSupport = checkSupport(expr.left, pos, matchers);
|
|
1170
1216
|
if (!leftSupport.supported)
|
|
1171
1217
|
return leftSupport;
|
|
1172
|
-
const rightSupport = checkSupport(expr.right, pos);
|
|
1218
|
+
const rightSupport = checkSupport(expr.right, pos, matchers);
|
|
1173
1219
|
if (!rightSupport.supported)
|
|
1174
1220
|
return rightSupport;
|
|
1175
1221
|
if (["===", "==", "!==", "!=", ">", "<", ">=", "<="].includes(expr.op)) {
|
|
@@ -1181,7 +1227,7 @@ function checkSupport(expr, pos) {
|
|
|
1181
1227
|
return { supported: false, reason: `Unknown operator: ${expr.op}` };
|
|
1182
1228
|
}
|
|
1183
1229
|
case "unary": {
|
|
1184
|
-
const argSupport = checkSupport(expr.argument, pos);
|
|
1230
|
+
const argSupport = checkSupport(expr.argument, pos, matchers);
|
|
1185
1231
|
if (!argSupport.supported)
|
|
1186
1232
|
return argSupport;
|
|
1187
1233
|
if (expr.op === "!") {
|
|
@@ -1193,25 +1239,25 @@ function checkSupport(expr, pos) {
|
|
|
1193
1239
|
return { supported: false, reason: `Unsupported unary operator: ${expr.op}` };
|
|
1194
1240
|
}
|
|
1195
1241
|
case "logical": {
|
|
1196
|
-
const leftSupport = checkSupport(expr.left, pos);
|
|
1242
|
+
const leftSupport = checkSupport(expr.left, pos, matchers);
|
|
1197
1243
|
if (!leftSupport.supported)
|
|
1198
1244
|
return leftSupport;
|
|
1199
1245
|
if (expr.op === "??" && expr.right.kind === "object-literal" && expr.right.properties.length === 0) {
|
|
1200
1246
|
return { supported: true, level: "L4" };
|
|
1201
1247
|
}
|
|
1202
|
-
const rightSupport = checkSupport(expr.right, pos);
|
|
1248
|
+
const rightSupport = checkSupport(expr.right, pos, matchers);
|
|
1203
1249
|
if (!rightSupport.supported)
|
|
1204
1250
|
return rightSupport;
|
|
1205
1251
|
return { supported: true, level: "L4" };
|
|
1206
1252
|
}
|
|
1207
1253
|
case "conditional": {
|
|
1208
|
-
const testSupport = checkSupport(expr.test, pos);
|
|
1254
|
+
const testSupport = checkSupport(expr.test, pos, matchers);
|
|
1209
1255
|
if (!testSupport.supported)
|
|
1210
1256
|
return testSupport;
|
|
1211
|
-
const consSupport = checkSupport(expr.consequent, pos);
|
|
1257
|
+
const consSupport = checkSupport(expr.consequent, pos, matchers);
|
|
1212
1258
|
if (!consSupport.supported)
|
|
1213
1259
|
return consSupport;
|
|
1214
|
-
const altSupport = checkSupport(expr.alternate, pos);
|
|
1260
|
+
const altSupport = checkSupport(expr.alternate, pos, matchers);
|
|
1215
1261
|
if (!altSupport.supported)
|
|
1216
1262
|
return altSupport;
|
|
1217
1263
|
return { supported: true, level: "L4" };
|
|
@@ -1219,7 +1265,7 @@ function checkSupport(expr, pos) {
|
|
|
1219
1265
|
case "template-literal": {
|
|
1220
1266
|
for (const part of expr.parts) {
|
|
1221
1267
|
if (part.type === "expression") {
|
|
1222
|
-
const partSupport = checkSupport(part.expr, pos);
|
|
1268
|
+
const partSupport = checkSupport(part.expr, pos, matchers);
|
|
1223
1269
|
if (!partSupport.supported)
|
|
1224
1270
|
return partSupport;
|
|
1225
1271
|
}
|
|
@@ -1941,7 +1987,7 @@ function identifierPath(callee) {
|
|
|
1941
1987
|
}
|
|
1942
1988
|
|
|
1943
1989
|
// ../jsx/src/prop-rewrite.ts
|
|
1944
|
-
import
|
|
1990
|
+
import ts7 from "typescript";
|
|
1945
1991
|
|
|
1946
1992
|
// ../jsx/src/ir-to-client-js/utils.ts
|
|
1947
1993
|
import ts3 from "typescript";
|
|
@@ -2091,19 +2137,61 @@ function resolveJsxChildrenProp(props) {
|
|
|
2091
2137
|
return [];
|
|
2092
2138
|
return prop.value.children ?? [];
|
|
2093
2139
|
}
|
|
2140
|
+
// ../jsx/src/ir-to-client-js/component-scope.ts
|
|
2141
|
+
function buildImportAliasMap(imports) {
|
|
2142
|
+
const aliases = new Map;
|
|
2143
|
+
for (const imp of imports) {
|
|
2144
|
+
if (imp.isTypeOnly)
|
|
2145
|
+
continue;
|
|
2146
|
+
for (const spec of imp.specifiers) {
|
|
2147
|
+
if (spec.isTypeOnly || spec.isDefault || spec.isNamespace || spec.alias === null)
|
|
2148
|
+
continue;
|
|
2149
|
+
aliases.set(spec.alias, spec.name);
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
return aliases;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2094
2155
|
// ../jsx/src/ir-to-client-js/csr-substitute.ts
|
|
2156
|
+
import ts5 from "typescript";
|
|
2157
|
+
|
|
2158
|
+
// ../jsx/src/props-binding.ts
|
|
2095
2159
|
import ts4 from "typescript";
|
|
2160
|
+
function isIdentifierName(key) {
|
|
2161
|
+
if (key.length === 0)
|
|
2162
|
+
return false;
|
|
2163
|
+
for (let i = 0;i < key.length; ) {
|
|
2164
|
+
const cp = key.codePointAt(i);
|
|
2165
|
+
const ok = i === 0 ? ts4.isIdentifierStart(cp, ts4.ScriptTarget.Latest) : ts4.isIdentifierPart(cp, ts4.ScriptTarget.Latest);
|
|
2166
|
+
if (!ok)
|
|
2167
|
+
return false;
|
|
2168
|
+
i += cp > 65535 ? 2 : 1;
|
|
2169
|
+
}
|
|
2170
|
+
return true;
|
|
2171
|
+
}
|
|
2172
|
+
function propsDestructureBinding(p) {
|
|
2173
|
+
const callerKey = p.sourceName ?? p.name;
|
|
2174
|
+
const localName = p.name;
|
|
2175
|
+
const binding = callerKey === localName ? localName : `${isIdentifierName(callerKey) ? callerKey : JSON.stringify(callerKey)}: ${localName}`;
|
|
2176
|
+
return p.defaultValue ? `${binding} = ${p.defaultValue}` : binding;
|
|
2177
|
+
}
|
|
2178
|
+
var EMPTY_SET = new Set;
|
|
2179
|
+
|
|
2180
|
+
// ../jsx/src/ir-to-client-js/csr-substitute.ts
|
|
2096
2181
|
function extractFreeIdentifiersFromText(text) {
|
|
2097
2182
|
if (!text || text.trim().length === 0)
|
|
2098
2183
|
return new Set;
|
|
2099
|
-
const sf =
|
|
2184
|
+
const sf = ts5.createSourceFile("__free_ids__.ts", `(${text});`, ts5.ScriptTarget.Latest, true, ts5.ScriptKind.TS);
|
|
2100
2185
|
const stmt = sf.statements[0];
|
|
2101
|
-
if (!stmt || !
|
|
2186
|
+
if (!stmt || !ts5.isExpressionStatement(stmt))
|
|
2102
2187
|
return new Set;
|
|
2103
|
-
const expr =
|
|
2188
|
+
const expr = ts5.isParenthesizedExpression(stmt.expression) ? stmt.expression.expression : stmt.expression;
|
|
2104
2189
|
return extractFreeIdentifiersFromNode(expr);
|
|
2105
2190
|
}
|
|
2106
2191
|
|
|
2192
|
+
// ../jsx/src/ir-to-client-js/rewrite-props-object.ts
|
|
2193
|
+
import ts6 from "typescript";
|
|
2194
|
+
|
|
2107
2195
|
// ../jsx/src/adapters/child-scope.ts
|
|
2108
2196
|
function derivesScopeFromSlot(comp) {
|
|
2109
2197
|
return comp.slotId != null && comp.loopItemRoot !== true;
|
|
@@ -2230,27 +2318,6 @@ var SKELETON_PATH_FORCE_CLOSE_GROUPS = [
|
|
|
2230
2318
|
new Set(["li"])
|
|
2231
2319
|
];
|
|
2232
2320
|
|
|
2233
|
-
// ../jsx/src/props-binding.ts
|
|
2234
|
-
import ts6 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 ? ts6.isIdentifierStart(cp, ts6.ScriptTarget.Latest) : ts6.isIdentifierPart(cp, ts6.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
|
-
|
|
2254
2321
|
// ../jsx/src/instrumentation.ts
|
|
2255
2322
|
var _counters = freshCounters();
|
|
2256
2323
|
function freshCounters() {
|
|
@@ -2264,20 +2331,21 @@ function freshCounters() {
|
|
|
2264
2331
|
}
|
|
2265
2332
|
|
|
2266
2333
|
// ../jsx/src/analyzer-context.ts
|
|
2267
|
-
import
|
|
2334
|
+
import ts9 from "typescript";
|
|
2268
2335
|
|
|
2269
2336
|
// ../jsx/src/strip-types.ts
|
|
2270
|
-
import
|
|
2337
|
+
import ts8 from "typescript";
|
|
2271
2338
|
|
|
2272
2339
|
// ../jsx/src/analyzer-context.ts
|
|
2273
|
-
var _typePrinter =
|
|
2274
|
-
var _blankTypeSourceFile =
|
|
2340
|
+
var _typePrinter = ts9.createPrinter({ removeComments: true, omitTrailingSemicolon: true });
|
|
2341
|
+
var _blankTypeSourceFile = ts9.createSourceFile("__bf_types__.ts", "", ts9.ScriptTarget.Latest);
|
|
2275
2342
|
|
|
2276
2343
|
// ../jsx/src/errors.ts
|
|
2277
2344
|
var ErrorCodes = {
|
|
2278
2345
|
MISSING_USE_CLIENT: "BF001",
|
|
2279
2346
|
CLIENT_IMPORTING_SERVER: "BF003",
|
|
2280
2347
|
SIGNAL_OUTSIDE_COMPONENT: "BF011",
|
|
2348
|
+
PRIMITIVE_VIA_NAMESPACE_IMPORT: "BF013",
|
|
2281
2349
|
UNSUPPORTED_JSX_PATTERN: "BF021",
|
|
2282
2350
|
MISSING_KEY_IN_LIST: "BF023",
|
|
2283
2351
|
MISSING_KEY_IN_NESTED_LIST: "BF024",
|
|
@@ -2310,6 +2378,7 @@ var errorMessages = {
|
|
|
2310
2378
|
[ErrorCodes.MISSING_USE_CLIENT]: "'use client' directive required for components with createSignal or event handlers",
|
|
2311
2379
|
[ErrorCodes.CLIENT_IMPORTING_SERVER]: "Client component cannot import server component",
|
|
2312
2380
|
[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.",
|
|
2381
|
+
[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.",
|
|
2313
2382
|
[ErrorCodes.UNSUPPORTED_JSX_PATTERN]: "Unsupported JSX pattern",
|
|
2314
2383
|
[ErrorCodes.MISSING_KEY_IN_LIST]: "Missing key attribute in list rendering. Add a key prop for efficient updates",
|
|
2315
2384
|
[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",
|
|
@@ -2501,46 +2570,46 @@ function extractFreeIdentifiersFromNode(node) {
|
|
|
2501
2570
|
const ids = new Set;
|
|
2502
2571
|
const boundNames = new Set;
|
|
2503
2572
|
function addBindingNames(name, out) {
|
|
2504
|
-
if (
|
|
2573
|
+
if (ts10.isIdentifier(name))
|
|
2505
2574
|
out.push(name.text);
|
|
2506
|
-
else if (
|
|
2575
|
+
else if (ts10.isObjectBindingPattern(name))
|
|
2507
2576
|
name.elements.forEach((e) => addBindingNames(e.name, out));
|
|
2508
|
-
else if (
|
|
2577
|
+
else if (ts10.isArrayBindingPattern(name))
|
|
2509
2578
|
name.elements.forEach((e) => {
|
|
2510
|
-
if (!
|
|
2579
|
+
if (!ts10.isOmittedExpression(e))
|
|
2511
2580
|
addBindingNames(e.name, out);
|
|
2512
2581
|
});
|
|
2513
2582
|
}
|
|
2514
2583
|
function visit(n) {
|
|
2515
|
-
if (
|
|
2584
|
+
if (ts10.isTypeNode(n))
|
|
2516
2585
|
return;
|
|
2517
|
-
if (
|
|
2586
|
+
if (ts10.isIdentifier(n)) {
|
|
2518
2587
|
const parent = n.parent;
|
|
2519
|
-
if (parent &&
|
|
2588
|
+
if (parent && ts10.isPropertyAccessExpression(parent) && parent.name === n)
|
|
2520
2589
|
return;
|
|
2521
|
-
if (parent &&
|
|
2590
|
+
if (parent && ts10.isPropertyAssignment(parent) && parent.name === n)
|
|
2522
2591
|
return;
|
|
2523
|
-
if (parent &&
|
|
2592
|
+
if (parent && ts10.isParameter(parent) && parent.name === n)
|
|
2524
2593
|
return;
|
|
2525
|
-
if (parent &&
|
|
2594
|
+
if (parent && ts10.isVariableDeclaration(parent) && parent.name === n)
|
|
2526
2595
|
return;
|
|
2527
2596
|
if (boundNames.has(n.text))
|
|
2528
2597
|
return;
|
|
2529
2598
|
ids.add(n.text);
|
|
2530
2599
|
return;
|
|
2531
2600
|
}
|
|
2532
|
-
if (
|
|
2601
|
+
if (ts10.isArrowFunction(n)) {
|
|
2533
2602
|
const params = [];
|
|
2534
2603
|
for (const p of n.parameters)
|
|
2535
2604
|
addBindingNames(p.name, params);
|
|
2536
2605
|
for (const name of params)
|
|
2537
2606
|
boundNames.add(name);
|
|
2538
|
-
|
|
2607
|
+
ts10.forEachChild(n, visit);
|
|
2539
2608
|
for (const name of params)
|
|
2540
2609
|
boundNames.delete(name);
|
|
2541
2610
|
return;
|
|
2542
2611
|
}
|
|
2543
|
-
|
|
2612
|
+
ts10.forEachChild(n, visit);
|
|
2544
2613
|
}
|
|
2545
2614
|
visit(node);
|
|
2546
2615
|
return ids;
|
|
@@ -2563,7 +2632,7 @@ var REACTIVE_PRIMITIVES = new Set([
|
|
|
2563
2632
|
]);
|
|
2564
2633
|
|
|
2565
2634
|
// ../jsx/src/jsx-to-ir.ts
|
|
2566
|
-
import
|
|
2635
|
+
import ts14 from "typescript";
|
|
2567
2636
|
|
|
2568
2637
|
// ../jsx/src/types.ts
|
|
2569
2638
|
var SCOPE_FORBIDDEN = {
|
|
@@ -2613,7 +2682,7 @@ function preambleAnalysisTemplateText(p) {
|
|
|
2613
2682
|
}
|
|
2614
2683
|
|
|
2615
2684
|
// ../jsx/src/module-exports.ts
|
|
2616
|
-
import
|
|
2685
|
+
import ts11 from "typescript";
|
|
2617
2686
|
function formatParamWithType(p) {
|
|
2618
2687
|
const rest = p.isRest ? "..." : "";
|
|
2619
2688
|
const optional = p.optional ? "?" : "";
|
|
@@ -2648,21 +2717,21 @@ function findAssignedNames(bodyText, candidates) {
|
|
|
2648
2717
|
const assigned = new Set;
|
|
2649
2718
|
if (candidates.size === 0)
|
|
2650
2719
|
return assigned;
|
|
2651
|
-
const sf =
|
|
2720
|
+
const sf = ts11.createSourceFile("bf-assignment-scan.tsx", bodyText, ts11.ScriptTarget.Latest, false, ts11.ScriptKind.TSX);
|
|
2652
2721
|
const record = (target) => {
|
|
2653
|
-
if (
|
|
2722
|
+
if (ts11.isIdentifier(target) && candidates.has(target.text)) {
|
|
2654
2723
|
assigned.add(target.text);
|
|
2655
2724
|
}
|
|
2656
2725
|
};
|
|
2657
2726
|
const visit = (node) => {
|
|
2658
|
-
if (
|
|
2727
|
+
if (ts11.isBinaryExpression(node) && isAssignmentOperator(node.operatorToken.kind)) {
|
|
2659
2728
|
record(node.left);
|
|
2660
|
-
} else if ((
|
|
2729
|
+
} else if ((ts11.isPrefixUnaryExpression(node) || ts11.isPostfixUnaryExpression(node)) && (node.operator === ts11.SyntaxKind.PlusPlusToken || node.operator === ts11.SyntaxKind.MinusMinusToken)) {
|
|
2661
2730
|
record(node.operand);
|
|
2662
2731
|
}
|
|
2663
|
-
|
|
2732
|
+
ts11.forEachChild(node, visit);
|
|
2664
2733
|
};
|
|
2665
|
-
|
|
2734
|
+
ts11.forEachChild(sf, visit);
|
|
2666
2735
|
return assigned;
|
|
2667
2736
|
}
|
|
2668
2737
|
function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNames) {
|
|
@@ -2685,14 +2754,14 @@ function closeOverWritersOfMutableBindings(primaryRefs, declarations, mutableNam
|
|
|
2685
2754
|
return reachable;
|
|
2686
2755
|
}
|
|
2687
2756
|
function isAssignmentOperator(kind) {
|
|
2688
|
-
return kind >=
|
|
2757
|
+
return kind >= ts11.SyntaxKind.FirstAssignment && kind <= ts11.SyntaxKind.LastAssignment;
|
|
2689
2758
|
}
|
|
2690
2759
|
|
|
2691
2760
|
// ../jsx/src/reactivity-checker.ts
|
|
2692
|
-
import
|
|
2761
|
+
import ts12 from "typescript";
|
|
2693
2762
|
|
|
2694
2763
|
// ../jsx/src/free-refs.ts
|
|
2695
|
-
import
|
|
2764
|
+
import ts13 from "typescript";
|
|
2696
2765
|
var _bindingMapCache = new WeakMap;
|
|
2697
2766
|
|
|
2698
2767
|
// ../jsx/src/to-locale-date-lowering.ts
|
|
@@ -3140,40 +3209,16 @@ var KEYWORDS_AND_GLOBALS = new Set([
|
|
|
3140
3209
|
]);
|
|
3141
3210
|
|
|
3142
3211
|
// ../jsx/src/ir-to-client-js/walk-prop-accesses.ts
|
|
3143
|
-
import ts14 from "typescript";
|
|
3144
|
-
|
|
3145
|
-
// ../jsx/src/ir-to-client-js/imports.ts
|
|
3146
|
-
import ts16 from "typescript";
|
|
3147
|
-
|
|
3148
|
-
// ../jsx/src/value-references.ts
|
|
3149
3212
|
import ts15 from "typescript";
|
|
3150
3213
|
|
|
3151
|
-
// ../jsx/src/
|
|
3214
|
+
// ../jsx/src/ir-to-client-js/imports.ts
|
|
3152
3215
|
import ts17 from "typescript";
|
|
3153
3216
|
|
|
3154
|
-
// ../jsx/src/
|
|
3155
|
-
|
|
3156
|
-
function registerLoweringPlugin(plugin) {
|
|
3157
|
-
const existing = plugins.findIndex((p) => p.name === plugin.name);
|
|
3158
|
-
if (existing >= 0)
|
|
3159
|
-
plugins[existing] = plugin;
|
|
3160
|
-
else
|
|
3161
|
-
plugins.push(plugin);
|
|
3162
|
-
}
|
|
3163
|
-
function prepareLoweringMatchers(metadata) {
|
|
3164
|
-
const matchers = [];
|
|
3165
|
-
for (const plugin of plugins) {
|
|
3166
|
-
const matcher = plugin.prepare(metadata);
|
|
3167
|
-
if (matcher)
|
|
3168
|
-
matchers.push(matcher);
|
|
3169
|
-
}
|
|
3170
|
-
return matchers;
|
|
3171
|
-
}
|
|
3172
|
-
function isValidHelperId(helper) {
|
|
3173
|
-
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
|
|
3174
|
-
}
|
|
3217
|
+
// ../jsx/src/value-references.ts
|
|
3218
|
+
import ts16 from "typescript";
|
|
3175
3219
|
|
|
3176
3220
|
// ../jsx/src/relocate.ts
|
|
3221
|
+
import ts18 from "typescript";
|
|
3177
3222
|
var REGISTRY_SAFE_BINDING_KINDS = new Set([
|
|
3178
3223
|
"global",
|
|
3179
3224
|
"module-import",
|
|
@@ -3366,10 +3411,10 @@ function matchSearchParamsMethodCall(callee, args, localNames) {
|
|
|
3366
3411
|
}
|
|
3367
3412
|
|
|
3368
3413
|
// ../jsx/src/ir-to-client-js/prune-unused-prop-extractions.ts
|
|
3369
|
-
import
|
|
3414
|
+
import ts19 from "typescript";
|
|
3370
3415
|
|
|
3371
3416
|
// ../jsx/src/ir-to-client-js/control-flow/plan/lazy-preamble.ts
|
|
3372
|
-
import
|
|
3417
|
+
import ts20 from "typescript";
|
|
3373
3418
|
var NO_PREAMBLE = {
|
|
3374
3419
|
lazySafe: true,
|
|
3375
3420
|
facts: { declaredNames: new Set, freeNames: new Set }
|
|
@@ -3419,7 +3464,7 @@ var INERT_BINDING_GLOBALS = new Set([
|
|
|
3419
3464
|
]);
|
|
3420
3465
|
|
|
3421
3466
|
// ../jsx/src/ir-to-client-js/emit-reactive.ts
|
|
3422
|
-
import
|
|
3467
|
+
import ts21 from "typescript";
|
|
3423
3468
|
|
|
3424
3469
|
// ../jsx/src/ir-to-client-js/control-flow/stringify/event-delegation.ts
|
|
3425
3470
|
var NON_BUBBLING_EVENTS = new Set([
|
|
@@ -3433,9 +3478,6 @@ var NON_BUBBLING_EVENTS = new Set([
|
|
|
3433
3478
|
"pointerleave"
|
|
3434
3479
|
]);
|
|
3435
3480
|
|
|
3436
|
-
// ../jsx/src/ir-to-client-js/rewrite-props-object.ts
|
|
3437
|
-
import ts21 from "typescript";
|
|
3438
|
-
|
|
3439
3481
|
// ../jsx/src/ir-to-client-js/source-map.ts
|
|
3440
3482
|
var BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
3441
3483
|
function encodeVLQ(value) {
|
|
@@ -4640,6 +4682,17 @@ function emitParsedExpr(expr, emitter) {
|
|
|
4640
4682
|
case "literal":
|
|
4641
4683
|
return emitter.literal(expr.value, expr.literalType);
|
|
4642
4684
|
case "call": {
|
|
4685
|
+
if (emitter.lowering) {
|
|
4686
|
+
for (const matcher of emitter.lowering.matchers) {
|
|
4687
|
+
const node = matcher(expr.callee, expr.args);
|
|
4688
|
+
if (!node)
|
|
4689
|
+
continue;
|
|
4690
|
+
const rendered = emitter.lowering.render(node, emit);
|
|
4691
|
+
if (rendered !== null)
|
|
4692
|
+
return rendered;
|
|
4693
|
+
break;
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4643
4696
|
const cb = asCallbackMethodCall(expr);
|
|
4644
4697
|
if (cb)
|
|
4645
4698
|
return emitter.callbackMethod(cb.method, cb.object, cb.arrow, cb.args, emit);
|
|
@@ -5697,6 +5750,21 @@ class ErbTopLevelEmitter {
|
|
|
5697
5750
|
constructor(ctx) {
|
|
5698
5751
|
this.ctx = ctx;
|
|
5699
5752
|
}
|
|
5753
|
+
get lowering() {
|
|
5754
|
+
return {
|
|
5755
|
+
matchers: this.ctx._loweringMatchers,
|
|
5756
|
+
render: (node, emit) => {
|
|
5757
|
+
if (node.kind === "guard-list" && node.helper === "query") {
|
|
5758
|
+
const qArgs = queryHrefArgs(node, emit);
|
|
5759
|
+
return `bf.query(${qArgs.join(", ")})`;
|
|
5760
|
+
}
|
|
5761
|
+
if (node.kind === "helper-call" && isValidHelperId(node.helper)) {
|
|
5762
|
+
return `bf.${node.helper}(${node.args.map(emit).join(", ")})`;
|
|
5763
|
+
}
|
|
5764
|
+
return null;
|
|
5765
|
+
}
|
|
5766
|
+
};
|
|
5767
|
+
}
|
|
5700
5768
|
identifier(name) {
|
|
5701
5769
|
if (name === "undefined" || name === "null")
|
|
5702
5770
|
return "nil";
|
|
@@ -6176,6 +6244,7 @@ class ErbAdapter extends BaseAdapter {
|
|
|
6176
6244
|
localConstants = [];
|
|
6177
6245
|
scope = BindingScope.EMPTY;
|
|
6178
6246
|
nullableOptionalProps = new Set;
|
|
6247
|
+
importAliases = new Map;
|
|
6179
6248
|
constructor(options = {}) {
|
|
6180
6249
|
super();
|
|
6181
6250
|
this.options = {
|
|
@@ -6196,6 +6265,7 @@ class ErbAdapter extends BaseAdapter {
|
|
|
6196
6265
|
this._searchParamsLocals = searchParamsLocalNames(ir.metadata);
|
|
6197
6266
|
this._loweringMatchers = prepareLoweringMatchers(ir.metadata);
|
|
6198
6267
|
this.localConstants = ir.metadata.localConstants ?? [];
|
|
6268
|
+
this.importAliases = buildImportAliasMap(ir.metadata.imports ?? []);
|
|
6199
6269
|
this.scope = BindingScope.EMPTY;
|
|
6200
6270
|
this.errors = [];
|
|
6201
6271
|
this.childrenCaptureCounter = 0;
|
|
@@ -6249,7 +6319,9 @@ class ErbAdapter extends BaseAdapter {
|
|
|
6249
6319
|
return null;
|
|
6250
6320
|
return {
|
|
6251
6321
|
condition: exprToString(parsed.test),
|
|
6252
|
-
consequent: exprToString(parsed.consequent)
|
|
6322
|
+
consequent: exprToString(parsed.consequent),
|
|
6323
|
+
testParsed: parsed.test,
|
|
6324
|
+
consequentParsed: parsed.consequent
|
|
6253
6325
|
};
|
|
6254
6326
|
}
|
|
6255
6327
|
resolveLiteralConst(name) {
|
|
@@ -6723,7 +6795,8 @@ ${renderedChildren}` : renderedChildren;
|
|
|
6723
6795
|
}
|
|
6724
6796
|
childrenCaptureCounter = 0;
|
|
6725
6797
|
toTemplateName(componentName) {
|
|
6726
|
-
|
|
6798
|
+
const declaredName = this.importAliases.get(componentName) ?? componentName;
|
|
6799
|
+
return declaredName.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
6727
6800
|
}
|
|
6728
6801
|
renderIfStatement(ifStmt) {
|
|
6729
6802
|
const condition = this.convertExpressionToRuby(ifStmt.condition);
|
|
@@ -6793,8 +6866,8 @@ ${children}`;
|
|
|
6793
6866
|
{
|
|
6794
6867
|
const m = this.parseUndefinedAlternateTernary(value.expr);
|
|
6795
6868
|
if (m) {
|
|
6796
|
-
const cond = this.convertExpressionToRuby(m.
|
|
6797
|
-
const val = this.convertExpressionToRuby(m.
|
|
6869
|
+
const cond = this.convertExpressionToRuby("", m.testParsed);
|
|
6870
|
+
const val = this.convertExpressionToRuby("", m.consequentParsed);
|
|
6798
6871
|
return `<% if bf.truthy?(${cond}) %>${name}="<%= bf.h(${val}) %>"<% end %>`;
|
|
6799
6872
|
}
|
|
6800
6873
|
}
|
|
@@ -6924,7 +6997,7 @@ ${children}`;
|
|
|
6924
6997
|
if (!startsAsObjectLiteral && !hasTaggedTemplate)
|
|
6925
6998
|
return false;
|
|
6926
6999
|
const parsed = parseExpression(expr.trim());
|
|
6927
|
-
const support = isSupported(parsed);
|
|
7000
|
+
const support = isSupported(parsed, { loweringMatchers: this._loweringMatchers });
|
|
6928
7001
|
if (parsed.kind !== "unsupported" && support.supported)
|
|
6929
7002
|
return false;
|
|
6930
7003
|
const reason = support.reason ?? (parsed.kind === "unsupported" ? parsed.reason : undefined);
|
|
@@ -6944,6 +7017,7 @@ ${reason}` : "";
|
|
|
6944
7017
|
get emitCtx() {
|
|
6945
7018
|
return {
|
|
6946
7019
|
_searchParamsLocals: this._searchParamsLocals,
|
|
7020
|
+
_loweringMatchers: this._loweringMatchers,
|
|
6947
7021
|
resolveModuleStringConst: (name) => this.resolveModuleStringConst(name),
|
|
6948
7022
|
resolveLiteralConst: (name) => this.resolveLiteralConst(name),
|
|
6949
7023
|
resolveStaticRecordLiteral: (o, k) => this.resolveStaticRecordLiteral(o, k),
|
|
@@ -6975,20 +7049,8 @@ ${reason}` : "";
|
|
|
6975
7049
|
return "''";
|
|
6976
7050
|
parsed = parseExpression(trimmed);
|
|
6977
7051
|
}
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
const node = matcher(parsed.callee, parsed.args);
|
|
6981
|
-
if (node?.kind === "guard-list" && node.helper === "query") {
|
|
6982
|
-
const argsRuby = queryHrefArgs(node, (n) => this.renderParsedExprToRuby(n));
|
|
6983
|
-
return `bf.query(${argsRuby.join(", ")})`;
|
|
6984
|
-
}
|
|
6985
|
-
if (node?.kind === "helper-call" && isValidHelperId(node.helper)) {
|
|
6986
|
-
const argsX = node.args.map((a) => this.renderParsedExprToRuby(a));
|
|
6987
|
-
return `bf.${node.helper}(${argsX.join(", ")})`;
|
|
6988
|
-
}
|
|
6989
|
-
}
|
|
6990
|
-
}
|
|
6991
|
-
const support = pos === "value" ? isSupportedValue(parsed) : isSupported(parsed);
|
|
7052
|
+
const supportOpts = { loweringMatchers: this._loweringMatchers };
|
|
7053
|
+
const support = pos === "value" ? isSupportedValue(parsed, supportOpts) : isSupported(parsed, supportOpts);
|
|
6992
7054
|
if (!support.supported) {
|
|
6993
7055
|
this.errors.push({
|
|
6994
7056
|
code: "BF101",
|