@barefootjs/jsx 0.17.1 → 0.18.1
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/adapters/interface.d.ts +20 -4
- package/dist/adapters/interface.d.ts.map +1 -1
- package/dist/adapters/parsed-expr-emitter.d.ts +3 -1
- package/dist/adapters/parsed-expr-emitter.d.ts.map +1 -1
- package/dist/analyzer-context.d.ts.map +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/augment-inherited-props.d.ts +19 -0
- package/dist/augment-inherited-props.d.ts.map +1 -1
- package/dist/compiler.d.ts.map +1 -1
- package/dist/expression-parser.d.ts +1 -0
- package/dist/expression-parser.d.ts.map +1 -1
- package/dist/index.d.ts +19 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +815 -251
- package/dist/ir-to-client-js/collect-elements.d.ts.map +1 -1
- package/dist/ir-to-client-js/compute-inlinability.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/build-loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts +9 -0
- package/dist/ir-to-client-js/control-flow/plan/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/loop.d.ts.map +1 -1
- package/dist/ir-to-client-js/control-flow/stringify/template-parse.d.ts +19 -0
- package/dist/ir-to-client-js/control-flow/stringify/template-parse.d.ts.map +1 -1
- package/dist/ir-to-client-js/emit-registration.d.ts +4 -2
- package/dist/ir-to-client-js/emit-registration.d.ts.map +1 -1
- package/dist/ir-to-client-js/html-template.d.ts +41 -0
- package/dist/ir-to-client-js/html-template.d.ts.map +1 -1
- package/dist/ir-to-client-js/types.d.ts +22 -1
- package/dist/ir-to-client-js/types.d.ts.map +1 -1
- package/dist/jsx-to-ir.d.ts.map +1 -1
- package/dist/loop-destructure.d.ts +55 -18
- package/dist/loop-destructure.d.ts.map +1 -1
- package/dist/lowering-registry.d.ts +13 -0
- package/dist/lowering-registry.d.ts.map +1 -1
- package/dist/relocate.d.ts +28 -0
- package/dist/relocate.d.ts.map +1 -1
- package/dist/ssr-defaults.d.ts.map +1 -1
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/__snapshots__/doc-examples.test.ts.snap +284 -12
- package/src/__tests__/augment-inherited-props.test.ts +96 -0
- package/src/__tests__/compiler-runtime-contract.test.ts +11 -1
- package/src/__tests__/compiler-stress-1244.test.ts +13 -4
- package/src/__tests__/csr-substitution-safety-divergence.test.ts +137 -0
- package/src/__tests__/destructured-map-params.test.ts +11 -1
- package/src/__tests__/expression-parser.test.ts +63 -2
- package/src/__tests__/ir-sort-comparator.test.ts +261 -0
- package/src/__tests__/loop-destructure.test.ts +313 -0
- package/src/__tests__/loop-hoisted-template.test.ts +235 -0
- package/src/__tests__/props-destructuring.test.ts +110 -0
- package/src/__tests__/serialize-parsed-expr.test.ts +70 -3
- package/src/__tests__/ssr-defaults.test.ts +20 -0
- package/src/__tests__/staged-ir/11-template-primitive-registry.test.ts +231 -1
- package/src/__tests__/tagged-template-interleave.test.ts +268 -0
- package/src/__tests__/unsupported-expression.test.ts +194 -7
- package/src/adapters/interface.ts +20 -4
- package/src/adapters/parsed-expr-emitter.ts +19 -2
- package/src/analyzer-context.ts +20 -0
- package/src/analyzer.ts +74 -1
- package/src/augment-inherited-props.ts +139 -9
- package/src/compiler.ts +4 -0
- package/src/expression-parser.ts +237 -56
- package/src/index.ts +23 -1
- package/src/ir-to-client-js/collect-elements.ts +15 -1
- package/src/ir-to-client-js/compute-inlinability.ts +6 -1
- package/src/ir-to-client-js/control-flow/plan/build-loop.ts +1 -0
- package/src/ir-to-client-js/control-flow/plan/loop.ts +9 -0
- package/src/ir-to-client-js/control-flow/stringify/loop.ts +30 -8
- package/src/ir-to-client-js/control-flow/stringify/template-parse.ts +30 -0
- package/src/ir-to-client-js/emit-registration.ts +4 -2
- package/src/ir-to-client-js/html-template.ts +198 -1
- package/src/ir-to-client-js/index.ts +1 -0
- package/src/ir-to-client-js/types.ts +22 -0
- package/src/jsx-to-ir.ts +409 -24
- package/src/loop-destructure.ts +89 -36
- package/src/lowering-registry.ts +16 -0
- package/src/relocate.ts +201 -14
- package/src/ssr-defaults.ts +34 -32
- package/src/types.ts +65 -0
package/dist/index.js
CHANGED
|
@@ -441,6 +441,7 @@ function convertNode(node, raw) {
|
|
|
441
441
|
if (callee.property === "flat") {
|
|
442
442
|
const depthNode = node.arguments[0];
|
|
443
443
|
let flatDepth;
|
|
444
|
+
let depthExpr;
|
|
444
445
|
if (depthNode === undefined) {
|
|
445
446
|
flatDepth = 1;
|
|
446
447
|
} else if (ts2.isIdentifier(depthNode) && depthNode.text === "Infinity") {
|
|
@@ -453,16 +454,23 @@ function convertNode(node, raw) {
|
|
|
453
454
|
n = -Number(depthNode.operand.text);
|
|
454
455
|
}
|
|
455
456
|
if (n === undefined || Number.isNaN(n)) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
457
|
+
const parsedDepth = convertNode(depthNode, raw);
|
|
458
|
+
if (checkSupport(parsedDepth).supported) {
|
|
459
|
+
depthExpr = parsedDepth;
|
|
460
|
+
flatDepth = 1;
|
|
461
|
+
} else {
|
|
462
|
+
return {
|
|
463
|
+
kind: "unsupported",
|
|
464
|
+
raw,
|
|
465
|
+
reason: `\`.flat(depth)\` needs a literal integer, \`Infinity\`, or a supported dynamic depth expression — this depth can't be resolved. Use a literal depth, a supported expression (prop/signal/arithmetic), or pre-compute the value before the template.`
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
const truncated = Math.trunc(n);
|
|
470
|
+
flatDepth = truncated < 0 ? 0 : truncated;
|
|
461
471
|
}
|
|
462
|
-
const truncated = Math.trunc(n);
|
|
463
|
-
flatDepth = truncated < 0 ? 0 : truncated;
|
|
464
472
|
}
|
|
465
|
-
return { kind: "array-method", method: "flat", object: callee.object, args: [], flatDepth };
|
|
473
|
+
return depthExpr !== undefined ? { kind: "array-method", method: "flat", object: callee.object, args: [], flatDepth, depthExpr } : { kind: "array-method", method: "flat", object: callee.object, args: [], flatDepth };
|
|
466
474
|
}
|
|
467
475
|
if (callee.property === "toLowerCase") {
|
|
468
476
|
return { kind: "array-method", method: "toLowerCase", object: callee.object, args };
|
|
@@ -1007,6 +1015,8 @@ function validateRestUsage(expr, restName, excludedTopKeys) {
|
|
|
1007
1015
|
walk(e.object);
|
|
1008
1016
|
for (const a of e.args)
|
|
1009
1017
|
walk(a);
|
|
1018
|
+
if (e.method === "flat" && e.depthExpr)
|
|
1019
|
+
walk(e.depthExpr);
|
|
1010
1020
|
return;
|
|
1011
1021
|
case "literal":
|
|
1012
1022
|
case "unsupported":
|
|
@@ -1092,6 +1102,8 @@ function collectIdentifiers(expr, out) {
|
|
|
1092
1102
|
case "array-method":
|
|
1093
1103
|
collectIdentifiers(expr.object, out);
|
|
1094
1104
|
expr.args.forEach((e) => collectIdentifiers(e, out));
|
|
1105
|
+
if (expr.method === "flat" && expr.depthExpr)
|
|
1106
|
+
collectIdentifiers(expr.depthExpr, out);
|
|
1095
1107
|
return;
|
|
1096
1108
|
case "literal":
|
|
1097
1109
|
case "regex":
|
|
@@ -1149,7 +1161,14 @@ function substituteDestructuredFields(expr, fieldMap, syntheticParam, restName)
|
|
|
1149
1161
|
return { kind: "array-literal", elements: e.elements.map(walk) };
|
|
1150
1162
|
case "array-method":
|
|
1151
1163
|
if (e.method === "flat") {
|
|
1152
|
-
return {
|
|
1164
|
+
return {
|
|
1165
|
+
kind: "array-method",
|
|
1166
|
+
method: "flat",
|
|
1167
|
+
object: walk(e.object),
|
|
1168
|
+
args: [],
|
|
1169
|
+
flatDepth: e.flatDepth,
|
|
1170
|
+
...e.depthExpr ? { depthExpr: walk(e.depthExpr) } : {}
|
|
1171
|
+
};
|
|
1153
1172
|
}
|
|
1154
1173
|
return { kind: "array-method", method: e.method, object: walk(e.object), args: e.args.map(walk) };
|
|
1155
1174
|
case "literal":
|
|
@@ -1246,6 +1265,11 @@ function checkSupport(expr) {
|
|
|
1246
1265
|
if (!argSupport.supported)
|
|
1247
1266
|
return argSupport;
|
|
1248
1267
|
}
|
|
1268
|
+
if (expr.method === "flat" && expr.depthExpr) {
|
|
1269
|
+
const depthSupport = checkSupport(expr.depthExpr);
|
|
1270
|
+
if (!depthSupport.supported)
|
|
1271
|
+
return depthSupport;
|
|
1272
|
+
}
|
|
1249
1273
|
return { supported: true, level: "L2" };
|
|
1250
1274
|
}
|
|
1251
1275
|
case "call": {
|
|
@@ -1345,6 +1369,9 @@ function checkSupport(expr) {
|
|
|
1345
1369
|
const leftSupport = checkSupport(expr.left);
|
|
1346
1370
|
if (!leftSupport.supported)
|
|
1347
1371
|
return leftSupport;
|
|
1372
|
+
if (expr.op === "??" && expr.right.kind === "object-literal" && expr.right.properties.length === 0) {
|
|
1373
|
+
return { supported: true, level: "L4" };
|
|
1374
|
+
}
|
|
1348
1375
|
const rightSupport = checkSupport(expr.right);
|
|
1349
1376
|
if (!rightSupport.supported)
|
|
1350
1377
|
return rightSupport;
|
|
@@ -1399,7 +1426,7 @@ function containsHigherOrder(expr) {
|
|
|
1399
1426
|
case "array-literal":
|
|
1400
1427
|
return expr.elements.some(containsHigherOrder);
|
|
1401
1428
|
case "array-method":
|
|
1402
|
-
return containsHigherOrder(expr.object) || expr.args.some(containsHigherOrder);
|
|
1429
|
+
return containsHigherOrder(expr.object) || expr.args.some(containsHigherOrder) || expr.method === "flat" && expr.depthExpr !== undefined && containsHigherOrder(expr.depthExpr);
|
|
1403
1430
|
default:
|
|
1404
1431
|
return false;
|
|
1405
1432
|
}
|
|
@@ -1567,7 +1594,10 @@ function usesPerPath(name, expr) {
|
|
|
1567
1594
|
case "array-literal":
|
|
1568
1595
|
return sum(e.elements);
|
|
1569
1596
|
case "array-method":
|
|
1570
|
-
|
|
1597
|
+
if (e.method === "flat") {
|
|
1598
|
+
return add(walk(e.object), e.depthExpr ? walk(e.depthExpr) : { min: 0, max: 0 });
|
|
1599
|
+
}
|
|
1600
|
+
return add(walk(e.object), sum(e.args));
|
|
1571
1601
|
case "object-literal":
|
|
1572
1602
|
return sum(e.properties.map((p) => p.value));
|
|
1573
1603
|
case "arrow":
|
|
@@ -1622,7 +1652,14 @@ function inlineBinding(expr, name, value) {
|
|
|
1622
1652
|
return { kind: "array-literal", elements: e.elements.map((el) => walk(el, enclosing)) };
|
|
1623
1653
|
case "array-method":
|
|
1624
1654
|
if (e.method === "flat") {
|
|
1625
|
-
return {
|
|
1655
|
+
return {
|
|
1656
|
+
kind: "array-method",
|
|
1657
|
+
method: "flat",
|
|
1658
|
+
object: walk(e.object, enclosing),
|
|
1659
|
+
args: [],
|
|
1660
|
+
flatDepth: e.flatDepth,
|
|
1661
|
+
...e.depthExpr ? { depthExpr: walk(e.depthExpr, enclosing) } : {}
|
|
1662
|
+
};
|
|
1626
1663
|
}
|
|
1627
1664
|
return { kind: "array-method", method: e.method, object: walk(e.object, enclosing), args: e.args.map((a) => walk(a, enclosing)) };
|
|
1628
1665
|
case "object-literal":
|
|
@@ -1753,6 +1790,9 @@ function exprToString(expr) {
|
|
|
1753
1790
|
return `[${expr.elements.map(exprToString).join(", ")}]`;
|
|
1754
1791
|
case "array-method":
|
|
1755
1792
|
if (expr.method === "flat") {
|
|
1793
|
+
if (expr.depthExpr) {
|
|
1794
|
+
return `${exprToString(expr.object)}.flat(${exprToString(expr.depthExpr)})`;
|
|
1795
|
+
}
|
|
1756
1796
|
const d = expr.flatDepth;
|
|
1757
1797
|
const depthSrc = d === "infinity" ? "Infinity" : String(d);
|
|
1758
1798
|
return `${exprToString(expr.object)}.flat(${d === 1 ? "" : depthSrc})`;
|
|
@@ -1804,6 +1844,9 @@ function stringifyParsedExpr(expr) {
|
|
|
1804
1844
|
return `[${expr.elements.map(stringifyParsedExpr).join(", ")}]`;
|
|
1805
1845
|
case "array-method":
|
|
1806
1846
|
if (expr.method === "flat") {
|
|
1847
|
+
if (expr.depthExpr) {
|
|
1848
|
+
return `${stringifyParsedExpr(expr.object)}.flat(${stringifyParsedExpr(expr.depthExpr)})`;
|
|
1849
|
+
}
|
|
1807
1850
|
const d = expr.flatDepth;
|
|
1808
1851
|
const depthSrc = d === "infinity" ? "Infinity" : String(d);
|
|
1809
1852
|
return `${stringifyParsedExpr(expr.object)}.flat(${d === 1 ? "" : depthSrc})`;
|
|
@@ -1847,8 +1890,9 @@ function materializeGetterCalls(expr, names) {
|
|
|
1847
1890
|
case "array-literal":
|
|
1848
1891
|
return { kind: "array-literal", elements: expr.elements.map(rw) };
|
|
1849
1892
|
case "array-method":
|
|
1850
|
-
if (expr.method === "flat")
|
|
1851
|
-
return { ...expr, object: rw(expr.object) };
|
|
1893
|
+
if (expr.method === "flat") {
|
|
1894
|
+
return { ...expr, object: rw(expr.object), ...expr.depthExpr ? { depthExpr: rw(expr.depthExpr) } : {} };
|
|
1895
|
+
}
|
|
1852
1896
|
return { ...expr, object: rw(expr.object), args: expr.args.map(rw) };
|
|
1853
1897
|
case "object-literal":
|
|
1854
1898
|
return {
|
|
@@ -1871,63 +1915,67 @@ function serializeParsedExpr(expr) {
|
|
|
1871
1915
|
}
|
|
1872
1916
|
function freeVarsInBody(body, params) {
|
|
1873
1917
|
const found = new Set;
|
|
1874
|
-
const visit = (e) => {
|
|
1918
|
+
const visit = (e, bound) => {
|
|
1875
1919
|
switch (e.kind) {
|
|
1876
1920
|
case "identifier":
|
|
1877
|
-
if (!
|
|
1921
|
+
if (!bound.has(e.name))
|
|
1878
1922
|
found.add(e.name);
|
|
1879
1923
|
return;
|
|
1880
1924
|
case "binary":
|
|
1881
1925
|
case "logical":
|
|
1882
|
-
visit(e.left);
|
|
1883
|
-
visit(e.right);
|
|
1926
|
+
visit(e.left, bound);
|
|
1927
|
+
visit(e.right, bound);
|
|
1884
1928
|
return;
|
|
1885
1929
|
case "unary":
|
|
1886
|
-
visit(e.argument);
|
|
1930
|
+
visit(e.argument, bound);
|
|
1887
1931
|
return;
|
|
1888
1932
|
case "conditional":
|
|
1889
|
-
visit(e.test);
|
|
1890
|
-
visit(e.consequent);
|
|
1891
|
-
visit(e.alternate);
|
|
1933
|
+
visit(e.test, bound);
|
|
1934
|
+
visit(e.consequent, bound);
|
|
1935
|
+
visit(e.alternate, bound);
|
|
1892
1936
|
return;
|
|
1893
1937
|
case "member":
|
|
1894
|
-
visit(e.object);
|
|
1938
|
+
visit(e.object, bound);
|
|
1895
1939
|
return;
|
|
1896
1940
|
case "index-access":
|
|
1897
|
-
visit(e.object);
|
|
1898
|
-
visit(e.index);
|
|
1941
|
+
visit(e.object, bound);
|
|
1942
|
+
visit(e.index, bound);
|
|
1899
1943
|
return;
|
|
1900
1944
|
case "call":
|
|
1901
1945
|
if (evalBuiltinCalleeName(e.callee) === null)
|
|
1902
|
-
visit(e.callee);
|
|
1903
|
-
e.args.forEach(visit);
|
|
1946
|
+
visit(e.callee, bound);
|
|
1947
|
+
e.args.forEach((a) => visit(a, bound));
|
|
1904
1948
|
return;
|
|
1905
1949
|
case "template-literal":
|
|
1906
1950
|
for (const p of e.parts)
|
|
1907
1951
|
if (p.type === "expression")
|
|
1908
|
-
visit(p.expr);
|
|
1952
|
+
visit(p.expr, bound);
|
|
1909
1953
|
return;
|
|
1910
1954
|
case "array-literal":
|
|
1911
|
-
e.elements.forEach(visit);
|
|
1955
|
+
e.elements.forEach((el) => visit(el, bound));
|
|
1912
1956
|
return;
|
|
1913
1957
|
case "object-literal":
|
|
1914
1958
|
for (const p of e.properties)
|
|
1915
|
-
visit(p.value);
|
|
1959
|
+
visit(p.value, bound);
|
|
1916
1960
|
return;
|
|
1917
1961
|
case "array-method":
|
|
1918
|
-
if (e.method === "includes") {
|
|
1919
|
-
visit(e.object);
|
|
1920
|
-
e.args.forEach(visit);
|
|
1962
|
+
if (e.method === "includes" || e.method === "join") {
|
|
1963
|
+
visit(e.object, bound);
|
|
1964
|
+
e.args.forEach((a) => visit(a, bound));
|
|
1921
1965
|
}
|
|
1922
1966
|
return;
|
|
1967
|
+
case "arrow": {
|
|
1968
|
+
const inner = e.params.length === 0 ? bound : new Set([...bound, ...e.params]);
|
|
1969
|
+
visit(e.body, inner);
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1923
1972
|
case "literal":
|
|
1924
|
-
case "arrow":
|
|
1925
1973
|
case "regex":
|
|
1926
1974
|
case "unsupported":
|
|
1927
1975
|
return;
|
|
1928
1976
|
}
|
|
1929
1977
|
};
|
|
1930
|
-
visit(body);
|
|
1978
|
+
visit(body, params);
|
|
1931
1979
|
return [...found].sort();
|
|
1932
1980
|
}
|
|
1933
1981
|
function freeIdentifiers(expr) {
|
|
@@ -1978,6 +2026,8 @@ function freeIdentifiers(expr) {
|
|
|
1978
2026
|
for (const a of e.args)
|
|
1979
2027
|
if (!visit(a, bound))
|
|
1980
2028
|
return false;
|
|
2029
|
+
if (e.method === "flat" && e.depthExpr && !visit(e.depthExpr, bound))
|
|
2030
|
+
return false;
|
|
1981
2031
|
return true;
|
|
1982
2032
|
case "object-literal":
|
|
1983
2033
|
for (const p of e.properties)
|
|
@@ -2073,6 +2123,20 @@ function toEvalNode(e) {
|
|
|
2073
2123
|
return object && index ? { kind: "index-access", object, index } : null;
|
|
2074
2124
|
}
|
|
2075
2125
|
case "call": {
|
|
2126
|
+
const cb = asCallbackMethodCall(e);
|
|
2127
|
+
if (cb && (cb.method === "map" || cb.method === "filter")) {
|
|
2128
|
+
const object = toEvalNode(cb.object);
|
|
2129
|
+
if (!object)
|
|
2130
|
+
return null;
|
|
2131
|
+
const body = toEvalNode(cb.arrow.body);
|
|
2132
|
+
if (!body)
|
|
2133
|
+
return null;
|
|
2134
|
+
return {
|
|
2135
|
+
kind: "call",
|
|
2136
|
+
callee: { kind: "member", object, property: cb.method, computed: false },
|
|
2137
|
+
args: [{ kind: "arrow", params: cb.arrow.params, body }]
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2076
2140
|
if (evalBuiltinCalleeName(e.callee) === null)
|
|
2077
2141
|
return null;
|
|
2078
2142
|
const callee = toEvalNode(e.callee);
|
|
@@ -2127,6 +2191,15 @@ function toEvalNode(e) {
|
|
|
2127
2191
|
const arg = toEvalNode(e.args[0]);
|
|
2128
2192
|
return object && arg ? { kind: "array-method", method: "includes", object, args: [arg] } : null;
|
|
2129
2193
|
}
|
|
2194
|
+
if (e.method === "join" && e.args.length <= 1) {
|
|
2195
|
+
const object = toEvalNode(e.object);
|
|
2196
|
+
if (!object)
|
|
2197
|
+
return null;
|
|
2198
|
+
if (e.args.length === 0)
|
|
2199
|
+
return { kind: "array-method", method: "join", object, args: [] };
|
|
2200
|
+
const sep = toEvalNode(e.args[0]);
|
|
2201
|
+
return sep ? { kind: "array-method", method: "join", object, args: [sep] } : null;
|
|
2202
|
+
}
|
|
2130
2203
|
return null;
|
|
2131
2204
|
}
|
|
2132
2205
|
case "arrow":
|
|
@@ -3282,6 +3355,89 @@ function irToHtmlTemplate(node, restSpreadNames, loopDepth = 0, loopParams, bran
|
|
|
3282
3355
|
return assertNever(node);
|
|
3283
3356
|
}
|
|
3284
3357
|
}
|
|
3358
|
+
function buildLoopSkeletonTemplate(node, safe) {
|
|
3359
|
+
switch (node.type) {
|
|
3360
|
+
case "element": {
|
|
3361
|
+
const attrParts = [];
|
|
3362
|
+
for (const a of node.attrs) {
|
|
3363
|
+
if (a.name === "...")
|
|
3364
|
+
return null;
|
|
3365
|
+
if (a.name === "dangerouslySetInnerHTML")
|
|
3366
|
+
return null;
|
|
3367
|
+
if (a.name === "key") {
|
|
3368
|
+
attrParts.push(`${keyAttrName(0)}=""`);
|
|
3369
|
+
continue;
|
|
3370
|
+
}
|
|
3371
|
+
const v = a.value;
|
|
3372
|
+
switch (v.kind) {
|
|
3373
|
+
case "literal":
|
|
3374
|
+
attrParts.push(`${toHtmlAttrName(a.name)}="${v.value}"`);
|
|
3375
|
+
break;
|
|
3376
|
+
case "boolean-attr":
|
|
3377
|
+
attrParts.push(toHtmlAttrName(a.name));
|
|
3378
|
+
break;
|
|
3379
|
+
case "boolean-shorthand":
|
|
3380
|
+
case "jsx-children":
|
|
3381
|
+
break;
|
|
3382
|
+
case "expression":
|
|
3383
|
+
case "template": {
|
|
3384
|
+
const attrKey = node.slotId ? `${node.slotId}::${a.name}` : null;
|
|
3385
|
+
if (!attrKey || !safe.reactiveAttrKeys.has(attrKey))
|
|
3386
|
+
return null;
|
|
3387
|
+
break;
|
|
3388
|
+
}
|
|
3389
|
+
case "spread":
|
|
3390
|
+
return null;
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
if (node.slotId)
|
|
3394
|
+
attrParts.push(`bf="${node.slotId}"`);
|
|
3395
|
+
const attrs = attrParts.join(" ");
|
|
3396
|
+
let children = "";
|
|
3397
|
+
for (const child of node.children) {
|
|
3398
|
+
const rendered = buildLoopSkeletonTemplate(child, safe);
|
|
3399
|
+
if (rendered === null)
|
|
3400
|
+
return null;
|
|
3401
|
+
children += rendered;
|
|
3402
|
+
}
|
|
3403
|
+
if (children || !VOID_ELEMENTS.has(node.tag)) {
|
|
3404
|
+
return `<${node.tag}${attrs ? " " + attrs : ""}>${children}</${node.tag}>`;
|
|
3405
|
+
}
|
|
3406
|
+
return `<${node.tag}${attrs ? " " + attrs : ""} />`;
|
|
3407
|
+
}
|
|
3408
|
+
case "text":
|
|
3409
|
+
return node.value;
|
|
3410
|
+
case "expression":
|
|
3411
|
+
if (node.expr === "null" || node.expr === "undefined")
|
|
3412
|
+
return "";
|
|
3413
|
+
if (!node.slotId) {
|
|
3414
|
+
return null;
|
|
3415
|
+
}
|
|
3416
|
+
if (!safe.reactiveTextSlotIds.has(node.slotId))
|
|
3417
|
+
return null;
|
|
3418
|
+
return `<!--bf:${node.slotId}--><!--/-->`;
|
|
3419
|
+
case "fragment": {
|
|
3420
|
+
let out = "";
|
|
3421
|
+
for (const child of node.children) {
|
|
3422
|
+
const rendered = buildLoopSkeletonTemplate(child, safe);
|
|
3423
|
+
if (rendered === null)
|
|
3424
|
+
return null;
|
|
3425
|
+
out += rendered;
|
|
3426
|
+
}
|
|
3427
|
+
return out;
|
|
3428
|
+
}
|
|
3429
|
+
case "conditional":
|
|
3430
|
+
case "component":
|
|
3431
|
+
case "loop":
|
|
3432
|
+
case "if-statement":
|
|
3433
|
+
case "provider":
|
|
3434
|
+
case "async":
|
|
3435
|
+
case "slot":
|
|
3436
|
+
return null;
|
|
3437
|
+
default:
|
|
3438
|
+
return assertNever(node);
|
|
3439
|
+
}
|
|
3440
|
+
}
|
|
3285
3441
|
function irToPlaceholderTemplate(node, restSpreadNames, loopDepth = 0, loopParams) {
|
|
3286
3442
|
const recurse = (n) => irToPlaceholderTemplate(n, restSpreadNames, loopDepth, loopParams);
|
|
3287
3443
|
const wrapExpr = (expr) => wrapExprWithLoopParams(expr, loopParams);
|
|
@@ -3681,7 +3837,23 @@ function generateCsrTemplate(node, inlinableConstants, ctx, insideLoop, restSpre
|
|
|
3681
3837
|
}
|
|
3682
3838
|
}
|
|
3683
3839
|
}
|
|
3684
|
-
|
|
3840
|
+
const effectiveUnsafeLocalNames = mergeCsrNullUnsafe(ctx, unsafeLocalNames);
|
|
3841
|
+
return generateCsrTemplateWithOpts(node, { inlinableConstants, restSpreadNames, propsObjectName, csrEnv, insideLoop, unsafeLocalNames: effectiveUnsafeLocalNames, deferredChildSlots, loopDepth: -1 });
|
|
3842
|
+
}
|
|
3843
|
+
function mergeCsrNullUnsafe(ctx, unsafeLocalNames) {
|
|
3844
|
+
let merged = null;
|
|
3845
|
+
let exemptNames = null;
|
|
3846
|
+
for (const [name, entry] of ctx.csrInlinable) {
|
|
3847
|
+
if (entry !== null || unsafeLocalNames?.has(name))
|
|
3848
|
+
continue;
|
|
3849
|
+
exemptNames ??= new Set(ctx.localConstants.filter((c) => c.isJsx || c.systemConstructKind).map((c) => c.name));
|
|
3850
|
+
if (exemptNames.has(name))
|
|
3851
|
+
continue;
|
|
3852
|
+
if (!merged)
|
|
3853
|
+
merged = new Set(unsafeLocalNames ?? []);
|
|
3854
|
+
merged.add(name);
|
|
3855
|
+
}
|
|
3856
|
+
return merged ?? unsafeLocalNames;
|
|
3685
3857
|
}
|
|
3686
3858
|
function buildCsrEnvForCtx(ctx, inlinableConstants, propsObjectName) {
|
|
3687
3859
|
const base = buildSignalMemoEnv(ctx.signals, ctx.memos, propsObjectName ?? null);
|
|
@@ -4269,6 +4441,15 @@ function createAnalyzerContext(sourceFile, filePath) {
|
|
|
4269
4441
|
checker: null,
|
|
4270
4442
|
componentBodyBlock: null,
|
|
4271
4443
|
getJS(node) {
|
|
4444
|
+
let ownSourceFile;
|
|
4445
|
+
try {
|
|
4446
|
+
ownSourceFile = node.getSourceFile();
|
|
4447
|
+
} catch {
|
|
4448
|
+
ownSourceFile = undefined;
|
|
4449
|
+
}
|
|
4450
|
+
if (ownSourceFile && ownSourceFile !== sourceFile) {
|
|
4451
|
+
return node.getText(ownSourceFile);
|
|
4452
|
+
}
|
|
4272
4453
|
return reconstructWithoutTypes(node, sourceFile, this.typeExcludeRanges);
|
|
4273
4454
|
}
|
|
4274
4455
|
};
|
|
@@ -6622,6 +6803,7 @@ function extractProps(param, ctx) {
|
|
|
6622
6803
|
loc: getSourceLocation(param, ctx.sourceFile, ctx.filePath),
|
|
6623
6804
|
hasIgnoreDirective: ignored
|
|
6624
6805
|
};
|
|
6806
|
+
const memberTypes = param.type ? collectMemberTypes(param.type, ctx) : null;
|
|
6625
6807
|
for (const element of param.name.elements) {
|
|
6626
6808
|
if (ts8.isBindingElement(element) && ts8.isIdentifier(element.name)) {
|
|
6627
6809
|
const localName = element.name.text;
|
|
@@ -6630,10 +6812,12 @@ function extractProps(param, ctx) {
|
|
|
6630
6812
|
ctx.restPropsName = localName;
|
|
6631
6813
|
continue;
|
|
6632
6814
|
}
|
|
6815
|
+
const sourcePropName = element.propertyName && ts8.isIdentifier(element.propertyName) ? element.propertyName.text : localName;
|
|
6816
|
+
const resolvedType = memberTypes?.get(sourcePropName) ?? { kind: "unknown", raw: "unknown" };
|
|
6633
6817
|
const defaultContainsArrow = element.initializer ? nodeContainsArrow(element.initializer) : false;
|
|
6634
6818
|
ctx.propsParams.push({
|
|
6635
6819
|
name: localName,
|
|
6636
|
-
type:
|
|
6820
|
+
type: resolvedType,
|
|
6637
6821
|
optional: !!element.initializer,
|
|
6638
6822
|
defaultValue,
|
|
6639
6823
|
defaultContainsArrow: defaultContainsArrow || undefined
|
|
@@ -6694,6 +6878,37 @@ function collectKeysFromMembers(members, ctx) {
|
|
|
6694
6878
|
}
|
|
6695
6879
|
return keys;
|
|
6696
6880
|
}
|
|
6881
|
+
function collectMemberTypes(typeNode, ctx) {
|
|
6882
|
+
const isResolvablePrimitive = (info) => info.kind === "primitive" && (info.primitive === "string" || info.primitive === "number" || info.primitive === "boolean");
|
|
6883
|
+
const fromMembers = (members) => {
|
|
6884
|
+
const map = new Map;
|
|
6885
|
+
for (const member of members) {
|
|
6886
|
+
if (ts8.isPropertySignature(member) && member.name && member.type && !member.questionToken) {
|
|
6887
|
+
const info = typeNodeToTypeInfo(member.type, ctx.sourceFile);
|
|
6888
|
+
if (info && isResolvablePrimitive(info)) {
|
|
6889
|
+
map.set(member.name.getText(ctx.sourceFile), info);
|
|
6890
|
+
}
|
|
6891
|
+
}
|
|
6892
|
+
}
|
|
6893
|
+
return map;
|
|
6894
|
+
};
|
|
6895
|
+
if (ts8.isTypeLiteralNode(typeNode)) {
|
|
6896
|
+
return fromMembers(typeNode.members);
|
|
6897
|
+
}
|
|
6898
|
+
if (ts8.isTypeReferenceNode(typeNode)) {
|
|
6899
|
+
const typeName = typeNode.typeName.getText(ctx.sourceFile);
|
|
6900
|
+
const typeDecl = findTypeDeclaration(typeName, ctx.sourceFile);
|
|
6901
|
+
if (!typeDecl)
|
|
6902
|
+
return null;
|
|
6903
|
+
if (ts8.isInterfaceDeclaration(typeDecl)) {
|
|
6904
|
+
return fromMembers(typeDecl.members);
|
|
6905
|
+
}
|
|
6906
|
+
if (ts8.isTypeAliasDeclaration(typeDecl) && ts8.isTypeLiteralNode(typeDecl.type)) {
|
|
6907
|
+
return fromMembers(typeDecl.type.members);
|
|
6908
|
+
}
|
|
6909
|
+
}
|
|
6910
|
+
return null;
|
|
6911
|
+
}
|
|
6697
6912
|
function extractPropsFromType(typeNode, ctx) {
|
|
6698
6913
|
if (ts8.isTypeLiteralNode(typeNode)) {
|
|
6699
6914
|
extractPropsFromTypeMembers(typeNode.members, ctx);
|
|
@@ -7388,6 +7603,119 @@ function pickAttrMetaFromIR(src) {
|
|
|
7388
7603
|
};
|
|
7389
7604
|
}
|
|
7390
7605
|
|
|
7606
|
+
// src/module-exports.ts
|
|
7607
|
+
function generateModuleExports(ir, extraInlineExported = new Set, rewriteRelativeImport) {
|
|
7608
|
+
const lines = [];
|
|
7609
|
+
for (const constant of ir.metadata.localConstants) {
|
|
7610
|
+
if (!constant.isExported)
|
|
7611
|
+
continue;
|
|
7612
|
+
const keyword = constant.declarationKind ?? "const";
|
|
7613
|
+
if (!constant.value) {
|
|
7614
|
+
lines.push(`export ${keyword} ${constant.name}`);
|
|
7615
|
+
continue;
|
|
7616
|
+
}
|
|
7617
|
+
const value = constant.value.trim();
|
|
7618
|
+
if (/^createContext\b/.test(value) || /^new WeakMap\b/.test(value))
|
|
7619
|
+
continue;
|
|
7620
|
+
lines.push(`export ${keyword} ${constant.name} = ${constant.value}`);
|
|
7621
|
+
}
|
|
7622
|
+
for (const func of ir.metadata.localFunctions) {
|
|
7623
|
+
if (!func.isExported)
|
|
7624
|
+
continue;
|
|
7625
|
+
const params = func.typedParams !== undefined ? func.typedParams : func.params.map(formatParamWithType).join(", ");
|
|
7626
|
+
const returnAnnotation = func.typedReturnType ? `: ${func.typedReturnType}` : "";
|
|
7627
|
+
const body = func.typedBody ?? func.body;
|
|
7628
|
+
const asyncKw = func.isAsync ? "async " : "";
|
|
7629
|
+
lines.push(`export ${asyncKw}function ${func.name}(${params})${returnAnnotation} ${body}`);
|
|
7630
|
+
}
|
|
7631
|
+
const inlineExported = collectInlineExportedNames(ir);
|
|
7632
|
+
for (const name of extraInlineExported)
|
|
7633
|
+
inlineExported.add(name);
|
|
7634
|
+
for (const block of ir.metadata.namedExports) {
|
|
7635
|
+
const isReexportFrom = block.source !== null;
|
|
7636
|
+
const survivingSpecs = block.specifiers.filter((spec) => {
|
|
7637
|
+
if (isReexportFrom)
|
|
7638
|
+
return true;
|
|
7639
|
+
return !(inlineExported.has(spec.name) && spec.alias == null);
|
|
7640
|
+
});
|
|
7641
|
+
if (survivingSpecs.length === 0)
|
|
7642
|
+
continue;
|
|
7643
|
+
const specText = survivingSpecs.map((s) => {
|
|
7644
|
+
const prefix = s.isTypeOnly ? "type " : "";
|
|
7645
|
+
return s.alias ? `${prefix}${s.name} as ${s.alias}` : `${prefix}${s.name}`;
|
|
7646
|
+
}).join(", ");
|
|
7647
|
+
const typeKw = block.isTypeOnly ? "type " : "";
|
|
7648
|
+
if (isReexportFrom) {
|
|
7649
|
+
const source = rewriteRelativeImport && block.source.startsWith(".") ? rewriteRelativeImport(block.source) : block.source;
|
|
7650
|
+
lines.push(`export ${typeKw}{ ${specText} } from '${source}'`);
|
|
7651
|
+
} else {
|
|
7652
|
+
lines.push(`export ${typeKw}{ ${specText} }`);
|
|
7653
|
+
}
|
|
7654
|
+
}
|
|
7655
|
+
return lines.length > 0 ? lines.join(`
|
|
7656
|
+
`) : null;
|
|
7657
|
+
}
|
|
7658
|
+
function collectInlineExportedNames(ir) {
|
|
7659
|
+
const names = new Set;
|
|
7660
|
+
for (const c of ir.metadata.localConstants) {
|
|
7661
|
+
if (c.isExported)
|
|
7662
|
+
names.add(c.name);
|
|
7663
|
+
}
|
|
7664
|
+
for (const f of ir.metadata.localFunctions) {
|
|
7665
|
+
if (f.isExported)
|
|
7666
|
+
names.add(f.name);
|
|
7667
|
+
}
|
|
7668
|
+
if (ir.metadata.isExported && ir.metadata.componentName) {
|
|
7669
|
+
names.add(ir.metadata.componentName);
|
|
7670
|
+
}
|
|
7671
|
+
return names;
|
|
7672
|
+
}
|
|
7673
|
+
function formatParamWithType(p) {
|
|
7674
|
+
const rest = p.isRest ? "..." : "";
|
|
7675
|
+
const optional = p.optional ? "?" : "";
|
|
7676
|
+
const typeAnnotation = p.type?.raw && p.type.raw !== "unknown" ? `: ${p.type.raw}` : "";
|
|
7677
|
+
const defaultPart = p.defaultValue !== undefined ? ` = ${p.defaultValue}` : "";
|
|
7678
|
+
return `${rest}${p.name}${optional}${typeAnnotation}${defaultPart}`;
|
|
7679
|
+
}
|
|
7680
|
+
function findReachableNames(primaryRefs, declarations) {
|
|
7681
|
+
const allNames = new Set(declarations.map((d) => d.name));
|
|
7682
|
+
const bodyMap = new Map(declarations.map((d) => [d.name, d.body]));
|
|
7683
|
+
const reachable = new Set;
|
|
7684
|
+
const queue = [];
|
|
7685
|
+
for (const name of allNames) {
|
|
7686
|
+
if (new RegExp(`\\b${name}\\b`).test(primaryRefs)) {
|
|
7687
|
+
reachable.add(name);
|
|
7688
|
+
queue.push(name);
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7691
|
+
while (queue.length > 0) {
|
|
7692
|
+
const current = queue.shift();
|
|
7693
|
+
const body = bodyMap.get(current) || "";
|
|
7694
|
+
for (const name of allNames) {
|
|
7695
|
+
if (!reachable.has(name) && new RegExp(`\\b${name}\\b`).test(body)) {
|
|
7696
|
+
reachable.add(name);
|
|
7697
|
+
queue.push(name);
|
|
7698
|
+
}
|
|
7699
|
+
}
|
|
7700
|
+
}
|
|
7701
|
+
return reachable;
|
|
7702
|
+
}
|
|
7703
|
+
function extractFunctionParams(value) {
|
|
7704
|
+
const arrowMatch = value.match(/^(?:async\s*)?\(([^)]*)\)\s*(?::\s*[^=]+)?\s*=>/);
|
|
7705
|
+
if (arrowMatch) {
|
|
7706
|
+
return arrowMatch[1].split(",").map((p) => p.trim().split(":")[0].split("=")[0].trim()).filter(Boolean).join(", ");
|
|
7707
|
+
}
|
|
7708
|
+
const singleMatch = value.match(/^(?:async\s*)?(\w+)\s*=>/);
|
|
7709
|
+
if (singleMatch) {
|
|
7710
|
+
return singleMatch[1];
|
|
7711
|
+
}
|
|
7712
|
+
const funcMatch = value.match(/^(?:async\s*)?function\s*\w*\s*\(([^)]*)\)/);
|
|
7713
|
+
if (funcMatch) {
|
|
7714
|
+
return funcMatch[1].split(",").map((p) => p.trim().split(":")[0].split("=")[0].trim()).filter(Boolean).join(", ");
|
|
7715
|
+
}
|
|
7716
|
+
return "";
|
|
7717
|
+
}
|
|
7718
|
+
|
|
7391
7719
|
// src/builtins.ts
|
|
7392
7720
|
var CLIENT_BUILTIN_SOURCE = "@barefootjs/client";
|
|
7393
7721
|
function isClientBuiltinName(name) {
|
|
@@ -8509,6 +8837,7 @@ function transformExpression(node, ctx) {
|
|
|
8509
8837
|
return transformExpressionInner(expr, ctx, node, isClientOnly);
|
|
8510
8838
|
}
|
|
8511
8839
|
function transformExpressionInner(expr, ctx, node, isClientOnly) {
|
|
8840
|
+
expr = tryDesugarInterleaveTaggedTemplate(expr, ctx);
|
|
8512
8841
|
checkBareSignalOrMemoIdentifier(expr, ctx);
|
|
8513
8842
|
if (ts11.isIdentifier(expr)) {
|
|
8514
8843
|
const jsxNode = ctx.analyzer.jsxConstants.get(expr.text);
|
|
@@ -9050,11 +9379,10 @@ function isIteratorShapeCall(node) {
|
|
|
9050
9379
|
return { array: node.expression.expression, shape: name };
|
|
9051
9380
|
}
|
|
9052
9381
|
function extractSortComparator(callback, _method, ctx) {
|
|
9053
|
-
const
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
unsupportedReason: `Sort comparator '${raw}' is not a supported shape. Accepted:
|
|
9382
|
+
const outerRaw = ctx.getJS(callback);
|
|
9383
|
+
const unsupported = () => ({
|
|
9384
|
+
result: null,
|
|
9385
|
+
unsupportedReason: `Sort comparator '${outerRaw}' is not a supported shape. Accepted:
|
|
9058
9386
|
` + ` (a, b) => a - b
|
|
9059
9387
|
` + ` (a, b) => a.field - b.field
|
|
9060
9388
|
` + ` (a, b) => a.localeCompare(b)
|
|
@@ -9062,15 +9390,25 @@ function extractSortComparator(callback, _method, ctx) {
|
|
|
9062
9390
|
` + ` (a, b) => a.field > b.field ? 1 : a.field < b.field ? -1 : 0
|
|
9063
9391
|
` + ` any of the above '||'-chained for multi-key tie-breaks
|
|
9064
9392
|
` + `(reverse the operands for descending order).`
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
if (
|
|
9393
|
+
});
|
|
9394
|
+
let resolvedNode = callback;
|
|
9395
|
+
if (ts11.isIdentifier(callback)) {
|
|
9396
|
+
const resolved = resolveSortComparatorIdentifier(callback.text, ctx);
|
|
9397
|
+
if (!resolved) {
|
|
9398
|
+
return {
|
|
9399
|
+
result: null,
|
|
9400
|
+
unsupportedReason: `Sort comparator '${outerRaw}' could not be resolved to a local function — ` + `declare it in the same file or inline it.`
|
|
9401
|
+
};
|
|
9402
|
+
}
|
|
9403
|
+
resolvedNode = resolved;
|
|
9404
|
+
}
|
|
9405
|
+
if (!ts11.isArrowFunction(resolvedNode) && !ts11.isFunctionExpression(resolvedNode)) {
|
|
9068
9406
|
return {
|
|
9069
9407
|
result: null,
|
|
9070
9408
|
unsupportedReason: "Sort comparator must be an arrow function or function expression"
|
|
9071
9409
|
};
|
|
9072
9410
|
}
|
|
9073
|
-
const arrow = tsNodeToParsedExpr(
|
|
9411
|
+
const arrow = tsNodeToParsedExpr(resolvedNode);
|
|
9074
9412
|
if (arrow.kind !== "arrow" || arrow.params.length !== 2)
|
|
9075
9413
|
return unsupported();
|
|
9076
9414
|
if (sortComparatorFromArrow(arrow) === null)
|
|
@@ -9084,6 +9422,21 @@ function extractSortComparator(callback, _method, ctx) {
|
|
|
9084
9422
|
}
|
|
9085
9423
|
};
|
|
9086
9424
|
}
|
|
9425
|
+
function resolveSortComparatorIdentifier(name, ctx) {
|
|
9426
|
+
const constInfo = findLocalConst(name, ctx);
|
|
9427
|
+
const fnInfo = findLocalFunction(name, ctx);
|
|
9428
|
+
if (constInfo && fnInfo)
|
|
9429
|
+
return null;
|
|
9430
|
+
if (constInfo) {
|
|
9431
|
+
const ast = parseConstInitializer(constInfo);
|
|
9432
|
+
return ast && (ts11.isArrowFunction(ast) || ts11.isFunctionExpression(ast)) ? ast : null;
|
|
9433
|
+
}
|
|
9434
|
+
if (fnInfo) {
|
|
9435
|
+
const ast = parseFunctionInfoAsExpr(fnInfo);
|
|
9436
|
+
return ast && (ts11.isArrowFunction(ast) || ts11.isFunctionExpression(ast)) ? ast : null;
|
|
9437
|
+
}
|
|
9438
|
+
return null;
|
|
9439
|
+
}
|
|
9087
9440
|
function extractFilterPredicate(callback, ctx) {
|
|
9088
9441
|
if (!ts11.isArrowFunction(callback))
|
|
9089
9442
|
return { result: null };
|
|
@@ -9156,7 +9509,7 @@ function extractLoopParamBindings(pattern) {
|
|
|
9156
9509
|
const appendDotAccess = (prefix, key) => {
|
|
9157
9510
|
return isIdent(key) ? `${prefix}.${key}` : `${prefix}[${JSON.stringify(key)}]`;
|
|
9158
9511
|
};
|
|
9159
|
-
const walk = (p, prefix) => {
|
|
9512
|
+
const walk = (p, prefix, segments) => {
|
|
9160
9513
|
if (unsupported)
|
|
9161
9514
|
return;
|
|
9162
9515
|
if (ts11.isArrayBindingPattern(p)) {
|
|
@@ -9173,15 +9526,17 @@ function extractLoopParamBindings(pattern) {
|
|
|
9173
9526
|
bindings.push({
|
|
9174
9527
|
name: el.name.text,
|
|
9175
9528
|
path: prefix,
|
|
9176
|
-
rest: { kind: "array", from: index }
|
|
9529
|
+
rest: { kind: "array", from: index },
|
|
9530
|
+
segments
|
|
9177
9531
|
});
|
|
9178
9532
|
return;
|
|
9179
9533
|
}
|
|
9180
9534
|
const path = `${prefix}[${index}]`;
|
|
9535
|
+
const nextSegments = [...segments, { kind: "index", index }];
|
|
9181
9536
|
if (ts11.isIdentifier(el.name)) {
|
|
9182
|
-
bindings.push({ name: el.name.text, path });
|
|
9537
|
+
bindings.push({ name: el.name.text, path, segments: nextSegments });
|
|
9183
9538
|
} else {
|
|
9184
|
-
walk(el.name, path);
|
|
9539
|
+
walk(el.name, path, nextSegments);
|
|
9185
9540
|
}
|
|
9186
9541
|
}
|
|
9187
9542
|
return;
|
|
@@ -9198,7 +9553,8 @@ function extractLoopParamBindings(pattern) {
|
|
|
9198
9553
|
bindings.push({
|
|
9199
9554
|
name: el.name.text,
|
|
9200
9555
|
path: prefix,
|
|
9201
|
-
rest: { kind: "object", exclude: collectedKeys }
|
|
9556
|
+
rest: { kind: "object", exclude: collectedKeys },
|
|
9557
|
+
segments
|
|
9202
9558
|
});
|
|
9203
9559
|
return;
|
|
9204
9560
|
}
|
|
@@ -9221,17 +9577,19 @@ function extractLoopParamBindings(pattern) {
|
|
|
9221
9577
|
unsupported = true;
|
|
9222
9578
|
return;
|
|
9223
9579
|
}
|
|
9224
|
-
|
|
9580
|
+
const keyIsIdent = isIdent(keyText);
|
|
9581
|
+
collectedKeys.push({ key: keyText, isIdent: keyIsIdent });
|
|
9225
9582
|
const path = appendDotAccess(prefix, keyText);
|
|
9583
|
+
const nextSegments = [...segments, { kind: "field", key: keyText, isIdent: keyIsIdent }];
|
|
9226
9584
|
if (ts11.isIdentifier(el.name)) {
|
|
9227
|
-
bindings.push({ name: el.name.text, path });
|
|
9585
|
+
bindings.push({ name: el.name.text, path, segments: nextSegments });
|
|
9228
9586
|
} else {
|
|
9229
|
-
walk(el.name, path);
|
|
9587
|
+
walk(el.name, path, nextSegments);
|
|
9230
9588
|
}
|
|
9231
9589
|
}
|
|
9232
9590
|
};
|
|
9233
9591
|
if (ts11.isArrayBindingPattern(pattern) || ts11.isObjectBindingPattern(pattern)) {
|
|
9234
|
-
walk(pattern, "");
|
|
9592
|
+
walk(pattern, "", []);
|
|
9235
9593
|
if (unsupported)
|
|
9236
9594
|
return { unsupported: true };
|
|
9237
9595
|
return bindings;
|
|
@@ -10000,6 +10358,7 @@ function getAttributeValue(attr, ctx) {
|
|
|
10000
10358
|
expr = branchInit;
|
|
10001
10359
|
}
|
|
10002
10360
|
}
|
|
10361
|
+
expr = tryDesugarInterleaveTaggedTemplate(expr, ctx);
|
|
10003
10362
|
if (ts11.isAwaitExpression(expr)) {
|
|
10004
10363
|
ctx.analyzer.errors.push(createError(ErrorCodes.STAGE_AWAIT_IN_TEMPLATE, getSourceLocation(expr, ctx.sourceFile, ctx.filePath)));
|
|
10005
10364
|
return AttrValueOf.expression("undefined");
|
|
@@ -10135,6 +10494,14 @@ function findLocalConst(name, ctx) {
|
|
|
10135
10494
|
const pool = fnScoped.length > 0 ? fnScoped : matches;
|
|
10136
10495
|
return pool[pool.length - 1];
|
|
10137
10496
|
}
|
|
10497
|
+
function findLocalFunction(name, ctx) {
|
|
10498
|
+
const matches = ctx.analyzer.localFunctions.filter((f) => f.name === name);
|
|
10499
|
+
if (matches.length === 0)
|
|
10500
|
+
return;
|
|
10501
|
+
const fnScoped = matches.filter((f) => !f.isModule);
|
|
10502
|
+
const pool = fnScoped.length > 0 ? fnScoped : matches;
|
|
10503
|
+
return pool[pool.length - 1];
|
|
10504
|
+
}
|
|
10138
10505
|
function isDynamicTagLocal(name, ctx) {
|
|
10139
10506
|
if (!hasDynamicTagBinding(name, ctx.sourceFile))
|
|
10140
10507
|
return false;
|
|
@@ -10229,10 +10596,151 @@ function parseConstInitializerImpl(c) {
|
|
|
10229
10596
|
function astText(node) {
|
|
10230
10597
|
return node.getText(node.getSourceFile());
|
|
10231
10598
|
}
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
const
|
|
10235
|
-
if (
|
|
10599
|
+
var functionInfoExprCache = new WeakMap;
|
|
10600
|
+
function parseFunctionInfoAsExpr(fn) {
|
|
10601
|
+
const cached = functionInfoExprCache.get(fn);
|
|
10602
|
+
if (cached !== undefined)
|
|
10603
|
+
return cached;
|
|
10604
|
+
const result = parseFunctionInfoAsExprImpl(fn);
|
|
10605
|
+
functionInfoExprCache.set(fn, result);
|
|
10606
|
+
return result;
|
|
10607
|
+
}
|
|
10608
|
+
function parseFunctionInfoAsExprImpl(fn) {
|
|
10609
|
+
if (!fn.body)
|
|
10610
|
+
return null;
|
|
10611
|
+
const params = fn.typedParams !== undefined ? fn.typedParams : fn.params.map(formatParamWithType).join(", ");
|
|
10612
|
+
const body = fn.typedBody ?? fn.body;
|
|
10613
|
+
const wrapped = `const __bf_resolve_fn__ = function(${params}) ${body}`;
|
|
10614
|
+
const sf = ts11.createSourceFile("__bf_resolve_fn.ts", wrapped, ts11.ScriptTarget.Latest, true, ts11.ScriptKind.TS);
|
|
10615
|
+
const stmt = sf.statements[0];
|
|
10616
|
+
if (!stmt || !ts11.isVariableStatement(stmt))
|
|
10617
|
+
return null;
|
|
10618
|
+
const decl = stmt.declarationList.declarations[0];
|
|
10619
|
+
if (!decl?.initializer)
|
|
10620
|
+
return null;
|
|
10621
|
+
return decl.initializer;
|
|
10622
|
+
}
|
|
10623
|
+
function tryDesugarInterleaveTaggedTemplate(expr, ctx) {
|
|
10624
|
+
if (!ts11.isTaggedTemplateExpression(expr))
|
|
10625
|
+
return expr;
|
|
10626
|
+
if (!ts11.isIdentifier(expr.tag))
|
|
10627
|
+
return expr;
|
|
10628
|
+
const resolvedTag = resolveInterleaveTagIdentifier(expr.tag.text, ctx);
|
|
10629
|
+
if (!resolvedTag)
|
|
10630
|
+
return expr;
|
|
10631
|
+
if (!isInterleaveTagFunction(resolvedTag))
|
|
10632
|
+
return expr;
|
|
10633
|
+
const rewritten = buildUntaggedTemplateLiteral(expr, ctx);
|
|
10634
|
+
return rewritten ?? expr;
|
|
10635
|
+
}
|
|
10636
|
+
function resolveInterleaveTagIdentifier(name, ctx) {
|
|
10637
|
+
const constInfo = findLocalConst(name, ctx);
|
|
10638
|
+
const fnInfo = findLocalFunction(name, ctx);
|
|
10639
|
+
if (constInfo && fnInfo)
|
|
10640
|
+
return null;
|
|
10641
|
+
if (constInfo) {
|
|
10642
|
+
const ast = parseConstInitializer(constInfo);
|
|
10643
|
+
return ast && (ts11.isArrowFunction(ast) || ts11.isFunctionExpression(ast)) ? ast : null;
|
|
10644
|
+
}
|
|
10645
|
+
if (fnInfo) {
|
|
10646
|
+
const ast = parseFunctionInfoAsExpr(fnInfo);
|
|
10647
|
+
return ast && (ts11.isArrowFunction(ast) || ts11.isFunctionExpression(ast)) ? ast : null;
|
|
10648
|
+
}
|
|
10649
|
+
return null;
|
|
10650
|
+
}
|
|
10651
|
+
function isInterleaveTagFunction(fn) {
|
|
10652
|
+
if (!ts11.isArrowFunction(fn) && !ts11.isFunctionExpression(fn))
|
|
10653
|
+
return false;
|
|
10654
|
+
if (fn.parameters.length !== 2)
|
|
10655
|
+
return false;
|
|
10656
|
+
const [partsParam, argsParam] = fn.parameters;
|
|
10657
|
+
if (!ts11.isIdentifier(partsParam.name) || partsParam.dotDotDotToken)
|
|
10658
|
+
return false;
|
|
10659
|
+
if (!ts11.isIdentifier(argsParam.name) || !argsParam.dotDotDotToken)
|
|
10660
|
+
return false;
|
|
10661
|
+
const parsed = tsNodeToParsedExpr(fn);
|
|
10662
|
+
if (parsed.kind !== "arrow")
|
|
10663
|
+
return false;
|
|
10664
|
+
return isInterleaveReduceCall(parsed.body, partsParam.name.text, argsParam.name.text);
|
|
10665
|
+
}
|
|
10666
|
+
function isInterleaveReduceCall(body, partsName, argsName) {
|
|
10667
|
+
if (body.kind !== "call" || body.args.length !== 2)
|
|
10668
|
+
return false;
|
|
10669
|
+
const { callee, args } = body;
|
|
10670
|
+
if (callee.kind !== "member" || callee.computed || callee.property !== "reduce")
|
|
10671
|
+
return false;
|
|
10672
|
+
if (callee.object.kind !== "identifier" || callee.object.name !== partsName)
|
|
10673
|
+
return false;
|
|
10674
|
+
const [callback, init] = args;
|
|
10675
|
+
if (init.kind !== "literal" || init.literalType !== "string" || init.value !== "")
|
|
10676
|
+
return false;
|
|
10677
|
+
if (callback.kind !== "arrow" || callback.params.length !== 3)
|
|
10678
|
+
return false;
|
|
10679
|
+
const [acc, p, i] = callback.params;
|
|
10680
|
+
return isInterleaveReduceCallbackBody(callback.body, acc, p, i, argsName);
|
|
10681
|
+
}
|
|
10682
|
+
function isInterleaveReduceCallbackBody(body, acc, p, i, argsName) {
|
|
10683
|
+
if (body.kind !== "binary" || body.op !== "+")
|
|
10684
|
+
return false;
|
|
10685
|
+
const { left, right } = body;
|
|
10686
|
+
if (left.kind !== "binary" || left.op !== "+")
|
|
10687
|
+
return false;
|
|
10688
|
+
if (left.left.kind !== "identifier" || left.left.name !== acc)
|
|
10689
|
+
return false;
|
|
10690
|
+
if (left.right.kind !== "identifier" || left.right.name !== p)
|
|
10691
|
+
return false;
|
|
10692
|
+
return isInterleaveSpanExpr(right, i, argsName);
|
|
10693
|
+
}
|
|
10694
|
+
function isInterleaveSpanExpr(expr, i, argsName) {
|
|
10695
|
+
let inner = expr;
|
|
10696
|
+
if (inner.kind === "call" && inner.args.length === 1 && inner.callee.kind === "identifier" && inner.callee.name === "String") {
|
|
10697
|
+
inner = inner.args[0];
|
|
10698
|
+
}
|
|
10699
|
+
if (inner.kind !== "logical" || inner.op !== "??")
|
|
10700
|
+
return false;
|
|
10701
|
+
if (inner.right.kind !== "literal" || inner.right.literalType !== "string" || inner.right.value !== "") {
|
|
10702
|
+
return false;
|
|
10703
|
+
}
|
|
10704
|
+
const idx = inner.left;
|
|
10705
|
+
if (idx.kind !== "index-access")
|
|
10706
|
+
return false;
|
|
10707
|
+
if (idx.object.kind !== "identifier" || idx.object.name !== argsName)
|
|
10708
|
+
return false;
|
|
10709
|
+
if (idx.index.kind !== "identifier" || idx.index.name !== i)
|
|
10710
|
+
return false;
|
|
10711
|
+
return true;
|
|
10712
|
+
}
|
|
10713
|
+
function buildUntaggedTemplateLiteral(node, ctx) {
|
|
10714
|
+
const template = node.template;
|
|
10715
|
+
let text;
|
|
10716
|
+
if (ts11.isNoSubstitutionTemplateLiteral(template)) {
|
|
10717
|
+
text = "`" + (template.rawText ?? template.text) + "`";
|
|
10718
|
+
} else {
|
|
10719
|
+
let body = template.head.rawText ?? template.head.text;
|
|
10720
|
+
for (const span of template.templateSpans) {
|
|
10721
|
+
const spanText = ctx.getJS(span.expression);
|
|
10722
|
+
body += "${(" + spanText + ") ?? ''}";
|
|
10723
|
+
body += span.literal.rawText ?? span.literal.text;
|
|
10724
|
+
}
|
|
10725
|
+
text = "`" + body + "`";
|
|
10726
|
+
}
|
|
10727
|
+
const wrapped = `const __bf_resolve_tagged__ = (${text})`;
|
|
10728
|
+
const sf = ts11.createSourceFile("__bf_resolve_tagged.tsx", wrapped, ts11.ScriptTarget.Latest, true, ts11.ScriptKind.TSX);
|
|
10729
|
+
const stmt = sf.statements[0];
|
|
10730
|
+
if (!stmt || !ts11.isVariableStatement(stmt))
|
|
10731
|
+
return null;
|
|
10732
|
+
const decl = stmt.declarationList.declarations[0];
|
|
10733
|
+
if (!decl?.initializer)
|
|
10734
|
+
return null;
|
|
10735
|
+
const result = ts11.isParenthesizedExpression(decl.initializer) ? decl.initializer.expression : decl.initializer;
|
|
10736
|
+
if (!ts11.isTemplateExpression(result) && !ts11.isNoSubstitutionTemplateLiteral(result))
|
|
10737
|
+
return null;
|
|
10738
|
+
return result;
|
|
10739
|
+
}
|
|
10740
|
+
function parseTernary(expr, ctx) {
|
|
10741
|
+
const whenTrueValue = getStringValue(expr.whenTrue);
|
|
10742
|
+
const whenFalseValue = getStringValue(expr.whenFalse);
|
|
10743
|
+
if (whenTrueValue !== null && whenFalseValue !== null) {
|
|
10236
10744
|
const condition = ctx.getJS(expr.condition);
|
|
10237
10745
|
return {
|
|
10238
10746
|
type: "ternary",
|
|
@@ -11344,6 +11852,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
11344
11852
|
const { useElementReconciliation, innerLoops } = decideLoopRendering(l, siblingOffsets, ctx);
|
|
11345
11853
|
let template = "";
|
|
11346
11854
|
let staticItemTemplate;
|
|
11855
|
+
let skeletonTemplate;
|
|
11347
11856
|
if (l.childComponent) {
|
|
11348
11857
|
template = "";
|
|
11349
11858
|
if (l.isStaticArray && l.children[0]) {
|
|
@@ -11354,6 +11863,11 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
11354
11863
|
template = useElementReconciliation ? irToPlaceholderTemplate(l.children[0], buildRestSpreadNames(ctx), 0, loopParamSpec) : irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx), 0, loopParamSpec);
|
|
11355
11864
|
if (l.isStaticArray) {
|
|
11356
11865
|
staticItemTemplate = useElementReconciliation ? irToPlaceholderTemplate(l.children[0], buildRestSpreadNames(ctx), 0) : irToHtmlTemplate(l.children[0], buildRestSpreadNames(ctx), 0);
|
|
11866
|
+
} else if (!useElementReconciliation && !l.bodyIsMultiRoot && !l.bodyIsItemConditional) {
|
|
11867
|
+
skeletonTemplate = buildLoopSkeletonTemplate(l.children[0], {
|
|
11868
|
+
reactiveAttrKeys: new Set(bindings.reactiveAttrs.map((a) => `${a.childSlotId}::${a.attrName}`)),
|
|
11869
|
+
reactiveTextSlotIds: new Set(bindings.reactiveTexts.map((t) => t.slotId))
|
|
11870
|
+
}) ?? undefined;
|
|
11357
11871
|
}
|
|
11358
11872
|
}
|
|
11359
11873
|
ctx.loopElements.push({
|
|
@@ -11371,6 +11885,7 @@ function collectElements(node, ctx, siblingOffsets, insideConditional = false) {
|
|
|
11371
11885
|
iterationShape: l.iterationShape,
|
|
11372
11886
|
template,
|
|
11373
11887
|
staticItemTemplate,
|
|
11888
|
+
skeletonTemplate,
|
|
11374
11889
|
childEventHandlers: childHandlers,
|
|
11375
11890
|
bindings,
|
|
11376
11891
|
childComponent: l.childComponent,
|
|
@@ -12259,6 +12774,45 @@ function collectComponentNames(node) {
|
|
|
12259
12774
|
|
|
12260
12775
|
// src/relocate.ts
|
|
12261
12776
|
import ts13 from "typescript";
|
|
12777
|
+
|
|
12778
|
+
// src/lowering-registry.ts
|
|
12779
|
+
var plugins = [];
|
|
12780
|
+
function registerLoweringPlugin(plugin) {
|
|
12781
|
+
const existing = plugins.findIndex((p) => p.name === plugin.name);
|
|
12782
|
+
if (existing >= 0)
|
|
12783
|
+
plugins[existing] = plugin;
|
|
12784
|
+
else
|
|
12785
|
+
plugins.push(plugin);
|
|
12786
|
+
}
|
|
12787
|
+
function getLoweringPlugins() {
|
|
12788
|
+
return [...plugins];
|
|
12789
|
+
}
|
|
12790
|
+
function prepareLoweringMatchers(metadata) {
|
|
12791
|
+
const matchers = [];
|
|
12792
|
+
for (const plugin of plugins) {
|
|
12793
|
+
const matcher = plugin.prepare(metadata);
|
|
12794
|
+
if (matcher)
|
|
12795
|
+
matchers.push(matcher);
|
|
12796
|
+
}
|
|
12797
|
+
return matchers;
|
|
12798
|
+
}
|
|
12799
|
+
function matchLoweringCall(callee, args, metadata) {
|
|
12800
|
+
for (const matcher of prepareLoweringMatchers(metadata)) {
|
|
12801
|
+
const node = matcher(callee, args);
|
|
12802
|
+
if (node)
|
|
12803
|
+
return node;
|
|
12804
|
+
}
|
|
12805
|
+
return null;
|
|
12806
|
+
}
|
|
12807
|
+
function isValidHelperId(helper) {
|
|
12808
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
|
|
12809
|
+
}
|
|
12810
|
+
function __resetLoweringPluginsForTest(next = []) {
|
|
12811
|
+
plugins.length = 0;
|
|
12812
|
+
plugins.push(...next);
|
|
12813
|
+
}
|
|
12814
|
+
|
|
12815
|
+
// src/relocate.ts
|
|
12262
12816
|
function classify(name, env) {
|
|
12263
12817
|
return env.bindings.get(name) ?? "global";
|
|
12264
12818
|
}
|
|
@@ -12293,6 +12847,14 @@ function decideAction(kind, toScope, env, name) {
|
|
|
12293
12847
|
return { action: "lift-to-prop", rewrittenAs: `${PROPS_PARAM}.${name}` };
|
|
12294
12848
|
}
|
|
12295
12849
|
if ((kind === "init-local" || kind === "sub-init-local") && toScope === "template") {
|
|
12850
|
+
const aliasTarget = env.aliasTargets?.get(name);
|
|
12851
|
+
if (aliasTarget !== undefined) {
|
|
12852
|
+
const targetLeftmost = aliasTarget.includes(".") ? aliasTarget.split(".")[0] : aliasTarget;
|
|
12853
|
+
const targetKind = classify(targetLeftmost, env);
|
|
12854
|
+
if (isVisibleIn(toScope, targetKind)) {
|
|
12855
|
+
return { action: "inline", rewrittenAs: aliasTarget };
|
|
12856
|
+
}
|
|
12857
|
+
}
|
|
12296
12858
|
const inlineForm = env.inlinable.get(name);
|
|
12297
12859
|
if (inlineForm !== undefined) {
|
|
12298
12860
|
return { action: "inline", rewrittenAs: inlineForm };
|
|
@@ -12372,6 +12934,8 @@ function isInlinableInTemplate(value, env) {
|
|
|
12372
12934
|
return { ok: true, rewrittenValue: r.text, decisions: r.decisions };
|
|
12373
12935
|
}
|
|
12374
12936
|
function getCalleeIdentifierPath(callee) {
|
|
12937
|
+
if (ts13.isParenthesizedExpression(callee))
|
|
12938
|
+
return getCalleeIdentifierPath(callee.expression);
|
|
12375
12939
|
if (ts13.isIdentifier(callee))
|
|
12376
12940
|
return callee.text;
|
|
12377
12941
|
if (ts13.isPropertyAccessExpression(callee)) {
|
|
@@ -12383,6 +12947,8 @@ function getCalleeIdentifierPath(callee) {
|
|
|
12383
12947
|
return null;
|
|
12384
12948
|
}
|
|
12385
12949
|
function getCalleeLeftmostIdentifier(callee) {
|
|
12950
|
+
if (ts13.isParenthesizedExpression(callee))
|
|
12951
|
+
return getCalleeLeftmostIdentifier(callee.expression);
|
|
12386
12952
|
if (ts13.isIdentifier(callee))
|
|
12387
12953
|
return callee.text;
|
|
12388
12954
|
if (ts13.isPropertyAccessExpression(callee)) {
|
|
@@ -12396,20 +12962,39 @@ var REGISTRY_SAFE_BINDING_KINDS = new Set([
|
|
|
12396
12962
|
"module-local"
|
|
12397
12963
|
]);
|
|
12398
12964
|
function isCallAcceptedByAdapter(call, env) {
|
|
12399
|
-
const
|
|
12400
|
-
if (
|
|
12965
|
+
const originalPath = getCalleeIdentifierPath(call.expression);
|
|
12966
|
+
if (originalPath === null)
|
|
12401
12967
|
return false;
|
|
12402
12968
|
const leftmost = getCalleeLeftmostIdentifier(call.expression);
|
|
12969
|
+
let resolvedPath = originalPath;
|
|
12970
|
+
let resolvedLeftmost = leftmost;
|
|
12403
12971
|
if (leftmost !== null) {
|
|
12404
|
-
const
|
|
12972
|
+
const aliasTarget = env.aliasTargets?.get(leftmost);
|
|
12973
|
+
if (aliasTarget !== undefined) {
|
|
12974
|
+
resolvedPath = originalPath === leftmost ? aliasTarget : `${aliasTarget}${originalPath.slice(leftmost.length)}`;
|
|
12975
|
+
resolvedLeftmost = aliasTarget.includes(".") ? aliasTarget.split(".")[0] : aliasTarget;
|
|
12976
|
+
}
|
|
12977
|
+
}
|
|
12978
|
+
if (resolvedLeftmost !== null) {
|
|
12979
|
+
const kind = env.bindings.get(resolvedLeftmost);
|
|
12405
12980
|
if (kind !== undefined && !REGISTRY_SAFE_BINDING_KINDS.has(kind)) {
|
|
12406
12981
|
return false;
|
|
12407
12982
|
}
|
|
12408
12983
|
}
|
|
12409
|
-
if (env.templatePrimitives && env.templatePrimitives[
|
|
12984
|
+
if (env.templatePrimitives && env.templatePrimitives[resolvedPath])
|
|
12410
12985
|
return true;
|
|
12411
|
-
if (env.acceptsTemplateCall && env.acceptsTemplateCall(
|
|
12986
|
+
if (env.acceptsTemplateCall && env.acceptsTemplateCall(resolvedPath))
|
|
12412
12987
|
return true;
|
|
12988
|
+
if (env.loweringMatchers && env.loweringMatchers.length > 0) {
|
|
12989
|
+
const parsed = tsNodeToParsedExpr(call);
|
|
12990
|
+
if (parsed.kind === "call") {
|
|
12991
|
+
const calleeForMatch = resolvedPath !== originalPath && !resolvedPath.includes(".") && parsed.callee.kind === "identifier" ? { kind: "identifier", name: resolvedPath } : parsed.callee;
|
|
12992
|
+
for (const matcher of env.loweringMatchers) {
|
|
12993
|
+
if (matcher(calleeForMatch, parsed.args))
|
|
12994
|
+
return true;
|
|
12995
|
+
}
|
|
12996
|
+
}
|
|
12997
|
+
}
|
|
12413
12998
|
return false;
|
|
12414
12999
|
}
|
|
12415
13000
|
function parseExpressionNode(text) {
|
|
@@ -12555,6 +13140,7 @@ function buildRelocateEnvFromIR(metadata, options) {
|
|
|
12555
13140
|
env.templatePrimitives = options.templatePrimitives;
|
|
12556
13141
|
if (options?.acceptsTemplateCall)
|
|
12557
13142
|
env.acceptsTemplateCall = options.acceptsTemplateCall;
|
|
13143
|
+
env.loweringMatchers = prepareLoweringMatchers(metadata);
|
|
12558
13144
|
return env;
|
|
12559
13145
|
}
|
|
12560
13146
|
function buildRelocateEnvFromFields(src) {
|
|
@@ -12603,14 +13189,35 @@ function buildRelocateEnvFromFields(src) {
|
|
|
12603
13189
|
if (kind === "prop")
|
|
12604
13190
|
propsForLift.add(name);
|
|
12605
13191
|
}
|
|
13192
|
+
const aliasTargets = new Map;
|
|
13193
|
+
for (const c of src.localConstants) {
|
|
13194
|
+
const kind = bindings.get(c.name);
|
|
13195
|
+
if (kind !== "init-local" && kind !== "module-local")
|
|
13196
|
+
continue;
|
|
13197
|
+
const target = identifierPathFromParsed(c.parsed);
|
|
13198
|
+
if (target !== null)
|
|
13199
|
+
aliasTargets.set(c.name, target);
|
|
13200
|
+
}
|
|
12606
13201
|
return {
|
|
12607
13202
|
bindings,
|
|
12608
13203
|
inlinable: new Map,
|
|
12609
13204
|
propsForLift,
|
|
12610
13205
|
propsObjectName,
|
|
12611
|
-
allowFallback: true
|
|
13206
|
+
allowFallback: true,
|
|
13207
|
+
aliasTargets
|
|
12612
13208
|
};
|
|
12613
13209
|
}
|
|
13210
|
+
function identifierPathFromParsed(expr) {
|
|
13211
|
+
if (!expr)
|
|
13212
|
+
return null;
|
|
13213
|
+
if (expr.kind === "identifier")
|
|
13214
|
+
return expr.name;
|
|
13215
|
+
if (expr.kind === "member" && !expr.computed) {
|
|
13216
|
+
const object = identifierPathFromParsed(expr.object);
|
|
13217
|
+
return object === null ? null : `${object}.${expr.property}`;
|
|
13218
|
+
}
|
|
13219
|
+
return null;
|
|
13220
|
+
}
|
|
12614
13221
|
|
|
12615
13222
|
// src/ir-to-client-js/compute-inlinability.ts
|
|
12616
13223
|
function buildEnvFromCtx(ctx) {
|
|
@@ -12630,7 +13237,7 @@ function buildEnvFromCtx(ctx) {
|
|
|
12630
13237
|
effects: ctx.effects,
|
|
12631
13238
|
onMounts: ctx.onMounts,
|
|
12632
13239
|
initStatements: ctx.initStatements,
|
|
12633
|
-
imports:
|
|
13240
|
+
imports: ctx.imports,
|
|
12634
13241
|
templateImports: [],
|
|
12635
13242
|
namedExports: [],
|
|
12636
13243
|
localFunctions: ctx.localFunctions,
|
|
@@ -15391,6 +15998,15 @@ function emitTemplateCloneInline(template) {
|
|
|
15391
15998
|
}
|
|
15392
15999
|
return `const __tpl = document.createElement('template'); __tpl.innerHTML = \`${template}\`; return __tpl.content.firstElementChild.cloneNode(true)`;
|
|
15393
16000
|
}
|
|
16001
|
+
function emitHoistedTemplateDecl(lines, indent, tplVar, skeletonTemplate) {
|
|
16002
|
+
const isSvg = templateRootIsSvg(skeletonTemplate);
|
|
16003
|
+
const html = isSvg ? `<svg>${skeletonTemplate}</svg>` : skeletonTemplate;
|
|
16004
|
+
lines.push(`${indent}const ${tplVar} = document.createElement('template')`);
|
|
16005
|
+
lines.push(`${indent}${tplVar}.innerHTML = \`${html}\``);
|
|
16006
|
+
}
|
|
16007
|
+
function hoistedCloneExpr(tplVar, skeletonTemplate) {
|
|
16008
|
+
return templateRootIsSvg(skeletonTemplate) ? `${tplVar}.content.firstElementChild.firstElementChild.cloneNode(true)` : `${tplVar}.content.firstElementChild.cloneNode(true)`;
|
|
16009
|
+
}
|
|
15394
16010
|
function emitTemplateCloneLines(template, indent) {
|
|
15395
16011
|
if (templateRootIsSvg(template)) {
|
|
15396
16012
|
return [
|
|
@@ -15689,6 +16305,7 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
15689
16305
|
indexParam,
|
|
15690
16306
|
mapPreambleWrapped,
|
|
15691
16307
|
template,
|
|
16308
|
+
skeletonTemplate,
|
|
15692
16309
|
reactiveEffects,
|
|
15693
16310
|
childRefs,
|
|
15694
16311
|
bodyIsMultiRoot,
|
|
@@ -15699,11 +16316,16 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
15699
16316
|
stringifyAnchoredLoop(lines, plan, topIndent, anchorKeyExpr);
|
|
15700
16317
|
return;
|
|
15701
16318
|
}
|
|
16319
|
+
const hoistedTpl = !bodyIsMultiRoot && skeletonTemplate ? skeletonTemplate : null;
|
|
16320
|
+
const tplVar = `__tpl_${markerId.replace(/[^A-Za-z0-9_$]/g, "_")}`;
|
|
16321
|
+
if (hoistedTpl) {
|
|
16322
|
+
emitHoistedTemplateDecl(lines, topIndent, tplVar, hoistedTpl);
|
|
16323
|
+
}
|
|
15702
16324
|
const loopBfId = plan.profileLoopId ? `, ${JSON.stringify(plan.profileLoopId)}` : "";
|
|
15703
16325
|
if (reactiveEffects === null && !bodyIsMultiRoot && childRefs.length === 0) {
|
|
15704
16326
|
const unwrapInline = paramUnwrap ? `${paramUnwrap} ` : "";
|
|
15705
16327
|
const preamble = mapPreambleWrapped ? `${mapPreambleWrapped}; ` : "";
|
|
15706
|
-
const cloneExpr = emitTemplateCloneInline(template);
|
|
16328
|
+
const cloneExpr = hoistedTpl ? `return ${hoistedCloneExpr(tplVar, hoistedTpl)}` : emitTemplateCloneInline(template);
|
|
15707
16329
|
lines.push(`${topIndent}mapArray(() => ${arrayExpr}, ${containerVar}, ${keyFn}, (${paramHead}, ${indexParam}, __existing) => { ${unwrapInline}${preamble}if (__existing) return __existing; ${cloneExpr} }, '${markerId}'${loopBfId})`);
|
|
15708
16330
|
return;
|
|
15709
16331
|
}
|
|
@@ -15713,12 +16335,16 @@ function stringifyPlainLoop(lines, plan, topIndent = " ") {
|
|
|
15713
16335
|
lines.push(`${bodyIndent}${paramUnwrap}`);
|
|
15714
16336
|
if (mapPreambleWrapped)
|
|
15715
16337
|
lines.push(`${bodyIndent}${mapPreambleWrapped}`);
|
|
15716
|
-
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
|
|
15720
|
-
|
|
15721
|
-
|
|
16338
|
+
if (hoistedTpl) {
|
|
16339
|
+
lines.push(`${bodyIndent}const __el = __existing ?? ${hoistedCloneExpr(tplVar, hoistedTpl)}`);
|
|
16340
|
+
} else {
|
|
16341
|
+
emitLoopItemElementSetup(lines, {
|
|
16342
|
+
template,
|
|
16343
|
+
bodyIsMultiRoot,
|
|
16344
|
+
indent: bodyIndent,
|
|
16345
|
+
singleRootLayout: "inline"
|
|
16346
|
+
});
|
|
16347
|
+
}
|
|
15722
16348
|
if (reactiveEffects !== null) {
|
|
15723
16349
|
stringifyReactiveEffects(lines, reactiveEffects, { indent: bodyIndent, elVar: "__el", bodyIsMultiRoot });
|
|
15724
16350
|
}
|
|
@@ -16404,6 +17030,7 @@ function buildPlainLoopPlan(elem, profileComponentName) {
|
|
|
16404
17030
|
indexParam: elem.index || "__idx",
|
|
16405
17031
|
mapPreambleWrapped: elem.mapPreamble ? wrap(elem.mapPreamble) : "",
|
|
16406
17032
|
template: elem.template,
|
|
17033
|
+
skeletonTemplate: elem.skeletonTemplate,
|
|
16407
17034
|
reactiveEffects: hasReactive2 ? buildLoopReactiveEffectsPlan(elem, profileComponentName) : null,
|
|
16408
17035
|
childRefs: buildChildRefBindings(elem.bindings.refs, elem.param, elem.paramBindings),
|
|
16409
17036
|
bodyIsMultiRoot: elem.bodyIsMultiRoot ?? false,
|
|
@@ -17010,6 +17637,7 @@ function createContext(ir, scope, adapterCapabilities, profile) {
|
|
|
17010
17637
|
initStatements: ir.metadata.initStatements ?? [],
|
|
17011
17638
|
localFunctions: ir.metadata.localFunctions,
|
|
17012
17639
|
localConstants: ir.metadata.localConstants,
|
|
17640
|
+
imports: ir.metadata.imports,
|
|
17013
17641
|
propsParams: ir.metadata.propsParams,
|
|
17014
17642
|
propsObjectName: ir.metadata.propsObjectName,
|
|
17015
17643
|
restPropsName: ir.metadata.restPropsName,
|
|
@@ -17093,119 +17721,6 @@ ${externalImports.join(`
|
|
|
17093
17721
|
return generatedCode.replace(IMPORT_PLACEHOLDER, allImports);
|
|
17094
17722
|
}
|
|
17095
17723
|
|
|
17096
|
-
// src/module-exports.ts
|
|
17097
|
-
function generateModuleExports(ir, extraInlineExported = new Set, rewriteRelativeImport) {
|
|
17098
|
-
const lines = [];
|
|
17099
|
-
for (const constant of ir.metadata.localConstants) {
|
|
17100
|
-
if (!constant.isExported)
|
|
17101
|
-
continue;
|
|
17102
|
-
const keyword = constant.declarationKind ?? "const";
|
|
17103
|
-
if (!constant.value) {
|
|
17104
|
-
lines.push(`export ${keyword} ${constant.name}`);
|
|
17105
|
-
continue;
|
|
17106
|
-
}
|
|
17107
|
-
const value = constant.value.trim();
|
|
17108
|
-
if (/^createContext\b/.test(value) || /^new WeakMap\b/.test(value))
|
|
17109
|
-
continue;
|
|
17110
|
-
lines.push(`export ${keyword} ${constant.name} = ${constant.value}`);
|
|
17111
|
-
}
|
|
17112
|
-
for (const func of ir.metadata.localFunctions) {
|
|
17113
|
-
if (!func.isExported)
|
|
17114
|
-
continue;
|
|
17115
|
-
const params = func.typedParams !== undefined ? func.typedParams : func.params.map(formatParamWithType).join(", ");
|
|
17116
|
-
const returnAnnotation = func.typedReturnType ? `: ${func.typedReturnType}` : "";
|
|
17117
|
-
const body = func.typedBody ?? func.body;
|
|
17118
|
-
const asyncKw = func.isAsync ? "async " : "";
|
|
17119
|
-
lines.push(`export ${asyncKw}function ${func.name}(${params})${returnAnnotation} ${body}`);
|
|
17120
|
-
}
|
|
17121
|
-
const inlineExported = collectInlineExportedNames(ir);
|
|
17122
|
-
for (const name of extraInlineExported)
|
|
17123
|
-
inlineExported.add(name);
|
|
17124
|
-
for (const block of ir.metadata.namedExports) {
|
|
17125
|
-
const isReexportFrom = block.source !== null;
|
|
17126
|
-
const survivingSpecs = block.specifiers.filter((spec) => {
|
|
17127
|
-
if (isReexportFrom)
|
|
17128
|
-
return true;
|
|
17129
|
-
return !(inlineExported.has(spec.name) && spec.alias == null);
|
|
17130
|
-
});
|
|
17131
|
-
if (survivingSpecs.length === 0)
|
|
17132
|
-
continue;
|
|
17133
|
-
const specText = survivingSpecs.map((s) => {
|
|
17134
|
-
const prefix = s.isTypeOnly ? "type " : "";
|
|
17135
|
-
return s.alias ? `${prefix}${s.name} as ${s.alias}` : `${prefix}${s.name}`;
|
|
17136
|
-
}).join(", ");
|
|
17137
|
-
const typeKw = block.isTypeOnly ? "type " : "";
|
|
17138
|
-
if (isReexportFrom) {
|
|
17139
|
-
const source = rewriteRelativeImport && block.source.startsWith(".") ? rewriteRelativeImport(block.source) : block.source;
|
|
17140
|
-
lines.push(`export ${typeKw}{ ${specText} } from '${source}'`);
|
|
17141
|
-
} else {
|
|
17142
|
-
lines.push(`export ${typeKw}{ ${specText} }`);
|
|
17143
|
-
}
|
|
17144
|
-
}
|
|
17145
|
-
return lines.length > 0 ? lines.join(`
|
|
17146
|
-
`) : null;
|
|
17147
|
-
}
|
|
17148
|
-
function collectInlineExportedNames(ir) {
|
|
17149
|
-
const names = new Set;
|
|
17150
|
-
for (const c of ir.metadata.localConstants) {
|
|
17151
|
-
if (c.isExported)
|
|
17152
|
-
names.add(c.name);
|
|
17153
|
-
}
|
|
17154
|
-
for (const f of ir.metadata.localFunctions) {
|
|
17155
|
-
if (f.isExported)
|
|
17156
|
-
names.add(f.name);
|
|
17157
|
-
}
|
|
17158
|
-
if (ir.metadata.isExported && ir.metadata.componentName) {
|
|
17159
|
-
names.add(ir.metadata.componentName);
|
|
17160
|
-
}
|
|
17161
|
-
return names;
|
|
17162
|
-
}
|
|
17163
|
-
function formatParamWithType(p) {
|
|
17164
|
-
const rest = p.isRest ? "..." : "";
|
|
17165
|
-
const optional = p.optional ? "?" : "";
|
|
17166
|
-
const typeAnnotation = p.type?.raw && p.type.raw !== "unknown" ? `: ${p.type.raw}` : "";
|
|
17167
|
-
const defaultPart = p.defaultValue !== undefined ? ` = ${p.defaultValue}` : "";
|
|
17168
|
-
return `${rest}${p.name}${optional}${typeAnnotation}${defaultPart}`;
|
|
17169
|
-
}
|
|
17170
|
-
function findReachableNames(primaryRefs, declarations) {
|
|
17171
|
-
const allNames = new Set(declarations.map((d) => d.name));
|
|
17172
|
-
const bodyMap = new Map(declarations.map((d) => [d.name, d.body]));
|
|
17173
|
-
const reachable = new Set;
|
|
17174
|
-
const queue = [];
|
|
17175
|
-
for (const name of allNames) {
|
|
17176
|
-
if (new RegExp(`\\b${name}\\b`).test(primaryRefs)) {
|
|
17177
|
-
reachable.add(name);
|
|
17178
|
-
queue.push(name);
|
|
17179
|
-
}
|
|
17180
|
-
}
|
|
17181
|
-
while (queue.length > 0) {
|
|
17182
|
-
const current = queue.shift();
|
|
17183
|
-
const body = bodyMap.get(current) || "";
|
|
17184
|
-
for (const name of allNames) {
|
|
17185
|
-
if (!reachable.has(name) && new RegExp(`\\b${name}\\b`).test(body)) {
|
|
17186
|
-
reachable.add(name);
|
|
17187
|
-
queue.push(name);
|
|
17188
|
-
}
|
|
17189
|
-
}
|
|
17190
|
-
}
|
|
17191
|
-
return reachable;
|
|
17192
|
-
}
|
|
17193
|
-
function extractFunctionParams(value) {
|
|
17194
|
-
const arrowMatch = value.match(/^(?:async\s*)?\(([^)]*)\)\s*(?::\s*[^=]+)?\s*=>/);
|
|
17195
|
-
if (arrowMatch) {
|
|
17196
|
-
return arrowMatch[1].split(",").map((p) => p.trim().split(":")[0].split("=")[0].trim()).filter(Boolean).join(", ");
|
|
17197
|
-
}
|
|
17198
|
-
const singleMatch = value.match(/^(?:async\s*)?(\w+)\s*=>/);
|
|
17199
|
-
if (singleMatch) {
|
|
17200
|
-
return singleMatch[1];
|
|
17201
|
-
}
|
|
17202
|
-
const funcMatch = value.match(/^(?:async\s*)?function\s*\w*\s*\(([^)]*)\)/);
|
|
17203
|
-
if (funcMatch) {
|
|
17204
|
-
return funcMatch[1].split(",").map((p) => p.trim().split(":")[0].split("=")[0].trim()).filter(Boolean).join(", ");
|
|
17205
|
-
}
|
|
17206
|
-
return "";
|
|
17207
|
-
}
|
|
17208
|
-
|
|
17209
17724
|
// src/css-layer-prefixer.ts
|
|
17210
17725
|
function prefixClass(cls, layerName) {
|
|
17211
17726
|
if (!cls || cls.startsWith("layer-"))
|
|
@@ -17713,16 +18228,14 @@ function extractSsrDefaults(metadata) {
|
|
|
17713
18228
|
propsLike.add(metadata.propsObjectName);
|
|
17714
18229
|
for (const p of metadata.propsParams)
|
|
17715
18230
|
propsLike.add(p.name);
|
|
17716
|
-
|
|
17717
|
-
|
|
17718
|
-
|
|
17719
|
-
|
|
17720
|
-
|
|
17721
|
-
|
|
17722
|
-
|
|
17723
|
-
|
|
17724
|
-
out[p.name] = { propName: p.name, value: null };
|
|
17725
|
-
}
|
|
18231
|
+
for (const p of metadata.propsParams) {
|
|
18232
|
+
if (p.isRest)
|
|
18233
|
+
continue;
|
|
18234
|
+
if (metadata.propsObjectName === null && p.defaultValue !== undefined) {
|
|
18235
|
+
const value = tryStaticEval(p.defaultValue, { bindings: {}, propsLike });
|
|
18236
|
+
out[p.name] = { propName: p.name, value: resultToJsonable(value) };
|
|
18237
|
+
} else {
|
|
18238
|
+
out[p.name] = { propName: p.name, value: null };
|
|
17726
18239
|
}
|
|
17727
18240
|
}
|
|
17728
18241
|
if (metadata.restPropsName) {
|
|
@@ -18044,10 +18557,13 @@ import ts17 from "typescript";
|
|
|
18044
18557
|
function collectContextConsumers(metadata) {
|
|
18045
18558
|
const constants = metadata.localConstants ?? [];
|
|
18046
18559
|
const contextDefaults = new Map;
|
|
18560
|
+
const contextDefaultKinds = new Map;
|
|
18047
18561
|
for (const c of constants) {
|
|
18048
18562
|
if (c.systemConstructKind !== "createContext" || c.value === undefined)
|
|
18049
18563
|
continue;
|
|
18050
18564
|
contextDefaults.set(c.name, parseCreateContextDefault(c.value));
|
|
18565
|
+
if (isObjectLiteralCreateContextDefault(c.value))
|
|
18566
|
+
contextDefaultKinds.set(c.name, "object");
|
|
18051
18567
|
}
|
|
18052
18568
|
if (contextDefaults.size === 0)
|
|
18053
18569
|
return [];
|
|
@@ -18061,7 +18577,8 @@ function collectContextConsumers(metadata) {
|
|
|
18061
18577
|
consumers.push({
|
|
18062
18578
|
localName: c.name,
|
|
18063
18579
|
contextName: ctxName,
|
|
18064
|
-
defaultValue: contextDefaults.get(ctxName) ?? null
|
|
18580
|
+
defaultValue: contextDefaults.get(ctxName) ?? null,
|
|
18581
|
+
defaultKind: contextDefaultKinds.get(ctxName)
|
|
18065
18582
|
});
|
|
18066
18583
|
}
|
|
18067
18584
|
return consumers;
|
|
@@ -18094,6 +18611,14 @@ function parseCreateContextDefault(source) {
|
|
|
18094
18611
|
return false;
|
|
18095
18612
|
return null;
|
|
18096
18613
|
}
|
|
18614
|
+
function isObjectLiteralCreateContextDefault(source) {
|
|
18615
|
+
const expr = parseSingleExpression(source);
|
|
18616
|
+
if (!expr || !ts17.isCallExpression(expr))
|
|
18617
|
+
return false;
|
|
18618
|
+
if (expr.arguments.length === 0)
|
|
18619
|
+
return false;
|
|
18620
|
+
return ts17.isObjectLiteralExpression(expr.arguments[0]);
|
|
18621
|
+
}
|
|
18097
18622
|
function parseSingleExpression(source) {
|
|
18098
18623
|
const sf = ts17.createSourceFile("__ctx.ts", `(${source})`, ts17.ScriptTarget.Latest, false);
|
|
18099
18624
|
const stmt = sf.statements[0];
|
|
@@ -18113,16 +18638,48 @@ function augmentInheritedPropAccesses(ir) {
|
|
|
18113
18638
|
const booleanAttrProps = new Set;
|
|
18114
18639
|
const accessed = new Set;
|
|
18115
18640
|
const accessRe = new RegExp(`(?:^|[^\\w$.])${propsObj}\\.([A-Za-z_$][\\w$]*)`, "g");
|
|
18116
|
-
const scan = (s) => {
|
|
18641
|
+
const scan = (s, also) => {
|
|
18117
18642
|
if (!s)
|
|
18118
18643
|
return;
|
|
18119
|
-
for (const m of s.matchAll(accessRe))
|
|
18644
|
+
for (const m of s.matchAll(accessRe)) {
|
|
18120
18645
|
accessed.add(m[1]);
|
|
18646
|
+
also?.add(m[1]);
|
|
18647
|
+
}
|
|
18648
|
+
};
|
|
18649
|
+
const coalesceLiteralTypes = new Map;
|
|
18650
|
+
const pinCoalesceLiterals = (s) => {
|
|
18651
|
+
if (!s || !s.includes(propsObj))
|
|
18652
|
+
return;
|
|
18653
|
+
const sf = ts17.createSourceFile("__aug.ts", `(${s})`, ts17.ScriptTarget.Latest, false);
|
|
18654
|
+
const visit3 = (n) => {
|
|
18655
|
+
if (ts17.isBinaryExpression(n) && (n.operatorToken.kind === ts17.SyntaxKind.QuestionQuestionToken || n.operatorToken.kind === ts17.SyntaxKind.BarBarToken)) {
|
|
18656
|
+
let left = n.left;
|
|
18657
|
+
while (ts17.isParenthesizedExpression(left))
|
|
18658
|
+
left = left.expression;
|
|
18659
|
+
if (ts17.isPropertyAccessExpression(left) && ts17.isIdentifier(left.expression) && left.expression.text === propsObj) {
|
|
18660
|
+
const name = left.name.text;
|
|
18661
|
+
let right = n.right;
|
|
18662
|
+
while (ts17.isParenthesizedExpression(right))
|
|
18663
|
+
right = right.expression;
|
|
18664
|
+
if (ts17.isPrefixUnaryExpression(right))
|
|
18665
|
+
right = right.operand;
|
|
18666
|
+
const kind = ts17.isNumericLiteral(right) ? "number" : right.kind === ts17.SyntaxKind.TrueKeyword || right.kind === ts17.SyntaxKind.FalseKeyword ? "boolean" : ts17.isStringLiteralLike(right) ? "string" : null;
|
|
18667
|
+
if (kind && !coalesceLiteralTypes.has(name))
|
|
18668
|
+
coalesceLiteralTypes.set(name, kind);
|
|
18669
|
+
}
|
|
18670
|
+
}
|
|
18671
|
+
ts17.forEachChild(n, visit3);
|
|
18672
|
+
};
|
|
18673
|
+
visit3(sf);
|
|
18121
18674
|
};
|
|
18122
|
-
for (const memo of ir.metadata.memos)
|
|
18675
|
+
for (const memo of ir.metadata.memos) {
|
|
18123
18676
|
scan(memo.computation);
|
|
18124
|
-
|
|
18677
|
+
pinCoalesceLiterals(memo.computation);
|
|
18678
|
+
}
|
|
18679
|
+
for (const signal of ir.metadata.signals) {
|
|
18125
18680
|
scan(signal.initialValue);
|
|
18681
|
+
pinCoalesceLiterals(signal.initialValue);
|
|
18682
|
+
}
|
|
18126
18683
|
for (const stmt of ir.metadata.initStatements ?? [])
|
|
18127
18684
|
scan(stmt.body);
|
|
18128
18685
|
for (const eff of ir.metadata.effects ?? [])
|
|
@@ -18131,11 +18688,39 @@ function augmentInheritedPropAccesses(ir) {
|
|
|
18131
18688
|
if (c.isModule)
|
|
18132
18689
|
continue;
|
|
18133
18690
|
scan(c.value);
|
|
18691
|
+
pinCoalesceLiterals(c.value);
|
|
18134
18692
|
}
|
|
18135
18693
|
const walk = (node) => {
|
|
18136
18694
|
if (!node)
|
|
18137
18695
|
return;
|
|
18696
|
+
const carrier = node;
|
|
18697
|
+
if (carrier.type === "expression") {
|
|
18698
|
+
scan(carrier.expr);
|
|
18699
|
+
pinCoalesceLiterals(carrier.expr);
|
|
18700
|
+
}
|
|
18701
|
+
scan(carrier.condition, bareRefProps);
|
|
18702
|
+
pinCoalesceLiterals(carrier.condition);
|
|
18703
|
+
scan(carrier.array, bareRefProps);
|
|
18138
18704
|
const el = node;
|
|
18705
|
+
for (const prop of node.props ?? []) {
|
|
18706
|
+
const v = prop.value;
|
|
18707
|
+
if (v?.parts) {
|
|
18708
|
+
for (const part of v.parts) {
|
|
18709
|
+
if (part.type === "string")
|
|
18710
|
+
scan(part.value);
|
|
18711
|
+
else if (part.type === "ternary") {
|
|
18712
|
+
scan(part.condition);
|
|
18713
|
+
scan(part.whenTrue);
|
|
18714
|
+
scan(part.whenFalse);
|
|
18715
|
+
} else if (part.type === "lookup")
|
|
18716
|
+
scan(part.key);
|
|
18717
|
+
}
|
|
18718
|
+
}
|
|
18719
|
+
if (v?.kind === "expression" && typeof v.expr === "string") {
|
|
18720
|
+
scan(v.expr, bareRefProps);
|
|
18721
|
+
pinCoalesceLiterals(v.expr);
|
|
18722
|
+
}
|
|
18723
|
+
}
|
|
18139
18724
|
for (const attr of el.attrs ?? []) {
|
|
18140
18725
|
const v = attr.value;
|
|
18141
18726
|
if (v?.parts) {
|
|
@@ -18182,11 +18767,13 @@ function augmentInheritedPropAccesses(ir) {
|
|
|
18182
18767
|
let raw;
|
|
18183
18768
|
if (booleanAttrProps.has(name))
|
|
18184
18769
|
raw = "boolean";
|
|
18770
|
+
else if (coalesceLiteralTypes.has(name))
|
|
18771
|
+
raw = coalesceLiteralTypes.get(name);
|
|
18185
18772
|
else if (bareRefProps.has(name))
|
|
18186
18773
|
raw = "unknown";
|
|
18187
18774
|
else
|
|
18188
18775
|
raw = "string";
|
|
18189
|
-
const type = raw === "
|
|
18776
|
+
const type = raw === "unknown" ? { kind: "unknown", raw: "unknown" } : { kind: "primitive", raw, primitive: raw };
|
|
18190
18777
|
ir.metadata.propsParams.push({ name, type, optional: true });
|
|
18191
18778
|
existing.add(name);
|
|
18192
18779
|
}
|
|
@@ -18558,7 +19145,8 @@ function compileMultipleComponents(source, filePath, componentNames, options) {
|
|
|
18558
19145
|
files.push({
|
|
18559
19146
|
path: dir + output.componentName + adapter.extension,
|
|
18560
19147
|
content: output.rawTemplate,
|
|
18561
|
-
type: "markedTemplate"
|
|
19148
|
+
type: "markedTemplate",
|
|
19149
|
+
componentName: output.componentName
|
|
18562
19150
|
});
|
|
18563
19151
|
const ir = entries.find((e) => e.componentIR.metadata.componentName === output.componentName);
|
|
18564
19152
|
const ssrDefaults = ir ? extractSsrDefaults(ir.componentIR.metadata) : undefined;
|
|
@@ -18566,7 +19154,8 @@ function compileMultipleComponents(source, filePath, componentNames, options) {
|
|
|
18566
19154
|
files.push({
|
|
18567
19155
|
path: dir + output.componentName + ".ssr-defaults.json",
|
|
18568
19156
|
content: JSON.stringify(ssrDefaults),
|
|
18569
|
-
type: "ssrDefaults"
|
|
19157
|
+
type: "ssrDefaults",
|
|
19158
|
+
componentName: output.componentName
|
|
18570
19159
|
});
|
|
18571
19160
|
}
|
|
18572
19161
|
}
|
|
@@ -18862,7 +19451,8 @@ function compileJSX(source, filePath, options) {
|
|
|
18862
19451
|
files.push({
|
|
18863
19452
|
path: filePath.replace(/\.tsx?$/, adapter.extension),
|
|
18864
19453
|
content,
|
|
18865
|
-
type: "markedTemplate"
|
|
19454
|
+
type: "markedTemplate",
|
|
19455
|
+
componentName: componentIR.metadata.componentName
|
|
18866
19456
|
});
|
|
18867
19457
|
{
|
|
18868
19458
|
const ssrDefaults = extractSsrDefaults(componentIR.metadata);
|
|
@@ -18870,7 +19460,8 @@ function compileJSX(source, filePath, options) {
|
|
|
18870
19460
|
files.push({
|
|
18871
19461
|
path: filePath.replace(/\.tsx?$/, ".ssr-defaults.json"),
|
|
18872
19462
|
content: JSON.stringify(ssrDefaults),
|
|
18873
|
-
type: "ssrDefaults"
|
|
19463
|
+
type: "ssrDefaults",
|
|
19464
|
+
componentName: componentIR.metadata.componentName
|
|
18874
19465
|
});
|
|
18875
19466
|
}
|
|
18876
19467
|
}
|
|
@@ -19439,7 +20030,7 @@ function emitParsedExpr(expr, emitter) {
|
|
|
19439
20030
|
return emitter.objectLiteral(expr.properties, expr.raw, emit);
|
|
19440
20031
|
case "array-method":
|
|
19441
20032
|
if (expr.method === "flat") {
|
|
19442
|
-
return emitter.flatMethod(expr.object, expr.flatDepth, emit);
|
|
20033
|
+
return emitter.flatMethod(expr.object, expr.depthExpr ? { expr: expr.depthExpr } : expr.flatDepth, emit);
|
|
19443
20034
|
}
|
|
19444
20035
|
return emitter.arrayMethod(expr.method, expr.object, expr.args, emit);
|
|
19445
20036
|
case "unsupported":
|
|
@@ -19512,39 +20103,6 @@ function isOmitBranch(node) {
|
|
|
19512
20103
|
}
|
|
19513
20104
|
return false;
|
|
19514
20105
|
}
|
|
19515
|
-
// src/lowering-registry.ts
|
|
19516
|
-
var plugins = [];
|
|
19517
|
-
function registerLoweringPlugin(plugin) {
|
|
19518
|
-
const existing = plugins.findIndex((p) => p.name === plugin.name);
|
|
19519
|
-
if (existing >= 0)
|
|
19520
|
-
plugins[existing] = plugin;
|
|
19521
|
-
else
|
|
19522
|
-
plugins.push(plugin);
|
|
19523
|
-
}
|
|
19524
|
-
function getLoweringPlugins() {
|
|
19525
|
-
return [...plugins];
|
|
19526
|
-
}
|
|
19527
|
-
function prepareLoweringMatchers(metadata) {
|
|
19528
|
-
const matchers = [];
|
|
19529
|
-
for (const plugin of plugins) {
|
|
19530
|
-
const matcher = plugin.prepare(metadata);
|
|
19531
|
-
if (matcher)
|
|
19532
|
-
matchers.push(matcher);
|
|
19533
|
-
}
|
|
19534
|
-
return matchers;
|
|
19535
|
-
}
|
|
19536
|
-
function matchLoweringCall(callee, args, metadata) {
|
|
19537
|
-
for (const matcher of prepareLoweringMatchers(metadata)) {
|
|
19538
|
-
const node = matcher(callee, args);
|
|
19539
|
-
if (node)
|
|
19540
|
-
return node;
|
|
19541
|
-
}
|
|
19542
|
-
return null;
|
|
19543
|
-
}
|
|
19544
|
-
function __resetLoweringPluginsForTest(next = []) {
|
|
19545
|
-
plugins.length = 0;
|
|
19546
|
-
plugins.push(...next);
|
|
19547
|
-
}
|
|
19548
20106
|
// src/builtin-lowering-plugins.ts
|
|
19549
20107
|
var queryHrefPlugin = {
|
|
19550
20108
|
name: "queryHref",
|
|
@@ -19718,8 +20276,7 @@ function parseAndMerge(content, importsBySource, otherImports, codeSections) {
|
|
|
19718
20276
|
}
|
|
19719
20277
|
}
|
|
19720
20278
|
// src/loop-destructure.ts
|
|
19721
|
-
|
|
19722
|
-
function isLowerableObjectRestDestructure(loop) {
|
|
20279
|
+
function isLowerableLoopDestructure(loop) {
|
|
19723
20280
|
const bindings = loop.paramBindings;
|
|
19724
20281
|
if (!bindings || bindings.length === 0)
|
|
19725
20282
|
return false;
|
|
@@ -19731,18 +20288,20 @@ function isLowerableObjectRestDestructure(loop) {
|
|
|
19731
20288
|
}
|
|
19732
20289
|
for (const b of bindings) {
|
|
19733
20290
|
if (b.rest) {
|
|
19734
|
-
if (b.
|
|
20291
|
+
if (!b.segments)
|
|
19735
20292
|
return false;
|
|
19736
|
-
} else if (!
|
|
20293
|
+
} else if (!b.segments || b.segments.length === 0) {
|
|
19737
20294
|
return false;
|
|
19738
20295
|
}
|
|
19739
20296
|
}
|
|
19740
|
-
const
|
|
19741
|
-
if (
|
|
20297
|
+
const objectRestNames = bindings.filter((b) => b.rest?.kind === "object").map((b) => b.name);
|
|
20298
|
+
if (objectRestNames.length === 0)
|
|
19742
20299
|
return true;
|
|
19743
|
-
return !restNamesMisused(loop,
|
|
20300
|
+
return !restNamesMisused(loop, objectRestNames);
|
|
19744
20301
|
}
|
|
20302
|
+
var isLowerableObjectRestDestructure = isLowerableLoopDestructure;
|
|
19745
20303
|
function restNamesMisused(loop, names) {
|
|
20304
|
+
const nameSet = new Set(names);
|
|
19746
20305
|
const valueUse = names.map((n) => new RegExp(`(?<![\\w.$])${escapeRe(n)}(?!\\s*\\??\\.)(?![\\w$])`));
|
|
19747
20306
|
let misused = false;
|
|
19748
20307
|
const check = (s) => {
|
|
@@ -19755,7 +20314,10 @@ function restNamesMisused(loop, names) {
|
|
|
19755
20314
|
}
|
|
19756
20315
|
}
|
|
19757
20316
|
};
|
|
19758
|
-
const attr = (v) => {
|
|
20317
|
+
const attr = (v, isIntrinsicElementAttrs) => {
|
|
20318
|
+
if (v.kind === "spread" && isIntrinsicElementAttrs && nameSet.has(v.expr.trim())) {
|
|
20319
|
+
return;
|
|
20320
|
+
}
|
|
19759
20321
|
if (v.kind === "expression" || v.kind === "spread") {
|
|
19760
20322
|
check(v.expr);
|
|
19761
20323
|
check(v.templateExpr);
|
|
@@ -19815,16 +20377,16 @@ function restNamesMisused(loop, names) {
|
|
|
19815
20377
|
visit3(node.alternate);
|
|
19816
20378
|
break;
|
|
19817
20379
|
case "element":
|
|
19818
|
-
node.attrs.forEach((a) => attr(a.value));
|
|
20380
|
+
node.attrs.forEach((a) => attr(a.value, true));
|
|
19819
20381
|
node.events.forEach((e) => check(e.handler));
|
|
19820
20382
|
node.children.forEach(visit3);
|
|
19821
20383
|
break;
|
|
19822
20384
|
case "component":
|
|
19823
|
-
node.props.forEach((p) => attr(p.value));
|
|
20385
|
+
node.props.forEach((p) => attr(p.value, false));
|
|
19824
20386
|
node.children.forEach(visit3);
|
|
19825
20387
|
break;
|
|
19826
20388
|
case "provider":
|
|
19827
|
-
attr(node.valueProp.value);
|
|
20389
|
+
attr(node.valueProp.value, false);
|
|
19828
20390
|
node.children.forEach(visit3);
|
|
19829
20391
|
break;
|
|
19830
20392
|
case "fragment":
|
|
@@ -22491,8 +23053,10 @@ export {
|
|
|
22491
23053
|
listComponentFunctions,
|
|
22492
23054
|
jsxToIR,
|
|
22493
23055
|
joinProfilerEvents,
|
|
23056
|
+
isValidHelperId,
|
|
22494
23057
|
isSupported,
|
|
22495
23058
|
isLowerableObjectRestDestructure,
|
|
23059
|
+
isLowerableLoopDestructure,
|
|
22496
23060
|
isBooleanAttr,
|
|
22497
23061
|
importsSearchParams,
|
|
22498
23062
|
identifierPath,
|