@farm.js/react 0.1.0-beta.3 → 0.1.0-beta.5
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 +133 -37
- package/dist/compiler-runtime.cjs +2052 -188
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +106 -4
- package/dist/compiler-runtime.d.ts +106 -4
- package/dist/compiler-runtime.mjs +2041 -189
- 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 +1224 -87
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1224 -87
- package/dist/vite.mjs.map +1 -1
- package/package.json +6 -3
package/dist/vite.cjs
CHANGED
|
@@ -6,6 +6,96 @@ var promises = require('fs/promises');
|
|
|
6
6
|
var path = require('path');
|
|
7
7
|
|
|
8
8
|
// src/vite.ts
|
|
9
|
+
var DELEGATABLE_KEYED_ROW_EVENTS = /* @__PURE__ */ new Set([
|
|
10
|
+
"onBeforeInput",
|
|
11
|
+
"onBlur",
|
|
12
|
+
"onChange",
|
|
13
|
+
"onClick",
|
|
14
|
+
"onCompositionEnd",
|
|
15
|
+
"onCompositionStart",
|
|
16
|
+
"onCompositionUpdate",
|
|
17
|
+
"onContextMenu",
|
|
18
|
+
"onCopy",
|
|
19
|
+
"onCut",
|
|
20
|
+
"onDoubleClick",
|
|
21
|
+
"onDrag",
|
|
22
|
+
"onDragEnd",
|
|
23
|
+
"onDragEnter",
|
|
24
|
+
"onDragExit",
|
|
25
|
+
"onDragLeave",
|
|
26
|
+
"onDragOver",
|
|
27
|
+
"onDragStart",
|
|
28
|
+
"onDrop",
|
|
29
|
+
"onFocus",
|
|
30
|
+
"onInput",
|
|
31
|
+
"onKeyDown",
|
|
32
|
+
"onKeyPress",
|
|
33
|
+
"onKeyUp",
|
|
34
|
+
"onMouseDown",
|
|
35
|
+
"onMouseMove",
|
|
36
|
+
"onMouseOut",
|
|
37
|
+
"onMouseOver",
|
|
38
|
+
"onMouseUp",
|
|
39
|
+
"onPaste",
|
|
40
|
+
"onPointerCancel",
|
|
41
|
+
"onPointerDown",
|
|
42
|
+
"onPointerMove",
|
|
43
|
+
"onPointerOut",
|
|
44
|
+
"onPointerOver",
|
|
45
|
+
"onPointerUp",
|
|
46
|
+
"onReset",
|
|
47
|
+
"onSubmit",
|
|
48
|
+
"onTouchCancel",
|
|
49
|
+
"onTouchEnd",
|
|
50
|
+
"onTouchMove",
|
|
51
|
+
"onTouchStart",
|
|
52
|
+
"onWheel"
|
|
53
|
+
]);
|
|
54
|
+
function canDelegateKeyedRowEvents(plan) {
|
|
55
|
+
if (plan.events.length === 0 || plan.conditionals.length > 0) return false;
|
|
56
|
+
if (plan.source.openingElement.attributes.some(
|
|
57
|
+
(attribute) => core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && /^on[A-Z]/.test(attribute.name.name)
|
|
58
|
+
)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return plan.events.every(
|
|
62
|
+
(event) => DELEGATABLE_KEYED_ROW_EVENTS.has(event.name.replace(/Capture$/, ""))
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
var COMPILER_RUNTIME_FEATURE_EXPORTS = {
|
|
66
|
+
conditional: "conditionalRuntimeFeature",
|
|
67
|
+
"host-conditional": "hostConditionalRuntimeFeature",
|
|
68
|
+
"conditional-ranges": "conditionalRangesRuntimeFeature",
|
|
69
|
+
"keyed-list": "keyedListRuntimeFeature",
|
|
70
|
+
"keyed-rows": "keyedRowsRuntimeFeature",
|
|
71
|
+
"keyed-rows-conditional": "keyedRowsConditionalRuntimeFeature",
|
|
72
|
+
"keyed-rows-host": "keyedRowsHostRuntimeFeature",
|
|
73
|
+
"keyed-rows-complete": "keyedRowsCompleteRuntimeFeature",
|
|
74
|
+
"keyed-ranges": "keyedRangesRuntimeFeature",
|
|
75
|
+
"mixed-ranges": "mixedRangesRuntimeFeature",
|
|
76
|
+
component: "componentRuntimeFeature"
|
|
77
|
+
};
|
|
78
|
+
function runtimeFeaturesForPlans(plans) {
|
|
79
|
+
const features = /* @__PURE__ */ new Set();
|
|
80
|
+
let keyedRowsHaveConditionals = false;
|
|
81
|
+
let keyedRowsHaveHostBlocks = false;
|
|
82
|
+
for (const plan of plans) {
|
|
83
|
+
if (plan.kind === "keyed-rows") {
|
|
84
|
+
keyedRowsHaveConditionals || (keyedRowsHaveConditionals = plan.conditionals.length > 0);
|
|
85
|
+
keyedRowsHaveHostBlocks || (keyedRowsHaveHostBlocks = Boolean(plan.descriptorBlocks?.size));
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (plan.kind in COMPILER_RUNTIME_FEATURE_EXPORTS) {
|
|
89
|
+
features.add(plan.kind);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (plans.some((plan) => plan.kind === "keyed-rows")) {
|
|
93
|
+
features.add(
|
|
94
|
+
keyedRowsHaveConditionals && keyedRowsHaveHostBlocks ? "keyed-rows-complete" : keyedRowsHaveConditionals ? "keyed-rows-conditional" : keyedRowsHaveHostBlocks ? "keyed-rows-host" : "keyed-rows"
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return [...features].sort();
|
|
98
|
+
}
|
|
9
99
|
var SAFE_GLOBAL_CALLS = /* @__PURE__ */ new Set(["Boolean", "Number", "String"]);
|
|
10
100
|
var SAFE_MATH_CALLS = /* @__PURE__ */ new Set(["abs", "ceil", "floor", "max", "min", "round", "sign", "trunc"]);
|
|
11
101
|
function isComponentName(name) {
|
|
@@ -90,6 +180,37 @@ function rewriteDestructuredPropAccess(expression, names, propsParameter) {
|
|
|
90
180
|
});
|
|
91
181
|
return file.program.body[0].expression;
|
|
92
182
|
}
|
|
183
|
+
function collectDestructuredPropNames(expression, names, propsParameter) {
|
|
184
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
185
|
+
if (names.size === 0) return referenced;
|
|
186
|
+
core.traverse(expressionFile(cloneExpression(expression)), {
|
|
187
|
+
MemberExpression(path) {
|
|
188
|
+
const { object, property, computed } = path.node;
|
|
189
|
+
if (computed || !core.types.isIdentifier(object, { name: propsParameter.name }) || !core.types.isIdentifier(property) || !names.has(property.name)) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
referenced.add(property.name);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
return referenced;
|
|
196
|
+
}
|
|
197
|
+
function rewriteTrackedPropAccess(expression, propsParameter, bindingsByName) {
|
|
198
|
+
if (bindingsByName.size === 0) return cloneExpression(expression);
|
|
199
|
+
const file = expressionFile(cloneExpression(expression));
|
|
200
|
+
core.traverse(file, {
|
|
201
|
+
MemberExpression(path) {
|
|
202
|
+
const { object, property, computed } = path.node;
|
|
203
|
+
if (computed || !core.types.isIdentifier(object, { name: propsParameter.name }) || !core.types.isIdentifier(property)) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const binding = bindingsByName.get(property.name);
|
|
207
|
+
if (!binding) return;
|
|
208
|
+
path.replaceWith(core.types.identifier(binding.valueName));
|
|
209
|
+
path.skip();
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
return file.program.body[0].expression;
|
|
213
|
+
}
|
|
93
214
|
function rewriteHandlerAccess(root, handlersByName) {
|
|
94
215
|
if (handlersByName.size === 0) return { root: core.types.cloneNode(root, true) };
|
|
95
216
|
const file = expressionFile(core.types.cloneNode(root, true));
|
|
@@ -769,7 +890,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
769
890
|
const reason = visit(row, []);
|
|
770
891
|
return reason ? { reason } : { bindings, events, conditionals };
|
|
771
892
|
}
|
|
772
|
-
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames) {
|
|
893
|
+
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false) {
|
|
773
894
|
let collection;
|
|
774
895
|
let keyCallback;
|
|
775
896
|
let renderCallback;
|
|
@@ -824,17 +945,29 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames) {
|
|
|
824
945
|
safeGlobals,
|
|
825
946
|
new Set([...statesByValue.values()].map((state) => state.setterName))
|
|
826
947
|
);
|
|
827
|
-
if (rowAnalysis.reason) return void 0;
|
|
948
|
+
if (rowAnalysis.reason && !acceptUnsupportedRow) return void 0;
|
|
949
|
+
const keyExpression = returnedExpression(keyCallback);
|
|
950
|
+
const structureDependencies = new Set(collectStateDependencies(collection, statesByValue));
|
|
951
|
+
if (keyExpression) {
|
|
952
|
+
for (const dependency of collectStateDependencies(keyExpression, statesByValue)) {
|
|
953
|
+
structureDependencies.add(dependency);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
828
956
|
return {
|
|
829
957
|
source,
|
|
830
958
|
collection,
|
|
959
|
+
structureDependencies: [...structureDependencies].sort((left, right) => left - right),
|
|
831
960
|
keyCallback,
|
|
832
961
|
renderCallback,
|
|
833
962
|
row,
|
|
834
963
|
dependencies,
|
|
835
|
-
bindings: rowAnalysis.bindings || []
|
|
964
|
+
bindings: (rowAnalysis.bindings || []).map((binding) => ({
|
|
965
|
+
...binding,
|
|
966
|
+
dependencies: collectStateDependencies(binding.value, statesByValue)
|
|
967
|
+
})),
|
|
836
968
|
events: rowAnalysis.events || [],
|
|
837
969
|
conditionals: rowAnalysis.conditionals || [],
|
|
970
|
+
rowReason: rowAnalysis.reason,
|
|
838
971
|
syntax
|
|
839
972
|
};
|
|
840
973
|
}
|
|
@@ -851,22 +984,7 @@ function analyzeKeyedRowsContainer(container, statesByValue, safeGlobals, listNa
|
|
|
851
984
|
}
|
|
852
985
|
const children = meaningfulJsxChildren(container);
|
|
853
986
|
if (children.length !== 1) return void 0;
|
|
854
|
-
return analyzeKeyedRowChild(children[0], statesByValue, safeGlobals, listNames);
|
|
855
|
-
}
|
|
856
|
-
function isStaticRangeSibling(element, statesByValue, safeGlobals) {
|
|
857
|
-
for (const child of meaningfulJsxChildren(element)) {
|
|
858
|
-
if (core.types.isJSXFragment(child)) return false;
|
|
859
|
-
if (core.types.isJSXElement(child)) {
|
|
860
|
-
if (!isHostElement(child) || !isStaticRangeSibling(child, statesByValue, safeGlobals)) {
|
|
861
|
-
return false;
|
|
862
|
-
}
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression) && !isTextExpression(child.expression, statesByValue, safeGlobals)) {
|
|
866
|
-
return false;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
return true;
|
|
987
|
+
return analyzeKeyedRowChild(children[0], statesByValue, safeGlobals, listNames, true);
|
|
870
988
|
}
|
|
871
989
|
function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, listNames, allowSingleRange = false) {
|
|
872
990
|
if (container.openingElement.attributes.some(
|
|
@@ -878,6 +996,7 @@ function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
878
996
|
if (children.length < (allowSingleRange ? 1 : 2)) return void 0;
|
|
879
997
|
const ranges = [];
|
|
880
998
|
const dependencies = /* @__PURE__ */ new Set();
|
|
999
|
+
const staticBindings = [];
|
|
881
1000
|
let staticBefore = 0;
|
|
882
1001
|
for (const child of children) {
|
|
883
1002
|
const range = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames);
|
|
@@ -898,18 +1017,31 @@ function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
898
1017
|
continue;
|
|
899
1018
|
}
|
|
900
1019
|
if (!core.types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
901
|
-
|
|
1020
|
+
const analysis = analyzeHostConditionalTree(child, safeGlobals, true, statesByValue);
|
|
1021
|
+
if (analysis.reason) return void 0;
|
|
1022
|
+
for (const binding of analysis.bindings || []) {
|
|
1023
|
+
staticBindings.push({
|
|
1024
|
+
...binding,
|
|
1025
|
+
segment: ranges.length,
|
|
1026
|
+
sibling: staticBefore
|
|
1027
|
+
});
|
|
1028
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1029
|
+
dependencies.add(dependency);
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
902
1032
|
staticBefore += 1;
|
|
903
1033
|
}
|
|
904
1034
|
if (ranges.length === 0) return void 0;
|
|
905
1035
|
return {
|
|
906
1036
|
ranges,
|
|
907
1037
|
trailing: staticBefore,
|
|
908
|
-
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
1038
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1039
|
+
staticBindings
|
|
909
1040
|
};
|
|
910
1041
|
}
|
|
911
|
-
function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
1042
|
+
function analyzeHostConditionalTree(branch, safeGlobals, allowStaticEvents = false, statefulOnly) {
|
|
912
1043
|
const bindings = [];
|
|
1044
|
+
const needsStaticBinding = (expression) => !statefulOnly || collectStateDependencies(expression, statefulOnly).length > 0;
|
|
913
1045
|
const visit = (element, path) => {
|
|
914
1046
|
const tag = element.openingElement.name;
|
|
915
1047
|
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
@@ -918,20 +1050,26 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
918
1050
|
if (tag.name === "svg") return "compiler-owned conditionals do not support SVG yet";
|
|
919
1051
|
for (const attribute of element.openingElement.attributes) {
|
|
920
1052
|
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
1053
|
+
if (statefulOnly && !needsStaticBinding(attribute.argument)) continue;
|
|
921
1054
|
return "compiler-owned conditionals do not support JSX attribute spreads";
|
|
922
1055
|
}
|
|
923
1056
|
const name = jsxAttributeName(attribute);
|
|
924
1057
|
if (!name) return "compiler-owned conditionals do not support namespaced JSX attributes";
|
|
925
1058
|
if (name === "ref" || name === "dangerouslySetInnerHTML" || name === "key") {
|
|
1059
|
+
if (statefulOnly && (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression) || !needsStaticBinding(attribute.value.expression))) {
|
|
1060
|
+
continue;
|
|
1061
|
+
}
|
|
926
1062
|
return `compiler-owned conditional ${name} requires React ownership`;
|
|
927
1063
|
}
|
|
928
1064
|
if (/^on[A-Z]/.test(name)) {
|
|
1065
|
+
if (allowStaticEvents) continue;
|
|
929
1066
|
return "compiler-owned conditional events require React ownership";
|
|
930
1067
|
}
|
|
931
1068
|
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
932
1069
|
continue;
|
|
933
1070
|
}
|
|
934
1071
|
const expression = attribute.value.expression;
|
|
1072
|
+
if (!needsStaticBinding(expression)) continue;
|
|
935
1073
|
if (name === "style") {
|
|
936
1074
|
if (!core.types.isObjectExpression(expression)) {
|
|
937
1075
|
return "compiler-owned conditional styles must use one inline object literal";
|
|
@@ -944,6 +1082,7 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
944
1082
|
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
945
1083
|
return "compiler-owned conditional style names must use camelCase or a CSS custom property";
|
|
946
1084
|
}
|
|
1085
|
+
if (!needsStaticBinding(property.value)) continue;
|
|
947
1086
|
const unsupported2 = validateDerivedExpression(property.value, safeGlobals);
|
|
948
1087
|
if (unsupported2) {
|
|
949
1088
|
return `compiler-owned conditional style ${propertyName} cannot use ${unsupported2}`;
|
|
@@ -978,14 +1117,20 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
978
1117
|
const expressions = element.children.filter(
|
|
979
1118
|
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
980
1119
|
);
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1120
|
+
const boundExpressions = statefulOnly ? expressions.filter((child) => needsStaticBinding(child.expression)) : expressions;
|
|
1121
|
+
if (boundExpressions.length > 0) {
|
|
1122
|
+
for (const child of expressions) {
|
|
1123
|
+
const unsupported = validateDerivedExpression(
|
|
1124
|
+
child.expression,
|
|
1125
|
+
safeGlobals
|
|
1126
|
+
);
|
|
1127
|
+
if (unsupported) return `compiler-owned conditional text cannot use ${unsupported}`;
|
|
1128
|
+
}
|
|
984
1129
|
}
|
|
985
|
-
if (nestedElements.length > 0 &&
|
|
1130
|
+
if (nestedElements.length > 0 && boundExpressions.length > 0) {
|
|
986
1131
|
return "compiler-owned conditionals do not support dynamic text beside nested elements yet";
|
|
987
1132
|
}
|
|
988
|
-
if (nestedElements.length === 0 &&
|
|
1133
|
+
if (nestedElements.length === 0 && boundExpressions.length > 0) {
|
|
989
1134
|
const parts = [];
|
|
990
1135
|
for (const child of element.children) {
|
|
991
1136
|
if (core.types.isJSXText(child)) {
|
|
@@ -1009,7 +1154,369 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
1009
1154
|
const reason = visit(branch, []);
|
|
1010
1155
|
return reason ? { reason } : { bindings };
|
|
1011
1156
|
}
|
|
1012
|
-
function
|
|
1157
|
+
function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1158
|
+
const bindings = [];
|
|
1159
|
+
const plans = [];
|
|
1160
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
1161
|
+
const visit = (element, path, owner) => {
|
|
1162
|
+
const tag = element.openingElement.name;
|
|
1163
|
+
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
1164
|
+
return "recursive compiler-owned blocks support host elements only";
|
|
1165
|
+
}
|
|
1166
|
+
if (tag.name === "svg") return "recursive compiler-owned blocks do not support SVG yet";
|
|
1167
|
+
for (const attribute of element.openingElement.attributes) {
|
|
1168
|
+
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
1169
|
+
return "recursive compiler-owned blocks do not support JSX attribute spreads";
|
|
1170
|
+
}
|
|
1171
|
+
const name = jsxAttributeName(attribute);
|
|
1172
|
+
if (!name) return "recursive compiler-owned blocks do not support namespaced attributes";
|
|
1173
|
+
if (name === "ref" || name === "dangerouslySetInnerHTML" || name === "key") {
|
|
1174
|
+
return `recursive compiler-owned block ${name} requires React ownership`;
|
|
1175
|
+
}
|
|
1176
|
+
if (/^on[A-Z]/.test(name)) {
|
|
1177
|
+
return "recursive compiler-owned block events require React ownership";
|
|
1178
|
+
}
|
|
1179
|
+
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
1180
|
+
continue;
|
|
1181
|
+
}
|
|
1182
|
+
const expression = attribute.value.expression;
|
|
1183
|
+
if (name === "style") {
|
|
1184
|
+
if (!core.types.isObjectExpression(expression)) {
|
|
1185
|
+
return "recursive compiler-owned styles must use one inline object literal";
|
|
1186
|
+
}
|
|
1187
|
+
for (const property of expression.properties) {
|
|
1188
|
+
if (!core.types.isObjectProperty(property) || property.computed || !core.types.isExpression(property.value)) {
|
|
1189
|
+
return "recursive compiler-owned styles do not support spreads, methods, or computed properties";
|
|
1190
|
+
}
|
|
1191
|
+
const propertyName = core.types.isIdentifier(property.key) ? property.key.name : core.types.isStringLiteral(property.key) ? property.key.value : void 0;
|
|
1192
|
+
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
1193
|
+
return "recursive compiler-owned style names must use camelCase or a CSS custom property";
|
|
1194
|
+
}
|
|
1195
|
+
const unsupported2 = validateDerivedExpression(property.value, safeGlobals);
|
|
1196
|
+
if (unsupported2) {
|
|
1197
|
+
return `recursive compiler-owned style ${propertyName} cannot use ${unsupported2}`;
|
|
1198
|
+
}
|
|
1199
|
+
bindings.push({
|
|
1200
|
+
kind: "style",
|
|
1201
|
+
path: [...path],
|
|
1202
|
+
name: propertyName,
|
|
1203
|
+
value: cloneExpression(property.value)
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
continue;
|
|
1207
|
+
}
|
|
1208
|
+
if (name === "children") {
|
|
1209
|
+
return "recursive compiler-owned children props are not supported yet";
|
|
1210
|
+
}
|
|
1211
|
+
const unsupported = validateDerivedExpression(expression, safeGlobals);
|
|
1212
|
+
if (unsupported) return `recursive compiler-owned ${name} cannot use ${unsupported}`;
|
|
1213
|
+
bindings.push({
|
|
1214
|
+
kind: "attribute",
|
|
1215
|
+
path: [...path],
|
|
1216
|
+
name,
|
|
1217
|
+
value: cloneExpression(expression)
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
const children = meaningfulJsxChildren(element);
|
|
1221
|
+
const hasConditionalRange = children.some(
|
|
1222
|
+
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression) && conditionalBlockShape(child.expression) !== null
|
|
1223
|
+
);
|
|
1224
|
+
const hasKeyedRange = children.some(
|
|
1225
|
+
(child) => analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true) !== void 0
|
|
1226
|
+
);
|
|
1227
|
+
if (hasConditionalRange && hasKeyedRange) {
|
|
1228
|
+
const id = allocateId();
|
|
1229
|
+
const mixed = analyzeMixedRangesContainer(
|
|
1230
|
+
element,
|
|
1231
|
+
statesByValue,
|
|
1232
|
+
safeGlobals,
|
|
1233
|
+
listNames,
|
|
1234
|
+
id,
|
|
1235
|
+
allocateId
|
|
1236
|
+
);
|
|
1237
|
+
if (mixed) {
|
|
1238
|
+
plans.push(...mixed.nestedPlans);
|
|
1239
|
+
for (const [nestedElement, plan2] of mixed.descriptorBlocks) {
|
|
1240
|
+
blocks.set(nestedElement, plan2);
|
|
1241
|
+
}
|
|
1242
|
+
const plan = {
|
|
1243
|
+
kind: "nested-host-mixed-ranges",
|
|
1244
|
+
id,
|
|
1245
|
+
parent: owner,
|
|
1246
|
+
dependencies: mixed.dependencies,
|
|
1247
|
+
source: element,
|
|
1248
|
+
ranges: mixed.ranges,
|
|
1249
|
+
trailing: mixed.trailing,
|
|
1250
|
+
staticBindings: mixed.staticBindings
|
|
1251
|
+
};
|
|
1252
|
+
plans.push(plan);
|
|
1253
|
+
blocks.set(element, plan);
|
|
1254
|
+
return void 0;
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
const conditionalChildren = /* @__PURE__ */ new Map();
|
|
1258
|
+
let conditionalContainer = children.length > 0;
|
|
1259
|
+
for (const child of children) {
|
|
1260
|
+
if (core.types.isJSXElement(child) && isHostElement(child)) continue;
|
|
1261
|
+
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1262
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1263
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1264
|
+
conditionalChildren.set(child.expression, shape);
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
conditionalContainer = false;
|
|
1269
|
+
break;
|
|
1270
|
+
}
|
|
1271
|
+
if (conditionalContainer && conditionalChildren.size > 0) {
|
|
1272
|
+
const id = allocateId();
|
|
1273
|
+
const ranges = [];
|
|
1274
|
+
const staticBindings = [];
|
|
1275
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1276
|
+
let staticBefore2 = 0;
|
|
1277
|
+
for (const child of children) {
|
|
1278
|
+
if (core.types.isJSXElement(child)) {
|
|
1279
|
+
const nested = analyzeRecursiveHostTree(
|
|
1280
|
+
child,
|
|
1281
|
+
statesByValue,
|
|
1282
|
+
safeGlobals,
|
|
1283
|
+
listNames,
|
|
1284
|
+
owner,
|
|
1285
|
+
allocateId
|
|
1286
|
+
);
|
|
1287
|
+
if (nested.reason) return nested.reason;
|
|
1288
|
+
plans.push(...nested.plans);
|
|
1289
|
+
for (const [nestedElement, plan2] of nested.blocks) blocks.set(nestedElement, plan2);
|
|
1290
|
+
for (const binding of nested.bindings) {
|
|
1291
|
+
staticBindings.push({
|
|
1292
|
+
...binding,
|
|
1293
|
+
segment: ranges.length,
|
|
1294
|
+
sibling: staticBefore2
|
|
1295
|
+
});
|
|
1296
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1297
|
+
dependencies.add(dependency);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
staticBefore2 += 1;
|
|
1301
|
+
continue;
|
|
1302
|
+
}
|
|
1303
|
+
if (!core.types.isJSXExpressionContainer(child) || core.types.isJSXEmptyExpression(child.expression)) {
|
|
1304
|
+
return "recursive conditional ranges contain an unsupported child";
|
|
1305
|
+
}
|
|
1306
|
+
const expression = child.expression;
|
|
1307
|
+
const shape = conditionalChildren.get(expression);
|
|
1308
|
+
const truthy = shape.truthy ? analyzeRecursiveHostTree(
|
|
1309
|
+
shape.truthy,
|
|
1310
|
+
statesByValue,
|
|
1311
|
+
safeGlobals,
|
|
1312
|
+
listNames,
|
|
1313
|
+
id,
|
|
1314
|
+
allocateId
|
|
1315
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1316
|
+
const falsy = shape.falsy ? analyzeRecursiveHostTree(
|
|
1317
|
+
shape.falsy,
|
|
1318
|
+
statesByValue,
|
|
1319
|
+
safeGlobals,
|
|
1320
|
+
listNames,
|
|
1321
|
+
id,
|
|
1322
|
+
allocateId
|
|
1323
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1324
|
+
if (truthy.reason) return truthy.reason;
|
|
1325
|
+
if (falsy.reason) return falsy.reason;
|
|
1326
|
+
plans.push(...truthy.plans, ...falsy.plans);
|
|
1327
|
+
for (const [nestedElement, plan2] of truthy.blocks) blocks.set(nestedElement, plan2);
|
|
1328
|
+
for (const [nestedElement, plan2] of falsy.blocks) blocks.set(nestedElement, plan2);
|
|
1329
|
+
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1330
|
+
dependencies.add(dependency);
|
|
1331
|
+
}
|
|
1332
|
+
for (const binding of [...truthy.bindings, ...falsy.bindings]) {
|
|
1333
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1334
|
+
dependencies.add(dependency);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
ranges.push({
|
|
1338
|
+
before: staticBefore2,
|
|
1339
|
+
source: expression,
|
|
1340
|
+
test: cloneExpression(shape.test),
|
|
1341
|
+
logical: shape.logical,
|
|
1342
|
+
truthy: shape.truthy,
|
|
1343
|
+
falsy: shape.falsy,
|
|
1344
|
+
truthyBindings: truthy.bindings,
|
|
1345
|
+
falsyBindings: falsy.bindings
|
|
1346
|
+
});
|
|
1347
|
+
staticBefore2 = 0;
|
|
1348
|
+
}
|
|
1349
|
+
const plan = {
|
|
1350
|
+
kind: "nested-host-conditional-ranges",
|
|
1351
|
+
id,
|
|
1352
|
+
parent: owner,
|
|
1353
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1354
|
+
source: element,
|
|
1355
|
+
ranges,
|
|
1356
|
+
trailing: staticBefore2,
|
|
1357
|
+
staticBindings
|
|
1358
|
+
};
|
|
1359
|
+
plans.push(plan);
|
|
1360
|
+
blocks.set(element, plan);
|
|
1361
|
+
return void 0;
|
|
1362
|
+
}
|
|
1363
|
+
const keyedRows = [];
|
|
1364
|
+
let keyedContainer = children.length > 0;
|
|
1365
|
+
let staticBefore = 0;
|
|
1366
|
+
const staticChildren = [];
|
|
1367
|
+
for (const child of children) {
|
|
1368
|
+
const range = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true);
|
|
1369
|
+
if (range) {
|
|
1370
|
+
keyedRows.push({ before: staticBefore, range });
|
|
1371
|
+
staticBefore = 0;
|
|
1372
|
+
} else if (core.types.isJSXElement(child) && isHostElement(child)) {
|
|
1373
|
+
staticChildren.push({
|
|
1374
|
+
element: child,
|
|
1375
|
+
segment: keyedRows.length,
|
|
1376
|
+
sibling: staticBefore
|
|
1377
|
+
});
|
|
1378
|
+
staticBefore += 1;
|
|
1379
|
+
} else {
|
|
1380
|
+
keyedContainer = false;
|
|
1381
|
+
break;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (keyedContainer && keyedRows.length > 0) {
|
|
1385
|
+
const id = allocateId();
|
|
1386
|
+
const keyedRanges = [];
|
|
1387
|
+
const staticBindings = [];
|
|
1388
|
+
const keyedDependencies = /* @__PURE__ */ new Set();
|
|
1389
|
+
for (const { before, range } of keyedRows) {
|
|
1390
|
+
if (range.events.length > 0) {
|
|
1391
|
+
return "recursive compiler-owned keyed rows cannot contain events";
|
|
1392
|
+
}
|
|
1393
|
+
const row = core.types.cloneNode(range.row, true);
|
|
1394
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1395
|
+
(attribute) => !core.types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1396
|
+
);
|
|
1397
|
+
const rowAnalysis = analyzeRecursiveHostTree(
|
|
1398
|
+
row,
|
|
1399
|
+
statesByValue,
|
|
1400
|
+
safeGlobals,
|
|
1401
|
+
listNames,
|
|
1402
|
+
id,
|
|
1403
|
+
allocateId
|
|
1404
|
+
);
|
|
1405
|
+
if (rowAnalysis.reason) return rowAnalysis.reason;
|
|
1406
|
+
plans.push(...rowAnalysis.plans);
|
|
1407
|
+
for (const [nestedElement, nestedPlan] of rowAnalysis.blocks) {
|
|
1408
|
+
blocks.set(nestedElement, nestedPlan);
|
|
1409
|
+
}
|
|
1410
|
+
keyedRanges.push({
|
|
1411
|
+
before,
|
|
1412
|
+
source: range.source,
|
|
1413
|
+
collection: range.collection,
|
|
1414
|
+
keyCallback: range.keyCallback,
|
|
1415
|
+
renderCallback: range.renderCallback,
|
|
1416
|
+
row,
|
|
1417
|
+
bindings: rowAnalysis.bindings,
|
|
1418
|
+
syntax: range.syntax
|
|
1419
|
+
});
|
|
1420
|
+
for (const dependency of range.dependencies) keyedDependencies.add(dependency);
|
|
1421
|
+
}
|
|
1422
|
+
for (const { element: child, segment, sibling } of staticChildren) {
|
|
1423
|
+
const nested = analyzeRecursiveHostTree(
|
|
1424
|
+
child,
|
|
1425
|
+
statesByValue,
|
|
1426
|
+
safeGlobals,
|
|
1427
|
+
listNames,
|
|
1428
|
+
owner,
|
|
1429
|
+
allocateId
|
|
1430
|
+
);
|
|
1431
|
+
if (nested.reason) return nested.reason;
|
|
1432
|
+
plans.push(...nested.plans);
|
|
1433
|
+
for (const [nestedElement, plan2] of nested.blocks) blocks.set(nestedElement, plan2);
|
|
1434
|
+
for (const binding of nested.bindings) {
|
|
1435
|
+
staticBindings.push({ ...binding, segment, sibling });
|
|
1436
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1437
|
+
keyedDependencies.add(dependency);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
const plan = {
|
|
1442
|
+
kind: "nested-host-keyed-ranges",
|
|
1443
|
+
id,
|
|
1444
|
+
parent: owner,
|
|
1445
|
+
dependencies: [...keyedDependencies].sort((left, right) => left - right),
|
|
1446
|
+
source: element,
|
|
1447
|
+
ranges: keyedRanges,
|
|
1448
|
+
trailing: staticBefore,
|
|
1449
|
+
staticBindings
|
|
1450
|
+
};
|
|
1451
|
+
plans.push(plan);
|
|
1452
|
+
blocks.set(element, plan);
|
|
1453
|
+
return void 0;
|
|
1454
|
+
}
|
|
1455
|
+
if (element.children.some((child) => core.types.isJSXFragment(child))) {
|
|
1456
|
+
return "recursive compiler-owned blocks do not support fragments yet";
|
|
1457
|
+
}
|
|
1458
|
+
const nestedElements = element.children.filter(
|
|
1459
|
+
(child) => core.types.isJSXElement(child)
|
|
1460
|
+
);
|
|
1461
|
+
const expressions = element.children.filter(
|
|
1462
|
+
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
1463
|
+
);
|
|
1464
|
+
for (const child of expressions) {
|
|
1465
|
+
const unsupported = validateDerivedExpression(child.expression, safeGlobals);
|
|
1466
|
+
if (unsupported) return `recursive compiler-owned text cannot use ${unsupported}`;
|
|
1467
|
+
}
|
|
1468
|
+
if (nestedElements.length > 0 && expressions.length > 0) {
|
|
1469
|
+
return "recursive compiler-owned blocks do not support dynamic text beside nested elements";
|
|
1470
|
+
}
|
|
1471
|
+
if (nestedElements.length === 0 && expressions.length > 0) {
|
|
1472
|
+
const parts = [];
|
|
1473
|
+
for (const child of element.children) {
|
|
1474
|
+
if (core.types.isJSXText(child)) {
|
|
1475
|
+
const text = cleanJsxText(child.value);
|
|
1476
|
+
if (text) parts.push(core.types.stringLiteral(text));
|
|
1477
|
+
} else if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1478
|
+
parts.push(cloneExpression(child.expression));
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
bindings.push({ kind: "text", path: [...path], value: core.types.arrayExpression(parts) });
|
|
1482
|
+
}
|
|
1483
|
+
let elementIndex = 0;
|
|
1484
|
+
for (const child of element.children) {
|
|
1485
|
+
if (!core.types.isJSXElement(child)) continue;
|
|
1486
|
+
const reason2 = visit(child, [...path, elementIndex], owner);
|
|
1487
|
+
if (reason2) return reason2;
|
|
1488
|
+
elementIndex += 1;
|
|
1489
|
+
}
|
|
1490
|
+
return void 0;
|
|
1491
|
+
};
|
|
1492
|
+
const reason = visit(branch, [], parent);
|
|
1493
|
+
return { bindings, plans, blocks, reason };
|
|
1494
|
+
}
|
|
1495
|
+
function analyzeCompilerOwnedKeyedRowHostBlocks(shape, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1496
|
+
if (shape.events.length > 0) return void 0;
|
|
1497
|
+
const row = core.types.cloneNode(shape.row, true);
|
|
1498
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1499
|
+
(attribute) => !core.types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1500
|
+
);
|
|
1501
|
+
const analysis = analyzeRecursiveHostTree(
|
|
1502
|
+
row,
|
|
1503
|
+
statesByValue,
|
|
1504
|
+
safeGlobals,
|
|
1505
|
+
listNames,
|
|
1506
|
+
parent,
|
|
1507
|
+
allocateId
|
|
1508
|
+
);
|
|
1509
|
+
if (analysis.reason || analysis.plans.length === 0) {
|
|
1510
|
+
return void 0;
|
|
1511
|
+
}
|
|
1512
|
+
return {
|
|
1513
|
+
row,
|
|
1514
|
+
bindings: analysis.bindings,
|
|
1515
|
+
descriptorBlocks: analysis.blocks,
|
|
1516
|
+
nestedPlans: analysis.plans
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
function analyzeHostConditionalContainer(container, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1013
1520
|
const containerName = container.openingElement.name;
|
|
1014
1521
|
if (!core.types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg") {
|
|
1015
1522
|
return void 0;
|
|
@@ -1031,8 +1538,22 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals)
|
|
|
1031
1538
|
}
|
|
1032
1539
|
const shape = conditionalBlockShape(children[0].expression);
|
|
1033
1540
|
if (!shape || validateDerivedExpression(shape.test, safeGlobals)) return void 0;
|
|
1034
|
-
const truthyAnalysis = shape.truthy ?
|
|
1035
|
-
|
|
1541
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1542
|
+
shape.truthy,
|
|
1543
|
+
statesByValue,
|
|
1544
|
+
safeGlobals,
|
|
1545
|
+
listNames,
|
|
1546
|
+
parent,
|
|
1547
|
+
allocateId
|
|
1548
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1549
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1550
|
+
shape.falsy,
|
|
1551
|
+
statesByValue,
|
|
1552
|
+
safeGlobals,
|
|
1553
|
+
listNames,
|
|
1554
|
+
parent,
|
|
1555
|
+
allocateId
|
|
1556
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1036
1557
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1037
1558
|
const dependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1038
1559
|
for (const binding of [...truthyAnalysis.bindings || [], ...falsyAnalysis.bindings || []]) {
|
|
@@ -1047,10 +1568,12 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals)
|
|
|
1047
1568
|
truthy: shape.truthy,
|
|
1048
1569
|
falsy: shape.falsy,
|
|
1049
1570
|
truthyBindings: truthyAnalysis.bindings || [],
|
|
1050
|
-
falsyBindings: falsyAnalysis.bindings || []
|
|
1571
|
+
falsyBindings: falsyAnalysis.bindings || [],
|
|
1572
|
+
descriptorBlocks: new Map([...truthyAnalysis.blocks, ...falsyAnalysis.blocks]),
|
|
1573
|
+
nestedPlans: [...truthyAnalysis.plans, ...falsyAnalysis.plans]
|
|
1051
1574
|
};
|
|
1052
1575
|
}
|
|
1053
|
-
function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals, allowSingleRange
|
|
1576
|
+
function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals, allowSingleRange, listNames, parent, allocateId) {
|
|
1054
1577
|
const containerName = container.openingElement.name;
|
|
1055
1578
|
if (!core.types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg" || container.openingElement.attributes.some(
|
|
1056
1579
|
(attribute) => core.types.isJSXSpreadAttribute(attribute) || core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
@@ -1061,14 +1584,34 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1061
1584
|
if (children.length < (allowSingleRange ? 1 : 2)) return void 0;
|
|
1062
1585
|
const ranges = [];
|
|
1063
1586
|
const dependencies = /* @__PURE__ */ new Set();
|
|
1587
|
+
const descriptorBlocks = /* @__PURE__ */ new Map();
|
|
1588
|
+
const nestedPlans = [];
|
|
1589
|
+
const staticBindings = [];
|
|
1064
1590
|
let staticBefore = 0;
|
|
1065
1591
|
for (const child of children) {
|
|
1066
1592
|
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1067
1593
|
const shape = conditionalBlockShape(child.expression);
|
|
1068
1594
|
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1069
|
-
const truthyAnalysis = shape.truthy ?
|
|
1070
|
-
|
|
1595
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1596
|
+
shape.truthy,
|
|
1597
|
+
statesByValue,
|
|
1598
|
+
safeGlobals,
|
|
1599
|
+
listNames,
|
|
1600
|
+
parent,
|
|
1601
|
+
allocateId
|
|
1602
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1603
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1604
|
+
shape.falsy,
|
|
1605
|
+
statesByValue,
|
|
1606
|
+
safeGlobals,
|
|
1607
|
+
listNames,
|
|
1608
|
+
parent,
|
|
1609
|
+
allocateId
|
|
1610
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1071
1611
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1612
|
+
nestedPlans.push(...truthyAnalysis.plans, ...falsyAnalysis.plans);
|
|
1613
|
+
for (const [element, plan] of truthyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
1614
|
+
for (const [element, plan] of falsyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
1072
1615
|
const rangeDependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1073
1616
|
for (const binding of [
|
|
1074
1617
|
...truthyAnalysis.bindings || [],
|
|
@@ -1094,14 +1637,158 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1094
1637
|
}
|
|
1095
1638
|
}
|
|
1096
1639
|
if (!core.types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
1097
|
-
|
|
1640
|
+
const staticAnalysis = analyzeHostConditionalTree(child, safeGlobals, true, statesByValue);
|
|
1641
|
+
if (staticAnalysis.reason) return void 0;
|
|
1642
|
+
for (const binding of staticAnalysis.bindings || []) {
|
|
1643
|
+
staticBindings.push({
|
|
1644
|
+
...binding,
|
|
1645
|
+
segment: ranges.length,
|
|
1646
|
+
sibling: staticBefore
|
|
1647
|
+
});
|
|
1648
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1649
|
+
dependencies.add(dependency);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1098
1652
|
staticBefore += 1;
|
|
1099
1653
|
}
|
|
1100
1654
|
if (ranges.length === 0) return void 0;
|
|
1101
1655
|
return {
|
|
1102
1656
|
ranges,
|
|
1103
1657
|
trailing: staticBefore,
|
|
1104
|
-
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
1658
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1659
|
+
staticBindings,
|
|
1660
|
+
descriptorBlocks,
|
|
1661
|
+
nestedPlans
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1665
|
+
const containerName = container.openingElement.name;
|
|
1666
|
+
if (!core.types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg" || container.openingElement.attributes.some(
|
|
1667
|
+
(attribute) => core.types.isJSXSpreadAttribute(attribute) || core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
1668
|
+
)) {
|
|
1669
|
+
return void 0;
|
|
1670
|
+
}
|
|
1671
|
+
const children = meaningfulJsxChildren(container);
|
|
1672
|
+
if (children.length < 2) return void 0;
|
|
1673
|
+
const ranges = [];
|
|
1674
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1675
|
+
const descriptorBlocks = /* @__PURE__ */ new Map();
|
|
1676
|
+
const nestedPlans = [];
|
|
1677
|
+
const staticBindings = [];
|
|
1678
|
+
let conditionalCount = 0;
|
|
1679
|
+
let keyedCount = 0;
|
|
1680
|
+
let staticBefore = 0;
|
|
1681
|
+
const mergeAnalysis = (analysis) => {
|
|
1682
|
+
if (analysis.reason) return false;
|
|
1683
|
+
nestedPlans.push(...analysis.plans);
|
|
1684
|
+
for (const [element, plan] of analysis.blocks) descriptorBlocks.set(element, plan);
|
|
1685
|
+
for (const binding of analysis.bindings) {
|
|
1686
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1687
|
+
dependencies.add(dependency);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
return true;
|
|
1691
|
+
};
|
|
1692
|
+
for (const child of children) {
|
|
1693
|
+
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1694
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1695
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1696
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1697
|
+
shape.truthy,
|
|
1698
|
+
statesByValue,
|
|
1699
|
+
safeGlobals,
|
|
1700
|
+
listNames,
|
|
1701
|
+
parent,
|
|
1702
|
+
allocateId
|
|
1703
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1704
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1705
|
+
shape.falsy,
|
|
1706
|
+
statesByValue,
|
|
1707
|
+
safeGlobals,
|
|
1708
|
+
listNames,
|
|
1709
|
+
parent,
|
|
1710
|
+
allocateId
|
|
1711
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1712
|
+
if (!mergeAnalysis(truthyAnalysis) || !mergeAnalysis(falsyAnalysis)) return void 0;
|
|
1713
|
+
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1714
|
+
dependencies.add(dependency);
|
|
1715
|
+
}
|
|
1716
|
+
ranges.push({
|
|
1717
|
+
rangeKind: "conditional",
|
|
1718
|
+
before: staticBefore,
|
|
1719
|
+
source: child.expression,
|
|
1720
|
+
test: cloneExpression(shape.test),
|
|
1721
|
+
logical: shape.logical,
|
|
1722
|
+
truthy: shape.truthy,
|
|
1723
|
+
falsy: shape.falsy,
|
|
1724
|
+
truthyBindings: truthyAnalysis.bindings,
|
|
1725
|
+
falsyBindings: falsyAnalysis.bindings
|
|
1726
|
+
});
|
|
1727
|
+
conditionalCount += 1;
|
|
1728
|
+
staticBefore = 0;
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
const keyed = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true);
|
|
1733
|
+
if (keyed) {
|
|
1734
|
+
if (keyed.events.length > 0) return void 0;
|
|
1735
|
+
const row = core.types.cloneNode(keyed.row, true);
|
|
1736
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1737
|
+
(attribute) => !core.types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1738
|
+
);
|
|
1739
|
+
const rowAnalysis = analyzeRecursiveHostTree(
|
|
1740
|
+
row,
|
|
1741
|
+
statesByValue,
|
|
1742
|
+
safeGlobals,
|
|
1743
|
+
listNames,
|
|
1744
|
+
parent,
|
|
1745
|
+
allocateId
|
|
1746
|
+
);
|
|
1747
|
+
if (!mergeAnalysis(rowAnalysis)) return void 0;
|
|
1748
|
+
for (const dependency of keyed.dependencies) dependencies.add(dependency);
|
|
1749
|
+
ranges.push({
|
|
1750
|
+
rangeKind: "keyed",
|
|
1751
|
+
before: staticBefore,
|
|
1752
|
+
source: keyed.source,
|
|
1753
|
+
collection: keyed.collection,
|
|
1754
|
+
keyCallback: keyed.keyCallback,
|
|
1755
|
+
renderCallback: keyed.renderCallback,
|
|
1756
|
+
row,
|
|
1757
|
+
bindings: rowAnalysis.bindings,
|
|
1758
|
+
syntax: keyed.syntax
|
|
1759
|
+
});
|
|
1760
|
+
keyedCount += 1;
|
|
1761
|
+
staticBefore = 0;
|
|
1762
|
+
continue;
|
|
1763
|
+
}
|
|
1764
|
+
if (!core.types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
1765
|
+
const staticAnalysis = analyzeRecursiveHostTree(
|
|
1766
|
+
child,
|
|
1767
|
+
statesByValue,
|
|
1768
|
+
safeGlobals,
|
|
1769
|
+
listNames,
|
|
1770
|
+
parent,
|
|
1771
|
+
allocateId
|
|
1772
|
+
);
|
|
1773
|
+
if (staticAnalysis.reason) return void 0;
|
|
1774
|
+
for (const binding of staticAnalysis.bindings) {
|
|
1775
|
+
staticBindings.push({
|
|
1776
|
+
...binding,
|
|
1777
|
+
segment: ranges.length,
|
|
1778
|
+
sibling: staticBefore
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
if (!mergeAnalysis(staticAnalysis)) return void 0;
|
|
1782
|
+
staticBefore += 1;
|
|
1783
|
+
}
|
|
1784
|
+
if (conditionalCount === 0 || keyedCount === 0) return void 0;
|
|
1785
|
+
return {
|
|
1786
|
+
ranges,
|
|
1787
|
+
trailing: staticBefore,
|
|
1788
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1789
|
+
staticBindings,
|
|
1790
|
+
descriptorBlocks,
|
|
1791
|
+
nestedPlans
|
|
1105
1792
|
};
|
|
1106
1793
|
}
|
|
1107
1794
|
function keyedListBoundary(blockRuntime, plan, source) {
|
|
@@ -1126,14 +1813,14 @@ function keyedListBoundary(blockRuntime, plan, source) {
|
|
|
1126
1813
|
true
|
|
1127
1814
|
);
|
|
1128
1815
|
}
|
|
1129
|
-
function hostElementDescriptor(element) {
|
|
1816
|
+
function hostElementDescriptor(element, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1130
1817
|
const tag = element.openingElement.name;
|
|
1131
1818
|
const attributes = [];
|
|
1132
1819
|
const styles = [];
|
|
1133
1820
|
for (const attribute of element.openingElement.attributes) {
|
|
1134
1821
|
if (!core.types.isJSXAttribute(attribute)) continue;
|
|
1135
1822
|
const name = jsxAttributeName(attribute);
|
|
1136
|
-
if (!name || name === "key" || /^on[A-Z]/.test(name)) continue;
|
|
1823
|
+
if (!name || name === "key" || name === "ref" || /^on[A-Z]/.test(name)) continue;
|
|
1137
1824
|
if (name === "style") {
|
|
1138
1825
|
if (core.types.isJSXExpressionContainer(attribute.value) && core.types.isObjectExpression(attribute.value.expression)) {
|
|
1139
1826
|
for (const property of attribute.value.expression.properties) {
|
|
@@ -1157,24 +1844,93 @@ function hostElementDescriptor(element) {
|
|
|
1157
1844
|
])
|
|
1158
1845
|
);
|
|
1159
1846
|
}
|
|
1847
|
+
const block = descriptorBlocks.get(element);
|
|
1848
|
+
const conditionalBySource = /* @__PURE__ */ new Map();
|
|
1849
|
+
const keyedBySource = /* @__PURE__ */ new Map();
|
|
1850
|
+
if (block?.kind === "nested-host-conditional-ranges") {
|
|
1851
|
+
for (const range of block.ranges) conditionalBySource.set(range.source, range);
|
|
1852
|
+
} else if (block?.kind === "nested-host-keyed-ranges") {
|
|
1853
|
+
for (const range of block.ranges) keyedBySource.set(range.source, range);
|
|
1854
|
+
} else if (block?.kind === "nested-host-mixed-ranges") {
|
|
1855
|
+
for (const range of block.ranges) {
|
|
1856
|
+
if (range.rangeKind === "conditional") conditionalBySource.set(range.source, range);
|
|
1857
|
+
else keyedBySource.set(range.source, range);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1160
1860
|
const children = [];
|
|
1161
1861
|
for (const child of element.children) {
|
|
1162
1862
|
if (core.types.isJSXText(child)) {
|
|
1163
1863
|
const text = cleanJsxText(child.value);
|
|
1164
1864
|
if (text) children.push(core.types.stringLiteral(text));
|
|
1165
1865
|
} else if (core.types.isJSXElement(child)) {
|
|
1166
|
-
|
|
1866
|
+
const keyedRange = keyedBySource.get(child);
|
|
1867
|
+
if (keyedRange) {
|
|
1868
|
+
if (block?.kind !== "nested-host-keyed-ranges") {
|
|
1869
|
+
children.push(keyedRangeDescriptorChildren(keyedRange, descriptorBlocks));
|
|
1870
|
+
}
|
|
1871
|
+
} else {
|
|
1872
|
+
children.push(hostElementDescriptor(child, descriptorBlocks));
|
|
1873
|
+
}
|
|
1167
1874
|
} else if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1168
|
-
|
|
1875
|
+
const conditionalRange = conditionalBySource.get(child.expression);
|
|
1876
|
+
const keyedRange = keyedBySource.get(child.expression);
|
|
1877
|
+
if (conditionalRange) {
|
|
1878
|
+
children.push(conditionalRangeDescriptorChild(conditionalRange, descriptorBlocks));
|
|
1879
|
+
} else if (keyedRange) {
|
|
1880
|
+
if (block?.kind !== "nested-host-keyed-ranges") {
|
|
1881
|
+
children.push(keyedRangeDescriptorChildren(keyedRange, descriptorBlocks));
|
|
1882
|
+
}
|
|
1883
|
+
} else {
|
|
1884
|
+
children.push(cloneExpression(child.expression));
|
|
1885
|
+
}
|
|
1169
1886
|
}
|
|
1170
1887
|
}
|
|
1171
|
-
|
|
1888
|
+
const properties = [
|
|
1172
1889
|
core.types.objectProperty(core.types.identifier("kind"), core.types.stringLiteral("element")),
|
|
1173
1890
|
core.types.objectProperty(core.types.identifier("tag"), core.types.stringLiteral(tag.name)),
|
|
1174
1891
|
core.types.objectProperty(core.types.identifier("attributes"), core.types.arrayExpression(attributes)),
|
|
1175
1892
|
core.types.objectProperty(core.types.identifier("styles"), core.types.arrayExpression(styles)),
|
|
1176
1893
|
core.types.objectProperty(core.types.identifier("children"), core.types.arrayExpression(children))
|
|
1177
|
-
]
|
|
1894
|
+
];
|
|
1895
|
+
if (block) {
|
|
1896
|
+
properties.push(
|
|
1897
|
+
core.types.objectProperty(core.types.identifier("block"), nestedHostBlockObject(block, descriptorBlocks))
|
|
1898
|
+
);
|
|
1899
|
+
}
|
|
1900
|
+
return core.types.objectExpression(properties);
|
|
1901
|
+
}
|
|
1902
|
+
function conditionalRangeDescriptorChild(range, descriptorBlocks) {
|
|
1903
|
+
const truthy = range.truthy ? hostElementDescriptor(range.truthy, descriptorBlocks) : core.types.nullLiteral();
|
|
1904
|
+
if (range.logical) {
|
|
1905
|
+
return core.types.logicalExpression("&&", cloneExpression(range.test), truthy);
|
|
1906
|
+
}
|
|
1907
|
+
return core.types.conditionalExpression(
|
|
1908
|
+
cloneExpression(range.test),
|
|
1909
|
+
truthy,
|
|
1910
|
+
range.falsy ? hostElementDescriptor(range.falsy, descriptorBlocks) : core.types.nullLiteral()
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1913
|
+
function keyedRangeDescriptorChildren(range, descriptorBlocks) {
|
|
1914
|
+
const parameters = range.renderCallback.params.map(
|
|
1915
|
+
(parameter) => core.types.cloneNode(parameter, true)
|
|
1916
|
+
);
|
|
1917
|
+
const callback = core.types.arrowFunctionExpression(
|
|
1918
|
+
parameters,
|
|
1919
|
+
hostElementDescriptor(range.row, descriptorBlocks)
|
|
1920
|
+
);
|
|
1921
|
+
const collection = cloneExpression(range.collection);
|
|
1922
|
+
if (range.syntax === "map") {
|
|
1923
|
+
return core.types.callExpression(core.types.memberExpression(collection, core.types.identifier("map")), [callback]);
|
|
1924
|
+
}
|
|
1925
|
+
return core.types.callExpression(
|
|
1926
|
+
core.types.memberExpression(
|
|
1927
|
+
core.types.callExpression(core.types.memberExpression(core.types.identifier("Array"), core.types.identifier("from")), [
|
|
1928
|
+
core.types.logicalExpression("||", collection, core.types.arrayExpression([]))
|
|
1929
|
+
]),
|
|
1930
|
+
core.types.identifier("map")
|
|
1931
|
+
),
|
|
1932
|
+
[callback]
|
|
1933
|
+
);
|
|
1178
1934
|
}
|
|
1179
1935
|
function keyedRowBindingObject(binding, parameters) {
|
|
1180
1936
|
const properties = [
|
|
@@ -1182,6 +1938,12 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1182
1938
|
core.types.objectProperty(
|
|
1183
1939
|
core.types.identifier("path"),
|
|
1184
1940
|
core.types.arrayExpression(binding.path.map((part) => core.types.numericLiteral(part)))
|
|
1941
|
+
),
|
|
1942
|
+
core.types.objectProperty(
|
|
1943
|
+
core.types.identifier("dependencies"),
|
|
1944
|
+
core.types.arrayExpression(
|
|
1945
|
+
(binding.dependencies || []).map((dependency) => core.types.numericLiteral(dependency))
|
|
1946
|
+
)
|
|
1185
1947
|
)
|
|
1186
1948
|
];
|
|
1187
1949
|
if (binding.name) {
|
|
@@ -1198,6 +1960,16 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1198
1960
|
);
|
|
1199
1961
|
return core.types.objectExpression(properties);
|
|
1200
1962
|
}
|
|
1963
|
+
function staticRangeBindingObject(binding) {
|
|
1964
|
+
const value = keyedRowBindingObject(binding, []);
|
|
1965
|
+
value.properties.splice(
|
|
1966
|
+
1,
|
|
1967
|
+
0,
|
|
1968
|
+
core.types.objectProperty(core.types.identifier("segment"), core.types.numericLiteral(binding.segment)),
|
|
1969
|
+
core.types.objectProperty(core.types.identifier("sibling"), core.types.numericLiteral(binding.sibling))
|
|
1970
|
+
);
|
|
1971
|
+
return value;
|
|
1972
|
+
}
|
|
1201
1973
|
function uniqueLocalIdentifier(base, nodes) {
|
|
1202
1974
|
const names = /* @__PURE__ */ new Set();
|
|
1203
1975
|
for (const node of nodes) {
|
|
@@ -1314,6 +2086,10 @@ function keyedRowEventObject(event, renderParameters) {
|
|
|
1314
2086
|
const parameters = [core.types.cloneNode(renderParameters[0], true), index, syntheticEvent];
|
|
1315
2087
|
return core.types.objectExpression([
|
|
1316
2088
|
core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(event.name)),
|
|
2089
|
+
core.types.objectProperty(
|
|
2090
|
+
core.types.identifier("path"),
|
|
2091
|
+
core.types.arrayExpression(event.path.map((part) => core.types.numericLiteral(part)))
|
|
2092
|
+
),
|
|
1317
2093
|
core.types.objectProperty(
|
|
1318
2094
|
core.types.identifier("invoke"),
|
|
1319
2095
|
core.types.arrowFunctionExpression(
|
|
@@ -1383,6 +2159,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1383
2159
|
plan.source,
|
|
1384
2160
|
...plan.conditionals.map((conditional) => conditional.test)
|
|
1385
2161
|
]);
|
|
2162
|
+
const delegatedEvents = canDelegateKeyedRowEvents(plan);
|
|
1386
2163
|
const renderSource = keyedRowsRenderSource(plan, eventFactory, conditionalFactory);
|
|
1387
2164
|
const renderFactoryParameters = plan.conditionals.length > 0 ? [core.types.cloneNode(eventFactory), core.types.cloneNode(conditionalFactory)] : plan.events.length > 0 ? [core.types.cloneNode(eventFactory)] : [];
|
|
1388
2165
|
return core.types.jsxElement(
|
|
@@ -1400,6 +2177,14 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1400
2177
|
core.types.jsxIdentifier("items"),
|
|
1401
2178
|
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], cloneExpression(plan.collection)))
|
|
1402
2179
|
),
|
|
2180
|
+
core.types.jsxAttribute(
|
|
2181
|
+
core.types.jsxIdentifier("structureDependencies"),
|
|
2182
|
+
core.types.jsxExpressionContainer(
|
|
2183
|
+
core.types.arrayExpression(
|
|
2184
|
+
plan.structureDependencies.map((dependency) => core.types.numericLiteral(dependency))
|
|
2185
|
+
)
|
|
2186
|
+
)
|
|
2187
|
+
),
|
|
1403
2188
|
core.types.jsxAttribute(
|
|
1404
2189
|
core.types.jsxIdentifier("rowKey"),
|
|
1405
2190
|
core.types.jsxExpressionContainer(core.types.cloneNode(plan.keyCallback, true))
|
|
@@ -1409,7 +2194,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1409
2194
|
core.types.jsxExpressionContainer(
|
|
1410
2195
|
core.types.arrowFunctionExpression(
|
|
1411
2196
|
parameters.map((parameter) => core.types.cloneNode(parameter, true)),
|
|
1412
|
-
hostElementDescriptor(plan.row)
|
|
2197
|
+
hostElementDescriptor(plan.row, plan.descriptorBlocks)
|
|
1413
2198
|
)
|
|
1414
2199
|
)
|
|
1415
2200
|
),
|
|
@@ -1429,7 +2214,13 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1429
2214
|
plan.events.map((event) => keyedRowEventObject(event, parameters))
|
|
1430
2215
|
)
|
|
1431
2216
|
)
|
|
1432
|
-
)
|
|
2217
|
+
),
|
|
2218
|
+
...delegatedEvents ? [
|
|
2219
|
+
core.types.jsxAttribute(
|
|
2220
|
+
core.types.jsxIdentifier("delegateEvents"),
|
|
2221
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
2222
|
+
)
|
|
2223
|
+
] : []
|
|
1433
2224
|
] : [],
|
|
1434
2225
|
...plan.conditionals.length > 0 ? [
|
|
1435
2226
|
core.types.jsxAttribute(
|
|
@@ -1442,6 +2233,12 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1442
2233
|
)
|
|
1443
2234
|
)
|
|
1444
2235
|
)
|
|
2236
|
+
] : [],
|
|
2237
|
+
...plan.descriptorBlocks?.size ? [
|
|
2238
|
+
core.types.jsxAttribute(
|
|
2239
|
+
core.types.jsxIdentifier("hostBlocks"),
|
|
2240
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
2241
|
+
)
|
|
1445
2242
|
] : []
|
|
1446
2243
|
],
|
|
1447
2244
|
true
|
|
@@ -1451,7 +2248,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1451
2248
|
true
|
|
1452
2249
|
);
|
|
1453
2250
|
}
|
|
1454
|
-
function keyedRangeObject(range) {
|
|
2251
|
+
function keyedRangeObject(range, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1455
2252
|
const parameters = range.renderCallback.params.map(
|
|
1456
2253
|
(parameter) => core.types.cloneNode(parameter, true)
|
|
1457
2254
|
);
|
|
@@ -1466,7 +2263,7 @@ function keyedRangeObject(range) {
|
|
|
1466
2263
|
core.types.identifier("create"),
|
|
1467
2264
|
core.types.arrowFunctionExpression(
|
|
1468
2265
|
parameters.map((parameter) => core.types.cloneNode(parameter, true)),
|
|
1469
|
-
hostElementDescriptor(range.row)
|
|
2266
|
+
hostElementDescriptor(range.row, descriptorBlocks)
|
|
1470
2267
|
)
|
|
1471
2268
|
),
|
|
1472
2269
|
core.types.objectProperty(
|
|
@@ -1510,6 +2307,12 @@ function keyedRangesBoundary(blockRuntime, plan) {
|
|
|
1510
2307
|
core.types.jsxAttribute(
|
|
1511
2308
|
core.types.jsxIdentifier("trailing"),
|
|
1512
2309
|
core.types.jsxExpressionContainer(core.types.numericLiteral(plan.trailing))
|
|
2310
|
+
),
|
|
2311
|
+
core.types.jsxAttribute(
|
|
2312
|
+
core.types.jsxIdentifier("bindings"),
|
|
2313
|
+
core.types.jsxExpressionContainer(
|
|
2314
|
+
core.types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2315
|
+
)
|
|
1513
2316
|
)
|
|
1514
2317
|
],
|
|
1515
2318
|
true
|
|
@@ -1519,11 +2322,11 @@ function keyedRangesBoundary(blockRuntime, plan) {
|
|
|
1519
2322
|
true
|
|
1520
2323
|
);
|
|
1521
2324
|
}
|
|
1522
|
-
function hostConditionalBranchObject(branch, bindings) {
|
|
2325
|
+
function hostConditionalBranchObject(branch, bindings, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1523
2326
|
return core.types.objectExpression([
|
|
1524
2327
|
core.types.objectProperty(
|
|
1525
2328
|
core.types.identifier("create"),
|
|
1526
|
-
core.types.arrowFunctionExpression([], hostElementDescriptor(branch))
|
|
2329
|
+
core.types.arrowFunctionExpression([], hostElementDescriptor(branch, descriptorBlocks))
|
|
1527
2330
|
),
|
|
1528
2331
|
core.types.objectProperty(
|
|
1529
2332
|
core.types.identifier("bindings"),
|
|
@@ -1552,7 +2355,9 @@ function hostConditionalBoundary(blockRuntime, plan) {
|
|
|
1552
2355
|
attributes.push(
|
|
1553
2356
|
core.types.jsxAttribute(
|
|
1554
2357
|
core.types.jsxIdentifier("truthy"),
|
|
1555
|
-
core.types.jsxExpressionContainer(
|
|
2358
|
+
core.types.jsxExpressionContainer(
|
|
2359
|
+
hostConditionalBranchObject(plan.truthy, plan.truthyBindings, plan.descriptorBlocks)
|
|
2360
|
+
)
|
|
1556
2361
|
)
|
|
1557
2362
|
);
|
|
1558
2363
|
}
|
|
@@ -1560,13 +2365,15 @@ function hostConditionalBoundary(blockRuntime, plan) {
|
|
|
1560
2365
|
attributes.push(
|
|
1561
2366
|
core.types.jsxAttribute(
|
|
1562
2367
|
core.types.jsxIdentifier("falsy"),
|
|
1563
|
-
core.types.jsxExpressionContainer(
|
|
2368
|
+
core.types.jsxExpressionContainer(
|
|
2369
|
+
hostConditionalBranchObject(plan.falsy, plan.falsyBindings, plan.descriptorBlocks)
|
|
2370
|
+
)
|
|
1564
2371
|
)
|
|
1565
2372
|
);
|
|
1566
2373
|
}
|
|
1567
2374
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
1568
2375
|
}
|
|
1569
|
-
function conditionalRangeObject(range) {
|
|
2376
|
+
function conditionalRangeObject(range, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1570
2377
|
const properties = [
|
|
1571
2378
|
core.types.objectProperty(core.types.identifier("before"), core.types.numericLiteral(range.before)),
|
|
1572
2379
|
core.types.objectProperty(
|
|
@@ -1581,7 +2388,7 @@ function conditionalRangeObject(range) {
|
|
|
1581
2388
|
properties.push(
|
|
1582
2389
|
core.types.objectProperty(
|
|
1583
2390
|
core.types.identifier("truthy"),
|
|
1584
|
-
hostConditionalBranchObject(range.truthy, range.truthyBindings)
|
|
2391
|
+
hostConditionalBranchObject(range.truthy, range.truthyBindings, descriptorBlocks)
|
|
1585
2392
|
)
|
|
1586
2393
|
);
|
|
1587
2394
|
}
|
|
@@ -1589,12 +2396,78 @@ function conditionalRangeObject(range) {
|
|
|
1589
2396
|
properties.push(
|
|
1590
2397
|
core.types.objectProperty(
|
|
1591
2398
|
core.types.identifier("falsy"),
|
|
1592
|
-
hostConditionalBranchObject(range.falsy, range.falsyBindings)
|
|
2399
|
+
hostConditionalBranchObject(range.falsy, range.falsyBindings, descriptorBlocks)
|
|
1593
2400
|
)
|
|
1594
2401
|
);
|
|
1595
2402
|
}
|
|
1596
2403
|
return core.types.objectExpression(properties);
|
|
1597
2404
|
}
|
|
2405
|
+
function nestedHostBlockObject(plan, descriptorBlocks) {
|
|
2406
|
+
const kind = plan.kind === "nested-host-conditional-ranges" ? "conditional-ranges" : plan.kind === "nested-host-keyed-ranges" ? "keyed-ranges" : "mixed-ranges";
|
|
2407
|
+
return core.types.objectExpression([
|
|
2408
|
+
core.types.objectProperty(core.types.identifier("kind"), core.types.stringLiteral(kind)),
|
|
2409
|
+
core.types.objectProperty(core.types.identifier("id"), core.types.numericLiteral(plan.id)),
|
|
2410
|
+
core.types.objectProperty(
|
|
2411
|
+
core.types.identifier("ranges"),
|
|
2412
|
+
core.types.arrayExpression(
|
|
2413
|
+
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))
|
|
2414
|
+
)
|
|
2415
|
+
),
|
|
2416
|
+
core.types.objectProperty(core.types.identifier("trailing"), core.types.numericLiteral(plan.trailing)),
|
|
2417
|
+
core.types.objectProperty(
|
|
2418
|
+
core.types.identifier("bindings"),
|
|
2419
|
+
core.types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2420
|
+
),
|
|
2421
|
+
...plan.kind === "nested-host-keyed-ranges" ? [core.types.objectProperty(core.types.identifier("staticChildrenOnly"), core.types.booleanLiteral(true))] : []
|
|
2422
|
+
]);
|
|
2423
|
+
}
|
|
2424
|
+
function mixedRangeObject(range, descriptorBlocks) {
|
|
2425
|
+
const value = range.rangeKind === "conditional" ? conditionalRangeObject(range, descriptorBlocks) : keyedRangeObject(range, descriptorBlocks);
|
|
2426
|
+
value.properties.unshift(
|
|
2427
|
+
core.types.objectProperty(core.types.identifier("kind"), core.types.stringLiteral(range.rangeKind))
|
|
2428
|
+
);
|
|
2429
|
+
return value;
|
|
2430
|
+
}
|
|
2431
|
+
function mixedRangesBoundary(blockRuntime, plan) {
|
|
2432
|
+
const name = core.types.jsxMemberExpression(
|
|
2433
|
+
core.types.jsxIdentifier(blockRuntime.name),
|
|
2434
|
+
core.types.jsxIdentifier("MixedRanges")
|
|
2435
|
+
);
|
|
2436
|
+
const source = core.types.cloneNode(plan.source, true);
|
|
2437
|
+
const rootRefIndex = source.openingElement.attributes.findIndex(
|
|
2438
|
+
(attribute) => core.types.isJSXAttribute(attribute) && jsxAttributeName(attribute) === "ref"
|
|
2439
|
+
);
|
|
2440
|
+
const rootRef = rootRefIndex >= 0 ? source.openingElement.attributes.splice(rootRefIndex, 1)[0] : void 0;
|
|
2441
|
+
const nestedPlan = {
|
|
2442
|
+
kind: "nested-host-mixed-ranges",
|
|
2443
|
+
id: plan.id,
|
|
2444
|
+
parent: plan.parent,
|
|
2445
|
+
dependencies: plan.dependencies,
|
|
2446
|
+
source: plan.source,
|
|
2447
|
+
ranges: plan.ranges,
|
|
2448
|
+
trailing: plan.trailing,
|
|
2449
|
+
staticBindings: plan.staticBindings
|
|
2450
|
+
};
|
|
2451
|
+
const descriptorBlocks = new Map(plan.descriptorBlocks);
|
|
2452
|
+
descriptorBlocks.set(plan.source, nestedPlan);
|
|
2453
|
+
const attributes = [
|
|
2454
|
+
core.types.jsxAttribute(core.types.jsxIdentifier("id"), core.types.jsxExpressionContainer(core.types.numericLiteral(plan.id))),
|
|
2455
|
+
core.types.jsxAttribute(
|
|
2456
|
+
core.types.jsxIdentifier("render"),
|
|
2457
|
+
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], source))
|
|
2458
|
+
),
|
|
2459
|
+
core.types.jsxAttribute(
|
|
2460
|
+
core.types.jsxIdentifier("create"),
|
|
2461
|
+
core.types.jsxExpressionContainer(
|
|
2462
|
+
core.types.arrowFunctionExpression([], hostElementDescriptor(plan.source, descriptorBlocks))
|
|
2463
|
+
)
|
|
2464
|
+
)
|
|
2465
|
+
];
|
|
2466
|
+
if (rootRef?.value) {
|
|
2467
|
+
attributes.push(core.types.jsxAttribute(core.types.jsxIdentifier("rootRef"), core.types.cloneNode(rootRef.value, true)));
|
|
2468
|
+
}
|
|
2469
|
+
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2470
|
+
}
|
|
1598
2471
|
function conditionalRangesBoundary(blockRuntime, plan) {
|
|
1599
2472
|
const name = core.types.jsxMemberExpression(
|
|
1600
2473
|
core.types.jsxIdentifier(blockRuntime.name),
|
|
@@ -1614,12 +2487,20 @@ function conditionalRangesBoundary(blockRuntime, plan) {
|
|
|
1614
2487
|
core.types.jsxAttribute(
|
|
1615
2488
|
core.types.jsxIdentifier("ranges"),
|
|
1616
2489
|
core.types.jsxExpressionContainer(
|
|
1617
|
-
core.types.arrayExpression(
|
|
2490
|
+
core.types.arrayExpression(
|
|
2491
|
+
plan.ranges.map((range) => conditionalRangeObject(range, plan.descriptorBlocks))
|
|
2492
|
+
)
|
|
1618
2493
|
)
|
|
1619
2494
|
),
|
|
1620
2495
|
core.types.jsxAttribute(
|
|
1621
2496
|
core.types.jsxIdentifier("trailing"),
|
|
1622
2497
|
core.types.jsxExpressionContainer(core.types.numericLiteral(plan.trailing))
|
|
2498
|
+
),
|
|
2499
|
+
core.types.jsxAttribute(
|
|
2500
|
+
core.types.jsxIdentifier("bindings"),
|
|
2501
|
+
core.types.jsxExpressionContainer(
|
|
2502
|
+
core.types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2503
|
+
)
|
|
1623
2504
|
)
|
|
1624
2505
|
];
|
|
1625
2506
|
if (rootRef?.value) {
|
|
@@ -1792,6 +2673,41 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1792
2673
|
}
|
|
1793
2674
|
if (core.types.isJSXElement(child)) {
|
|
1794
2675
|
if (isHostElement(child)) {
|
|
2676
|
+
const mixedRangeStart = nextId;
|
|
2677
|
+
const mixedRangeId = nextId++;
|
|
2678
|
+
const mixedRanges = insideConditional ? void 0 : analyzeMixedRangesContainer(
|
|
2679
|
+
child,
|
|
2680
|
+
statesByValue,
|
|
2681
|
+
safeGlobals,
|
|
2682
|
+
listNames,
|
|
2683
|
+
mixedRangeId,
|
|
2684
|
+
() => nextId++
|
|
2685
|
+
);
|
|
2686
|
+
if (mixedRanges) {
|
|
2687
|
+
plans.push({
|
|
2688
|
+
kind: "mixed-ranges",
|
|
2689
|
+
id: mixedRangeId,
|
|
2690
|
+
parent,
|
|
2691
|
+
dependencies: mixedRanges.dependencies,
|
|
2692
|
+
source: child,
|
|
2693
|
+
ranges: mixedRanges.ranges,
|
|
2694
|
+
trailing: mixedRanges.trailing,
|
|
2695
|
+
staticBindings: mixedRanges.staticBindings,
|
|
2696
|
+
descriptorBlocks: mixedRanges.descriptorBlocks
|
|
2697
|
+
});
|
|
2698
|
+
plans.push(...mixedRanges.nestedPlans);
|
|
2699
|
+
for (const range of mixedRanges.ranges) {
|
|
2700
|
+
if (range.rangeKind === "conditional") {
|
|
2701
|
+
conditionalExpressions.add(range.source);
|
|
2702
|
+
} else if (core.types.isJSXElement(range.source)) {
|
|
2703
|
+
ownedElements.add(range.source);
|
|
2704
|
+
} else {
|
|
2705
|
+
keyedExpressions.add(range.source);
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
continue;
|
|
2709
|
+
}
|
|
2710
|
+
nextId = mixedRangeStart;
|
|
1795
2711
|
const keyedRanges = insideConditional ? void 0 : analyzeKeyedRangesContainer(child, statesByValue, safeGlobals, listNames);
|
|
1796
2712
|
if (keyedRanges) {
|
|
1797
2713
|
plans.push({
|
|
@@ -1801,7 +2717,8 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1801
2717
|
dependencies: keyedRanges.dependencies,
|
|
1802
2718
|
source: child,
|
|
1803
2719
|
ranges: keyedRanges.ranges,
|
|
1804
|
-
trailing: keyedRanges.trailing
|
|
2720
|
+
trailing: keyedRanges.trailing,
|
|
2721
|
+
staticBindings: keyedRanges.staticBindings
|
|
1805
2722
|
});
|
|
1806
2723
|
for (const range of keyedRanges.ranges) {
|
|
1807
2724
|
if (core.types.isJSXElement(range.source)) ownedElements.add(range.source);
|
|
@@ -1809,58 +2726,102 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1809
2726
|
}
|
|
1810
2727
|
continue;
|
|
1811
2728
|
}
|
|
1812
|
-
const
|
|
2729
|
+
const conditionalRangeStart = nextId;
|
|
2730
|
+
const conditionalRangeId = nextId++;
|
|
2731
|
+
const conditionalRanges = insideConditional ? void 0 : analyzeConditionalRangesContainer(
|
|
2732
|
+
child,
|
|
2733
|
+
statesByValue,
|
|
2734
|
+
safeGlobals,
|
|
2735
|
+
false,
|
|
2736
|
+
listNames,
|
|
2737
|
+
conditionalRangeId,
|
|
2738
|
+
() => nextId++
|
|
2739
|
+
);
|
|
1813
2740
|
if (conditionalRanges) {
|
|
1814
2741
|
plans.push({
|
|
1815
2742
|
kind: "conditional-ranges",
|
|
1816
|
-
id:
|
|
2743
|
+
id: conditionalRangeId,
|
|
1817
2744
|
parent,
|
|
1818
2745
|
dependencies: conditionalRanges.dependencies,
|
|
1819
2746
|
source: child,
|
|
1820
2747
|
ranges: conditionalRanges.ranges,
|
|
1821
|
-
trailing: conditionalRanges.trailing
|
|
2748
|
+
trailing: conditionalRanges.trailing,
|
|
2749
|
+
staticBindings: conditionalRanges.staticBindings,
|
|
2750
|
+
descriptorBlocks: conditionalRanges.descriptorBlocks
|
|
1822
2751
|
});
|
|
2752
|
+
plans.push(...conditionalRanges.nestedPlans || []);
|
|
1823
2753
|
for (const range of conditionalRanges.ranges) {
|
|
1824
2754
|
conditionalExpressions.add(range.source);
|
|
1825
2755
|
}
|
|
1826
2756
|
continue;
|
|
1827
2757
|
}
|
|
2758
|
+
nextId = conditionalRangeStart;
|
|
2759
|
+
const hostConditionalStart = nextId;
|
|
2760
|
+
const hostConditionalId = nextId++;
|
|
1828
2761
|
const hostConditional = analyzeHostConditionalContainer(
|
|
1829
2762
|
child,
|
|
1830
2763
|
statesByValue,
|
|
1831
|
-
safeGlobals
|
|
2764
|
+
safeGlobals,
|
|
2765
|
+
listNames,
|
|
2766
|
+
hostConditionalId,
|
|
2767
|
+
() => nextId++
|
|
1832
2768
|
);
|
|
1833
2769
|
if (hostConditional) {
|
|
1834
2770
|
plans.push({
|
|
1835
2771
|
kind: "host-conditional",
|
|
1836
|
-
id:
|
|
2772
|
+
id: hostConditionalId,
|
|
1837
2773
|
parent,
|
|
1838
2774
|
source: child,
|
|
1839
2775
|
...hostConditional
|
|
1840
2776
|
});
|
|
2777
|
+
plans.push(...hostConditional.nestedPlans || []);
|
|
1841
2778
|
ownedElements.add(child);
|
|
1842
2779
|
continue;
|
|
1843
2780
|
}
|
|
2781
|
+
nextId = hostConditionalStart;
|
|
2782
|
+
const keyedRowsStart = nextId;
|
|
2783
|
+
const keyedRowsId = nextId++;
|
|
1844
2784
|
const keyedRows = analyzeKeyedRowsContainer(child, statesByValue, safeGlobals, listNames);
|
|
1845
2785
|
if (keyedRows) {
|
|
2786
|
+
const nestedStart = nextId;
|
|
2787
|
+
const hostBlocks = analyzeCompilerOwnedKeyedRowHostBlocks(
|
|
2788
|
+
keyedRows,
|
|
2789
|
+
statesByValue,
|
|
2790
|
+
safeGlobals,
|
|
2791
|
+
listNames,
|
|
2792
|
+
keyedRowsId,
|
|
2793
|
+
() => nextId++
|
|
2794
|
+
);
|
|
2795
|
+
if (!hostBlocks) nextId = nestedStart;
|
|
2796
|
+
if (keyedRows.rowReason && !hostBlocks) {
|
|
2797
|
+
nextId = keyedRowsStart;
|
|
2798
|
+
const nested2 = visitHost(child, parent, insideConditional);
|
|
2799
|
+
if (nested2.reason) return { dependencies, reason: nested2.reason };
|
|
2800
|
+
mergeDependencies(dependencies, nested2.dependencies);
|
|
2801
|
+
continue;
|
|
2802
|
+
}
|
|
1846
2803
|
plans.push({
|
|
1847
2804
|
kind: "keyed-rows",
|
|
1848
|
-
id:
|
|
2805
|
+
id: keyedRowsId,
|
|
1849
2806
|
parent,
|
|
1850
2807
|
dependencies: keyedRows.dependencies,
|
|
1851
2808
|
source: child,
|
|
1852
2809
|
collection: keyedRows.collection,
|
|
2810
|
+
structureDependencies: keyedRows.structureDependencies,
|
|
1853
2811
|
keyCallback: keyedRows.keyCallback,
|
|
1854
2812
|
renderCallback: keyedRows.renderCallback,
|
|
1855
|
-
row: keyedRows.row,
|
|
1856
|
-
bindings: keyedRows.bindings,
|
|
2813
|
+
row: hostBlocks?.row || keyedRows.row,
|
|
2814
|
+
bindings: hostBlocks?.bindings || keyedRows.bindings,
|
|
1857
2815
|
events: keyedRows.events,
|
|
1858
|
-
conditionals: keyedRows.conditionals,
|
|
2816
|
+
conditionals: hostBlocks ? [] : keyedRows.conditionals,
|
|
2817
|
+
descriptorBlocks: hostBlocks?.descriptorBlocks,
|
|
1859
2818
|
syntax: keyedRows.syntax
|
|
1860
2819
|
});
|
|
2820
|
+
plans.push(...hostBlocks?.nestedPlans || []);
|
|
1861
2821
|
ownedElements.add(child);
|
|
1862
2822
|
continue;
|
|
1863
2823
|
}
|
|
2824
|
+
nextId = keyedRowsStart;
|
|
1864
2825
|
const nested = visitHost(child, parent, insideConditional);
|
|
1865
2826
|
if (nested.reason) return { dependencies, reason: nested.reason };
|
|
1866
2827
|
mergeDependencies(dependencies, nested.dependencies);
|
|
@@ -1957,6 +2918,46 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1957
2918
|
}
|
|
1958
2919
|
return { dependencies };
|
|
1959
2920
|
};
|
|
2921
|
+
const rootMixedRangeStart = nextId;
|
|
2922
|
+
const rootMixedRangeId = nextId++;
|
|
2923
|
+
const rootMixedRanges = analyzeMixedRangesContainer(
|
|
2924
|
+
root,
|
|
2925
|
+
statesByValue,
|
|
2926
|
+
safeGlobals,
|
|
2927
|
+
listNames,
|
|
2928
|
+
rootMixedRangeId,
|
|
2929
|
+
() => nextId++
|
|
2930
|
+
);
|
|
2931
|
+
if (rootMixedRanges) {
|
|
2932
|
+
plans.push({
|
|
2933
|
+
kind: "mixed-ranges",
|
|
2934
|
+
id: rootMixedRangeId,
|
|
2935
|
+
dependencies: rootMixedRanges.dependencies,
|
|
2936
|
+
source: root,
|
|
2937
|
+
ranges: rootMixedRanges.ranges,
|
|
2938
|
+
trailing: rootMixedRanges.trailing,
|
|
2939
|
+
staticBindings: rootMixedRanges.staticBindings,
|
|
2940
|
+
descriptorBlocks: rootMixedRanges.descriptorBlocks
|
|
2941
|
+
});
|
|
2942
|
+
plans.push(...rootMixedRanges.nestedPlans);
|
|
2943
|
+
for (const range of rootMixedRanges.ranges) {
|
|
2944
|
+
if (range.rangeKind === "conditional") {
|
|
2945
|
+
conditionalExpressions.add(range.source);
|
|
2946
|
+
} else if (core.types.isJSXElement(range.source)) {
|
|
2947
|
+
ownedElements.add(range.source);
|
|
2948
|
+
} else {
|
|
2949
|
+
keyedExpressions.add(range.source);
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2952
|
+
return {
|
|
2953
|
+
plans,
|
|
2954
|
+
componentElements,
|
|
2955
|
+
conditionalExpressions,
|
|
2956
|
+
ownedElements,
|
|
2957
|
+
keyedExpressions
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
2960
|
+
nextId = rootMixedRangeStart;
|
|
1960
2961
|
const rootRanges = analyzeKeyedRangesContainer(root, statesByValue, safeGlobals, listNames, true);
|
|
1961
2962
|
if (rootRanges) {
|
|
1962
2963
|
plans.push({
|
|
@@ -1965,7 +2966,8 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1965
2966
|
dependencies: rootRanges.dependencies,
|
|
1966
2967
|
source: root,
|
|
1967
2968
|
ranges: rootRanges.ranges,
|
|
1968
|
-
trailing: rootRanges.trailing
|
|
2969
|
+
trailing: rootRanges.trailing,
|
|
2970
|
+
staticBindings: rootRanges.staticBindings
|
|
1969
2971
|
});
|
|
1970
2972
|
for (const range of rootRanges.ranges) {
|
|
1971
2973
|
if (core.types.isJSXElement(range.source)) ownedElements.add(range.source);
|
|
@@ -1979,21 +2981,29 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1979
2981
|
keyedExpressions
|
|
1980
2982
|
};
|
|
1981
2983
|
}
|
|
2984
|
+
const rootConditionalRangeStart = nextId;
|
|
2985
|
+
const rootConditionalRangeId = nextId++;
|
|
1982
2986
|
const rootConditionalRanges = analyzeConditionalRangesContainer(
|
|
1983
2987
|
root,
|
|
1984
2988
|
statesByValue,
|
|
1985
2989
|
safeGlobals,
|
|
1986
|
-
true
|
|
2990
|
+
true,
|
|
2991
|
+
listNames,
|
|
2992
|
+
rootConditionalRangeId,
|
|
2993
|
+
() => nextId++
|
|
1987
2994
|
);
|
|
1988
2995
|
if (rootConditionalRanges) {
|
|
1989
2996
|
plans.push({
|
|
1990
2997
|
kind: "conditional-ranges",
|
|
1991
|
-
id:
|
|
2998
|
+
id: rootConditionalRangeId,
|
|
1992
2999
|
dependencies: rootConditionalRanges.dependencies,
|
|
1993
3000
|
source: root,
|
|
1994
3001
|
ranges: rootConditionalRanges.ranges,
|
|
1995
|
-
trailing: rootConditionalRanges.trailing
|
|
3002
|
+
trailing: rootConditionalRanges.trailing,
|
|
3003
|
+
staticBindings: rootConditionalRanges.staticBindings,
|
|
3004
|
+
descriptorBlocks: rootConditionalRanges.descriptorBlocks
|
|
1996
3005
|
});
|
|
3006
|
+
plans.push(...rootConditionalRanges.nestedPlans || []);
|
|
1997
3007
|
for (const range of rootConditionalRanges.ranges) {
|
|
1998
3008
|
conditionalExpressions.add(range.source);
|
|
1999
3009
|
}
|
|
@@ -2005,6 +3015,7 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
2005
3015
|
keyedExpressions
|
|
2006
3016
|
};
|
|
2007
3017
|
}
|
|
3018
|
+
nextId = rootConditionalRangeStart;
|
|
2008
3019
|
const result = visitHost(root, void 0, false);
|
|
2009
3020
|
if (result.reason) return { reason: result.reason };
|
|
2010
3021
|
return {
|
|
@@ -2042,6 +3053,9 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
2042
3053
|
plans.map((plan) => [plan.source, plan])
|
|
2043
3054
|
);
|
|
2044
3055
|
const rootPlan = planBySource.get(root);
|
|
3056
|
+
if (rootPlan?.kind === "mixed-ranges") {
|
|
3057
|
+
return mixedRangesBoundary(blockRuntime, rootPlan);
|
|
3058
|
+
}
|
|
2045
3059
|
if (rootPlan?.kind === "keyed-ranges") {
|
|
2046
3060
|
return keyedRangesBoundary(blockRuntime, rootPlan);
|
|
2047
3061
|
}
|
|
@@ -2055,6 +3069,9 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
2055
3069
|
if (plan2?.kind === "host-conditional") {
|
|
2056
3070
|
return hostConditionalBoundary(blockRuntime, plan2);
|
|
2057
3071
|
}
|
|
3072
|
+
if (plan2?.kind === "mixed-ranges") {
|
|
3073
|
+
return mixedRangesBoundary(blockRuntime, plan2);
|
|
3074
|
+
}
|
|
2058
3075
|
if (plan2?.kind === "keyed-rows") {
|
|
2059
3076
|
return keyedRowsBoundary(blockRuntime, plan2);
|
|
2060
3077
|
}
|
|
@@ -2104,6 +3121,31 @@ function assignStableBindingTargets(bindings) {
|
|
|
2104
3121
|
binding.target = target;
|
|
2105
3122
|
}
|
|
2106
3123
|
}
|
|
3124
|
+
function markShortCircuitBindings(bindings) {
|
|
3125
|
+
for (const binding of bindings) {
|
|
3126
|
+
if (binding.kind === "block" || binding.dependencies.length < 2) continue;
|
|
3127
|
+
let shortCircuits = false;
|
|
3128
|
+
core.traverse(expressionFile(core.types.cloneNode(binding.value, true)), {
|
|
3129
|
+
ConditionalExpression(path) {
|
|
3130
|
+
shortCircuits = true;
|
|
3131
|
+
path.stop();
|
|
3132
|
+
},
|
|
3133
|
+
LogicalExpression(path) {
|
|
3134
|
+
shortCircuits = true;
|
|
3135
|
+
path.stop();
|
|
3136
|
+
},
|
|
3137
|
+
OptionalCallExpression(path) {
|
|
3138
|
+
shortCircuits = true;
|
|
3139
|
+
path.stop();
|
|
3140
|
+
},
|
|
3141
|
+
OptionalMemberExpression(path) {
|
|
3142
|
+
shortCircuits = true;
|
|
3143
|
+
path.stop();
|
|
3144
|
+
}
|
|
3145
|
+
});
|
|
3146
|
+
if (shortCircuits) binding.tracking = "dynamic";
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
2107
3149
|
function lowerStableBindingTargets(root, bindings, blockRuntime, ownedElements) {
|
|
2108
3150
|
const targetByPath = /* @__PURE__ */ new Map();
|
|
2109
3151
|
for (const binding of bindings) {
|
|
@@ -2373,6 +3415,9 @@ function bindingObject(binding, propsParameter, stateParameter, statesByValue, s
|
|
|
2373
3415
|
core.types.objectProperty(core.types.identifier("target"), core.types.numericLiteral(binding.target))
|
|
2374
3416
|
);
|
|
2375
3417
|
}
|
|
3418
|
+
if (binding.tracking) {
|
|
3419
|
+
properties.push(core.types.objectProperty(core.types.identifier("tracking"), core.types.stringLiteral(binding.tracking)));
|
|
3420
|
+
}
|
|
2376
3421
|
if (binding.name)
|
|
2377
3422
|
properties.push(core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(binding.name)));
|
|
2378
3423
|
properties.push(
|
|
@@ -2391,7 +3436,7 @@ function wrapperElement(definitionIdentifier, props) {
|
|
|
2391
3436
|
const attributes = props ? [core.types.jsxSpreadAttribute(core.types.cloneNode(props))] : [];
|
|
2392
3437
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2393
3438
|
}
|
|
2394
|
-
function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames, listNames, moduleId) {
|
|
3439
|
+
function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureIdentifiers, usedRuntimeFeatures, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
2395
3440
|
const { path, name, statementPath } = candidate;
|
|
2396
3441
|
if (path.node.async || path.node.generator)
|
|
2397
3442
|
return "async and generator components are not supported";
|
|
@@ -2508,8 +3553,34 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2508
3553
|
);
|
|
2509
3554
|
const setterReason = validateSetterUsage(expandedRoot, statesBySetter);
|
|
2510
3555
|
if (setterReason) return setterReason;
|
|
3556
|
+
const referencedPropNames = collectDestructuredPropNames(
|
|
3557
|
+
expandedRoot,
|
|
3558
|
+
propsPlan.destructuredNames,
|
|
3559
|
+
propsPlan.definitionParameter
|
|
3560
|
+
);
|
|
3561
|
+
let propBindings = referencedPropNames.has("children") ? [] : [...propsPlan.destructuredNames].filter((propName) => referencedPropNames.has(propName)).map(
|
|
3562
|
+
(localName, propIndex) => ({
|
|
3563
|
+
localName,
|
|
3564
|
+
valueName: path.scope.generateUidIdentifier(`farmProp${propIndex}`).name,
|
|
3565
|
+
index: states.length + propIndex
|
|
3566
|
+
})
|
|
3567
|
+
);
|
|
3568
|
+
const propBindingsByName = new Map(propBindings.map((binding) => [binding.localName, binding]));
|
|
3569
|
+
let reactiveByValue = new Map(statesByValue);
|
|
3570
|
+
for (const binding of propBindings) {
|
|
3571
|
+
reactiveByValue.set(binding.valueName, {
|
|
3572
|
+
valueName: binding.valueName,
|
|
3573
|
+
setterName: "",
|
|
3574
|
+
index: binding.index
|
|
3575
|
+
});
|
|
3576
|
+
}
|
|
3577
|
+
let expandedReactiveRoot = rewriteTrackedPropAccess(
|
|
3578
|
+
expandedRoot,
|
|
3579
|
+
propsPlan.definitionParameter,
|
|
3580
|
+
propBindingsByName
|
|
3581
|
+
);
|
|
2511
3582
|
const referencedComponentNames = /* @__PURE__ */ new Set();
|
|
2512
|
-
core.traverse(expressionFile(core.types.cloneNode(
|
|
3583
|
+
core.traverse(expressionFile(core.types.cloneNode(expandedReactiveRoot, true)), {
|
|
2513
3584
|
JSXOpeningElement(componentPath) {
|
|
2514
3585
|
const componentName = componentPath.node.name;
|
|
2515
3586
|
if (core.types.isJSXIdentifier(componentName) && isComponentName(componentName.name)) {
|
|
@@ -2526,32 +3597,55 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2526
3597
|
);
|
|
2527
3598
|
})
|
|
2528
3599
|
);
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
3600
|
+
let blockAnalysis = analyzeComposableBlocks(
|
|
3601
|
+
expandedReactiveRoot,
|
|
3602
|
+
reactiveByValue,
|
|
2532
3603
|
safeGlobals,
|
|
2533
3604
|
listNames,
|
|
2534
3605
|
allowedComponentNames
|
|
2535
3606
|
);
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
expandedRoot,
|
|
2540
|
-
statesByValue,
|
|
3607
|
+
let analysis = analyzeHostTree(
|
|
3608
|
+
expandedReactiveRoot,
|
|
3609
|
+
reactiveByValue,
|
|
2541
3610
|
safeGlobals,
|
|
2542
3611
|
blockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
2543
3612
|
blockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
2544
3613
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
2545
3614
|
blockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
2546
3615
|
);
|
|
3616
|
+
if (propBindings.length > 0 && (blockAnalysis.reason || analysis.reason)) {
|
|
3617
|
+
propBindings = [];
|
|
3618
|
+
reactiveByValue = new Map(statesByValue);
|
|
3619
|
+
expandedReactiveRoot = core.types.cloneNode(expandedRoot, true);
|
|
3620
|
+
blockAnalysis = analyzeComposableBlocks(
|
|
3621
|
+
expandedReactiveRoot,
|
|
3622
|
+
reactiveByValue,
|
|
3623
|
+
safeGlobals,
|
|
3624
|
+
listNames,
|
|
3625
|
+
allowedComponentNames
|
|
3626
|
+
);
|
|
3627
|
+
analysis = analyzeHostTree(
|
|
3628
|
+
expandedReactiveRoot,
|
|
3629
|
+
reactiveByValue,
|
|
3630
|
+
safeGlobals,
|
|
3631
|
+
blockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
3632
|
+
blockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
3633
|
+
blockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
3634
|
+
blockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
3635
|
+
);
|
|
3636
|
+
}
|
|
3637
|
+
if (blockAnalysis.reason) return blockAnalysis.reason;
|
|
2547
3638
|
if (analysis.reason) return analysis.reason;
|
|
3639
|
+
const blockPlans = blockAnalysis.plans || [];
|
|
3640
|
+
const runtimeFeatures = runtimeFeaturesForPlans(blockPlans);
|
|
3641
|
+
markShortCircuitBindings(analysis.bindings || []);
|
|
2548
3642
|
assignStableBindingTargets(analysis.bindings || []);
|
|
2549
3643
|
const stateParameter = path.scope.generateUidIdentifier("farmState");
|
|
2550
3644
|
const blockParameter = path.scope.generateUidIdentifier("farmBlocks");
|
|
2551
3645
|
const definitionIdentifier = path.scope.generateUidIdentifier(`${name}Compiled`);
|
|
2552
3646
|
const propsParameter = propsPlan.definitionParameter;
|
|
2553
3647
|
const rootWithTargets = lowerStableBindingTargets(
|
|
2554
|
-
|
|
3648
|
+
expandedReactiveRoot,
|
|
2555
3649
|
analysis.bindings || [],
|
|
2556
3650
|
blockParameter,
|
|
2557
3651
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set()
|
|
@@ -2565,12 +3659,13 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2565
3659
|
const rewrittenRoot = rewriteStateAccess(
|
|
2566
3660
|
rootWithBlocks,
|
|
2567
3661
|
stateParameter,
|
|
2568
|
-
|
|
3662
|
+
reactiveByValue,
|
|
2569
3663
|
statesBySetter
|
|
2570
3664
|
);
|
|
2571
3665
|
const definition = core.types.callExpression(core.types.cloneNode(createComponentIdentifier), [
|
|
2572
3666
|
core.types.objectExpression([
|
|
2573
3667
|
core.types.objectProperty(core.types.identifier("displayName"), core.types.stringLiteral(name)),
|
|
3668
|
+
core.types.objectProperty(core.types.identifier("reactivity"), core.types.stringLiteral(reactivity)),
|
|
2574
3669
|
core.types.spreadElement(
|
|
2575
3670
|
core.types.conditionalExpression(
|
|
2576
3671
|
core.types.memberExpression(
|
|
@@ -2581,7 +3676,9 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2581
3676
|
core.types.objectProperty(core.types.identifier("hmrId"), core.types.stringLiteral(`${moduleId}#${name}`)),
|
|
2582
3677
|
core.types.objectProperty(
|
|
2583
3678
|
core.types.identifier("stateSignature"),
|
|
2584
|
-
core.types.stringLiteral(
|
|
3679
|
+
core.types.stringLiteral(
|
|
3680
|
+
propBindings.length === 0 ? String(states.length) : `${states.length}:${propBindings.map((binding) => binding.localName).join(",")}`
|
|
3681
|
+
)
|
|
2585
3682
|
)
|
|
2586
3683
|
]),
|
|
2587
3684
|
core.types.objectExpression([])
|
|
@@ -2604,6 +3701,22 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2604
3701
|
)
|
|
2605
3702
|
)
|
|
2606
3703
|
),
|
|
3704
|
+
...propBindings.length > 0 ? [
|
|
3705
|
+
core.types.objectProperty(
|
|
3706
|
+
core.types.identifier("readProps"),
|
|
3707
|
+
core.types.arrowFunctionExpression(
|
|
3708
|
+
[core.types.cloneNode(propsParameter)],
|
|
3709
|
+
core.types.arrayExpression(
|
|
3710
|
+
propBindings.map(
|
|
3711
|
+
(binding) => core.types.memberExpression(
|
|
3712
|
+
core.types.cloneNode(propsParameter),
|
|
3713
|
+
core.types.identifier(binding.localName)
|
|
3714
|
+
)
|
|
3715
|
+
)
|
|
3716
|
+
)
|
|
3717
|
+
)
|
|
3718
|
+
)
|
|
3719
|
+
] : [],
|
|
2607
3720
|
core.types.objectProperty(
|
|
2608
3721
|
core.types.identifier("render"),
|
|
2609
3722
|
core.types.arrowFunctionExpression(
|
|
@@ -2623,11 +3736,14 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2623
3736
|
dependencies: block.dependencies
|
|
2624
3737
|
}))
|
|
2625
3738
|
].map(
|
|
2626
|
-
(binding) => bindingObject(binding, propsParameter, stateParameter,
|
|
3739
|
+
(binding) => bindingObject(binding, propsParameter, stateParameter, reactiveByValue, statesBySetter)
|
|
2627
3740
|
)
|
|
2628
3741
|
)
|
|
2629
3742
|
)
|
|
2630
|
-
])
|
|
3743
|
+
]),
|
|
3744
|
+
core.types.arrayExpression(
|
|
3745
|
+
runtimeFeatures.map((feature) => core.types.cloneNode(runtimeFeatureIdentifiers.get(feature)))
|
|
3746
|
+
)
|
|
2631
3747
|
]);
|
|
2632
3748
|
path.get("body").replaceWith(
|
|
2633
3749
|
core.types.blockStatement([
|
|
@@ -2637,6 +3753,7 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2637
3753
|
statementPath.insertAfter(
|
|
2638
3754
|
core.types.variableDeclaration("const", [core.types.variableDeclarator(definitionIdentifier, definition)])
|
|
2639
3755
|
);
|
|
3756
|
+
for (const feature of runtimeFeatures) usedRuntimeFeatures.add(feature);
|
|
2640
3757
|
return void 0;
|
|
2641
3758
|
}
|
|
2642
3759
|
function collectCandidates(programPath) {
|
|
@@ -2704,6 +3821,13 @@ async function compileReactModule(code, id, options) {
|
|
|
2704
3821
|
}
|
|
2705
3822
|
const candidates = collectCandidates(programPath);
|
|
2706
3823
|
const createComponentIdentifier = programPath.scope.generateUidIdentifier("createCompiledComponent");
|
|
3824
|
+
const runtimeFeatureIdentifiers = new Map(
|
|
3825
|
+
Object.entries(COMPILER_RUNTIME_FEATURE_EXPORTS).map(([feature, exportName]) => [
|
|
3826
|
+
feature,
|
|
3827
|
+
programPath.scope.generateUidIdentifier(exportName)
|
|
3828
|
+
])
|
|
3829
|
+
);
|
|
3830
|
+
const usedRuntimeFeatures = /* @__PURE__ */ new Set();
|
|
2707
3831
|
for (const candidate of candidates) {
|
|
2708
3832
|
const functionDirectives = new Set(
|
|
2709
3833
|
core.types.isBlockStatement(candidate.path.node.body) ? directiveValues(candidate.path.node.body) : []
|
|
@@ -2714,10 +3838,13 @@ async function compileReactModule(code, id, options) {
|
|
|
2714
3838
|
const reason = compileCandidate(
|
|
2715
3839
|
candidate,
|
|
2716
3840
|
createComponentIdentifier,
|
|
3841
|
+
runtimeFeatureIdentifiers,
|
|
3842
|
+
usedRuntimeFeatures,
|
|
2717
3843
|
useStateNames,
|
|
2718
3844
|
reactNames,
|
|
2719
3845
|
listNames,
|
|
2720
|
-
id
|
|
3846
|
+
id,
|
|
3847
|
+
options.reactivity
|
|
2721
3848
|
);
|
|
2722
3849
|
if (reason) {
|
|
2723
3850
|
diagnostics.push({
|
|
@@ -2736,7 +3863,13 @@ async function compileReactModule(code, id, options) {
|
|
|
2736
3863
|
[
|
|
2737
3864
|
core.types.importSpecifier(
|
|
2738
3865
|
createComponentIdentifier,
|
|
2739
|
-
core.types.identifier("
|
|
3866
|
+
core.types.identifier("createCompiledComponentWithFeatures")
|
|
3867
|
+
),
|
|
3868
|
+
...[...usedRuntimeFeatures].sort().map(
|
|
3869
|
+
(feature) => core.types.importSpecifier(
|
|
3870
|
+
core.types.cloneNode(runtimeFeatureIdentifiers.get(feature)),
|
|
3871
|
+
core.types.identifier(COMPILER_RUNTIME_FEATURE_EXPORTS[feature])
|
|
3872
|
+
)
|
|
2740
3873
|
)
|
|
2741
3874
|
],
|
|
2742
3875
|
core.types.stringLiteral("@farm.js/react/compiler-runtime")
|
|
@@ -2844,6 +3977,10 @@ function normalizeReactCompilerOptions(value) {
|
|
|
2844
3977
|
if (!["fallback", "warn", "error"].includes(onUnsupported)) {
|
|
2845
3978
|
throw new TypeError(`Unknown unsupported-component behavior: ${String(onUnsupported)}`);
|
|
2846
3979
|
}
|
|
3980
|
+
const reactivity = options.reactivity || "hybrid";
|
|
3981
|
+
if (reactivity !== "static" && reactivity !== "hybrid") {
|
|
3982
|
+
throw new TypeError(`Unknown React compiler reactivity mode: ${String(reactivity)}`);
|
|
3983
|
+
}
|
|
2847
3984
|
if (options.report !== void 0 && typeof options.report !== "boolean") {
|
|
2848
3985
|
throw new TypeError("The React compiler report option must be a boolean.");
|
|
2849
3986
|
}
|
|
@@ -2854,7 +3991,7 @@ function normalizeReactCompilerOptions(value) {
|
|
|
2854
3991
|
}
|
|
2855
3992
|
const reportFile = normalizeCompilerReportFile(options.reportFile);
|
|
2856
3993
|
const report = options.report === true || options.reportFile !== void 0;
|
|
2857
|
-
return { mode, directive, onUnsupported, report, reportFile };
|
|
3994
|
+
return { mode, directive, onUnsupported, reactivity, report, reportFile };
|
|
2858
3995
|
}
|
|
2859
3996
|
|
|
2860
3997
|
// src/vite.ts
|
|
@@ -2870,7 +4007,7 @@ function readCompilerOptions(rendererOptions) {
|
|
|
2870
4007
|
);
|
|
2871
4008
|
}
|
|
2872
4009
|
const normalized = compiler;
|
|
2873
|
-
if ((normalized.mode === "infer" || normalized.mode === "annotation") && typeof normalized.directive === "string" && (normalized.onUnsupported === "fallback" || normalized.onUnsupported === "warn" || normalized.onUnsupported === "error")) {
|
|
4010
|
+
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")) {
|
|
2874
4011
|
return normalized;
|
|
2875
4012
|
}
|
|
2876
4013
|
return normalizeReactCompilerOptions(compiler);
|