@farm.js/react 0.1.0-beta.3 → 0.1.0-beta.4
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/README.md +120 -37
- package/dist/compiler-runtime.cjs +1925 -156
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +76 -1
- package/dist/compiler-runtime.d.ts +76 -1
- package/dist/compiler-runtime.mjs +1925 -156
- package/dist/compiler-runtime.mjs.map +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.mjs +5 -1
- package/dist/index.mjs.map +1 -1
- package/dist/list.cjs +18 -1
- package/dist/list.cjs.map +1 -1
- package/dist/list.mjs +18 -1
- package/dist/list.mjs.map +1 -1
- package/dist/vite.cjs +1168 -85
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1168 -85
- package/dist/vite.mjs.map +1 -1
- package/package.json +4 -3
package/dist/vite.mjs
CHANGED
|
@@ -4,6 +4,62 @@ import { mkdir, writeFile } from 'fs/promises';
|
|
|
4
4
|
import { resolve, dirname, relative } from 'path';
|
|
5
5
|
|
|
6
6
|
// src/vite.ts
|
|
7
|
+
var DELEGATABLE_KEYED_ROW_EVENTS = /* @__PURE__ */ new Set([
|
|
8
|
+
"onBeforeInput",
|
|
9
|
+
"onBlur",
|
|
10
|
+
"onChange",
|
|
11
|
+
"onClick",
|
|
12
|
+
"onCompositionEnd",
|
|
13
|
+
"onCompositionStart",
|
|
14
|
+
"onCompositionUpdate",
|
|
15
|
+
"onContextMenu",
|
|
16
|
+
"onCopy",
|
|
17
|
+
"onCut",
|
|
18
|
+
"onDoubleClick",
|
|
19
|
+
"onDrag",
|
|
20
|
+
"onDragEnd",
|
|
21
|
+
"onDragEnter",
|
|
22
|
+
"onDragExit",
|
|
23
|
+
"onDragLeave",
|
|
24
|
+
"onDragOver",
|
|
25
|
+
"onDragStart",
|
|
26
|
+
"onDrop",
|
|
27
|
+
"onFocus",
|
|
28
|
+
"onInput",
|
|
29
|
+
"onKeyDown",
|
|
30
|
+
"onKeyPress",
|
|
31
|
+
"onKeyUp",
|
|
32
|
+
"onMouseDown",
|
|
33
|
+
"onMouseMove",
|
|
34
|
+
"onMouseOut",
|
|
35
|
+
"onMouseOver",
|
|
36
|
+
"onMouseUp",
|
|
37
|
+
"onPaste",
|
|
38
|
+
"onPointerCancel",
|
|
39
|
+
"onPointerDown",
|
|
40
|
+
"onPointerMove",
|
|
41
|
+
"onPointerOut",
|
|
42
|
+
"onPointerOver",
|
|
43
|
+
"onPointerUp",
|
|
44
|
+
"onReset",
|
|
45
|
+
"onSubmit",
|
|
46
|
+
"onTouchCancel",
|
|
47
|
+
"onTouchEnd",
|
|
48
|
+
"onTouchMove",
|
|
49
|
+
"onTouchStart",
|
|
50
|
+
"onWheel"
|
|
51
|
+
]);
|
|
52
|
+
function canDelegateKeyedRowEvents(plan) {
|
|
53
|
+
if (plan.events.length === 0 || plan.conditionals.length > 0) return false;
|
|
54
|
+
if (plan.source.openingElement.attributes.some(
|
|
55
|
+
(attribute) => types.isJSXAttribute(attribute) && types.isJSXIdentifier(attribute.name) && /^on[A-Z]/.test(attribute.name.name)
|
|
56
|
+
)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return plan.events.every(
|
|
60
|
+
(event) => DELEGATABLE_KEYED_ROW_EVENTS.has(event.name.replace(/Capture$/, ""))
|
|
61
|
+
);
|
|
62
|
+
}
|
|
7
63
|
var SAFE_GLOBAL_CALLS = /* @__PURE__ */ new Set(["Boolean", "Number", "String"]);
|
|
8
64
|
var SAFE_MATH_CALLS = /* @__PURE__ */ new Set(["abs", "ceil", "floor", "max", "min", "round", "sign", "trunc"]);
|
|
9
65
|
function isComponentName(name) {
|
|
@@ -88,6 +144,37 @@ function rewriteDestructuredPropAccess(expression, names, propsParameter) {
|
|
|
88
144
|
});
|
|
89
145
|
return file.program.body[0].expression;
|
|
90
146
|
}
|
|
147
|
+
function collectDestructuredPropNames(expression, names, propsParameter) {
|
|
148
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
149
|
+
if (names.size === 0) return referenced;
|
|
150
|
+
traverse(expressionFile(cloneExpression(expression)), {
|
|
151
|
+
MemberExpression(path) {
|
|
152
|
+
const { object, property, computed } = path.node;
|
|
153
|
+
if (computed || !types.isIdentifier(object, { name: propsParameter.name }) || !types.isIdentifier(property) || !names.has(property.name)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
referenced.add(property.name);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
return referenced;
|
|
160
|
+
}
|
|
161
|
+
function rewriteTrackedPropAccess(expression, propsParameter, bindingsByName) {
|
|
162
|
+
if (bindingsByName.size === 0) return cloneExpression(expression);
|
|
163
|
+
const file = expressionFile(cloneExpression(expression));
|
|
164
|
+
traverse(file, {
|
|
165
|
+
MemberExpression(path) {
|
|
166
|
+
const { object, property, computed } = path.node;
|
|
167
|
+
if (computed || !types.isIdentifier(object, { name: propsParameter.name }) || !types.isIdentifier(property)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const binding = bindingsByName.get(property.name);
|
|
171
|
+
if (!binding) return;
|
|
172
|
+
path.replaceWith(types.identifier(binding.valueName));
|
|
173
|
+
path.skip();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
return file.program.body[0].expression;
|
|
177
|
+
}
|
|
91
178
|
function rewriteHandlerAccess(root, handlersByName) {
|
|
92
179
|
if (handlersByName.size === 0) return { root: types.cloneNode(root, true) };
|
|
93
180
|
const file = expressionFile(types.cloneNode(root, true));
|
|
@@ -767,7 +854,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
767
854
|
const reason = visit(row, []);
|
|
768
855
|
return reason ? { reason } : { bindings, events, conditionals };
|
|
769
856
|
}
|
|
770
|
-
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames) {
|
|
857
|
+
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false) {
|
|
771
858
|
let collection;
|
|
772
859
|
let keyCallback;
|
|
773
860
|
let renderCallback;
|
|
@@ -822,17 +909,29 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames) {
|
|
|
822
909
|
safeGlobals,
|
|
823
910
|
new Set([...statesByValue.values()].map((state) => state.setterName))
|
|
824
911
|
);
|
|
825
|
-
if (rowAnalysis.reason) return void 0;
|
|
912
|
+
if (rowAnalysis.reason && !acceptUnsupportedRow) return void 0;
|
|
913
|
+
const keyExpression = returnedExpression(keyCallback);
|
|
914
|
+
const structureDependencies = new Set(collectStateDependencies(collection, statesByValue));
|
|
915
|
+
if (keyExpression) {
|
|
916
|
+
for (const dependency of collectStateDependencies(keyExpression, statesByValue)) {
|
|
917
|
+
structureDependencies.add(dependency);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
826
920
|
return {
|
|
827
921
|
source,
|
|
828
922
|
collection,
|
|
923
|
+
structureDependencies: [...structureDependencies].sort((left, right) => left - right),
|
|
829
924
|
keyCallback,
|
|
830
925
|
renderCallback,
|
|
831
926
|
row,
|
|
832
927
|
dependencies,
|
|
833
|
-
bindings: rowAnalysis.bindings || []
|
|
928
|
+
bindings: (rowAnalysis.bindings || []).map((binding) => ({
|
|
929
|
+
...binding,
|
|
930
|
+
dependencies: collectStateDependencies(binding.value, statesByValue)
|
|
931
|
+
})),
|
|
834
932
|
events: rowAnalysis.events || [],
|
|
835
933
|
conditionals: rowAnalysis.conditionals || [],
|
|
934
|
+
rowReason: rowAnalysis.reason,
|
|
836
935
|
syntax
|
|
837
936
|
};
|
|
838
937
|
}
|
|
@@ -849,22 +948,7 @@ function analyzeKeyedRowsContainer(container, statesByValue, safeGlobals, listNa
|
|
|
849
948
|
}
|
|
850
949
|
const children = meaningfulJsxChildren(container);
|
|
851
950
|
if (children.length !== 1) return void 0;
|
|
852
|
-
return analyzeKeyedRowChild(children[0], statesByValue, safeGlobals, listNames);
|
|
853
|
-
}
|
|
854
|
-
function isStaticRangeSibling(element, statesByValue, safeGlobals) {
|
|
855
|
-
for (const child of meaningfulJsxChildren(element)) {
|
|
856
|
-
if (types.isJSXFragment(child)) return false;
|
|
857
|
-
if (types.isJSXElement(child)) {
|
|
858
|
-
if (!isHostElement(child) || !isStaticRangeSibling(child, statesByValue, safeGlobals)) {
|
|
859
|
-
return false;
|
|
860
|
-
}
|
|
861
|
-
continue;
|
|
862
|
-
}
|
|
863
|
-
if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression) && !isTextExpression(child.expression, statesByValue, safeGlobals)) {
|
|
864
|
-
return false;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
return true;
|
|
951
|
+
return analyzeKeyedRowChild(children[0], statesByValue, safeGlobals, listNames, true);
|
|
868
952
|
}
|
|
869
953
|
function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, listNames, allowSingleRange = false) {
|
|
870
954
|
if (container.openingElement.attributes.some(
|
|
@@ -876,6 +960,7 @@ function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
876
960
|
if (children.length < (allowSingleRange ? 1 : 2)) return void 0;
|
|
877
961
|
const ranges = [];
|
|
878
962
|
const dependencies = /* @__PURE__ */ new Set();
|
|
963
|
+
const staticBindings = [];
|
|
879
964
|
let staticBefore = 0;
|
|
880
965
|
for (const child of children) {
|
|
881
966
|
const range = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames);
|
|
@@ -896,18 +981,31 @@ function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
896
981
|
continue;
|
|
897
982
|
}
|
|
898
983
|
if (!types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
899
|
-
|
|
984
|
+
const analysis = analyzeHostConditionalTree(child, safeGlobals, true, statesByValue);
|
|
985
|
+
if (analysis.reason) return void 0;
|
|
986
|
+
for (const binding of analysis.bindings || []) {
|
|
987
|
+
staticBindings.push({
|
|
988
|
+
...binding,
|
|
989
|
+
segment: ranges.length,
|
|
990
|
+
sibling: staticBefore
|
|
991
|
+
});
|
|
992
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
993
|
+
dependencies.add(dependency);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
900
996
|
staticBefore += 1;
|
|
901
997
|
}
|
|
902
998
|
if (ranges.length === 0) return void 0;
|
|
903
999
|
return {
|
|
904
1000
|
ranges,
|
|
905
1001
|
trailing: staticBefore,
|
|
906
|
-
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
1002
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1003
|
+
staticBindings
|
|
907
1004
|
};
|
|
908
1005
|
}
|
|
909
|
-
function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
1006
|
+
function analyzeHostConditionalTree(branch, safeGlobals, allowStaticEvents = false, statefulOnly) {
|
|
910
1007
|
const bindings = [];
|
|
1008
|
+
const needsStaticBinding = (expression) => !statefulOnly || collectStateDependencies(expression, statefulOnly).length > 0;
|
|
911
1009
|
const visit = (element, path) => {
|
|
912
1010
|
const tag = element.openingElement.name;
|
|
913
1011
|
if (!types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
@@ -916,20 +1014,26 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
916
1014
|
if (tag.name === "svg") return "compiler-owned conditionals do not support SVG yet";
|
|
917
1015
|
for (const attribute of element.openingElement.attributes) {
|
|
918
1016
|
if (types.isJSXSpreadAttribute(attribute)) {
|
|
1017
|
+
if (statefulOnly && !needsStaticBinding(attribute.argument)) continue;
|
|
919
1018
|
return "compiler-owned conditionals do not support JSX attribute spreads";
|
|
920
1019
|
}
|
|
921
1020
|
const name = jsxAttributeName(attribute);
|
|
922
1021
|
if (!name) return "compiler-owned conditionals do not support namespaced JSX attributes";
|
|
923
1022
|
if (name === "ref" || name === "dangerouslySetInnerHTML" || name === "key") {
|
|
1023
|
+
if (statefulOnly && (!types.isJSXExpressionContainer(attribute.value) || types.isJSXEmptyExpression(attribute.value.expression) || !needsStaticBinding(attribute.value.expression))) {
|
|
1024
|
+
continue;
|
|
1025
|
+
}
|
|
924
1026
|
return `compiler-owned conditional ${name} requires React ownership`;
|
|
925
1027
|
}
|
|
926
1028
|
if (/^on[A-Z]/.test(name)) {
|
|
1029
|
+
if (allowStaticEvents) continue;
|
|
927
1030
|
return "compiler-owned conditional events require React ownership";
|
|
928
1031
|
}
|
|
929
1032
|
if (!types.isJSXExpressionContainer(attribute.value) || types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
930
1033
|
continue;
|
|
931
1034
|
}
|
|
932
1035
|
const expression = attribute.value.expression;
|
|
1036
|
+
if (!needsStaticBinding(expression)) continue;
|
|
933
1037
|
if (name === "style") {
|
|
934
1038
|
if (!types.isObjectExpression(expression)) {
|
|
935
1039
|
return "compiler-owned conditional styles must use one inline object literal";
|
|
@@ -942,6 +1046,7 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
942
1046
|
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
943
1047
|
return "compiler-owned conditional style names must use camelCase or a CSS custom property";
|
|
944
1048
|
}
|
|
1049
|
+
if (!needsStaticBinding(property.value)) continue;
|
|
945
1050
|
const unsupported2 = validateDerivedExpression(property.value, safeGlobals);
|
|
946
1051
|
if (unsupported2) {
|
|
947
1052
|
return `compiler-owned conditional style ${propertyName} cannot use ${unsupported2}`;
|
|
@@ -976,14 +1081,20 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
976
1081
|
const expressions = element.children.filter(
|
|
977
1082
|
(child) => types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)
|
|
978
1083
|
);
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1084
|
+
const boundExpressions = statefulOnly ? expressions.filter((child) => needsStaticBinding(child.expression)) : expressions;
|
|
1085
|
+
if (boundExpressions.length > 0) {
|
|
1086
|
+
for (const child of expressions) {
|
|
1087
|
+
const unsupported = validateDerivedExpression(
|
|
1088
|
+
child.expression,
|
|
1089
|
+
safeGlobals
|
|
1090
|
+
);
|
|
1091
|
+
if (unsupported) return `compiler-owned conditional text cannot use ${unsupported}`;
|
|
1092
|
+
}
|
|
982
1093
|
}
|
|
983
|
-
if (nestedElements.length > 0 &&
|
|
1094
|
+
if (nestedElements.length > 0 && boundExpressions.length > 0) {
|
|
984
1095
|
return "compiler-owned conditionals do not support dynamic text beside nested elements yet";
|
|
985
1096
|
}
|
|
986
|
-
if (nestedElements.length === 0 &&
|
|
1097
|
+
if (nestedElements.length === 0 && boundExpressions.length > 0) {
|
|
987
1098
|
const parts = [];
|
|
988
1099
|
for (const child of element.children) {
|
|
989
1100
|
if (types.isJSXText(child)) {
|
|
@@ -1007,7 +1118,369 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
1007
1118
|
const reason = visit(branch, []);
|
|
1008
1119
|
return reason ? { reason } : { bindings };
|
|
1009
1120
|
}
|
|
1010
|
-
function
|
|
1121
|
+
function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1122
|
+
const bindings = [];
|
|
1123
|
+
const plans = [];
|
|
1124
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
1125
|
+
const visit = (element, path, owner) => {
|
|
1126
|
+
const tag = element.openingElement.name;
|
|
1127
|
+
if (!types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
1128
|
+
return "recursive compiler-owned blocks support host elements only";
|
|
1129
|
+
}
|
|
1130
|
+
if (tag.name === "svg") return "recursive compiler-owned blocks do not support SVG yet";
|
|
1131
|
+
for (const attribute of element.openingElement.attributes) {
|
|
1132
|
+
if (types.isJSXSpreadAttribute(attribute)) {
|
|
1133
|
+
return "recursive compiler-owned blocks do not support JSX attribute spreads";
|
|
1134
|
+
}
|
|
1135
|
+
const name = jsxAttributeName(attribute);
|
|
1136
|
+
if (!name) return "recursive compiler-owned blocks do not support namespaced attributes";
|
|
1137
|
+
if (name === "ref" || name === "dangerouslySetInnerHTML" || name === "key") {
|
|
1138
|
+
return `recursive compiler-owned block ${name} requires React ownership`;
|
|
1139
|
+
}
|
|
1140
|
+
if (/^on[A-Z]/.test(name)) {
|
|
1141
|
+
return "recursive compiler-owned block events require React ownership";
|
|
1142
|
+
}
|
|
1143
|
+
if (!types.isJSXExpressionContainer(attribute.value) || types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
const expression = attribute.value.expression;
|
|
1147
|
+
if (name === "style") {
|
|
1148
|
+
if (!types.isObjectExpression(expression)) {
|
|
1149
|
+
return "recursive compiler-owned styles must use one inline object literal";
|
|
1150
|
+
}
|
|
1151
|
+
for (const property of expression.properties) {
|
|
1152
|
+
if (!types.isObjectProperty(property) || property.computed || !types.isExpression(property.value)) {
|
|
1153
|
+
return "recursive compiler-owned styles do not support spreads, methods, or computed properties";
|
|
1154
|
+
}
|
|
1155
|
+
const propertyName = types.isIdentifier(property.key) ? property.key.name : types.isStringLiteral(property.key) ? property.key.value : void 0;
|
|
1156
|
+
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
1157
|
+
return "recursive compiler-owned style names must use camelCase or a CSS custom property";
|
|
1158
|
+
}
|
|
1159
|
+
const unsupported2 = validateDerivedExpression(property.value, safeGlobals);
|
|
1160
|
+
if (unsupported2) {
|
|
1161
|
+
return `recursive compiler-owned style ${propertyName} cannot use ${unsupported2}`;
|
|
1162
|
+
}
|
|
1163
|
+
bindings.push({
|
|
1164
|
+
kind: "style",
|
|
1165
|
+
path: [...path],
|
|
1166
|
+
name: propertyName,
|
|
1167
|
+
value: cloneExpression(property.value)
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
if (name === "children") {
|
|
1173
|
+
return "recursive compiler-owned children props are not supported yet";
|
|
1174
|
+
}
|
|
1175
|
+
const unsupported = validateDerivedExpression(expression, safeGlobals);
|
|
1176
|
+
if (unsupported) return `recursive compiler-owned ${name} cannot use ${unsupported}`;
|
|
1177
|
+
bindings.push({
|
|
1178
|
+
kind: "attribute",
|
|
1179
|
+
path: [...path],
|
|
1180
|
+
name,
|
|
1181
|
+
value: cloneExpression(expression)
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
const children = meaningfulJsxChildren(element);
|
|
1185
|
+
const hasConditionalRange = children.some(
|
|
1186
|
+
(child) => types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression) && conditionalBlockShape(child.expression) !== null
|
|
1187
|
+
);
|
|
1188
|
+
const hasKeyedRange = children.some(
|
|
1189
|
+
(child) => analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true) !== void 0
|
|
1190
|
+
);
|
|
1191
|
+
if (hasConditionalRange && hasKeyedRange) {
|
|
1192
|
+
const id = allocateId();
|
|
1193
|
+
const mixed = analyzeMixedRangesContainer(
|
|
1194
|
+
element,
|
|
1195
|
+
statesByValue,
|
|
1196
|
+
safeGlobals,
|
|
1197
|
+
listNames,
|
|
1198
|
+
id,
|
|
1199
|
+
allocateId
|
|
1200
|
+
);
|
|
1201
|
+
if (mixed) {
|
|
1202
|
+
plans.push(...mixed.nestedPlans);
|
|
1203
|
+
for (const [nestedElement, plan2] of mixed.descriptorBlocks) {
|
|
1204
|
+
blocks.set(nestedElement, plan2);
|
|
1205
|
+
}
|
|
1206
|
+
const plan = {
|
|
1207
|
+
kind: "nested-host-mixed-ranges",
|
|
1208
|
+
id,
|
|
1209
|
+
parent: owner,
|
|
1210
|
+
dependencies: mixed.dependencies,
|
|
1211
|
+
source: element,
|
|
1212
|
+
ranges: mixed.ranges,
|
|
1213
|
+
trailing: mixed.trailing,
|
|
1214
|
+
staticBindings: mixed.staticBindings
|
|
1215
|
+
};
|
|
1216
|
+
plans.push(plan);
|
|
1217
|
+
blocks.set(element, plan);
|
|
1218
|
+
return void 0;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
const conditionalChildren = /* @__PURE__ */ new Map();
|
|
1222
|
+
let conditionalContainer = children.length > 0;
|
|
1223
|
+
for (const child of children) {
|
|
1224
|
+
if (types.isJSXElement(child) && isHostElement(child)) continue;
|
|
1225
|
+
if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)) {
|
|
1226
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1227
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1228
|
+
conditionalChildren.set(child.expression, shape);
|
|
1229
|
+
continue;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
conditionalContainer = false;
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
if (conditionalContainer && conditionalChildren.size > 0) {
|
|
1236
|
+
const id = allocateId();
|
|
1237
|
+
const ranges = [];
|
|
1238
|
+
const staticBindings = [];
|
|
1239
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1240
|
+
let staticBefore2 = 0;
|
|
1241
|
+
for (const child of children) {
|
|
1242
|
+
if (types.isJSXElement(child)) {
|
|
1243
|
+
const nested = analyzeRecursiveHostTree(
|
|
1244
|
+
child,
|
|
1245
|
+
statesByValue,
|
|
1246
|
+
safeGlobals,
|
|
1247
|
+
listNames,
|
|
1248
|
+
owner,
|
|
1249
|
+
allocateId
|
|
1250
|
+
);
|
|
1251
|
+
if (nested.reason) return nested.reason;
|
|
1252
|
+
plans.push(...nested.plans);
|
|
1253
|
+
for (const [nestedElement, plan2] of nested.blocks) blocks.set(nestedElement, plan2);
|
|
1254
|
+
for (const binding of nested.bindings) {
|
|
1255
|
+
staticBindings.push({
|
|
1256
|
+
...binding,
|
|
1257
|
+
segment: ranges.length,
|
|
1258
|
+
sibling: staticBefore2
|
|
1259
|
+
});
|
|
1260
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1261
|
+
dependencies.add(dependency);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
staticBefore2 += 1;
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
if (!types.isJSXExpressionContainer(child) || types.isJSXEmptyExpression(child.expression)) {
|
|
1268
|
+
return "recursive conditional ranges contain an unsupported child";
|
|
1269
|
+
}
|
|
1270
|
+
const expression = child.expression;
|
|
1271
|
+
const shape = conditionalChildren.get(expression);
|
|
1272
|
+
const truthy = shape.truthy ? analyzeRecursiveHostTree(
|
|
1273
|
+
shape.truthy,
|
|
1274
|
+
statesByValue,
|
|
1275
|
+
safeGlobals,
|
|
1276
|
+
listNames,
|
|
1277
|
+
id,
|
|
1278
|
+
allocateId
|
|
1279
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1280
|
+
const falsy = shape.falsy ? analyzeRecursiveHostTree(
|
|
1281
|
+
shape.falsy,
|
|
1282
|
+
statesByValue,
|
|
1283
|
+
safeGlobals,
|
|
1284
|
+
listNames,
|
|
1285
|
+
id,
|
|
1286
|
+
allocateId
|
|
1287
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1288
|
+
if (truthy.reason) return truthy.reason;
|
|
1289
|
+
if (falsy.reason) return falsy.reason;
|
|
1290
|
+
plans.push(...truthy.plans, ...falsy.plans);
|
|
1291
|
+
for (const [nestedElement, plan2] of truthy.blocks) blocks.set(nestedElement, plan2);
|
|
1292
|
+
for (const [nestedElement, plan2] of falsy.blocks) blocks.set(nestedElement, plan2);
|
|
1293
|
+
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1294
|
+
dependencies.add(dependency);
|
|
1295
|
+
}
|
|
1296
|
+
for (const binding of [...truthy.bindings, ...falsy.bindings]) {
|
|
1297
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1298
|
+
dependencies.add(dependency);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
ranges.push({
|
|
1302
|
+
before: staticBefore2,
|
|
1303
|
+
source: expression,
|
|
1304
|
+
test: cloneExpression(shape.test),
|
|
1305
|
+
logical: shape.logical,
|
|
1306
|
+
truthy: shape.truthy,
|
|
1307
|
+
falsy: shape.falsy,
|
|
1308
|
+
truthyBindings: truthy.bindings,
|
|
1309
|
+
falsyBindings: falsy.bindings
|
|
1310
|
+
});
|
|
1311
|
+
staticBefore2 = 0;
|
|
1312
|
+
}
|
|
1313
|
+
const plan = {
|
|
1314
|
+
kind: "nested-host-conditional-ranges",
|
|
1315
|
+
id,
|
|
1316
|
+
parent: owner,
|
|
1317
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1318
|
+
source: element,
|
|
1319
|
+
ranges,
|
|
1320
|
+
trailing: staticBefore2,
|
|
1321
|
+
staticBindings
|
|
1322
|
+
};
|
|
1323
|
+
plans.push(plan);
|
|
1324
|
+
blocks.set(element, plan);
|
|
1325
|
+
return void 0;
|
|
1326
|
+
}
|
|
1327
|
+
const keyedRows = [];
|
|
1328
|
+
let keyedContainer = children.length > 0;
|
|
1329
|
+
let staticBefore = 0;
|
|
1330
|
+
const staticChildren = [];
|
|
1331
|
+
for (const child of children) {
|
|
1332
|
+
const range = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true);
|
|
1333
|
+
if (range) {
|
|
1334
|
+
keyedRows.push({ before: staticBefore, range });
|
|
1335
|
+
staticBefore = 0;
|
|
1336
|
+
} else if (types.isJSXElement(child) && isHostElement(child)) {
|
|
1337
|
+
staticChildren.push({
|
|
1338
|
+
element: child,
|
|
1339
|
+
segment: keyedRows.length,
|
|
1340
|
+
sibling: staticBefore
|
|
1341
|
+
});
|
|
1342
|
+
staticBefore += 1;
|
|
1343
|
+
} else {
|
|
1344
|
+
keyedContainer = false;
|
|
1345
|
+
break;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
if (keyedContainer && keyedRows.length > 0) {
|
|
1349
|
+
const id = allocateId();
|
|
1350
|
+
const keyedRanges = [];
|
|
1351
|
+
const staticBindings = [];
|
|
1352
|
+
const keyedDependencies = /* @__PURE__ */ new Set();
|
|
1353
|
+
for (const { before, range } of keyedRows) {
|
|
1354
|
+
if (range.events.length > 0) {
|
|
1355
|
+
return "recursive compiler-owned keyed rows cannot contain events";
|
|
1356
|
+
}
|
|
1357
|
+
const row = types.cloneNode(range.row, true);
|
|
1358
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1359
|
+
(attribute) => !types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1360
|
+
);
|
|
1361
|
+
const rowAnalysis = analyzeRecursiveHostTree(
|
|
1362
|
+
row,
|
|
1363
|
+
statesByValue,
|
|
1364
|
+
safeGlobals,
|
|
1365
|
+
listNames,
|
|
1366
|
+
id,
|
|
1367
|
+
allocateId
|
|
1368
|
+
);
|
|
1369
|
+
if (rowAnalysis.reason) return rowAnalysis.reason;
|
|
1370
|
+
plans.push(...rowAnalysis.plans);
|
|
1371
|
+
for (const [nestedElement, nestedPlan] of rowAnalysis.blocks) {
|
|
1372
|
+
blocks.set(nestedElement, nestedPlan);
|
|
1373
|
+
}
|
|
1374
|
+
keyedRanges.push({
|
|
1375
|
+
before,
|
|
1376
|
+
source: range.source,
|
|
1377
|
+
collection: range.collection,
|
|
1378
|
+
keyCallback: range.keyCallback,
|
|
1379
|
+
renderCallback: range.renderCallback,
|
|
1380
|
+
row,
|
|
1381
|
+
bindings: rowAnalysis.bindings,
|
|
1382
|
+
syntax: range.syntax
|
|
1383
|
+
});
|
|
1384
|
+
for (const dependency of range.dependencies) keyedDependencies.add(dependency);
|
|
1385
|
+
}
|
|
1386
|
+
for (const { element: child, segment, sibling } of staticChildren) {
|
|
1387
|
+
const nested = analyzeRecursiveHostTree(
|
|
1388
|
+
child,
|
|
1389
|
+
statesByValue,
|
|
1390
|
+
safeGlobals,
|
|
1391
|
+
listNames,
|
|
1392
|
+
owner,
|
|
1393
|
+
allocateId
|
|
1394
|
+
);
|
|
1395
|
+
if (nested.reason) return nested.reason;
|
|
1396
|
+
plans.push(...nested.plans);
|
|
1397
|
+
for (const [nestedElement, plan2] of nested.blocks) blocks.set(nestedElement, plan2);
|
|
1398
|
+
for (const binding of nested.bindings) {
|
|
1399
|
+
staticBindings.push({ ...binding, segment, sibling });
|
|
1400
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1401
|
+
keyedDependencies.add(dependency);
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
const plan = {
|
|
1406
|
+
kind: "nested-host-keyed-ranges",
|
|
1407
|
+
id,
|
|
1408
|
+
parent: owner,
|
|
1409
|
+
dependencies: [...keyedDependencies].sort((left, right) => left - right),
|
|
1410
|
+
source: element,
|
|
1411
|
+
ranges: keyedRanges,
|
|
1412
|
+
trailing: staticBefore,
|
|
1413
|
+
staticBindings
|
|
1414
|
+
};
|
|
1415
|
+
plans.push(plan);
|
|
1416
|
+
blocks.set(element, plan);
|
|
1417
|
+
return void 0;
|
|
1418
|
+
}
|
|
1419
|
+
if (element.children.some((child) => types.isJSXFragment(child))) {
|
|
1420
|
+
return "recursive compiler-owned blocks do not support fragments yet";
|
|
1421
|
+
}
|
|
1422
|
+
const nestedElements = element.children.filter(
|
|
1423
|
+
(child) => types.isJSXElement(child)
|
|
1424
|
+
);
|
|
1425
|
+
const expressions = element.children.filter(
|
|
1426
|
+
(child) => types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)
|
|
1427
|
+
);
|
|
1428
|
+
for (const child of expressions) {
|
|
1429
|
+
const unsupported = validateDerivedExpression(child.expression, safeGlobals);
|
|
1430
|
+
if (unsupported) return `recursive compiler-owned text cannot use ${unsupported}`;
|
|
1431
|
+
}
|
|
1432
|
+
if (nestedElements.length > 0 && expressions.length > 0) {
|
|
1433
|
+
return "recursive compiler-owned blocks do not support dynamic text beside nested elements";
|
|
1434
|
+
}
|
|
1435
|
+
if (nestedElements.length === 0 && expressions.length > 0) {
|
|
1436
|
+
const parts = [];
|
|
1437
|
+
for (const child of element.children) {
|
|
1438
|
+
if (types.isJSXText(child)) {
|
|
1439
|
+
const text = cleanJsxText(child.value);
|
|
1440
|
+
if (text) parts.push(types.stringLiteral(text));
|
|
1441
|
+
} else if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)) {
|
|
1442
|
+
parts.push(cloneExpression(child.expression));
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
bindings.push({ kind: "text", path: [...path], value: types.arrayExpression(parts) });
|
|
1446
|
+
}
|
|
1447
|
+
let elementIndex = 0;
|
|
1448
|
+
for (const child of element.children) {
|
|
1449
|
+
if (!types.isJSXElement(child)) continue;
|
|
1450
|
+
const reason2 = visit(child, [...path, elementIndex], owner);
|
|
1451
|
+
if (reason2) return reason2;
|
|
1452
|
+
elementIndex += 1;
|
|
1453
|
+
}
|
|
1454
|
+
return void 0;
|
|
1455
|
+
};
|
|
1456
|
+
const reason = visit(branch, [], parent);
|
|
1457
|
+
return { bindings, plans, blocks, reason };
|
|
1458
|
+
}
|
|
1459
|
+
function analyzeCompilerOwnedKeyedRowHostBlocks(shape, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1460
|
+
if (shape.events.length > 0) return void 0;
|
|
1461
|
+
const row = types.cloneNode(shape.row, true);
|
|
1462
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1463
|
+
(attribute) => !types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1464
|
+
);
|
|
1465
|
+
const analysis = analyzeRecursiveHostTree(
|
|
1466
|
+
row,
|
|
1467
|
+
statesByValue,
|
|
1468
|
+
safeGlobals,
|
|
1469
|
+
listNames,
|
|
1470
|
+
parent,
|
|
1471
|
+
allocateId
|
|
1472
|
+
);
|
|
1473
|
+
if (analysis.reason || analysis.plans.length === 0) {
|
|
1474
|
+
return void 0;
|
|
1475
|
+
}
|
|
1476
|
+
return {
|
|
1477
|
+
row,
|
|
1478
|
+
bindings: analysis.bindings,
|
|
1479
|
+
descriptorBlocks: analysis.blocks,
|
|
1480
|
+
nestedPlans: analysis.plans
|
|
1481
|
+
};
|
|
1482
|
+
}
|
|
1483
|
+
function analyzeHostConditionalContainer(container, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1011
1484
|
const containerName = container.openingElement.name;
|
|
1012
1485
|
if (!types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg") {
|
|
1013
1486
|
return void 0;
|
|
@@ -1029,8 +1502,22 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals)
|
|
|
1029
1502
|
}
|
|
1030
1503
|
const shape = conditionalBlockShape(children[0].expression);
|
|
1031
1504
|
if (!shape || validateDerivedExpression(shape.test, safeGlobals)) return void 0;
|
|
1032
|
-
const truthyAnalysis = shape.truthy ?
|
|
1033
|
-
|
|
1505
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1506
|
+
shape.truthy,
|
|
1507
|
+
statesByValue,
|
|
1508
|
+
safeGlobals,
|
|
1509
|
+
listNames,
|
|
1510
|
+
parent,
|
|
1511
|
+
allocateId
|
|
1512
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1513
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1514
|
+
shape.falsy,
|
|
1515
|
+
statesByValue,
|
|
1516
|
+
safeGlobals,
|
|
1517
|
+
listNames,
|
|
1518
|
+
parent,
|
|
1519
|
+
allocateId
|
|
1520
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1034
1521
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1035
1522
|
const dependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1036
1523
|
for (const binding of [...truthyAnalysis.bindings || [], ...falsyAnalysis.bindings || []]) {
|
|
@@ -1045,10 +1532,12 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals)
|
|
|
1045
1532
|
truthy: shape.truthy,
|
|
1046
1533
|
falsy: shape.falsy,
|
|
1047
1534
|
truthyBindings: truthyAnalysis.bindings || [],
|
|
1048
|
-
falsyBindings: falsyAnalysis.bindings || []
|
|
1535
|
+
falsyBindings: falsyAnalysis.bindings || [],
|
|
1536
|
+
descriptorBlocks: new Map([...truthyAnalysis.blocks, ...falsyAnalysis.blocks]),
|
|
1537
|
+
nestedPlans: [...truthyAnalysis.plans, ...falsyAnalysis.plans]
|
|
1049
1538
|
};
|
|
1050
1539
|
}
|
|
1051
|
-
function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals, allowSingleRange
|
|
1540
|
+
function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals, allowSingleRange, listNames, parent, allocateId) {
|
|
1052
1541
|
const containerName = container.openingElement.name;
|
|
1053
1542
|
if (!types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg" || container.openingElement.attributes.some(
|
|
1054
1543
|
(attribute) => types.isJSXSpreadAttribute(attribute) || types.isJSXAttribute(attribute) && types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
@@ -1059,14 +1548,34 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1059
1548
|
if (children.length < (allowSingleRange ? 1 : 2)) return void 0;
|
|
1060
1549
|
const ranges = [];
|
|
1061
1550
|
const dependencies = /* @__PURE__ */ new Set();
|
|
1551
|
+
const descriptorBlocks = /* @__PURE__ */ new Map();
|
|
1552
|
+
const nestedPlans = [];
|
|
1553
|
+
const staticBindings = [];
|
|
1062
1554
|
let staticBefore = 0;
|
|
1063
1555
|
for (const child of children) {
|
|
1064
1556
|
if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)) {
|
|
1065
1557
|
const shape = conditionalBlockShape(child.expression);
|
|
1066
1558
|
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1067
|
-
const truthyAnalysis = shape.truthy ?
|
|
1068
|
-
|
|
1559
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1560
|
+
shape.truthy,
|
|
1561
|
+
statesByValue,
|
|
1562
|
+
safeGlobals,
|
|
1563
|
+
listNames,
|
|
1564
|
+
parent,
|
|
1565
|
+
allocateId
|
|
1566
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1567
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1568
|
+
shape.falsy,
|
|
1569
|
+
statesByValue,
|
|
1570
|
+
safeGlobals,
|
|
1571
|
+
listNames,
|
|
1572
|
+
parent,
|
|
1573
|
+
allocateId
|
|
1574
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1069
1575
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1576
|
+
nestedPlans.push(...truthyAnalysis.plans, ...falsyAnalysis.plans);
|
|
1577
|
+
for (const [element, plan] of truthyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
1578
|
+
for (const [element, plan] of falsyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
1070
1579
|
const rangeDependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1071
1580
|
for (const binding of [
|
|
1072
1581
|
...truthyAnalysis.bindings || [],
|
|
@@ -1092,14 +1601,158 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1092
1601
|
}
|
|
1093
1602
|
}
|
|
1094
1603
|
if (!types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
1095
|
-
|
|
1604
|
+
const staticAnalysis = analyzeHostConditionalTree(child, safeGlobals, true, statesByValue);
|
|
1605
|
+
if (staticAnalysis.reason) return void 0;
|
|
1606
|
+
for (const binding of staticAnalysis.bindings || []) {
|
|
1607
|
+
staticBindings.push({
|
|
1608
|
+
...binding,
|
|
1609
|
+
segment: ranges.length,
|
|
1610
|
+
sibling: staticBefore
|
|
1611
|
+
});
|
|
1612
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1613
|
+
dependencies.add(dependency);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1096
1616
|
staticBefore += 1;
|
|
1097
1617
|
}
|
|
1098
1618
|
if (ranges.length === 0) return void 0;
|
|
1099
1619
|
return {
|
|
1100
1620
|
ranges,
|
|
1101
1621
|
trailing: staticBefore,
|
|
1102
|
-
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
1622
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1623
|
+
staticBindings,
|
|
1624
|
+
descriptorBlocks,
|
|
1625
|
+
nestedPlans
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1629
|
+
const containerName = container.openingElement.name;
|
|
1630
|
+
if (!types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg" || container.openingElement.attributes.some(
|
|
1631
|
+
(attribute) => types.isJSXSpreadAttribute(attribute) || types.isJSXAttribute(attribute) && types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
1632
|
+
)) {
|
|
1633
|
+
return void 0;
|
|
1634
|
+
}
|
|
1635
|
+
const children = meaningfulJsxChildren(container);
|
|
1636
|
+
if (children.length < 2) return void 0;
|
|
1637
|
+
const ranges = [];
|
|
1638
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1639
|
+
const descriptorBlocks = /* @__PURE__ */ new Map();
|
|
1640
|
+
const nestedPlans = [];
|
|
1641
|
+
const staticBindings = [];
|
|
1642
|
+
let conditionalCount = 0;
|
|
1643
|
+
let keyedCount = 0;
|
|
1644
|
+
let staticBefore = 0;
|
|
1645
|
+
const mergeAnalysis = (analysis) => {
|
|
1646
|
+
if (analysis.reason) return false;
|
|
1647
|
+
nestedPlans.push(...analysis.plans);
|
|
1648
|
+
for (const [element, plan] of analysis.blocks) descriptorBlocks.set(element, plan);
|
|
1649
|
+
for (const binding of analysis.bindings) {
|
|
1650
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1651
|
+
dependencies.add(dependency);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
return true;
|
|
1655
|
+
};
|
|
1656
|
+
for (const child of children) {
|
|
1657
|
+
if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)) {
|
|
1658
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1659
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1660
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1661
|
+
shape.truthy,
|
|
1662
|
+
statesByValue,
|
|
1663
|
+
safeGlobals,
|
|
1664
|
+
listNames,
|
|
1665
|
+
parent,
|
|
1666
|
+
allocateId
|
|
1667
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1668
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1669
|
+
shape.falsy,
|
|
1670
|
+
statesByValue,
|
|
1671
|
+
safeGlobals,
|
|
1672
|
+
listNames,
|
|
1673
|
+
parent,
|
|
1674
|
+
allocateId
|
|
1675
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1676
|
+
if (!mergeAnalysis(truthyAnalysis) || !mergeAnalysis(falsyAnalysis)) return void 0;
|
|
1677
|
+
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1678
|
+
dependencies.add(dependency);
|
|
1679
|
+
}
|
|
1680
|
+
ranges.push({
|
|
1681
|
+
rangeKind: "conditional",
|
|
1682
|
+
before: staticBefore,
|
|
1683
|
+
source: child.expression,
|
|
1684
|
+
test: cloneExpression(shape.test),
|
|
1685
|
+
logical: shape.logical,
|
|
1686
|
+
truthy: shape.truthy,
|
|
1687
|
+
falsy: shape.falsy,
|
|
1688
|
+
truthyBindings: truthyAnalysis.bindings,
|
|
1689
|
+
falsyBindings: falsyAnalysis.bindings
|
|
1690
|
+
});
|
|
1691
|
+
conditionalCount += 1;
|
|
1692
|
+
staticBefore = 0;
|
|
1693
|
+
continue;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
const keyed = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true);
|
|
1697
|
+
if (keyed) {
|
|
1698
|
+
if (keyed.events.length > 0) return void 0;
|
|
1699
|
+
const row = types.cloneNode(keyed.row, true);
|
|
1700
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1701
|
+
(attribute) => !types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1702
|
+
);
|
|
1703
|
+
const rowAnalysis = analyzeRecursiveHostTree(
|
|
1704
|
+
row,
|
|
1705
|
+
statesByValue,
|
|
1706
|
+
safeGlobals,
|
|
1707
|
+
listNames,
|
|
1708
|
+
parent,
|
|
1709
|
+
allocateId
|
|
1710
|
+
);
|
|
1711
|
+
if (!mergeAnalysis(rowAnalysis)) return void 0;
|
|
1712
|
+
for (const dependency of keyed.dependencies) dependencies.add(dependency);
|
|
1713
|
+
ranges.push({
|
|
1714
|
+
rangeKind: "keyed",
|
|
1715
|
+
before: staticBefore,
|
|
1716
|
+
source: keyed.source,
|
|
1717
|
+
collection: keyed.collection,
|
|
1718
|
+
keyCallback: keyed.keyCallback,
|
|
1719
|
+
renderCallback: keyed.renderCallback,
|
|
1720
|
+
row,
|
|
1721
|
+
bindings: rowAnalysis.bindings,
|
|
1722
|
+
syntax: keyed.syntax
|
|
1723
|
+
});
|
|
1724
|
+
keyedCount += 1;
|
|
1725
|
+
staticBefore = 0;
|
|
1726
|
+
continue;
|
|
1727
|
+
}
|
|
1728
|
+
if (!types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
1729
|
+
const staticAnalysis = analyzeRecursiveHostTree(
|
|
1730
|
+
child,
|
|
1731
|
+
statesByValue,
|
|
1732
|
+
safeGlobals,
|
|
1733
|
+
listNames,
|
|
1734
|
+
parent,
|
|
1735
|
+
allocateId
|
|
1736
|
+
);
|
|
1737
|
+
if (staticAnalysis.reason) return void 0;
|
|
1738
|
+
for (const binding of staticAnalysis.bindings) {
|
|
1739
|
+
staticBindings.push({
|
|
1740
|
+
...binding,
|
|
1741
|
+
segment: ranges.length,
|
|
1742
|
+
sibling: staticBefore
|
|
1743
|
+
});
|
|
1744
|
+
}
|
|
1745
|
+
if (!mergeAnalysis(staticAnalysis)) return void 0;
|
|
1746
|
+
staticBefore += 1;
|
|
1747
|
+
}
|
|
1748
|
+
if (conditionalCount === 0 || keyedCount === 0) return void 0;
|
|
1749
|
+
return {
|
|
1750
|
+
ranges,
|
|
1751
|
+
trailing: staticBefore,
|
|
1752
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1753
|
+
staticBindings,
|
|
1754
|
+
descriptorBlocks,
|
|
1755
|
+
nestedPlans
|
|
1103
1756
|
};
|
|
1104
1757
|
}
|
|
1105
1758
|
function keyedListBoundary(blockRuntime, plan, source) {
|
|
@@ -1124,14 +1777,14 @@ function keyedListBoundary(blockRuntime, plan, source) {
|
|
|
1124
1777
|
true
|
|
1125
1778
|
);
|
|
1126
1779
|
}
|
|
1127
|
-
function hostElementDescriptor(element) {
|
|
1780
|
+
function hostElementDescriptor(element, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1128
1781
|
const tag = element.openingElement.name;
|
|
1129
1782
|
const attributes = [];
|
|
1130
1783
|
const styles = [];
|
|
1131
1784
|
for (const attribute of element.openingElement.attributes) {
|
|
1132
1785
|
if (!types.isJSXAttribute(attribute)) continue;
|
|
1133
1786
|
const name = jsxAttributeName(attribute);
|
|
1134
|
-
if (!name || name === "key" || /^on[A-Z]/.test(name)) continue;
|
|
1787
|
+
if (!name || name === "key" || name === "ref" || /^on[A-Z]/.test(name)) continue;
|
|
1135
1788
|
if (name === "style") {
|
|
1136
1789
|
if (types.isJSXExpressionContainer(attribute.value) && types.isObjectExpression(attribute.value.expression)) {
|
|
1137
1790
|
for (const property of attribute.value.expression.properties) {
|
|
@@ -1155,24 +1808,93 @@ function hostElementDescriptor(element) {
|
|
|
1155
1808
|
])
|
|
1156
1809
|
);
|
|
1157
1810
|
}
|
|
1811
|
+
const block = descriptorBlocks.get(element);
|
|
1812
|
+
const conditionalBySource = /* @__PURE__ */ new Map();
|
|
1813
|
+
const keyedBySource = /* @__PURE__ */ new Map();
|
|
1814
|
+
if (block?.kind === "nested-host-conditional-ranges") {
|
|
1815
|
+
for (const range of block.ranges) conditionalBySource.set(range.source, range);
|
|
1816
|
+
} else if (block?.kind === "nested-host-keyed-ranges") {
|
|
1817
|
+
for (const range of block.ranges) keyedBySource.set(range.source, range);
|
|
1818
|
+
} else if (block?.kind === "nested-host-mixed-ranges") {
|
|
1819
|
+
for (const range of block.ranges) {
|
|
1820
|
+
if (range.rangeKind === "conditional") conditionalBySource.set(range.source, range);
|
|
1821
|
+
else keyedBySource.set(range.source, range);
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1158
1824
|
const children = [];
|
|
1159
1825
|
for (const child of element.children) {
|
|
1160
1826
|
if (types.isJSXText(child)) {
|
|
1161
1827
|
const text = cleanJsxText(child.value);
|
|
1162
1828
|
if (text) children.push(types.stringLiteral(text));
|
|
1163
1829
|
} else if (types.isJSXElement(child)) {
|
|
1164
|
-
|
|
1830
|
+
const keyedRange = keyedBySource.get(child);
|
|
1831
|
+
if (keyedRange) {
|
|
1832
|
+
if (block?.kind !== "nested-host-keyed-ranges") {
|
|
1833
|
+
children.push(keyedRangeDescriptorChildren(keyedRange, descriptorBlocks));
|
|
1834
|
+
}
|
|
1835
|
+
} else {
|
|
1836
|
+
children.push(hostElementDescriptor(child, descriptorBlocks));
|
|
1837
|
+
}
|
|
1165
1838
|
} else if (types.isJSXExpressionContainer(child) && !types.isJSXEmptyExpression(child.expression)) {
|
|
1166
|
-
|
|
1839
|
+
const conditionalRange = conditionalBySource.get(child.expression);
|
|
1840
|
+
const keyedRange = keyedBySource.get(child.expression);
|
|
1841
|
+
if (conditionalRange) {
|
|
1842
|
+
children.push(conditionalRangeDescriptorChild(conditionalRange, descriptorBlocks));
|
|
1843
|
+
} else if (keyedRange) {
|
|
1844
|
+
if (block?.kind !== "nested-host-keyed-ranges") {
|
|
1845
|
+
children.push(keyedRangeDescriptorChildren(keyedRange, descriptorBlocks));
|
|
1846
|
+
}
|
|
1847
|
+
} else {
|
|
1848
|
+
children.push(cloneExpression(child.expression));
|
|
1849
|
+
}
|
|
1167
1850
|
}
|
|
1168
1851
|
}
|
|
1169
|
-
|
|
1852
|
+
const properties = [
|
|
1170
1853
|
types.objectProperty(types.identifier("kind"), types.stringLiteral("element")),
|
|
1171
1854
|
types.objectProperty(types.identifier("tag"), types.stringLiteral(tag.name)),
|
|
1172
1855
|
types.objectProperty(types.identifier("attributes"), types.arrayExpression(attributes)),
|
|
1173
1856
|
types.objectProperty(types.identifier("styles"), types.arrayExpression(styles)),
|
|
1174
1857
|
types.objectProperty(types.identifier("children"), types.arrayExpression(children))
|
|
1175
|
-
]
|
|
1858
|
+
];
|
|
1859
|
+
if (block) {
|
|
1860
|
+
properties.push(
|
|
1861
|
+
types.objectProperty(types.identifier("block"), nestedHostBlockObject(block, descriptorBlocks))
|
|
1862
|
+
);
|
|
1863
|
+
}
|
|
1864
|
+
return types.objectExpression(properties);
|
|
1865
|
+
}
|
|
1866
|
+
function conditionalRangeDescriptorChild(range, descriptorBlocks) {
|
|
1867
|
+
const truthy = range.truthy ? hostElementDescriptor(range.truthy, descriptorBlocks) : types.nullLiteral();
|
|
1868
|
+
if (range.logical) {
|
|
1869
|
+
return types.logicalExpression("&&", cloneExpression(range.test), truthy);
|
|
1870
|
+
}
|
|
1871
|
+
return types.conditionalExpression(
|
|
1872
|
+
cloneExpression(range.test),
|
|
1873
|
+
truthy,
|
|
1874
|
+
range.falsy ? hostElementDescriptor(range.falsy, descriptorBlocks) : types.nullLiteral()
|
|
1875
|
+
);
|
|
1876
|
+
}
|
|
1877
|
+
function keyedRangeDescriptorChildren(range, descriptorBlocks) {
|
|
1878
|
+
const parameters = range.renderCallback.params.map(
|
|
1879
|
+
(parameter) => types.cloneNode(parameter, true)
|
|
1880
|
+
);
|
|
1881
|
+
const callback = types.arrowFunctionExpression(
|
|
1882
|
+
parameters,
|
|
1883
|
+
hostElementDescriptor(range.row, descriptorBlocks)
|
|
1884
|
+
);
|
|
1885
|
+
const collection = cloneExpression(range.collection);
|
|
1886
|
+
if (range.syntax === "map") {
|
|
1887
|
+
return types.callExpression(types.memberExpression(collection, types.identifier("map")), [callback]);
|
|
1888
|
+
}
|
|
1889
|
+
return types.callExpression(
|
|
1890
|
+
types.memberExpression(
|
|
1891
|
+
types.callExpression(types.memberExpression(types.identifier("Array"), types.identifier("from")), [
|
|
1892
|
+
types.logicalExpression("||", collection, types.arrayExpression([]))
|
|
1893
|
+
]),
|
|
1894
|
+
types.identifier("map")
|
|
1895
|
+
),
|
|
1896
|
+
[callback]
|
|
1897
|
+
);
|
|
1176
1898
|
}
|
|
1177
1899
|
function keyedRowBindingObject(binding, parameters) {
|
|
1178
1900
|
const properties = [
|
|
@@ -1180,6 +1902,12 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1180
1902
|
types.objectProperty(
|
|
1181
1903
|
types.identifier("path"),
|
|
1182
1904
|
types.arrayExpression(binding.path.map((part) => types.numericLiteral(part)))
|
|
1905
|
+
),
|
|
1906
|
+
types.objectProperty(
|
|
1907
|
+
types.identifier("dependencies"),
|
|
1908
|
+
types.arrayExpression(
|
|
1909
|
+
(binding.dependencies || []).map((dependency) => types.numericLiteral(dependency))
|
|
1910
|
+
)
|
|
1183
1911
|
)
|
|
1184
1912
|
];
|
|
1185
1913
|
if (binding.name) {
|
|
@@ -1196,6 +1924,16 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1196
1924
|
);
|
|
1197
1925
|
return types.objectExpression(properties);
|
|
1198
1926
|
}
|
|
1927
|
+
function staticRangeBindingObject(binding) {
|
|
1928
|
+
const value = keyedRowBindingObject(binding, []);
|
|
1929
|
+
value.properties.splice(
|
|
1930
|
+
1,
|
|
1931
|
+
0,
|
|
1932
|
+
types.objectProperty(types.identifier("segment"), types.numericLiteral(binding.segment)),
|
|
1933
|
+
types.objectProperty(types.identifier("sibling"), types.numericLiteral(binding.sibling))
|
|
1934
|
+
);
|
|
1935
|
+
return value;
|
|
1936
|
+
}
|
|
1199
1937
|
function uniqueLocalIdentifier(base, nodes) {
|
|
1200
1938
|
const names = /* @__PURE__ */ new Set();
|
|
1201
1939
|
for (const node of nodes) {
|
|
@@ -1312,6 +2050,10 @@ function keyedRowEventObject(event, renderParameters) {
|
|
|
1312
2050
|
const parameters = [types.cloneNode(renderParameters[0], true), index, syntheticEvent];
|
|
1313
2051
|
return types.objectExpression([
|
|
1314
2052
|
types.objectProperty(types.identifier("name"), types.stringLiteral(event.name)),
|
|
2053
|
+
types.objectProperty(
|
|
2054
|
+
types.identifier("path"),
|
|
2055
|
+
types.arrayExpression(event.path.map((part) => types.numericLiteral(part)))
|
|
2056
|
+
),
|
|
1315
2057
|
types.objectProperty(
|
|
1316
2058
|
types.identifier("invoke"),
|
|
1317
2059
|
types.arrowFunctionExpression(
|
|
@@ -1381,6 +2123,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1381
2123
|
plan.source,
|
|
1382
2124
|
...plan.conditionals.map((conditional) => conditional.test)
|
|
1383
2125
|
]);
|
|
2126
|
+
const delegatedEvents = canDelegateKeyedRowEvents(plan);
|
|
1384
2127
|
const renderSource = keyedRowsRenderSource(plan, eventFactory, conditionalFactory);
|
|
1385
2128
|
const renderFactoryParameters = plan.conditionals.length > 0 ? [types.cloneNode(eventFactory), types.cloneNode(conditionalFactory)] : plan.events.length > 0 ? [types.cloneNode(eventFactory)] : [];
|
|
1386
2129
|
return types.jsxElement(
|
|
@@ -1398,6 +2141,14 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1398
2141
|
types.jsxIdentifier("items"),
|
|
1399
2142
|
types.jsxExpressionContainer(types.arrowFunctionExpression([], cloneExpression(plan.collection)))
|
|
1400
2143
|
),
|
|
2144
|
+
types.jsxAttribute(
|
|
2145
|
+
types.jsxIdentifier("structureDependencies"),
|
|
2146
|
+
types.jsxExpressionContainer(
|
|
2147
|
+
types.arrayExpression(
|
|
2148
|
+
plan.structureDependencies.map((dependency) => types.numericLiteral(dependency))
|
|
2149
|
+
)
|
|
2150
|
+
)
|
|
2151
|
+
),
|
|
1401
2152
|
types.jsxAttribute(
|
|
1402
2153
|
types.jsxIdentifier("rowKey"),
|
|
1403
2154
|
types.jsxExpressionContainer(types.cloneNode(plan.keyCallback, true))
|
|
@@ -1407,7 +2158,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1407
2158
|
types.jsxExpressionContainer(
|
|
1408
2159
|
types.arrowFunctionExpression(
|
|
1409
2160
|
parameters.map((parameter) => types.cloneNode(parameter, true)),
|
|
1410
|
-
hostElementDescriptor(plan.row)
|
|
2161
|
+
hostElementDescriptor(plan.row, plan.descriptorBlocks)
|
|
1411
2162
|
)
|
|
1412
2163
|
)
|
|
1413
2164
|
),
|
|
@@ -1427,7 +2178,13 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1427
2178
|
plan.events.map((event) => keyedRowEventObject(event, parameters))
|
|
1428
2179
|
)
|
|
1429
2180
|
)
|
|
1430
|
-
)
|
|
2181
|
+
),
|
|
2182
|
+
...delegatedEvents ? [
|
|
2183
|
+
types.jsxAttribute(
|
|
2184
|
+
types.jsxIdentifier("delegateEvents"),
|
|
2185
|
+
types.jsxExpressionContainer(types.booleanLiteral(true))
|
|
2186
|
+
)
|
|
2187
|
+
] : []
|
|
1431
2188
|
] : [],
|
|
1432
2189
|
...plan.conditionals.length > 0 ? [
|
|
1433
2190
|
types.jsxAttribute(
|
|
@@ -1440,6 +2197,12 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1440
2197
|
)
|
|
1441
2198
|
)
|
|
1442
2199
|
)
|
|
2200
|
+
] : [],
|
|
2201
|
+
...plan.descriptorBlocks?.size ? [
|
|
2202
|
+
types.jsxAttribute(
|
|
2203
|
+
types.jsxIdentifier("hostBlocks"),
|
|
2204
|
+
types.jsxExpressionContainer(types.booleanLiteral(true))
|
|
2205
|
+
)
|
|
1443
2206
|
] : []
|
|
1444
2207
|
],
|
|
1445
2208
|
true
|
|
@@ -1449,7 +2212,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1449
2212
|
true
|
|
1450
2213
|
);
|
|
1451
2214
|
}
|
|
1452
|
-
function keyedRangeObject(range) {
|
|
2215
|
+
function keyedRangeObject(range, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1453
2216
|
const parameters = range.renderCallback.params.map(
|
|
1454
2217
|
(parameter) => types.cloneNode(parameter, true)
|
|
1455
2218
|
);
|
|
@@ -1464,7 +2227,7 @@ function keyedRangeObject(range) {
|
|
|
1464
2227
|
types.identifier("create"),
|
|
1465
2228
|
types.arrowFunctionExpression(
|
|
1466
2229
|
parameters.map((parameter) => types.cloneNode(parameter, true)),
|
|
1467
|
-
hostElementDescriptor(range.row)
|
|
2230
|
+
hostElementDescriptor(range.row, descriptorBlocks)
|
|
1468
2231
|
)
|
|
1469
2232
|
),
|
|
1470
2233
|
types.objectProperty(
|
|
@@ -1508,6 +2271,12 @@ function keyedRangesBoundary(blockRuntime, plan) {
|
|
|
1508
2271
|
types.jsxAttribute(
|
|
1509
2272
|
types.jsxIdentifier("trailing"),
|
|
1510
2273
|
types.jsxExpressionContainer(types.numericLiteral(plan.trailing))
|
|
2274
|
+
),
|
|
2275
|
+
types.jsxAttribute(
|
|
2276
|
+
types.jsxIdentifier("bindings"),
|
|
2277
|
+
types.jsxExpressionContainer(
|
|
2278
|
+
types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2279
|
+
)
|
|
1511
2280
|
)
|
|
1512
2281
|
],
|
|
1513
2282
|
true
|
|
@@ -1517,11 +2286,11 @@ function keyedRangesBoundary(blockRuntime, plan) {
|
|
|
1517
2286
|
true
|
|
1518
2287
|
);
|
|
1519
2288
|
}
|
|
1520
|
-
function hostConditionalBranchObject(branch, bindings) {
|
|
2289
|
+
function hostConditionalBranchObject(branch, bindings, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1521
2290
|
return types.objectExpression([
|
|
1522
2291
|
types.objectProperty(
|
|
1523
2292
|
types.identifier("create"),
|
|
1524
|
-
types.arrowFunctionExpression([], hostElementDescriptor(branch))
|
|
2293
|
+
types.arrowFunctionExpression([], hostElementDescriptor(branch, descriptorBlocks))
|
|
1525
2294
|
),
|
|
1526
2295
|
types.objectProperty(
|
|
1527
2296
|
types.identifier("bindings"),
|
|
@@ -1550,7 +2319,9 @@ function hostConditionalBoundary(blockRuntime, plan) {
|
|
|
1550
2319
|
attributes.push(
|
|
1551
2320
|
types.jsxAttribute(
|
|
1552
2321
|
types.jsxIdentifier("truthy"),
|
|
1553
|
-
types.jsxExpressionContainer(
|
|
2322
|
+
types.jsxExpressionContainer(
|
|
2323
|
+
hostConditionalBranchObject(plan.truthy, plan.truthyBindings, plan.descriptorBlocks)
|
|
2324
|
+
)
|
|
1554
2325
|
)
|
|
1555
2326
|
);
|
|
1556
2327
|
}
|
|
@@ -1558,13 +2329,15 @@ function hostConditionalBoundary(blockRuntime, plan) {
|
|
|
1558
2329
|
attributes.push(
|
|
1559
2330
|
types.jsxAttribute(
|
|
1560
2331
|
types.jsxIdentifier("falsy"),
|
|
1561
|
-
types.jsxExpressionContainer(
|
|
2332
|
+
types.jsxExpressionContainer(
|
|
2333
|
+
hostConditionalBranchObject(plan.falsy, plan.falsyBindings, plan.descriptorBlocks)
|
|
2334
|
+
)
|
|
1562
2335
|
)
|
|
1563
2336
|
);
|
|
1564
2337
|
}
|
|
1565
2338
|
return types.jsxElement(types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
1566
2339
|
}
|
|
1567
|
-
function conditionalRangeObject(range) {
|
|
2340
|
+
function conditionalRangeObject(range, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1568
2341
|
const properties = [
|
|
1569
2342
|
types.objectProperty(types.identifier("before"), types.numericLiteral(range.before)),
|
|
1570
2343
|
types.objectProperty(
|
|
@@ -1579,7 +2352,7 @@ function conditionalRangeObject(range) {
|
|
|
1579
2352
|
properties.push(
|
|
1580
2353
|
types.objectProperty(
|
|
1581
2354
|
types.identifier("truthy"),
|
|
1582
|
-
hostConditionalBranchObject(range.truthy, range.truthyBindings)
|
|
2355
|
+
hostConditionalBranchObject(range.truthy, range.truthyBindings, descriptorBlocks)
|
|
1583
2356
|
)
|
|
1584
2357
|
);
|
|
1585
2358
|
}
|
|
@@ -1587,12 +2360,78 @@ function conditionalRangeObject(range) {
|
|
|
1587
2360
|
properties.push(
|
|
1588
2361
|
types.objectProperty(
|
|
1589
2362
|
types.identifier("falsy"),
|
|
1590
|
-
hostConditionalBranchObject(range.falsy, range.falsyBindings)
|
|
2363
|
+
hostConditionalBranchObject(range.falsy, range.falsyBindings, descriptorBlocks)
|
|
1591
2364
|
)
|
|
1592
2365
|
);
|
|
1593
2366
|
}
|
|
1594
2367
|
return types.objectExpression(properties);
|
|
1595
2368
|
}
|
|
2369
|
+
function nestedHostBlockObject(plan, descriptorBlocks) {
|
|
2370
|
+
const kind = plan.kind === "nested-host-conditional-ranges" ? "conditional-ranges" : plan.kind === "nested-host-keyed-ranges" ? "keyed-ranges" : "mixed-ranges";
|
|
2371
|
+
return types.objectExpression([
|
|
2372
|
+
types.objectProperty(types.identifier("kind"), types.stringLiteral(kind)),
|
|
2373
|
+
types.objectProperty(types.identifier("id"), types.numericLiteral(plan.id)),
|
|
2374
|
+
types.objectProperty(
|
|
2375
|
+
types.identifier("ranges"),
|
|
2376
|
+
types.arrayExpression(
|
|
2377
|
+
plan.kind === "nested-host-conditional-ranges" ? plan.ranges.map((range) => conditionalRangeObject(range, descriptorBlocks)) : plan.kind === "nested-host-keyed-ranges" ? plan.ranges.map((range) => keyedRangeObject(range, descriptorBlocks)) : plan.ranges.map((range) => mixedRangeObject(range, descriptorBlocks))
|
|
2378
|
+
)
|
|
2379
|
+
),
|
|
2380
|
+
types.objectProperty(types.identifier("trailing"), types.numericLiteral(plan.trailing)),
|
|
2381
|
+
types.objectProperty(
|
|
2382
|
+
types.identifier("bindings"),
|
|
2383
|
+
types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2384
|
+
),
|
|
2385
|
+
...plan.kind === "nested-host-keyed-ranges" ? [types.objectProperty(types.identifier("staticChildrenOnly"), types.booleanLiteral(true))] : []
|
|
2386
|
+
]);
|
|
2387
|
+
}
|
|
2388
|
+
function mixedRangeObject(range, descriptorBlocks) {
|
|
2389
|
+
const value = range.rangeKind === "conditional" ? conditionalRangeObject(range, descriptorBlocks) : keyedRangeObject(range, descriptorBlocks);
|
|
2390
|
+
value.properties.unshift(
|
|
2391
|
+
types.objectProperty(types.identifier("kind"), types.stringLiteral(range.rangeKind))
|
|
2392
|
+
);
|
|
2393
|
+
return value;
|
|
2394
|
+
}
|
|
2395
|
+
function mixedRangesBoundary(blockRuntime, plan) {
|
|
2396
|
+
const name = types.jsxMemberExpression(
|
|
2397
|
+
types.jsxIdentifier(blockRuntime.name),
|
|
2398
|
+
types.jsxIdentifier("MixedRanges")
|
|
2399
|
+
);
|
|
2400
|
+
const source = types.cloneNode(plan.source, true);
|
|
2401
|
+
const rootRefIndex = source.openingElement.attributes.findIndex(
|
|
2402
|
+
(attribute) => types.isJSXAttribute(attribute) && jsxAttributeName(attribute) === "ref"
|
|
2403
|
+
);
|
|
2404
|
+
const rootRef = rootRefIndex >= 0 ? source.openingElement.attributes.splice(rootRefIndex, 1)[0] : void 0;
|
|
2405
|
+
const nestedPlan = {
|
|
2406
|
+
kind: "nested-host-mixed-ranges",
|
|
2407
|
+
id: plan.id,
|
|
2408
|
+
parent: plan.parent,
|
|
2409
|
+
dependencies: plan.dependencies,
|
|
2410
|
+
source: plan.source,
|
|
2411
|
+
ranges: plan.ranges,
|
|
2412
|
+
trailing: plan.trailing,
|
|
2413
|
+
staticBindings: plan.staticBindings
|
|
2414
|
+
};
|
|
2415
|
+
const descriptorBlocks = new Map(plan.descriptorBlocks);
|
|
2416
|
+
descriptorBlocks.set(plan.source, nestedPlan);
|
|
2417
|
+
const attributes = [
|
|
2418
|
+
types.jsxAttribute(types.jsxIdentifier("id"), types.jsxExpressionContainer(types.numericLiteral(plan.id))),
|
|
2419
|
+
types.jsxAttribute(
|
|
2420
|
+
types.jsxIdentifier("render"),
|
|
2421
|
+
types.jsxExpressionContainer(types.arrowFunctionExpression([], source))
|
|
2422
|
+
),
|
|
2423
|
+
types.jsxAttribute(
|
|
2424
|
+
types.jsxIdentifier("create"),
|
|
2425
|
+
types.jsxExpressionContainer(
|
|
2426
|
+
types.arrowFunctionExpression([], hostElementDescriptor(plan.source, descriptorBlocks))
|
|
2427
|
+
)
|
|
2428
|
+
)
|
|
2429
|
+
];
|
|
2430
|
+
if (rootRef?.value) {
|
|
2431
|
+
attributes.push(types.jsxAttribute(types.jsxIdentifier("rootRef"), types.cloneNode(rootRef.value, true)));
|
|
2432
|
+
}
|
|
2433
|
+
return types.jsxElement(types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2434
|
+
}
|
|
1596
2435
|
function conditionalRangesBoundary(blockRuntime, plan) {
|
|
1597
2436
|
const name = types.jsxMemberExpression(
|
|
1598
2437
|
types.jsxIdentifier(blockRuntime.name),
|
|
@@ -1612,12 +2451,20 @@ function conditionalRangesBoundary(blockRuntime, plan) {
|
|
|
1612
2451
|
types.jsxAttribute(
|
|
1613
2452
|
types.jsxIdentifier("ranges"),
|
|
1614
2453
|
types.jsxExpressionContainer(
|
|
1615
|
-
types.arrayExpression(
|
|
2454
|
+
types.arrayExpression(
|
|
2455
|
+
plan.ranges.map((range) => conditionalRangeObject(range, plan.descriptorBlocks))
|
|
2456
|
+
)
|
|
1616
2457
|
)
|
|
1617
2458
|
),
|
|
1618
2459
|
types.jsxAttribute(
|
|
1619
2460
|
types.jsxIdentifier("trailing"),
|
|
1620
2461
|
types.jsxExpressionContainer(types.numericLiteral(plan.trailing))
|
|
2462
|
+
),
|
|
2463
|
+
types.jsxAttribute(
|
|
2464
|
+
types.jsxIdentifier("bindings"),
|
|
2465
|
+
types.jsxExpressionContainer(
|
|
2466
|
+
types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2467
|
+
)
|
|
1621
2468
|
)
|
|
1622
2469
|
];
|
|
1623
2470
|
if (rootRef?.value) {
|
|
@@ -1790,6 +2637,41 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1790
2637
|
}
|
|
1791
2638
|
if (types.isJSXElement(child)) {
|
|
1792
2639
|
if (isHostElement(child)) {
|
|
2640
|
+
const mixedRangeStart = nextId;
|
|
2641
|
+
const mixedRangeId = nextId++;
|
|
2642
|
+
const mixedRanges = insideConditional ? void 0 : analyzeMixedRangesContainer(
|
|
2643
|
+
child,
|
|
2644
|
+
statesByValue,
|
|
2645
|
+
safeGlobals,
|
|
2646
|
+
listNames,
|
|
2647
|
+
mixedRangeId,
|
|
2648
|
+
() => nextId++
|
|
2649
|
+
);
|
|
2650
|
+
if (mixedRanges) {
|
|
2651
|
+
plans.push({
|
|
2652
|
+
kind: "mixed-ranges",
|
|
2653
|
+
id: mixedRangeId,
|
|
2654
|
+
parent,
|
|
2655
|
+
dependencies: mixedRanges.dependencies,
|
|
2656
|
+
source: child,
|
|
2657
|
+
ranges: mixedRanges.ranges,
|
|
2658
|
+
trailing: mixedRanges.trailing,
|
|
2659
|
+
staticBindings: mixedRanges.staticBindings,
|
|
2660
|
+
descriptorBlocks: mixedRanges.descriptorBlocks
|
|
2661
|
+
});
|
|
2662
|
+
plans.push(...mixedRanges.nestedPlans);
|
|
2663
|
+
for (const range of mixedRanges.ranges) {
|
|
2664
|
+
if (range.rangeKind === "conditional") {
|
|
2665
|
+
conditionalExpressions.add(range.source);
|
|
2666
|
+
} else if (types.isJSXElement(range.source)) {
|
|
2667
|
+
ownedElements.add(range.source);
|
|
2668
|
+
} else {
|
|
2669
|
+
keyedExpressions.add(range.source);
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
continue;
|
|
2673
|
+
}
|
|
2674
|
+
nextId = mixedRangeStart;
|
|
1793
2675
|
const keyedRanges = insideConditional ? void 0 : analyzeKeyedRangesContainer(child, statesByValue, safeGlobals, listNames);
|
|
1794
2676
|
if (keyedRanges) {
|
|
1795
2677
|
plans.push({
|
|
@@ -1799,7 +2681,8 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1799
2681
|
dependencies: keyedRanges.dependencies,
|
|
1800
2682
|
source: child,
|
|
1801
2683
|
ranges: keyedRanges.ranges,
|
|
1802
|
-
trailing: keyedRanges.trailing
|
|
2684
|
+
trailing: keyedRanges.trailing,
|
|
2685
|
+
staticBindings: keyedRanges.staticBindings
|
|
1803
2686
|
});
|
|
1804
2687
|
for (const range of keyedRanges.ranges) {
|
|
1805
2688
|
if (types.isJSXElement(range.source)) ownedElements.add(range.source);
|
|
@@ -1807,58 +2690,102 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1807
2690
|
}
|
|
1808
2691
|
continue;
|
|
1809
2692
|
}
|
|
1810
|
-
const
|
|
2693
|
+
const conditionalRangeStart = nextId;
|
|
2694
|
+
const conditionalRangeId = nextId++;
|
|
2695
|
+
const conditionalRanges = insideConditional ? void 0 : analyzeConditionalRangesContainer(
|
|
2696
|
+
child,
|
|
2697
|
+
statesByValue,
|
|
2698
|
+
safeGlobals,
|
|
2699
|
+
false,
|
|
2700
|
+
listNames,
|
|
2701
|
+
conditionalRangeId,
|
|
2702
|
+
() => nextId++
|
|
2703
|
+
);
|
|
1811
2704
|
if (conditionalRanges) {
|
|
1812
2705
|
plans.push({
|
|
1813
2706
|
kind: "conditional-ranges",
|
|
1814
|
-
id:
|
|
2707
|
+
id: conditionalRangeId,
|
|
1815
2708
|
parent,
|
|
1816
2709
|
dependencies: conditionalRanges.dependencies,
|
|
1817
2710
|
source: child,
|
|
1818
2711
|
ranges: conditionalRanges.ranges,
|
|
1819
|
-
trailing: conditionalRanges.trailing
|
|
2712
|
+
trailing: conditionalRanges.trailing,
|
|
2713
|
+
staticBindings: conditionalRanges.staticBindings,
|
|
2714
|
+
descriptorBlocks: conditionalRanges.descriptorBlocks
|
|
1820
2715
|
});
|
|
2716
|
+
plans.push(...conditionalRanges.nestedPlans || []);
|
|
1821
2717
|
for (const range of conditionalRanges.ranges) {
|
|
1822
2718
|
conditionalExpressions.add(range.source);
|
|
1823
2719
|
}
|
|
1824
2720
|
continue;
|
|
1825
2721
|
}
|
|
2722
|
+
nextId = conditionalRangeStart;
|
|
2723
|
+
const hostConditionalStart = nextId;
|
|
2724
|
+
const hostConditionalId = nextId++;
|
|
1826
2725
|
const hostConditional = analyzeHostConditionalContainer(
|
|
1827
2726
|
child,
|
|
1828
2727
|
statesByValue,
|
|
1829
|
-
safeGlobals
|
|
2728
|
+
safeGlobals,
|
|
2729
|
+
listNames,
|
|
2730
|
+
hostConditionalId,
|
|
2731
|
+
() => nextId++
|
|
1830
2732
|
);
|
|
1831
2733
|
if (hostConditional) {
|
|
1832
2734
|
plans.push({
|
|
1833
2735
|
kind: "host-conditional",
|
|
1834
|
-
id:
|
|
2736
|
+
id: hostConditionalId,
|
|
1835
2737
|
parent,
|
|
1836
2738
|
source: child,
|
|
1837
2739
|
...hostConditional
|
|
1838
2740
|
});
|
|
2741
|
+
plans.push(...hostConditional.nestedPlans || []);
|
|
1839
2742
|
ownedElements.add(child);
|
|
1840
2743
|
continue;
|
|
1841
2744
|
}
|
|
2745
|
+
nextId = hostConditionalStart;
|
|
2746
|
+
const keyedRowsStart = nextId;
|
|
2747
|
+
const keyedRowsId = nextId++;
|
|
1842
2748
|
const keyedRows = analyzeKeyedRowsContainer(child, statesByValue, safeGlobals, listNames);
|
|
1843
2749
|
if (keyedRows) {
|
|
2750
|
+
const nestedStart = nextId;
|
|
2751
|
+
const hostBlocks = analyzeCompilerOwnedKeyedRowHostBlocks(
|
|
2752
|
+
keyedRows,
|
|
2753
|
+
statesByValue,
|
|
2754
|
+
safeGlobals,
|
|
2755
|
+
listNames,
|
|
2756
|
+
keyedRowsId,
|
|
2757
|
+
() => nextId++
|
|
2758
|
+
);
|
|
2759
|
+
if (!hostBlocks) nextId = nestedStart;
|
|
2760
|
+
if (keyedRows.rowReason && !hostBlocks) {
|
|
2761
|
+
nextId = keyedRowsStart;
|
|
2762
|
+
const nested2 = visitHost(child, parent, insideConditional);
|
|
2763
|
+
if (nested2.reason) return { dependencies, reason: nested2.reason };
|
|
2764
|
+
mergeDependencies(dependencies, nested2.dependencies);
|
|
2765
|
+
continue;
|
|
2766
|
+
}
|
|
1844
2767
|
plans.push({
|
|
1845
2768
|
kind: "keyed-rows",
|
|
1846
|
-
id:
|
|
2769
|
+
id: keyedRowsId,
|
|
1847
2770
|
parent,
|
|
1848
2771
|
dependencies: keyedRows.dependencies,
|
|
1849
2772
|
source: child,
|
|
1850
2773
|
collection: keyedRows.collection,
|
|
2774
|
+
structureDependencies: keyedRows.structureDependencies,
|
|
1851
2775
|
keyCallback: keyedRows.keyCallback,
|
|
1852
2776
|
renderCallback: keyedRows.renderCallback,
|
|
1853
|
-
row: keyedRows.row,
|
|
1854
|
-
bindings: keyedRows.bindings,
|
|
2777
|
+
row: hostBlocks?.row || keyedRows.row,
|
|
2778
|
+
bindings: hostBlocks?.bindings || keyedRows.bindings,
|
|
1855
2779
|
events: keyedRows.events,
|
|
1856
|
-
conditionals: keyedRows.conditionals,
|
|
2780
|
+
conditionals: hostBlocks ? [] : keyedRows.conditionals,
|
|
2781
|
+
descriptorBlocks: hostBlocks?.descriptorBlocks,
|
|
1857
2782
|
syntax: keyedRows.syntax
|
|
1858
2783
|
});
|
|
2784
|
+
plans.push(...hostBlocks?.nestedPlans || []);
|
|
1859
2785
|
ownedElements.add(child);
|
|
1860
2786
|
continue;
|
|
1861
2787
|
}
|
|
2788
|
+
nextId = keyedRowsStart;
|
|
1862
2789
|
const nested = visitHost(child, parent, insideConditional);
|
|
1863
2790
|
if (nested.reason) return { dependencies, reason: nested.reason };
|
|
1864
2791
|
mergeDependencies(dependencies, nested.dependencies);
|
|
@@ -1955,6 +2882,46 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1955
2882
|
}
|
|
1956
2883
|
return { dependencies };
|
|
1957
2884
|
};
|
|
2885
|
+
const rootMixedRangeStart = nextId;
|
|
2886
|
+
const rootMixedRangeId = nextId++;
|
|
2887
|
+
const rootMixedRanges = analyzeMixedRangesContainer(
|
|
2888
|
+
root,
|
|
2889
|
+
statesByValue,
|
|
2890
|
+
safeGlobals,
|
|
2891
|
+
listNames,
|
|
2892
|
+
rootMixedRangeId,
|
|
2893
|
+
() => nextId++
|
|
2894
|
+
);
|
|
2895
|
+
if (rootMixedRanges) {
|
|
2896
|
+
plans.push({
|
|
2897
|
+
kind: "mixed-ranges",
|
|
2898
|
+
id: rootMixedRangeId,
|
|
2899
|
+
dependencies: rootMixedRanges.dependencies,
|
|
2900
|
+
source: root,
|
|
2901
|
+
ranges: rootMixedRanges.ranges,
|
|
2902
|
+
trailing: rootMixedRanges.trailing,
|
|
2903
|
+
staticBindings: rootMixedRanges.staticBindings,
|
|
2904
|
+
descriptorBlocks: rootMixedRanges.descriptorBlocks
|
|
2905
|
+
});
|
|
2906
|
+
plans.push(...rootMixedRanges.nestedPlans);
|
|
2907
|
+
for (const range of rootMixedRanges.ranges) {
|
|
2908
|
+
if (range.rangeKind === "conditional") {
|
|
2909
|
+
conditionalExpressions.add(range.source);
|
|
2910
|
+
} else if (types.isJSXElement(range.source)) {
|
|
2911
|
+
ownedElements.add(range.source);
|
|
2912
|
+
} else {
|
|
2913
|
+
keyedExpressions.add(range.source);
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
return {
|
|
2917
|
+
plans,
|
|
2918
|
+
componentElements,
|
|
2919
|
+
conditionalExpressions,
|
|
2920
|
+
ownedElements,
|
|
2921
|
+
keyedExpressions
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
nextId = rootMixedRangeStart;
|
|
1958
2925
|
const rootRanges = analyzeKeyedRangesContainer(root, statesByValue, safeGlobals, listNames, true);
|
|
1959
2926
|
if (rootRanges) {
|
|
1960
2927
|
plans.push({
|
|
@@ -1963,7 +2930,8 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1963
2930
|
dependencies: rootRanges.dependencies,
|
|
1964
2931
|
source: root,
|
|
1965
2932
|
ranges: rootRanges.ranges,
|
|
1966
|
-
trailing: rootRanges.trailing
|
|
2933
|
+
trailing: rootRanges.trailing,
|
|
2934
|
+
staticBindings: rootRanges.staticBindings
|
|
1967
2935
|
});
|
|
1968
2936
|
for (const range of rootRanges.ranges) {
|
|
1969
2937
|
if (types.isJSXElement(range.source)) ownedElements.add(range.source);
|
|
@@ -1977,21 +2945,29 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1977
2945
|
keyedExpressions
|
|
1978
2946
|
};
|
|
1979
2947
|
}
|
|
2948
|
+
const rootConditionalRangeStart = nextId;
|
|
2949
|
+
const rootConditionalRangeId = nextId++;
|
|
1980
2950
|
const rootConditionalRanges = analyzeConditionalRangesContainer(
|
|
1981
2951
|
root,
|
|
1982
2952
|
statesByValue,
|
|
1983
2953
|
safeGlobals,
|
|
1984
|
-
true
|
|
2954
|
+
true,
|
|
2955
|
+
listNames,
|
|
2956
|
+
rootConditionalRangeId,
|
|
2957
|
+
() => nextId++
|
|
1985
2958
|
);
|
|
1986
2959
|
if (rootConditionalRanges) {
|
|
1987
2960
|
plans.push({
|
|
1988
2961
|
kind: "conditional-ranges",
|
|
1989
|
-
id:
|
|
2962
|
+
id: rootConditionalRangeId,
|
|
1990
2963
|
dependencies: rootConditionalRanges.dependencies,
|
|
1991
2964
|
source: root,
|
|
1992
2965
|
ranges: rootConditionalRanges.ranges,
|
|
1993
|
-
trailing: rootConditionalRanges.trailing
|
|
2966
|
+
trailing: rootConditionalRanges.trailing,
|
|
2967
|
+
staticBindings: rootConditionalRanges.staticBindings,
|
|
2968
|
+
descriptorBlocks: rootConditionalRanges.descriptorBlocks
|
|
1994
2969
|
});
|
|
2970
|
+
plans.push(...rootConditionalRanges.nestedPlans || []);
|
|
1995
2971
|
for (const range of rootConditionalRanges.ranges) {
|
|
1996
2972
|
conditionalExpressions.add(range.source);
|
|
1997
2973
|
}
|
|
@@ -2003,6 +2979,7 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
2003
2979
|
keyedExpressions
|
|
2004
2980
|
};
|
|
2005
2981
|
}
|
|
2982
|
+
nextId = rootConditionalRangeStart;
|
|
2006
2983
|
const result = visitHost(root, void 0, false);
|
|
2007
2984
|
if (result.reason) return { reason: result.reason };
|
|
2008
2985
|
return {
|
|
@@ -2040,6 +3017,9 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
2040
3017
|
plans.map((plan) => [plan.source, plan])
|
|
2041
3018
|
);
|
|
2042
3019
|
const rootPlan = planBySource.get(root);
|
|
3020
|
+
if (rootPlan?.kind === "mixed-ranges") {
|
|
3021
|
+
return mixedRangesBoundary(blockRuntime, rootPlan);
|
|
3022
|
+
}
|
|
2043
3023
|
if (rootPlan?.kind === "keyed-ranges") {
|
|
2044
3024
|
return keyedRangesBoundary(blockRuntime, rootPlan);
|
|
2045
3025
|
}
|
|
@@ -2053,6 +3033,9 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
2053
3033
|
if (plan2?.kind === "host-conditional") {
|
|
2054
3034
|
return hostConditionalBoundary(blockRuntime, plan2);
|
|
2055
3035
|
}
|
|
3036
|
+
if (plan2?.kind === "mixed-ranges") {
|
|
3037
|
+
return mixedRangesBoundary(blockRuntime, plan2);
|
|
3038
|
+
}
|
|
2056
3039
|
if (plan2?.kind === "keyed-rows") {
|
|
2057
3040
|
return keyedRowsBoundary(blockRuntime, plan2);
|
|
2058
3041
|
}
|
|
@@ -2102,6 +3085,31 @@ function assignStableBindingTargets(bindings) {
|
|
|
2102
3085
|
binding.target = target;
|
|
2103
3086
|
}
|
|
2104
3087
|
}
|
|
3088
|
+
function markShortCircuitBindings(bindings) {
|
|
3089
|
+
for (const binding of bindings) {
|
|
3090
|
+
if (binding.kind === "block" || binding.dependencies.length < 2) continue;
|
|
3091
|
+
let shortCircuits = false;
|
|
3092
|
+
traverse(expressionFile(types.cloneNode(binding.value, true)), {
|
|
3093
|
+
ConditionalExpression(path) {
|
|
3094
|
+
shortCircuits = true;
|
|
3095
|
+
path.stop();
|
|
3096
|
+
},
|
|
3097
|
+
LogicalExpression(path) {
|
|
3098
|
+
shortCircuits = true;
|
|
3099
|
+
path.stop();
|
|
3100
|
+
},
|
|
3101
|
+
OptionalCallExpression(path) {
|
|
3102
|
+
shortCircuits = true;
|
|
3103
|
+
path.stop();
|
|
3104
|
+
},
|
|
3105
|
+
OptionalMemberExpression(path) {
|
|
3106
|
+
shortCircuits = true;
|
|
3107
|
+
path.stop();
|
|
3108
|
+
}
|
|
3109
|
+
});
|
|
3110
|
+
if (shortCircuits) binding.tracking = "dynamic";
|
|
3111
|
+
}
|
|
3112
|
+
}
|
|
2105
3113
|
function lowerStableBindingTargets(root, bindings, blockRuntime, ownedElements) {
|
|
2106
3114
|
const targetByPath = /* @__PURE__ */ new Map();
|
|
2107
3115
|
for (const binding of bindings) {
|
|
@@ -2371,6 +3379,9 @@ function bindingObject(binding, propsParameter, stateParameter, statesByValue, s
|
|
|
2371
3379
|
types.objectProperty(types.identifier("target"), types.numericLiteral(binding.target))
|
|
2372
3380
|
);
|
|
2373
3381
|
}
|
|
3382
|
+
if (binding.tracking) {
|
|
3383
|
+
properties.push(types.objectProperty(types.identifier("tracking"), types.stringLiteral(binding.tracking)));
|
|
3384
|
+
}
|
|
2374
3385
|
if (binding.name)
|
|
2375
3386
|
properties.push(types.objectProperty(types.identifier("name"), types.stringLiteral(binding.name)));
|
|
2376
3387
|
properties.push(
|
|
@@ -2389,7 +3400,7 @@ function wrapperElement(definitionIdentifier, props) {
|
|
|
2389
3400
|
const attributes = props ? [types.jsxSpreadAttribute(types.cloneNode(props))] : [];
|
|
2390
3401
|
return types.jsxElement(types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2391
3402
|
}
|
|
2392
|
-
function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames, listNames, moduleId) {
|
|
3403
|
+
function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
2393
3404
|
const { path, name, statementPath } = candidate;
|
|
2394
3405
|
if (path.node.async || path.node.generator)
|
|
2395
3406
|
return "async and generator components are not supported";
|
|
@@ -2506,8 +3517,34 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2506
3517
|
);
|
|
2507
3518
|
const setterReason = validateSetterUsage(expandedRoot, statesBySetter);
|
|
2508
3519
|
if (setterReason) return setterReason;
|
|
3520
|
+
const referencedPropNames = collectDestructuredPropNames(
|
|
3521
|
+
expandedRoot,
|
|
3522
|
+
propsPlan.destructuredNames,
|
|
3523
|
+
propsPlan.definitionParameter
|
|
3524
|
+
);
|
|
3525
|
+
let propBindings = referencedPropNames.has("children") ? [] : [...propsPlan.destructuredNames].filter((propName) => referencedPropNames.has(propName)).map(
|
|
3526
|
+
(localName, propIndex) => ({
|
|
3527
|
+
localName,
|
|
3528
|
+
valueName: path.scope.generateUidIdentifier(`farmProp${propIndex}`).name,
|
|
3529
|
+
index: states.length + propIndex
|
|
3530
|
+
})
|
|
3531
|
+
);
|
|
3532
|
+
const propBindingsByName = new Map(propBindings.map((binding) => [binding.localName, binding]));
|
|
3533
|
+
let reactiveByValue = new Map(statesByValue);
|
|
3534
|
+
for (const binding of propBindings) {
|
|
3535
|
+
reactiveByValue.set(binding.valueName, {
|
|
3536
|
+
valueName: binding.valueName,
|
|
3537
|
+
setterName: "",
|
|
3538
|
+
index: binding.index
|
|
3539
|
+
});
|
|
3540
|
+
}
|
|
3541
|
+
let expandedReactiveRoot = rewriteTrackedPropAccess(
|
|
3542
|
+
expandedRoot,
|
|
3543
|
+
propsPlan.definitionParameter,
|
|
3544
|
+
propBindingsByName
|
|
3545
|
+
);
|
|
2509
3546
|
const referencedComponentNames = /* @__PURE__ */ new Set();
|
|
2510
|
-
traverse(expressionFile(types.cloneNode(
|
|
3547
|
+
traverse(expressionFile(types.cloneNode(expandedReactiveRoot, true)), {
|
|
2511
3548
|
JSXOpeningElement(componentPath) {
|
|
2512
3549
|
const componentName = componentPath.node.name;
|
|
2513
3550
|
if (types.isJSXIdentifier(componentName) && isComponentName(componentName.name)) {
|
|
@@ -2524,32 +3561,54 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2524
3561
|
);
|
|
2525
3562
|
})
|
|
2526
3563
|
);
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
3564
|
+
let blockAnalysis = analyzeComposableBlocks(
|
|
3565
|
+
expandedReactiveRoot,
|
|
3566
|
+
reactiveByValue,
|
|
2530
3567
|
safeGlobals,
|
|
2531
3568
|
listNames,
|
|
2532
3569
|
allowedComponentNames
|
|
2533
3570
|
);
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
expandedRoot,
|
|
2538
|
-
statesByValue,
|
|
3571
|
+
let analysis = analyzeHostTree(
|
|
3572
|
+
expandedReactiveRoot,
|
|
3573
|
+
reactiveByValue,
|
|
2539
3574
|
safeGlobals,
|
|
2540
3575
|
blockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
2541
3576
|
blockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
2542
3577
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
2543
3578
|
blockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
2544
3579
|
);
|
|
3580
|
+
if (propBindings.length > 0 && (blockAnalysis.reason || analysis.reason)) {
|
|
3581
|
+
propBindings = [];
|
|
3582
|
+
reactiveByValue = new Map(statesByValue);
|
|
3583
|
+
expandedReactiveRoot = types.cloneNode(expandedRoot, true);
|
|
3584
|
+
blockAnalysis = analyzeComposableBlocks(
|
|
3585
|
+
expandedReactiveRoot,
|
|
3586
|
+
reactiveByValue,
|
|
3587
|
+
safeGlobals,
|
|
3588
|
+
listNames,
|
|
3589
|
+
allowedComponentNames
|
|
3590
|
+
);
|
|
3591
|
+
analysis = analyzeHostTree(
|
|
3592
|
+
expandedReactiveRoot,
|
|
3593
|
+
reactiveByValue,
|
|
3594
|
+
safeGlobals,
|
|
3595
|
+
blockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
3596
|
+
blockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
3597
|
+
blockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
3598
|
+
blockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
3599
|
+
);
|
|
3600
|
+
}
|
|
3601
|
+
if (blockAnalysis.reason) return blockAnalysis.reason;
|
|
2545
3602
|
if (analysis.reason) return analysis.reason;
|
|
3603
|
+
const blockPlans = blockAnalysis.plans || [];
|
|
3604
|
+
markShortCircuitBindings(analysis.bindings || []);
|
|
2546
3605
|
assignStableBindingTargets(analysis.bindings || []);
|
|
2547
3606
|
const stateParameter = path.scope.generateUidIdentifier("farmState");
|
|
2548
3607
|
const blockParameter = path.scope.generateUidIdentifier("farmBlocks");
|
|
2549
3608
|
const definitionIdentifier = path.scope.generateUidIdentifier(`${name}Compiled`);
|
|
2550
3609
|
const propsParameter = propsPlan.definitionParameter;
|
|
2551
3610
|
const rootWithTargets = lowerStableBindingTargets(
|
|
2552
|
-
|
|
3611
|
+
expandedReactiveRoot,
|
|
2553
3612
|
analysis.bindings || [],
|
|
2554
3613
|
blockParameter,
|
|
2555
3614
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set()
|
|
@@ -2563,12 +3622,13 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2563
3622
|
const rewrittenRoot = rewriteStateAccess(
|
|
2564
3623
|
rootWithBlocks,
|
|
2565
3624
|
stateParameter,
|
|
2566
|
-
|
|
3625
|
+
reactiveByValue,
|
|
2567
3626
|
statesBySetter
|
|
2568
3627
|
);
|
|
2569
3628
|
const definition = types.callExpression(types.cloneNode(createComponentIdentifier), [
|
|
2570
3629
|
types.objectExpression([
|
|
2571
3630
|
types.objectProperty(types.identifier("displayName"), types.stringLiteral(name)),
|
|
3631
|
+
types.objectProperty(types.identifier("reactivity"), types.stringLiteral(reactivity)),
|
|
2572
3632
|
types.spreadElement(
|
|
2573
3633
|
types.conditionalExpression(
|
|
2574
3634
|
types.memberExpression(
|
|
@@ -2579,7 +3639,9 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2579
3639
|
types.objectProperty(types.identifier("hmrId"), types.stringLiteral(`${moduleId}#${name}`)),
|
|
2580
3640
|
types.objectProperty(
|
|
2581
3641
|
types.identifier("stateSignature"),
|
|
2582
|
-
types.stringLiteral(
|
|
3642
|
+
types.stringLiteral(
|
|
3643
|
+
propBindings.length === 0 ? String(states.length) : `${states.length}:${propBindings.map((binding) => binding.localName).join(",")}`
|
|
3644
|
+
)
|
|
2583
3645
|
)
|
|
2584
3646
|
]),
|
|
2585
3647
|
types.objectExpression([])
|
|
@@ -2602,6 +3664,22 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2602
3664
|
)
|
|
2603
3665
|
)
|
|
2604
3666
|
),
|
|
3667
|
+
...propBindings.length > 0 ? [
|
|
3668
|
+
types.objectProperty(
|
|
3669
|
+
types.identifier("readProps"),
|
|
3670
|
+
types.arrowFunctionExpression(
|
|
3671
|
+
[types.cloneNode(propsParameter)],
|
|
3672
|
+
types.arrayExpression(
|
|
3673
|
+
propBindings.map(
|
|
3674
|
+
(binding) => types.memberExpression(
|
|
3675
|
+
types.cloneNode(propsParameter),
|
|
3676
|
+
types.identifier(binding.localName)
|
|
3677
|
+
)
|
|
3678
|
+
)
|
|
3679
|
+
)
|
|
3680
|
+
)
|
|
3681
|
+
)
|
|
3682
|
+
] : [],
|
|
2605
3683
|
types.objectProperty(
|
|
2606
3684
|
types.identifier("render"),
|
|
2607
3685
|
types.arrowFunctionExpression(
|
|
@@ -2621,7 +3699,7 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2621
3699
|
dependencies: block.dependencies
|
|
2622
3700
|
}))
|
|
2623
3701
|
].map(
|
|
2624
|
-
(binding) => bindingObject(binding, propsParameter, stateParameter,
|
|
3702
|
+
(binding) => bindingObject(binding, propsParameter, stateParameter, reactiveByValue, statesBySetter)
|
|
2625
3703
|
)
|
|
2626
3704
|
)
|
|
2627
3705
|
)
|
|
@@ -2715,7 +3793,8 @@ async function compileReactModule(code, id, options) {
|
|
|
2715
3793
|
useStateNames,
|
|
2716
3794
|
reactNames,
|
|
2717
3795
|
listNames,
|
|
2718
|
-
id
|
|
3796
|
+
id,
|
|
3797
|
+
options.reactivity
|
|
2719
3798
|
);
|
|
2720
3799
|
if (reason) {
|
|
2721
3800
|
diagnostics.push({
|
|
@@ -2842,6 +3921,10 @@ function normalizeReactCompilerOptions(value) {
|
|
|
2842
3921
|
if (!["fallback", "warn", "error"].includes(onUnsupported)) {
|
|
2843
3922
|
throw new TypeError(`Unknown unsupported-component behavior: ${String(onUnsupported)}`);
|
|
2844
3923
|
}
|
|
3924
|
+
const reactivity = options.reactivity || "hybrid";
|
|
3925
|
+
if (reactivity !== "static" && reactivity !== "hybrid") {
|
|
3926
|
+
throw new TypeError(`Unknown React compiler reactivity mode: ${String(reactivity)}`);
|
|
3927
|
+
}
|
|
2845
3928
|
if (options.report !== void 0 && typeof options.report !== "boolean") {
|
|
2846
3929
|
throw new TypeError("The React compiler report option must be a boolean.");
|
|
2847
3930
|
}
|
|
@@ -2852,7 +3935,7 @@ function normalizeReactCompilerOptions(value) {
|
|
|
2852
3935
|
}
|
|
2853
3936
|
const reportFile = normalizeCompilerReportFile(options.reportFile);
|
|
2854
3937
|
const report = options.report === true || options.reportFile !== void 0;
|
|
2855
|
-
return { mode, directive, onUnsupported, report, reportFile };
|
|
3938
|
+
return { mode, directive, onUnsupported, reactivity, report, reportFile };
|
|
2856
3939
|
}
|
|
2857
3940
|
|
|
2858
3941
|
// src/vite.ts
|
|
@@ -2868,7 +3951,7 @@ function readCompilerOptions(rendererOptions) {
|
|
|
2868
3951
|
);
|
|
2869
3952
|
}
|
|
2870
3953
|
const normalized = compiler;
|
|
2871
|
-
if ((normalized.mode === "infer" || normalized.mode === "annotation") && typeof normalized.directive === "string" && (normalized.onUnsupported === "fallback" || normalized.onUnsupported === "warn" || normalized.onUnsupported === "error")) {
|
|
3954
|
+
if ((normalized.mode === "infer" || normalized.mode === "annotation") && typeof normalized.directive === "string" && (normalized.reactivity === "static" || normalized.reactivity === "hybrid") && (normalized.onUnsupported === "fallback" || normalized.onUnsupported === "warn" || normalized.onUnsupported === "error")) {
|
|
2872
3955
|
return normalized;
|
|
2873
3956
|
}
|
|
2874
3957
|
return normalizeReactCompilerOptions(compiler);
|