@farm.js/react 0.1.0-beta.2 → 0.1.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -42
- package/dist/compiler-runtime.cjs +2087 -134
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +94 -1
- package/dist/compiler-runtime.d.ts +94 -1
- package/dist/compiler-runtime.mjs +2087 -134
- 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 +1321 -75
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1321 -75
- package/dist/vite.mjs.map +1 -1
- package/package.json +4 -3
package/dist/vite.cjs
CHANGED
|
@@ -6,6 +6,62 @@ 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
|
+
}
|
|
9
65
|
var SAFE_GLOBAL_CALLS = /* @__PURE__ */ new Set(["Boolean", "Number", "String"]);
|
|
10
66
|
var SAFE_MATH_CALLS = /* @__PURE__ */ new Set(["abs", "ceil", "floor", "max", "min", "round", "sign", "trunc"]);
|
|
11
67
|
function isComponentName(name) {
|
|
@@ -90,6 +146,37 @@ function rewriteDestructuredPropAccess(expression, names, propsParameter) {
|
|
|
90
146
|
});
|
|
91
147
|
return file.program.body[0].expression;
|
|
92
148
|
}
|
|
149
|
+
function collectDestructuredPropNames(expression, names, propsParameter) {
|
|
150
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
151
|
+
if (names.size === 0) return referenced;
|
|
152
|
+
core.traverse(expressionFile(cloneExpression(expression)), {
|
|
153
|
+
MemberExpression(path) {
|
|
154
|
+
const { object, property, computed } = path.node;
|
|
155
|
+
if (computed || !core.types.isIdentifier(object, { name: propsParameter.name }) || !core.types.isIdentifier(property) || !names.has(property.name)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
referenced.add(property.name);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
return referenced;
|
|
162
|
+
}
|
|
163
|
+
function rewriteTrackedPropAccess(expression, propsParameter, bindingsByName) {
|
|
164
|
+
if (bindingsByName.size === 0) return cloneExpression(expression);
|
|
165
|
+
const file = expressionFile(cloneExpression(expression));
|
|
166
|
+
core.traverse(file, {
|
|
167
|
+
MemberExpression(path) {
|
|
168
|
+
const { object, property, computed } = path.node;
|
|
169
|
+
if (computed || !core.types.isIdentifier(object, { name: propsParameter.name }) || !core.types.isIdentifier(property)) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const binding = bindingsByName.get(property.name);
|
|
173
|
+
if (!binding) return;
|
|
174
|
+
path.replaceWith(core.types.identifier(binding.valueName));
|
|
175
|
+
path.skip();
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
return file.program.body[0].expression;
|
|
179
|
+
}
|
|
93
180
|
function rewriteHandlerAccess(root, handlersByName) {
|
|
94
181
|
if (handlersByName.size === 0) return { root: core.types.cloneNode(root, true) };
|
|
95
182
|
const file = expressionFile(core.types.cloneNode(root, true));
|
|
@@ -769,7 +856,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
769
856
|
const reason = visit(row, []);
|
|
770
857
|
return reason ? { reason } : { bindings, events, conditionals };
|
|
771
858
|
}
|
|
772
|
-
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames) {
|
|
859
|
+
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false) {
|
|
773
860
|
let collection;
|
|
774
861
|
let keyCallback;
|
|
775
862
|
let renderCallback;
|
|
@@ -824,17 +911,29 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames) {
|
|
|
824
911
|
safeGlobals,
|
|
825
912
|
new Set([...statesByValue.values()].map((state) => state.setterName))
|
|
826
913
|
);
|
|
827
|
-
if (rowAnalysis.reason) return void 0;
|
|
914
|
+
if (rowAnalysis.reason && !acceptUnsupportedRow) return void 0;
|
|
915
|
+
const keyExpression = returnedExpression(keyCallback);
|
|
916
|
+
const structureDependencies = new Set(collectStateDependencies(collection, statesByValue));
|
|
917
|
+
if (keyExpression) {
|
|
918
|
+
for (const dependency of collectStateDependencies(keyExpression, statesByValue)) {
|
|
919
|
+
structureDependencies.add(dependency);
|
|
920
|
+
}
|
|
921
|
+
}
|
|
828
922
|
return {
|
|
829
923
|
source,
|
|
830
924
|
collection,
|
|
925
|
+
structureDependencies: [...structureDependencies].sort((left, right) => left - right),
|
|
831
926
|
keyCallback,
|
|
832
927
|
renderCallback,
|
|
833
928
|
row,
|
|
834
929
|
dependencies,
|
|
835
|
-
bindings: rowAnalysis.bindings || []
|
|
930
|
+
bindings: (rowAnalysis.bindings || []).map((binding) => ({
|
|
931
|
+
...binding,
|
|
932
|
+
dependencies: collectStateDependencies(binding.value, statesByValue)
|
|
933
|
+
})),
|
|
836
934
|
events: rowAnalysis.events || [],
|
|
837
935
|
conditionals: rowAnalysis.conditionals || [],
|
|
936
|
+
rowReason: rowAnalysis.reason,
|
|
838
937
|
syntax
|
|
839
938
|
};
|
|
840
939
|
}
|
|
@@ -851,22 +950,7 @@ function analyzeKeyedRowsContainer(container, statesByValue, safeGlobals, listNa
|
|
|
851
950
|
}
|
|
852
951
|
const children = meaningfulJsxChildren(container);
|
|
853
952
|
if (children.length !== 1) return void 0;
|
|
854
|
-
return analyzeKeyedRowChild(children[0], statesByValue, safeGlobals, listNames);
|
|
855
|
-
}
|
|
856
|
-
function isStaticKeyedRangeSibling(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) || !isStaticKeyedRangeSibling(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;
|
|
953
|
+
return analyzeKeyedRowChild(children[0], statesByValue, safeGlobals, listNames, true);
|
|
870
954
|
}
|
|
871
955
|
function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, listNames, allowSingleRange = false) {
|
|
872
956
|
if (container.openingElement.attributes.some(
|
|
@@ -878,6 +962,7 @@ function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
878
962
|
if (children.length < (allowSingleRange ? 1 : 2)) return void 0;
|
|
879
963
|
const ranges = [];
|
|
880
964
|
const dependencies = /* @__PURE__ */ new Set();
|
|
965
|
+
const staticBindings = [];
|
|
881
966
|
let staticBefore = 0;
|
|
882
967
|
for (const child of children) {
|
|
883
968
|
const range = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames);
|
|
@@ -898,18 +983,31 @@ function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
898
983
|
continue;
|
|
899
984
|
}
|
|
900
985
|
if (!core.types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
901
|
-
|
|
986
|
+
const analysis = analyzeHostConditionalTree(child, safeGlobals, true, statesByValue);
|
|
987
|
+
if (analysis.reason) return void 0;
|
|
988
|
+
for (const binding of analysis.bindings || []) {
|
|
989
|
+
staticBindings.push({
|
|
990
|
+
...binding,
|
|
991
|
+
segment: ranges.length,
|
|
992
|
+
sibling: staticBefore
|
|
993
|
+
});
|
|
994
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
995
|
+
dependencies.add(dependency);
|
|
996
|
+
}
|
|
997
|
+
}
|
|
902
998
|
staticBefore += 1;
|
|
903
999
|
}
|
|
904
1000
|
if (ranges.length === 0) return void 0;
|
|
905
1001
|
return {
|
|
906
1002
|
ranges,
|
|
907
1003
|
trailing: staticBefore,
|
|
908
|
-
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
1004
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1005
|
+
staticBindings
|
|
909
1006
|
};
|
|
910
1007
|
}
|
|
911
|
-
function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
1008
|
+
function analyzeHostConditionalTree(branch, safeGlobals, allowStaticEvents = false, statefulOnly) {
|
|
912
1009
|
const bindings = [];
|
|
1010
|
+
const needsStaticBinding = (expression) => !statefulOnly || collectStateDependencies(expression, statefulOnly).length > 0;
|
|
913
1011
|
const visit = (element, path) => {
|
|
914
1012
|
const tag = element.openingElement.name;
|
|
915
1013
|
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
@@ -918,20 +1016,26 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
918
1016
|
if (tag.name === "svg") return "compiler-owned conditionals do not support SVG yet";
|
|
919
1017
|
for (const attribute of element.openingElement.attributes) {
|
|
920
1018
|
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
1019
|
+
if (statefulOnly && !needsStaticBinding(attribute.argument)) continue;
|
|
921
1020
|
return "compiler-owned conditionals do not support JSX attribute spreads";
|
|
922
1021
|
}
|
|
923
1022
|
const name = jsxAttributeName(attribute);
|
|
924
1023
|
if (!name) return "compiler-owned conditionals do not support namespaced JSX attributes";
|
|
925
1024
|
if (name === "ref" || name === "dangerouslySetInnerHTML" || name === "key") {
|
|
1025
|
+
if (statefulOnly && (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression) || !needsStaticBinding(attribute.value.expression))) {
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
926
1028
|
return `compiler-owned conditional ${name} requires React ownership`;
|
|
927
1029
|
}
|
|
928
1030
|
if (/^on[A-Z]/.test(name)) {
|
|
1031
|
+
if (allowStaticEvents) continue;
|
|
929
1032
|
return "compiler-owned conditional events require React ownership";
|
|
930
1033
|
}
|
|
931
1034
|
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
932
1035
|
continue;
|
|
933
1036
|
}
|
|
934
1037
|
const expression = attribute.value.expression;
|
|
1038
|
+
if (!needsStaticBinding(expression)) continue;
|
|
935
1039
|
if (name === "style") {
|
|
936
1040
|
if (!core.types.isObjectExpression(expression)) {
|
|
937
1041
|
return "compiler-owned conditional styles must use one inline object literal";
|
|
@@ -944,6 +1048,7 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
944
1048
|
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
945
1049
|
return "compiler-owned conditional style names must use camelCase or a CSS custom property";
|
|
946
1050
|
}
|
|
1051
|
+
if (!needsStaticBinding(property.value)) continue;
|
|
947
1052
|
const unsupported2 = validateDerivedExpression(property.value, safeGlobals);
|
|
948
1053
|
if (unsupported2) {
|
|
949
1054
|
return `compiler-owned conditional style ${propertyName} cannot use ${unsupported2}`;
|
|
@@ -978,14 +1083,20 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
978
1083
|
const expressions = element.children.filter(
|
|
979
1084
|
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
980
1085
|
);
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1086
|
+
const boundExpressions = statefulOnly ? expressions.filter((child) => needsStaticBinding(child.expression)) : expressions;
|
|
1087
|
+
if (boundExpressions.length > 0) {
|
|
1088
|
+
for (const child of expressions) {
|
|
1089
|
+
const unsupported = validateDerivedExpression(
|
|
1090
|
+
child.expression,
|
|
1091
|
+
safeGlobals
|
|
1092
|
+
);
|
|
1093
|
+
if (unsupported) return `compiler-owned conditional text cannot use ${unsupported}`;
|
|
1094
|
+
}
|
|
984
1095
|
}
|
|
985
|
-
if (nestedElements.length > 0 &&
|
|
1096
|
+
if (nestedElements.length > 0 && boundExpressions.length > 0) {
|
|
986
1097
|
return "compiler-owned conditionals do not support dynamic text beside nested elements yet";
|
|
987
1098
|
}
|
|
988
|
-
if (nestedElements.length === 0 &&
|
|
1099
|
+
if (nestedElements.length === 0 && boundExpressions.length > 0) {
|
|
989
1100
|
const parts = [];
|
|
990
1101
|
for (const child of element.children) {
|
|
991
1102
|
if (core.types.isJSXText(child)) {
|
|
@@ -1009,7 +1120,369 @@ function analyzeHostConditionalTree(branch, safeGlobals) {
|
|
|
1009
1120
|
const reason = visit(branch, []);
|
|
1010
1121
|
return reason ? { reason } : { bindings };
|
|
1011
1122
|
}
|
|
1012
|
-
function
|
|
1123
|
+
function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1124
|
+
const bindings = [];
|
|
1125
|
+
const plans = [];
|
|
1126
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
1127
|
+
const visit = (element, path, owner) => {
|
|
1128
|
+
const tag = element.openingElement.name;
|
|
1129
|
+
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
1130
|
+
return "recursive compiler-owned blocks support host elements only";
|
|
1131
|
+
}
|
|
1132
|
+
if (tag.name === "svg") return "recursive compiler-owned blocks do not support SVG yet";
|
|
1133
|
+
for (const attribute of element.openingElement.attributes) {
|
|
1134
|
+
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
1135
|
+
return "recursive compiler-owned blocks do not support JSX attribute spreads";
|
|
1136
|
+
}
|
|
1137
|
+
const name = jsxAttributeName(attribute);
|
|
1138
|
+
if (!name) return "recursive compiler-owned blocks do not support namespaced attributes";
|
|
1139
|
+
if (name === "ref" || name === "dangerouslySetInnerHTML" || name === "key") {
|
|
1140
|
+
return `recursive compiler-owned block ${name} requires React ownership`;
|
|
1141
|
+
}
|
|
1142
|
+
if (/^on[A-Z]/.test(name)) {
|
|
1143
|
+
return "recursive compiler-owned block events require React ownership";
|
|
1144
|
+
}
|
|
1145
|
+
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
const expression = attribute.value.expression;
|
|
1149
|
+
if (name === "style") {
|
|
1150
|
+
if (!core.types.isObjectExpression(expression)) {
|
|
1151
|
+
return "recursive compiler-owned styles must use one inline object literal";
|
|
1152
|
+
}
|
|
1153
|
+
for (const property of expression.properties) {
|
|
1154
|
+
if (!core.types.isObjectProperty(property) || property.computed || !core.types.isExpression(property.value)) {
|
|
1155
|
+
return "recursive compiler-owned styles do not support spreads, methods, or computed properties";
|
|
1156
|
+
}
|
|
1157
|
+
const propertyName = core.types.isIdentifier(property.key) ? property.key.name : core.types.isStringLiteral(property.key) ? property.key.value : void 0;
|
|
1158
|
+
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
1159
|
+
return "recursive compiler-owned style names must use camelCase or a CSS custom property";
|
|
1160
|
+
}
|
|
1161
|
+
const unsupported2 = validateDerivedExpression(property.value, safeGlobals);
|
|
1162
|
+
if (unsupported2) {
|
|
1163
|
+
return `recursive compiler-owned style ${propertyName} cannot use ${unsupported2}`;
|
|
1164
|
+
}
|
|
1165
|
+
bindings.push({
|
|
1166
|
+
kind: "style",
|
|
1167
|
+
path: [...path],
|
|
1168
|
+
name: propertyName,
|
|
1169
|
+
value: cloneExpression(property.value)
|
|
1170
|
+
});
|
|
1171
|
+
}
|
|
1172
|
+
continue;
|
|
1173
|
+
}
|
|
1174
|
+
if (name === "children") {
|
|
1175
|
+
return "recursive compiler-owned children props are not supported yet";
|
|
1176
|
+
}
|
|
1177
|
+
const unsupported = validateDerivedExpression(expression, safeGlobals);
|
|
1178
|
+
if (unsupported) return `recursive compiler-owned ${name} cannot use ${unsupported}`;
|
|
1179
|
+
bindings.push({
|
|
1180
|
+
kind: "attribute",
|
|
1181
|
+
path: [...path],
|
|
1182
|
+
name,
|
|
1183
|
+
value: cloneExpression(expression)
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
const children = meaningfulJsxChildren(element);
|
|
1187
|
+
const hasConditionalRange = children.some(
|
|
1188
|
+
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression) && conditionalBlockShape(child.expression) !== null
|
|
1189
|
+
);
|
|
1190
|
+
const hasKeyedRange = children.some(
|
|
1191
|
+
(child) => analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true) !== void 0
|
|
1192
|
+
);
|
|
1193
|
+
if (hasConditionalRange && hasKeyedRange) {
|
|
1194
|
+
const id = allocateId();
|
|
1195
|
+
const mixed = analyzeMixedRangesContainer(
|
|
1196
|
+
element,
|
|
1197
|
+
statesByValue,
|
|
1198
|
+
safeGlobals,
|
|
1199
|
+
listNames,
|
|
1200
|
+
id,
|
|
1201
|
+
allocateId
|
|
1202
|
+
);
|
|
1203
|
+
if (mixed) {
|
|
1204
|
+
plans.push(...mixed.nestedPlans);
|
|
1205
|
+
for (const [nestedElement, plan2] of mixed.descriptorBlocks) {
|
|
1206
|
+
blocks.set(nestedElement, plan2);
|
|
1207
|
+
}
|
|
1208
|
+
const plan = {
|
|
1209
|
+
kind: "nested-host-mixed-ranges",
|
|
1210
|
+
id,
|
|
1211
|
+
parent: owner,
|
|
1212
|
+
dependencies: mixed.dependencies,
|
|
1213
|
+
source: element,
|
|
1214
|
+
ranges: mixed.ranges,
|
|
1215
|
+
trailing: mixed.trailing,
|
|
1216
|
+
staticBindings: mixed.staticBindings
|
|
1217
|
+
};
|
|
1218
|
+
plans.push(plan);
|
|
1219
|
+
blocks.set(element, plan);
|
|
1220
|
+
return void 0;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
const conditionalChildren = /* @__PURE__ */ new Map();
|
|
1224
|
+
let conditionalContainer = children.length > 0;
|
|
1225
|
+
for (const child of children) {
|
|
1226
|
+
if (core.types.isJSXElement(child) && isHostElement(child)) continue;
|
|
1227
|
+
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1228
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1229
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1230
|
+
conditionalChildren.set(child.expression, shape);
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
conditionalContainer = false;
|
|
1235
|
+
break;
|
|
1236
|
+
}
|
|
1237
|
+
if (conditionalContainer && conditionalChildren.size > 0) {
|
|
1238
|
+
const id = allocateId();
|
|
1239
|
+
const ranges = [];
|
|
1240
|
+
const staticBindings = [];
|
|
1241
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1242
|
+
let staticBefore2 = 0;
|
|
1243
|
+
for (const child of children) {
|
|
1244
|
+
if (core.types.isJSXElement(child)) {
|
|
1245
|
+
const nested = analyzeRecursiveHostTree(
|
|
1246
|
+
child,
|
|
1247
|
+
statesByValue,
|
|
1248
|
+
safeGlobals,
|
|
1249
|
+
listNames,
|
|
1250
|
+
owner,
|
|
1251
|
+
allocateId
|
|
1252
|
+
);
|
|
1253
|
+
if (nested.reason) return nested.reason;
|
|
1254
|
+
plans.push(...nested.plans);
|
|
1255
|
+
for (const [nestedElement, plan2] of nested.blocks) blocks.set(nestedElement, plan2);
|
|
1256
|
+
for (const binding of nested.bindings) {
|
|
1257
|
+
staticBindings.push({
|
|
1258
|
+
...binding,
|
|
1259
|
+
segment: ranges.length,
|
|
1260
|
+
sibling: staticBefore2
|
|
1261
|
+
});
|
|
1262
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1263
|
+
dependencies.add(dependency);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
staticBefore2 += 1;
|
|
1267
|
+
continue;
|
|
1268
|
+
}
|
|
1269
|
+
if (!core.types.isJSXExpressionContainer(child) || core.types.isJSXEmptyExpression(child.expression)) {
|
|
1270
|
+
return "recursive conditional ranges contain an unsupported child";
|
|
1271
|
+
}
|
|
1272
|
+
const expression = child.expression;
|
|
1273
|
+
const shape = conditionalChildren.get(expression);
|
|
1274
|
+
const truthy = shape.truthy ? analyzeRecursiveHostTree(
|
|
1275
|
+
shape.truthy,
|
|
1276
|
+
statesByValue,
|
|
1277
|
+
safeGlobals,
|
|
1278
|
+
listNames,
|
|
1279
|
+
id,
|
|
1280
|
+
allocateId
|
|
1281
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1282
|
+
const falsy = shape.falsy ? analyzeRecursiveHostTree(
|
|
1283
|
+
shape.falsy,
|
|
1284
|
+
statesByValue,
|
|
1285
|
+
safeGlobals,
|
|
1286
|
+
listNames,
|
|
1287
|
+
id,
|
|
1288
|
+
allocateId
|
|
1289
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1290
|
+
if (truthy.reason) return truthy.reason;
|
|
1291
|
+
if (falsy.reason) return falsy.reason;
|
|
1292
|
+
plans.push(...truthy.plans, ...falsy.plans);
|
|
1293
|
+
for (const [nestedElement, plan2] of truthy.blocks) blocks.set(nestedElement, plan2);
|
|
1294
|
+
for (const [nestedElement, plan2] of falsy.blocks) blocks.set(nestedElement, plan2);
|
|
1295
|
+
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1296
|
+
dependencies.add(dependency);
|
|
1297
|
+
}
|
|
1298
|
+
for (const binding of [...truthy.bindings, ...falsy.bindings]) {
|
|
1299
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1300
|
+
dependencies.add(dependency);
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
ranges.push({
|
|
1304
|
+
before: staticBefore2,
|
|
1305
|
+
source: expression,
|
|
1306
|
+
test: cloneExpression(shape.test),
|
|
1307
|
+
logical: shape.logical,
|
|
1308
|
+
truthy: shape.truthy,
|
|
1309
|
+
falsy: shape.falsy,
|
|
1310
|
+
truthyBindings: truthy.bindings,
|
|
1311
|
+
falsyBindings: falsy.bindings
|
|
1312
|
+
});
|
|
1313
|
+
staticBefore2 = 0;
|
|
1314
|
+
}
|
|
1315
|
+
const plan = {
|
|
1316
|
+
kind: "nested-host-conditional-ranges",
|
|
1317
|
+
id,
|
|
1318
|
+
parent: owner,
|
|
1319
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1320
|
+
source: element,
|
|
1321
|
+
ranges,
|
|
1322
|
+
trailing: staticBefore2,
|
|
1323
|
+
staticBindings
|
|
1324
|
+
};
|
|
1325
|
+
plans.push(plan);
|
|
1326
|
+
blocks.set(element, plan);
|
|
1327
|
+
return void 0;
|
|
1328
|
+
}
|
|
1329
|
+
const keyedRows = [];
|
|
1330
|
+
let keyedContainer = children.length > 0;
|
|
1331
|
+
let staticBefore = 0;
|
|
1332
|
+
const staticChildren = [];
|
|
1333
|
+
for (const child of children) {
|
|
1334
|
+
const range = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true);
|
|
1335
|
+
if (range) {
|
|
1336
|
+
keyedRows.push({ before: staticBefore, range });
|
|
1337
|
+
staticBefore = 0;
|
|
1338
|
+
} else if (core.types.isJSXElement(child) && isHostElement(child)) {
|
|
1339
|
+
staticChildren.push({
|
|
1340
|
+
element: child,
|
|
1341
|
+
segment: keyedRows.length,
|
|
1342
|
+
sibling: staticBefore
|
|
1343
|
+
});
|
|
1344
|
+
staticBefore += 1;
|
|
1345
|
+
} else {
|
|
1346
|
+
keyedContainer = false;
|
|
1347
|
+
break;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
if (keyedContainer && keyedRows.length > 0) {
|
|
1351
|
+
const id = allocateId();
|
|
1352
|
+
const keyedRanges = [];
|
|
1353
|
+
const staticBindings = [];
|
|
1354
|
+
const keyedDependencies = /* @__PURE__ */ new Set();
|
|
1355
|
+
for (const { before, range } of keyedRows) {
|
|
1356
|
+
if (range.events.length > 0) {
|
|
1357
|
+
return "recursive compiler-owned keyed rows cannot contain events";
|
|
1358
|
+
}
|
|
1359
|
+
const row = core.types.cloneNode(range.row, true);
|
|
1360
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1361
|
+
(attribute) => !core.types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1362
|
+
);
|
|
1363
|
+
const rowAnalysis = analyzeRecursiveHostTree(
|
|
1364
|
+
row,
|
|
1365
|
+
statesByValue,
|
|
1366
|
+
safeGlobals,
|
|
1367
|
+
listNames,
|
|
1368
|
+
id,
|
|
1369
|
+
allocateId
|
|
1370
|
+
);
|
|
1371
|
+
if (rowAnalysis.reason) return rowAnalysis.reason;
|
|
1372
|
+
plans.push(...rowAnalysis.plans);
|
|
1373
|
+
for (const [nestedElement, nestedPlan] of rowAnalysis.blocks) {
|
|
1374
|
+
blocks.set(nestedElement, nestedPlan);
|
|
1375
|
+
}
|
|
1376
|
+
keyedRanges.push({
|
|
1377
|
+
before,
|
|
1378
|
+
source: range.source,
|
|
1379
|
+
collection: range.collection,
|
|
1380
|
+
keyCallback: range.keyCallback,
|
|
1381
|
+
renderCallback: range.renderCallback,
|
|
1382
|
+
row,
|
|
1383
|
+
bindings: rowAnalysis.bindings,
|
|
1384
|
+
syntax: range.syntax
|
|
1385
|
+
});
|
|
1386
|
+
for (const dependency of range.dependencies) keyedDependencies.add(dependency);
|
|
1387
|
+
}
|
|
1388
|
+
for (const { element: child, segment, sibling } of staticChildren) {
|
|
1389
|
+
const nested = analyzeRecursiveHostTree(
|
|
1390
|
+
child,
|
|
1391
|
+
statesByValue,
|
|
1392
|
+
safeGlobals,
|
|
1393
|
+
listNames,
|
|
1394
|
+
owner,
|
|
1395
|
+
allocateId
|
|
1396
|
+
);
|
|
1397
|
+
if (nested.reason) return nested.reason;
|
|
1398
|
+
plans.push(...nested.plans);
|
|
1399
|
+
for (const [nestedElement, plan2] of nested.blocks) blocks.set(nestedElement, plan2);
|
|
1400
|
+
for (const binding of nested.bindings) {
|
|
1401
|
+
staticBindings.push({ ...binding, segment, sibling });
|
|
1402
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1403
|
+
keyedDependencies.add(dependency);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
const plan = {
|
|
1408
|
+
kind: "nested-host-keyed-ranges",
|
|
1409
|
+
id,
|
|
1410
|
+
parent: owner,
|
|
1411
|
+
dependencies: [...keyedDependencies].sort((left, right) => left - right),
|
|
1412
|
+
source: element,
|
|
1413
|
+
ranges: keyedRanges,
|
|
1414
|
+
trailing: staticBefore,
|
|
1415
|
+
staticBindings
|
|
1416
|
+
};
|
|
1417
|
+
plans.push(plan);
|
|
1418
|
+
blocks.set(element, plan);
|
|
1419
|
+
return void 0;
|
|
1420
|
+
}
|
|
1421
|
+
if (element.children.some((child) => core.types.isJSXFragment(child))) {
|
|
1422
|
+
return "recursive compiler-owned blocks do not support fragments yet";
|
|
1423
|
+
}
|
|
1424
|
+
const nestedElements = element.children.filter(
|
|
1425
|
+
(child) => core.types.isJSXElement(child)
|
|
1426
|
+
);
|
|
1427
|
+
const expressions = element.children.filter(
|
|
1428
|
+
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
1429
|
+
);
|
|
1430
|
+
for (const child of expressions) {
|
|
1431
|
+
const unsupported = validateDerivedExpression(child.expression, safeGlobals);
|
|
1432
|
+
if (unsupported) return `recursive compiler-owned text cannot use ${unsupported}`;
|
|
1433
|
+
}
|
|
1434
|
+
if (nestedElements.length > 0 && expressions.length > 0) {
|
|
1435
|
+
return "recursive compiler-owned blocks do not support dynamic text beside nested elements";
|
|
1436
|
+
}
|
|
1437
|
+
if (nestedElements.length === 0 && expressions.length > 0) {
|
|
1438
|
+
const parts = [];
|
|
1439
|
+
for (const child of element.children) {
|
|
1440
|
+
if (core.types.isJSXText(child)) {
|
|
1441
|
+
const text = cleanJsxText(child.value);
|
|
1442
|
+
if (text) parts.push(core.types.stringLiteral(text));
|
|
1443
|
+
} else if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1444
|
+
parts.push(cloneExpression(child.expression));
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
bindings.push({ kind: "text", path: [...path], value: core.types.arrayExpression(parts) });
|
|
1448
|
+
}
|
|
1449
|
+
let elementIndex = 0;
|
|
1450
|
+
for (const child of element.children) {
|
|
1451
|
+
if (!core.types.isJSXElement(child)) continue;
|
|
1452
|
+
const reason2 = visit(child, [...path, elementIndex], owner);
|
|
1453
|
+
if (reason2) return reason2;
|
|
1454
|
+
elementIndex += 1;
|
|
1455
|
+
}
|
|
1456
|
+
return void 0;
|
|
1457
|
+
};
|
|
1458
|
+
const reason = visit(branch, [], parent);
|
|
1459
|
+
return { bindings, plans, blocks, reason };
|
|
1460
|
+
}
|
|
1461
|
+
function analyzeCompilerOwnedKeyedRowHostBlocks(shape, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1462
|
+
if (shape.events.length > 0) return void 0;
|
|
1463
|
+
const row = core.types.cloneNode(shape.row, true);
|
|
1464
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1465
|
+
(attribute) => !core.types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1466
|
+
);
|
|
1467
|
+
const analysis = analyzeRecursiveHostTree(
|
|
1468
|
+
row,
|
|
1469
|
+
statesByValue,
|
|
1470
|
+
safeGlobals,
|
|
1471
|
+
listNames,
|
|
1472
|
+
parent,
|
|
1473
|
+
allocateId
|
|
1474
|
+
);
|
|
1475
|
+
if (analysis.reason || analysis.plans.length === 0) {
|
|
1476
|
+
return void 0;
|
|
1477
|
+
}
|
|
1478
|
+
return {
|
|
1479
|
+
row,
|
|
1480
|
+
bindings: analysis.bindings,
|
|
1481
|
+
descriptorBlocks: analysis.blocks,
|
|
1482
|
+
nestedPlans: analysis.plans
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
function analyzeHostConditionalContainer(container, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1013
1486
|
const containerName = container.openingElement.name;
|
|
1014
1487
|
if (!core.types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg") {
|
|
1015
1488
|
return void 0;
|
|
@@ -1031,8 +1504,22 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals)
|
|
|
1031
1504
|
}
|
|
1032
1505
|
const shape = conditionalBlockShape(children[0].expression);
|
|
1033
1506
|
if (!shape || validateDerivedExpression(shape.test, safeGlobals)) return void 0;
|
|
1034
|
-
const truthyAnalysis = shape.truthy ?
|
|
1035
|
-
|
|
1507
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1508
|
+
shape.truthy,
|
|
1509
|
+
statesByValue,
|
|
1510
|
+
safeGlobals,
|
|
1511
|
+
listNames,
|
|
1512
|
+
parent,
|
|
1513
|
+
allocateId
|
|
1514
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1515
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1516
|
+
shape.falsy,
|
|
1517
|
+
statesByValue,
|
|
1518
|
+
safeGlobals,
|
|
1519
|
+
listNames,
|
|
1520
|
+
parent,
|
|
1521
|
+
allocateId
|
|
1522
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1036
1523
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1037
1524
|
const dependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1038
1525
|
for (const binding of [...truthyAnalysis.bindings || [], ...falsyAnalysis.bindings || []]) {
|
|
@@ -1042,12 +1529,232 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals)
|
|
|
1042
1529
|
}
|
|
1043
1530
|
return {
|
|
1044
1531
|
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1045
|
-
test: cloneExpression(shape.test),
|
|
1046
|
-
logical: shape.logical,
|
|
1047
|
-
truthy: shape.truthy,
|
|
1048
|
-
falsy: shape.falsy,
|
|
1049
|
-
truthyBindings: truthyAnalysis.bindings || [],
|
|
1050
|
-
falsyBindings: falsyAnalysis.bindings || []
|
|
1532
|
+
test: cloneExpression(shape.test),
|
|
1533
|
+
logical: shape.logical,
|
|
1534
|
+
truthy: shape.truthy,
|
|
1535
|
+
falsy: shape.falsy,
|
|
1536
|
+
truthyBindings: truthyAnalysis.bindings || [],
|
|
1537
|
+
falsyBindings: falsyAnalysis.bindings || [],
|
|
1538
|
+
descriptorBlocks: new Map([...truthyAnalysis.blocks, ...falsyAnalysis.blocks]),
|
|
1539
|
+
nestedPlans: [...truthyAnalysis.plans, ...falsyAnalysis.plans]
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals, allowSingleRange, listNames, parent, allocateId) {
|
|
1543
|
+
const containerName = container.openingElement.name;
|
|
1544
|
+
if (!core.types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg" || container.openingElement.attributes.some(
|
|
1545
|
+
(attribute) => core.types.isJSXSpreadAttribute(attribute) || core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
1546
|
+
)) {
|
|
1547
|
+
return void 0;
|
|
1548
|
+
}
|
|
1549
|
+
const children = meaningfulJsxChildren(container);
|
|
1550
|
+
if (children.length < (allowSingleRange ? 1 : 2)) return void 0;
|
|
1551
|
+
const ranges = [];
|
|
1552
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1553
|
+
const descriptorBlocks = /* @__PURE__ */ new Map();
|
|
1554
|
+
const nestedPlans = [];
|
|
1555
|
+
const staticBindings = [];
|
|
1556
|
+
let staticBefore = 0;
|
|
1557
|
+
for (const child of children) {
|
|
1558
|
+
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1559
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1560
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1561
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1562
|
+
shape.truthy,
|
|
1563
|
+
statesByValue,
|
|
1564
|
+
safeGlobals,
|
|
1565
|
+
listNames,
|
|
1566
|
+
parent,
|
|
1567
|
+
allocateId
|
|
1568
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1569
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1570
|
+
shape.falsy,
|
|
1571
|
+
statesByValue,
|
|
1572
|
+
safeGlobals,
|
|
1573
|
+
listNames,
|
|
1574
|
+
parent,
|
|
1575
|
+
allocateId
|
|
1576
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1577
|
+
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1578
|
+
nestedPlans.push(...truthyAnalysis.plans, ...falsyAnalysis.plans);
|
|
1579
|
+
for (const [element, plan] of truthyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
1580
|
+
for (const [element, plan] of falsyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
1581
|
+
const rangeDependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1582
|
+
for (const binding of [
|
|
1583
|
+
...truthyAnalysis.bindings || [],
|
|
1584
|
+
...falsyAnalysis.bindings || []
|
|
1585
|
+
]) {
|
|
1586
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1587
|
+
rangeDependencies.add(dependency);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
for (const dependency of rangeDependencies) dependencies.add(dependency);
|
|
1591
|
+
ranges.push({
|
|
1592
|
+
before: staticBefore,
|
|
1593
|
+
source: child.expression,
|
|
1594
|
+
test: cloneExpression(shape.test),
|
|
1595
|
+
logical: shape.logical,
|
|
1596
|
+
truthy: shape.truthy,
|
|
1597
|
+
falsy: shape.falsy,
|
|
1598
|
+
truthyBindings: truthyAnalysis.bindings || [],
|
|
1599
|
+
falsyBindings: falsyAnalysis.bindings || []
|
|
1600
|
+
});
|
|
1601
|
+
staticBefore = 0;
|
|
1602
|
+
continue;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
if (!core.types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
1606
|
+
const staticAnalysis = analyzeHostConditionalTree(child, safeGlobals, true, statesByValue);
|
|
1607
|
+
if (staticAnalysis.reason) return void 0;
|
|
1608
|
+
for (const binding of staticAnalysis.bindings || []) {
|
|
1609
|
+
staticBindings.push({
|
|
1610
|
+
...binding,
|
|
1611
|
+
segment: ranges.length,
|
|
1612
|
+
sibling: staticBefore
|
|
1613
|
+
});
|
|
1614
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1615
|
+
dependencies.add(dependency);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
staticBefore += 1;
|
|
1619
|
+
}
|
|
1620
|
+
if (ranges.length === 0) return void 0;
|
|
1621
|
+
return {
|
|
1622
|
+
ranges,
|
|
1623
|
+
trailing: staticBefore,
|
|
1624
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1625
|
+
staticBindings,
|
|
1626
|
+
descriptorBlocks,
|
|
1627
|
+
nestedPlans
|
|
1628
|
+
};
|
|
1629
|
+
}
|
|
1630
|
+
function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, listNames, parent, allocateId) {
|
|
1631
|
+
const containerName = container.openingElement.name;
|
|
1632
|
+
if (!core.types.isJSXIdentifier(containerName) || !/^[a-z]/.test(containerName.name) || containerName.name === "svg" || container.openingElement.attributes.some(
|
|
1633
|
+
(attribute) => core.types.isJSXSpreadAttribute(attribute) || core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
1634
|
+
)) {
|
|
1635
|
+
return void 0;
|
|
1636
|
+
}
|
|
1637
|
+
const children = meaningfulJsxChildren(container);
|
|
1638
|
+
if (children.length < 2) return void 0;
|
|
1639
|
+
const ranges = [];
|
|
1640
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
1641
|
+
const descriptorBlocks = /* @__PURE__ */ new Map();
|
|
1642
|
+
const nestedPlans = [];
|
|
1643
|
+
const staticBindings = [];
|
|
1644
|
+
let conditionalCount = 0;
|
|
1645
|
+
let keyedCount = 0;
|
|
1646
|
+
let staticBefore = 0;
|
|
1647
|
+
const mergeAnalysis = (analysis) => {
|
|
1648
|
+
if (analysis.reason) return false;
|
|
1649
|
+
nestedPlans.push(...analysis.plans);
|
|
1650
|
+
for (const [element, plan] of analysis.blocks) descriptorBlocks.set(element, plan);
|
|
1651
|
+
for (const binding of analysis.bindings) {
|
|
1652
|
+
for (const dependency of collectStateDependencies(binding.value, statesByValue)) {
|
|
1653
|
+
dependencies.add(dependency);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
return true;
|
|
1657
|
+
};
|
|
1658
|
+
for (const child of children) {
|
|
1659
|
+
if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1660
|
+
const shape = conditionalBlockShape(child.expression);
|
|
1661
|
+
if (shape && !validateDerivedExpression(shape.test, safeGlobals)) {
|
|
1662
|
+
const truthyAnalysis = shape.truthy ? analyzeRecursiveHostTree(
|
|
1663
|
+
shape.truthy,
|
|
1664
|
+
statesByValue,
|
|
1665
|
+
safeGlobals,
|
|
1666
|
+
listNames,
|
|
1667
|
+
parent,
|
|
1668
|
+
allocateId
|
|
1669
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1670
|
+
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1671
|
+
shape.falsy,
|
|
1672
|
+
statesByValue,
|
|
1673
|
+
safeGlobals,
|
|
1674
|
+
listNames,
|
|
1675
|
+
parent,
|
|
1676
|
+
allocateId
|
|
1677
|
+
) : { bindings: [], plans: [], blocks: /* @__PURE__ */ new Map() };
|
|
1678
|
+
if (!mergeAnalysis(truthyAnalysis) || !mergeAnalysis(falsyAnalysis)) return void 0;
|
|
1679
|
+
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1680
|
+
dependencies.add(dependency);
|
|
1681
|
+
}
|
|
1682
|
+
ranges.push({
|
|
1683
|
+
rangeKind: "conditional",
|
|
1684
|
+
before: staticBefore,
|
|
1685
|
+
source: child.expression,
|
|
1686
|
+
test: cloneExpression(shape.test),
|
|
1687
|
+
logical: shape.logical,
|
|
1688
|
+
truthy: shape.truthy,
|
|
1689
|
+
falsy: shape.falsy,
|
|
1690
|
+
truthyBindings: truthyAnalysis.bindings,
|
|
1691
|
+
falsyBindings: falsyAnalysis.bindings
|
|
1692
|
+
});
|
|
1693
|
+
conditionalCount += 1;
|
|
1694
|
+
staticBefore = 0;
|
|
1695
|
+
continue;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
const keyed = analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, true);
|
|
1699
|
+
if (keyed) {
|
|
1700
|
+
if (keyed.events.length > 0) return void 0;
|
|
1701
|
+
const row = core.types.cloneNode(keyed.row, true);
|
|
1702
|
+
row.openingElement.attributes = row.openingElement.attributes.filter(
|
|
1703
|
+
(attribute) => !core.types.isJSXAttribute(attribute) || jsxAttributeName(attribute) !== "key"
|
|
1704
|
+
);
|
|
1705
|
+
const rowAnalysis = analyzeRecursiveHostTree(
|
|
1706
|
+
row,
|
|
1707
|
+
statesByValue,
|
|
1708
|
+
safeGlobals,
|
|
1709
|
+
listNames,
|
|
1710
|
+
parent,
|
|
1711
|
+
allocateId
|
|
1712
|
+
);
|
|
1713
|
+
if (!mergeAnalysis(rowAnalysis)) return void 0;
|
|
1714
|
+
for (const dependency of keyed.dependencies) dependencies.add(dependency);
|
|
1715
|
+
ranges.push({
|
|
1716
|
+
rangeKind: "keyed",
|
|
1717
|
+
before: staticBefore,
|
|
1718
|
+
source: keyed.source,
|
|
1719
|
+
collection: keyed.collection,
|
|
1720
|
+
keyCallback: keyed.keyCallback,
|
|
1721
|
+
renderCallback: keyed.renderCallback,
|
|
1722
|
+
row,
|
|
1723
|
+
bindings: rowAnalysis.bindings,
|
|
1724
|
+
syntax: keyed.syntax
|
|
1725
|
+
});
|
|
1726
|
+
keyedCount += 1;
|
|
1727
|
+
staticBefore = 0;
|
|
1728
|
+
continue;
|
|
1729
|
+
}
|
|
1730
|
+
if (!core.types.isJSXElement(child) || !isHostElement(child)) return void 0;
|
|
1731
|
+
const staticAnalysis = analyzeRecursiveHostTree(
|
|
1732
|
+
child,
|
|
1733
|
+
statesByValue,
|
|
1734
|
+
safeGlobals,
|
|
1735
|
+
listNames,
|
|
1736
|
+
parent,
|
|
1737
|
+
allocateId
|
|
1738
|
+
);
|
|
1739
|
+
if (staticAnalysis.reason) return void 0;
|
|
1740
|
+
for (const binding of staticAnalysis.bindings) {
|
|
1741
|
+
staticBindings.push({
|
|
1742
|
+
...binding,
|
|
1743
|
+
segment: ranges.length,
|
|
1744
|
+
sibling: staticBefore
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
if (!mergeAnalysis(staticAnalysis)) return void 0;
|
|
1748
|
+
staticBefore += 1;
|
|
1749
|
+
}
|
|
1750
|
+
if (conditionalCount === 0 || keyedCount === 0) return void 0;
|
|
1751
|
+
return {
|
|
1752
|
+
ranges,
|
|
1753
|
+
trailing: staticBefore,
|
|
1754
|
+
dependencies: [...dependencies].sort((left, right) => left - right),
|
|
1755
|
+
staticBindings,
|
|
1756
|
+
descriptorBlocks,
|
|
1757
|
+
nestedPlans
|
|
1051
1758
|
};
|
|
1052
1759
|
}
|
|
1053
1760
|
function keyedListBoundary(blockRuntime, plan, source) {
|
|
@@ -1072,14 +1779,14 @@ function keyedListBoundary(blockRuntime, plan, source) {
|
|
|
1072
1779
|
true
|
|
1073
1780
|
);
|
|
1074
1781
|
}
|
|
1075
|
-
function hostElementDescriptor(element) {
|
|
1782
|
+
function hostElementDescriptor(element, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1076
1783
|
const tag = element.openingElement.name;
|
|
1077
1784
|
const attributes = [];
|
|
1078
1785
|
const styles = [];
|
|
1079
1786
|
for (const attribute of element.openingElement.attributes) {
|
|
1080
1787
|
if (!core.types.isJSXAttribute(attribute)) continue;
|
|
1081
1788
|
const name = jsxAttributeName(attribute);
|
|
1082
|
-
if (!name || name === "key" || /^on[A-Z]/.test(name)) continue;
|
|
1789
|
+
if (!name || name === "key" || name === "ref" || /^on[A-Z]/.test(name)) continue;
|
|
1083
1790
|
if (name === "style") {
|
|
1084
1791
|
if (core.types.isJSXExpressionContainer(attribute.value) && core.types.isObjectExpression(attribute.value.expression)) {
|
|
1085
1792
|
for (const property of attribute.value.expression.properties) {
|
|
@@ -1103,24 +1810,93 @@ function hostElementDescriptor(element) {
|
|
|
1103
1810
|
])
|
|
1104
1811
|
);
|
|
1105
1812
|
}
|
|
1813
|
+
const block = descriptorBlocks.get(element);
|
|
1814
|
+
const conditionalBySource = /* @__PURE__ */ new Map();
|
|
1815
|
+
const keyedBySource = /* @__PURE__ */ new Map();
|
|
1816
|
+
if (block?.kind === "nested-host-conditional-ranges") {
|
|
1817
|
+
for (const range of block.ranges) conditionalBySource.set(range.source, range);
|
|
1818
|
+
} else if (block?.kind === "nested-host-keyed-ranges") {
|
|
1819
|
+
for (const range of block.ranges) keyedBySource.set(range.source, range);
|
|
1820
|
+
} else if (block?.kind === "nested-host-mixed-ranges") {
|
|
1821
|
+
for (const range of block.ranges) {
|
|
1822
|
+
if (range.rangeKind === "conditional") conditionalBySource.set(range.source, range);
|
|
1823
|
+
else keyedBySource.set(range.source, range);
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1106
1826
|
const children = [];
|
|
1107
1827
|
for (const child of element.children) {
|
|
1108
1828
|
if (core.types.isJSXText(child)) {
|
|
1109
1829
|
const text = cleanJsxText(child.value);
|
|
1110
1830
|
if (text) children.push(core.types.stringLiteral(text));
|
|
1111
1831
|
} else if (core.types.isJSXElement(child)) {
|
|
1112
|
-
|
|
1832
|
+
const keyedRange = keyedBySource.get(child);
|
|
1833
|
+
if (keyedRange) {
|
|
1834
|
+
if (block?.kind !== "nested-host-keyed-ranges") {
|
|
1835
|
+
children.push(keyedRangeDescriptorChildren(keyedRange, descriptorBlocks));
|
|
1836
|
+
}
|
|
1837
|
+
} else {
|
|
1838
|
+
children.push(hostElementDescriptor(child, descriptorBlocks));
|
|
1839
|
+
}
|
|
1113
1840
|
} else if (core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)) {
|
|
1114
|
-
|
|
1841
|
+
const conditionalRange = conditionalBySource.get(child.expression);
|
|
1842
|
+
const keyedRange = keyedBySource.get(child.expression);
|
|
1843
|
+
if (conditionalRange) {
|
|
1844
|
+
children.push(conditionalRangeDescriptorChild(conditionalRange, descriptorBlocks));
|
|
1845
|
+
} else if (keyedRange) {
|
|
1846
|
+
if (block?.kind !== "nested-host-keyed-ranges") {
|
|
1847
|
+
children.push(keyedRangeDescriptorChildren(keyedRange, descriptorBlocks));
|
|
1848
|
+
}
|
|
1849
|
+
} else {
|
|
1850
|
+
children.push(cloneExpression(child.expression));
|
|
1851
|
+
}
|
|
1115
1852
|
}
|
|
1116
1853
|
}
|
|
1117
|
-
|
|
1854
|
+
const properties = [
|
|
1118
1855
|
core.types.objectProperty(core.types.identifier("kind"), core.types.stringLiteral("element")),
|
|
1119
1856
|
core.types.objectProperty(core.types.identifier("tag"), core.types.stringLiteral(tag.name)),
|
|
1120
1857
|
core.types.objectProperty(core.types.identifier("attributes"), core.types.arrayExpression(attributes)),
|
|
1121
1858
|
core.types.objectProperty(core.types.identifier("styles"), core.types.arrayExpression(styles)),
|
|
1122
1859
|
core.types.objectProperty(core.types.identifier("children"), core.types.arrayExpression(children))
|
|
1123
|
-
]
|
|
1860
|
+
];
|
|
1861
|
+
if (block) {
|
|
1862
|
+
properties.push(
|
|
1863
|
+
core.types.objectProperty(core.types.identifier("block"), nestedHostBlockObject(block, descriptorBlocks))
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
return core.types.objectExpression(properties);
|
|
1867
|
+
}
|
|
1868
|
+
function conditionalRangeDescriptorChild(range, descriptorBlocks) {
|
|
1869
|
+
const truthy = range.truthy ? hostElementDescriptor(range.truthy, descriptorBlocks) : core.types.nullLiteral();
|
|
1870
|
+
if (range.logical) {
|
|
1871
|
+
return core.types.logicalExpression("&&", cloneExpression(range.test), truthy);
|
|
1872
|
+
}
|
|
1873
|
+
return core.types.conditionalExpression(
|
|
1874
|
+
cloneExpression(range.test),
|
|
1875
|
+
truthy,
|
|
1876
|
+
range.falsy ? hostElementDescriptor(range.falsy, descriptorBlocks) : core.types.nullLiteral()
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
function keyedRangeDescriptorChildren(range, descriptorBlocks) {
|
|
1880
|
+
const parameters = range.renderCallback.params.map(
|
|
1881
|
+
(parameter) => core.types.cloneNode(parameter, true)
|
|
1882
|
+
);
|
|
1883
|
+
const callback = core.types.arrowFunctionExpression(
|
|
1884
|
+
parameters,
|
|
1885
|
+
hostElementDescriptor(range.row, descriptorBlocks)
|
|
1886
|
+
);
|
|
1887
|
+
const collection = cloneExpression(range.collection);
|
|
1888
|
+
if (range.syntax === "map") {
|
|
1889
|
+
return core.types.callExpression(core.types.memberExpression(collection, core.types.identifier("map")), [callback]);
|
|
1890
|
+
}
|
|
1891
|
+
return core.types.callExpression(
|
|
1892
|
+
core.types.memberExpression(
|
|
1893
|
+
core.types.callExpression(core.types.memberExpression(core.types.identifier("Array"), core.types.identifier("from")), [
|
|
1894
|
+
core.types.logicalExpression("||", collection, core.types.arrayExpression([]))
|
|
1895
|
+
]),
|
|
1896
|
+
core.types.identifier("map")
|
|
1897
|
+
),
|
|
1898
|
+
[callback]
|
|
1899
|
+
);
|
|
1124
1900
|
}
|
|
1125
1901
|
function keyedRowBindingObject(binding, parameters) {
|
|
1126
1902
|
const properties = [
|
|
@@ -1128,6 +1904,12 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1128
1904
|
core.types.objectProperty(
|
|
1129
1905
|
core.types.identifier("path"),
|
|
1130
1906
|
core.types.arrayExpression(binding.path.map((part) => core.types.numericLiteral(part)))
|
|
1907
|
+
),
|
|
1908
|
+
core.types.objectProperty(
|
|
1909
|
+
core.types.identifier("dependencies"),
|
|
1910
|
+
core.types.arrayExpression(
|
|
1911
|
+
(binding.dependencies || []).map((dependency) => core.types.numericLiteral(dependency))
|
|
1912
|
+
)
|
|
1131
1913
|
)
|
|
1132
1914
|
];
|
|
1133
1915
|
if (binding.name) {
|
|
@@ -1144,6 +1926,16 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1144
1926
|
);
|
|
1145
1927
|
return core.types.objectExpression(properties);
|
|
1146
1928
|
}
|
|
1929
|
+
function staticRangeBindingObject(binding) {
|
|
1930
|
+
const value = keyedRowBindingObject(binding, []);
|
|
1931
|
+
value.properties.splice(
|
|
1932
|
+
1,
|
|
1933
|
+
0,
|
|
1934
|
+
core.types.objectProperty(core.types.identifier("segment"), core.types.numericLiteral(binding.segment)),
|
|
1935
|
+
core.types.objectProperty(core.types.identifier("sibling"), core.types.numericLiteral(binding.sibling))
|
|
1936
|
+
);
|
|
1937
|
+
return value;
|
|
1938
|
+
}
|
|
1147
1939
|
function uniqueLocalIdentifier(base, nodes) {
|
|
1148
1940
|
const names = /* @__PURE__ */ new Set();
|
|
1149
1941
|
for (const node of nodes) {
|
|
@@ -1260,6 +2052,10 @@ function keyedRowEventObject(event, renderParameters) {
|
|
|
1260
2052
|
const parameters = [core.types.cloneNode(renderParameters[0], true), index, syntheticEvent];
|
|
1261
2053
|
return core.types.objectExpression([
|
|
1262
2054
|
core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(event.name)),
|
|
2055
|
+
core.types.objectProperty(
|
|
2056
|
+
core.types.identifier("path"),
|
|
2057
|
+
core.types.arrayExpression(event.path.map((part) => core.types.numericLiteral(part)))
|
|
2058
|
+
),
|
|
1263
2059
|
core.types.objectProperty(
|
|
1264
2060
|
core.types.identifier("invoke"),
|
|
1265
2061
|
core.types.arrowFunctionExpression(
|
|
@@ -1329,6 +2125,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1329
2125
|
plan.source,
|
|
1330
2126
|
...plan.conditionals.map((conditional) => conditional.test)
|
|
1331
2127
|
]);
|
|
2128
|
+
const delegatedEvents = canDelegateKeyedRowEvents(plan);
|
|
1332
2129
|
const renderSource = keyedRowsRenderSource(plan, eventFactory, conditionalFactory);
|
|
1333
2130
|
const renderFactoryParameters = plan.conditionals.length > 0 ? [core.types.cloneNode(eventFactory), core.types.cloneNode(conditionalFactory)] : plan.events.length > 0 ? [core.types.cloneNode(eventFactory)] : [];
|
|
1334
2131
|
return core.types.jsxElement(
|
|
@@ -1346,6 +2143,14 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1346
2143
|
core.types.jsxIdentifier("items"),
|
|
1347
2144
|
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], cloneExpression(plan.collection)))
|
|
1348
2145
|
),
|
|
2146
|
+
core.types.jsxAttribute(
|
|
2147
|
+
core.types.jsxIdentifier("structureDependencies"),
|
|
2148
|
+
core.types.jsxExpressionContainer(
|
|
2149
|
+
core.types.arrayExpression(
|
|
2150
|
+
plan.structureDependencies.map((dependency) => core.types.numericLiteral(dependency))
|
|
2151
|
+
)
|
|
2152
|
+
)
|
|
2153
|
+
),
|
|
1349
2154
|
core.types.jsxAttribute(
|
|
1350
2155
|
core.types.jsxIdentifier("rowKey"),
|
|
1351
2156
|
core.types.jsxExpressionContainer(core.types.cloneNode(plan.keyCallback, true))
|
|
@@ -1355,7 +2160,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1355
2160
|
core.types.jsxExpressionContainer(
|
|
1356
2161
|
core.types.arrowFunctionExpression(
|
|
1357
2162
|
parameters.map((parameter) => core.types.cloneNode(parameter, true)),
|
|
1358
|
-
hostElementDescriptor(plan.row)
|
|
2163
|
+
hostElementDescriptor(plan.row, plan.descriptorBlocks)
|
|
1359
2164
|
)
|
|
1360
2165
|
)
|
|
1361
2166
|
),
|
|
@@ -1375,7 +2180,13 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1375
2180
|
plan.events.map((event) => keyedRowEventObject(event, parameters))
|
|
1376
2181
|
)
|
|
1377
2182
|
)
|
|
1378
|
-
)
|
|
2183
|
+
),
|
|
2184
|
+
...delegatedEvents ? [
|
|
2185
|
+
core.types.jsxAttribute(
|
|
2186
|
+
core.types.jsxIdentifier("delegateEvents"),
|
|
2187
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
2188
|
+
)
|
|
2189
|
+
] : []
|
|
1379
2190
|
] : [],
|
|
1380
2191
|
...plan.conditionals.length > 0 ? [
|
|
1381
2192
|
core.types.jsxAttribute(
|
|
@@ -1388,6 +2199,12 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1388
2199
|
)
|
|
1389
2200
|
)
|
|
1390
2201
|
)
|
|
2202
|
+
] : [],
|
|
2203
|
+
...plan.descriptorBlocks?.size ? [
|
|
2204
|
+
core.types.jsxAttribute(
|
|
2205
|
+
core.types.jsxIdentifier("hostBlocks"),
|
|
2206
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
2207
|
+
)
|
|
1391
2208
|
] : []
|
|
1392
2209
|
],
|
|
1393
2210
|
true
|
|
@@ -1397,7 +2214,7 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
1397
2214
|
true
|
|
1398
2215
|
);
|
|
1399
2216
|
}
|
|
1400
|
-
function keyedRangeObject(range) {
|
|
2217
|
+
function keyedRangeObject(range, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1401
2218
|
const parameters = range.renderCallback.params.map(
|
|
1402
2219
|
(parameter) => core.types.cloneNode(parameter, true)
|
|
1403
2220
|
);
|
|
@@ -1412,7 +2229,7 @@ function keyedRangeObject(range) {
|
|
|
1412
2229
|
core.types.identifier("create"),
|
|
1413
2230
|
core.types.arrowFunctionExpression(
|
|
1414
2231
|
parameters.map((parameter) => core.types.cloneNode(parameter, true)),
|
|
1415
|
-
hostElementDescriptor(range.row)
|
|
2232
|
+
hostElementDescriptor(range.row, descriptorBlocks)
|
|
1416
2233
|
)
|
|
1417
2234
|
),
|
|
1418
2235
|
core.types.objectProperty(
|
|
@@ -1456,6 +2273,12 @@ function keyedRangesBoundary(blockRuntime, plan) {
|
|
|
1456
2273
|
core.types.jsxAttribute(
|
|
1457
2274
|
core.types.jsxIdentifier("trailing"),
|
|
1458
2275
|
core.types.jsxExpressionContainer(core.types.numericLiteral(plan.trailing))
|
|
2276
|
+
),
|
|
2277
|
+
core.types.jsxAttribute(
|
|
2278
|
+
core.types.jsxIdentifier("bindings"),
|
|
2279
|
+
core.types.jsxExpressionContainer(
|
|
2280
|
+
core.types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2281
|
+
)
|
|
1459
2282
|
)
|
|
1460
2283
|
],
|
|
1461
2284
|
true
|
|
@@ -1465,11 +2288,11 @@ function keyedRangesBoundary(blockRuntime, plan) {
|
|
|
1465
2288
|
true
|
|
1466
2289
|
);
|
|
1467
2290
|
}
|
|
1468
|
-
function hostConditionalBranchObject(branch, bindings) {
|
|
2291
|
+
function hostConditionalBranchObject(branch, bindings, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
1469
2292
|
return core.types.objectExpression([
|
|
1470
2293
|
core.types.objectProperty(
|
|
1471
2294
|
core.types.identifier("create"),
|
|
1472
|
-
core.types.arrowFunctionExpression([], hostElementDescriptor(branch))
|
|
2295
|
+
core.types.arrowFunctionExpression([], hostElementDescriptor(branch, descriptorBlocks))
|
|
1473
2296
|
),
|
|
1474
2297
|
core.types.objectProperty(
|
|
1475
2298
|
core.types.identifier("bindings"),
|
|
@@ -1498,7 +2321,9 @@ function hostConditionalBoundary(blockRuntime, plan) {
|
|
|
1498
2321
|
attributes.push(
|
|
1499
2322
|
core.types.jsxAttribute(
|
|
1500
2323
|
core.types.jsxIdentifier("truthy"),
|
|
1501
|
-
core.types.jsxExpressionContainer(
|
|
2324
|
+
core.types.jsxExpressionContainer(
|
|
2325
|
+
hostConditionalBranchObject(plan.truthy, plan.truthyBindings, plan.descriptorBlocks)
|
|
2326
|
+
)
|
|
1502
2327
|
)
|
|
1503
2328
|
);
|
|
1504
2329
|
}
|
|
@@ -1506,10 +2331,147 @@ function hostConditionalBoundary(blockRuntime, plan) {
|
|
|
1506
2331
|
attributes.push(
|
|
1507
2332
|
core.types.jsxAttribute(
|
|
1508
2333
|
core.types.jsxIdentifier("falsy"),
|
|
1509
|
-
core.types.jsxExpressionContainer(
|
|
2334
|
+
core.types.jsxExpressionContainer(
|
|
2335
|
+
hostConditionalBranchObject(plan.falsy, plan.falsyBindings, plan.descriptorBlocks)
|
|
2336
|
+
)
|
|
2337
|
+
)
|
|
2338
|
+
);
|
|
2339
|
+
}
|
|
2340
|
+
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2341
|
+
}
|
|
2342
|
+
function conditionalRangeObject(range, descriptorBlocks = /* @__PURE__ */ new Map()) {
|
|
2343
|
+
const properties = [
|
|
2344
|
+
core.types.objectProperty(core.types.identifier("before"), core.types.numericLiteral(range.before)),
|
|
2345
|
+
core.types.objectProperty(
|
|
2346
|
+
core.types.identifier("test"),
|
|
2347
|
+
core.types.arrowFunctionExpression([], cloneExpression(range.test))
|
|
2348
|
+
)
|
|
2349
|
+
];
|
|
2350
|
+
if (range.logical) {
|
|
2351
|
+
properties.push(core.types.objectProperty(core.types.identifier("logical"), core.types.booleanLiteral(true)));
|
|
2352
|
+
}
|
|
2353
|
+
if (range.truthy) {
|
|
2354
|
+
properties.push(
|
|
2355
|
+
core.types.objectProperty(
|
|
2356
|
+
core.types.identifier("truthy"),
|
|
2357
|
+
hostConditionalBranchObject(range.truthy, range.truthyBindings, descriptorBlocks)
|
|
2358
|
+
)
|
|
2359
|
+
);
|
|
2360
|
+
}
|
|
2361
|
+
if (range.falsy) {
|
|
2362
|
+
properties.push(
|
|
2363
|
+
core.types.objectProperty(
|
|
2364
|
+
core.types.identifier("falsy"),
|
|
2365
|
+
hostConditionalBranchObject(range.falsy, range.falsyBindings, descriptorBlocks)
|
|
1510
2366
|
)
|
|
1511
2367
|
);
|
|
1512
2368
|
}
|
|
2369
|
+
return core.types.objectExpression(properties);
|
|
2370
|
+
}
|
|
2371
|
+
function nestedHostBlockObject(plan, descriptorBlocks) {
|
|
2372
|
+
const kind = plan.kind === "nested-host-conditional-ranges" ? "conditional-ranges" : plan.kind === "nested-host-keyed-ranges" ? "keyed-ranges" : "mixed-ranges";
|
|
2373
|
+
return core.types.objectExpression([
|
|
2374
|
+
core.types.objectProperty(core.types.identifier("kind"), core.types.stringLiteral(kind)),
|
|
2375
|
+
core.types.objectProperty(core.types.identifier("id"), core.types.numericLiteral(plan.id)),
|
|
2376
|
+
core.types.objectProperty(
|
|
2377
|
+
core.types.identifier("ranges"),
|
|
2378
|
+
core.types.arrayExpression(
|
|
2379
|
+
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))
|
|
2380
|
+
)
|
|
2381
|
+
),
|
|
2382
|
+
core.types.objectProperty(core.types.identifier("trailing"), core.types.numericLiteral(plan.trailing)),
|
|
2383
|
+
core.types.objectProperty(
|
|
2384
|
+
core.types.identifier("bindings"),
|
|
2385
|
+
core.types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2386
|
+
),
|
|
2387
|
+
...plan.kind === "nested-host-keyed-ranges" ? [core.types.objectProperty(core.types.identifier("staticChildrenOnly"), core.types.booleanLiteral(true))] : []
|
|
2388
|
+
]);
|
|
2389
|
+
}
|
|
2390
|
+
function mixedRangeObject(range, descriptorBlocks) {
|
|
2391
|
+
const value = range.rangeKind === "conditional" ? conditionalRangeObject(range, descriptorBlocks) : keyedRangeObject(range, descriptorBlocks);
|
|
2392
|
+
value.properties.unshift(
|
|
2393
|
+
core.types.objectProperty(core.types.identifier("kind"), core.types.stringLiteral(range.rangeKind))
|
|
2394
|
+
);
|
|
2395
|
+
return value;
|
|
2396
|
+
}
|
|
2397
|
+
function mixedRangesBoundary(blockRuntime, plan) {
|
|
2398
|
+
const name = core.types.jsxMemberExpression(
|
|
2399
|
+
core.types.jsxIdentifier(blockRuntime.name),
|
|
2400
|
+
core.types.jsxIdentifier("MixedRanges")
|
|
2401
|
+
);
|
|
2402
|
+
const source = core.types.cloneNode(plan.source, true);
|
|
2403
|
+
const rootRefIndex = source.openingElement.attributes.findIndex(
|
|
2404
|
+
(attribute) => core.types.isJSXAttribute(attribute) && jsxAttributeName(attribute) === "ref"
|
|
2405
|
+
);
|
|
2406
|
+
const rootRef = rootRefIndex >= 0 ? source.openingElement.attributes.splice(rootRefIndex, 1)[0] : void 0;
|
|
2407
|
+
const nestedPlan = {
|
|
2408
|
+
kind: "nested-host-mixed-ranges",
|
|
2409
|
+
id: plan.id,
|
|
2410
|
+
parent: plan.parent,
|
|
2411
|
+
dependencies: plan.dependencies,
|
|
2412
|
+
source: plan.source,
|
|
2413
|
+
ranges: plan.ranges,
|
|
2414
|
+
trailing: plan.trailing,
|
|
2415
|
+
staticBindings: plan.staticBindings
|
|
2416
|
+
};
|
|
2417
|
+
const descriptorBlocks = new Map(plan.descriptorBlocks);
|
|
2418
|
+
descriptorBlocks.set(plan.source, nestedPlan);
|
|
2419
|
+
const attributes = [
|
|
2420
|
+
core.types.jsxAttribute(core.types.jsxIdentifier("id"), core.types.jsxExpressionContainer(core.types.numericLiteral(plan.id))),
|
|
2421
|
+
core.types.jsxAttribute(
|
|
2422
|
+
core.types.jsxIdentifier("render"),
|
|
2423
|
+
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], source))
|
|
2424
|
+
),
|
|
2425
|
+
core.types.jsxAttribute(
|
|
2426
|
+
core.types.jsxIdentifier("create"),
|
|
2427
|
+
core.types.jsxExpressionContainer(
|
|
2428
|
+
core.types.arrowFunctionExpression([], hostElementDescriptor(plan.source, descriptorBlocks))
|
|
2429
|
+
)
|
|
2430
|
+
)
|
|
2431
|
+
];
|
|
2432
|
+
if (rootRef?.value) {
|
|
2433
|
+
attributes.push(core.types.jsxAttribute(core.types.jsxIdentifier("rootRef"), core.types.cloneNode(rootRef.value, true)));
|
|
2434
|
+
}
|
|
2435
|
+
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2436
|
+
}
|
|
2437
|
+
function conditionalRangesBoundary(blockRuntime, plan) {
|
|
2438
|
+
const name = core.types.jsxMemberExpression(
|
|
2439
|
+
core.types.jsxIdentifier(blockRuntime.name),
|
|
2440
|
+
core.types.jsxIdentifier("ConditionalRanges")
|
|
2441
|
+
);
|
|
2442
|
+
const source = core.types.cloneNode(plan.source, true);
|
|
2443
|
+
const rootRefIndex = source.openingElement.attributes.findIndex(
|
|
2444
|
+
(attribute) => core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && attribute.name.name === "ref"
|
|
2445
|
+
);
|
|
2446
|
+
const rootRef = rootRefIndex >= 0 ? source.openingElement.attributes.splice(rootRefIndex, 1)[0] : void 0;
|
|
2447
|
+
const attributes = [
|
|
2448
|
+
core.types.jsxAttribute(core.types.jsxIdentifier("id"), core.types.jsxExpressionContainer(core.types.numericLiteral(plan.id))),
|
|
2449
|
+
core.types.jsxAttribute(
|
|
2450
|
+
core.types.jsxIdentifier("render"),
|
|
2451
|
+
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], source))
|
|
2452
|
+
),
|
|
2453
|
+
core.types.jsxAttribute(
|
|
2454
|
+
core.types.jsxIdentifier("ranges"),
|
|
2455
|
+
core.types.jsxExpressionContainer(
|
|
2456
|
+
core.types.arrayExpression(
|
|
2457
|
+
plan.ranges.map((range) => conditionalRangeObject(range, plan.descriptorBlocks))
|
|
2458
|
+
)
|
|
2459
|
+
)
|
|
2460
|
+
),
|
|
2461
|
+
core.types.jsxAttribute(
|
|
2462
|
+
core.types.jsxIdentifier("trailing"),
|
|
2463
|
+
core.types.jsxExpressionContainer(core.types.numericLiteral(plan.trailing))
|
|
2464
|
+
),
|
|
2465
|
+
core.types.jsxAttribute(
|
|
2466
|
+
core.types.jsxIdentifier("bindings"),
|
|
2467
|
+
core.types.jsxExpressionContainer(
|
|
2468
|
+
core.types.arrayExpression(plan.staticBindings.map(staticRangeBindingObject))
|
|
2469
|
+
)
|
|
2470
|
+
)
|
|
2471
|
+
];
|
|
2472
|
+
if (rootRef?.value) {
|
|
2473
|
+
attributes.push(core.types.jsxAttribute(core.types.jsxIdentifier("rootRef"), core.types.cloneNode(rootRef.value, true)));
|
|
2474
|
+
}
|
|
1513
2475
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
1514
2476
|
}
|
|
1515
2477
|
function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allowedComponentNames) {
|
|
@@ -1677,6 +2639,41 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1677
2639
|
}
|
|
1678
2640
|
if (core.types.isJSXElement(child)) {
|
|
1679
2641
|
if (isHostElement(child)) {
|
|
2642
|
+
const mixedRangeStart = nextId;
|
|
2643
|
+
const mixedRangeId = nextId++;
|
|
2644
|
+
const mixedRanges = insideConditional ? void 0 : analyzeMixedRangesContainer(
|
|
2645
|
+
child,
|
|
2646
|
+
statesByValue,
|
|
2647
|
+
safeGlobals,
|
|
2648
|
+
listNames,
|
|
2649
|
+
mixedRangeId,
|
|
2650
|
+
() => nextId++
|
|
2651
|
+
);
|
|
2652
|
+
if (mixedRanges) {
|
|
2653
|
+
plans.push({
|
|
2654
|
+
kind: "mixed-ranges",
|
|
2655
|
+
id: mixedRangeId,
|
|
2656
|
+
parent,
|
|
2657
|
+
dependencies: mixedRanges.dependencies,
|
|
2658
|
+
source: child,
|
|
2659
|
+
ranges: mixedRanges.ranges,
|
|
2660
|
+
trailing: mixedRanges.trailing,
|
|
2661
|
+
staticBindings: mixedRanges.staticBindings,
|
|
2662
|
+
descriptorBlocks: mixedRanges.descriptorBlocks
|
|
2663
|
+
});
|
|
2664
|
+
plans.push(...mixedRanges.nestedPlans);
|
|
2665
|
+
for (const range of mixedRanges.ranges) {
|
|
2666
|
+
if (range.rangeKind === "conditional") {
|
|
2667
|
+
conditionalExpressions.add(range.source);
|
|
2668
|
+
} else if (core.types.isJSXElement(range.source)) {
|
|
2669
|
+
ownedElements.add(range.source);
|
|
2670
|
+
} else {
|
|
2671
|
+
keyedExpressions.add(range.source);
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
continue;
|
|
2675
|
+
}
|
|
2676
|
+
nextId = mixedRangeStart;
|
|
1680
2677
|
const keyedRanges = insideConditional ? void 0 : analyzeKeyedRangesContainer(child, statesByValue, safeGlobals, listNames);
|
|
1681
2678
|
if (keyedRanges) {
|
|
1682
2679
|
plans.push({
|
|
@@ -1686,7 +2683,8 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1686
2683
|
dependencies: keyedRanges.dependencies,
|
|
1687
2684
|
source: child,
|
|
1688
2685
|
ranges: keyedRanges.ranges,
|
|
1689
|
-
trailing: keyedRanges.trailing
|
|
2686
|
+
trailing: keyedRanges.trailing,
|
|
2687
|
+
staticBindings: keyedRanges.staticBindings
|
|
1690
2688
|
});
|
|
1691
2689
|
for (const range of keyedRanges.ranges) {
|
|
1692
2690
|
if (core.types.isJSXElement(range.source)) ownedElements.add(range.source);
|
|
@@ -1694,42 +2692,102 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1694
2692
|
}
|
|
1695
2693
|
continue;
|
|
1696
2694
|
}
|
|
2695
|
+
const conditionalRangeStart = nextId;
|
|
2696
|
+
const conditionalRangeId = nextId++;
|
|
2697
|
+
const conditionalRanges = insideConditional ? void 0 : analyzeConditionalRangesContainer(
|
|
2698
|
+
child,
|
|
2699
|
+
statesByValue,
|
|
2700
|
+
safeGlobals,
|
|
2701
|
+
false,
|
|
2702
|
+
listNames,
|
|
2703
|
+
conditionalRangeId,
|
|
2704
|
+
() => nextId++
|
|
2705
|
+
);
|
|
2706
|
+
if (conditionalRanges) {
|
|
2707
|
+
plans.push({
|
|
2708
|
+
kind: "conditional-ranges",
|
|
2709
|
+
id: conditionalRangeId,
|
|
2710
|
+
parent,
|
|
2711
|
+
dependencies: conditionalRanges.dependencies,
|
|
2712
|
+
source: child,
|
|
2713
|
+
ranges: conditionalRanges.ranges,
|
|
2714
|
+
trailing: conditionalRanges.trailing,
|
|
2715
|
+
staticBindings: conditionalRanges.staticBindings,
|
|
2716
|
+
descriptorBlocks: conditionalRanges.descriptorBlocks
|
|
2717
|
+
});
|
|
2718
|
+
plans.push(...conditionalRanges.nestedPlans || []);
|
|
2719
|
+
for (const range of conditionalRanges.ranges) {
|
|
2720
|
+
conditionalExpressions.add(range.source);
|
|
2721
|
+
}
|
|
2722
|
+
continue;
|
|
2723
|
+
}
|
|
2724
|
+
nextId = conditionalRangeStart;
|
|
2725
|
+
const hostConditionalStart = nextId;
|
|
2726
|
+
const hostConditionalId = nextId++;
|
|
1697
2727
|
const hostConditional = analyzeHostConditionalContainer(
|
|
1698
2728
|
child,
|
|
1699
2729
|
statesByValue,
|
|
1700
|
-
safeGlobals
|
|
2730
|
+
safeGlobals,
|
|
2731
|
+
listNames,
|
|
2732
|
+
hostConditionalId,
|
|
2733
|
+
() => nextId++
|
|
1701
2734
|
);
|
|
1702
2735
|
if (hostConditional) {
|
|
1703
2736
|
plans.push({
|
|
1704
2737
|
kind: "host-conditional",
|
|
1705
|
-
id:
|
|
2738
|
+
id: hostConditionalId,
|
|
1706
2739
|
parent,
|
|
1707
2740
|
source: child,
|
|
1708
2741
|
...hostConditional
|
|
1709
2742
|
});
|
|
2743
|
+
plans.push(...hostConditional.nestedPlans || []);
|
|
1710
2744
|
ownedElements.add(child);
|
|
1711
2745
|
continue;
|
|
1712
2746
|
}
|
|
2747
|
+
nextId = hostConditionalStart;
|
|
2748
|
+
const keyedRowsStart = nextId;
|
|
2749
|
+
const keyedRowsId = nextId++;
|
|
1713
2750
|
const keyedRows = analyzeKeyedRowsContainer(child, statesByValue, safeGlobals, listNames);
|
|
1714
2751
|
if (keyedRows) {
|
|
2752
|
+
const nestedStart = nextId;
|
|
2753
|
+
const hostBlocks = analyzeCompilerOwnedKeyedRowHostBlocks(
|
|
2754
|
+
keyedRows,
|
|
2755
|
+
statesByValue,
|
|
2756
|
+
safeGlobals,
|
|
2757
|
+
listNames,
|
|
2758
|
+
keyedRowsId,
|
|
2759
|
+
() => nextId++
|
|
2760
|
+
);
|
|
2761
|
+
if (!hostBlocks) nextId = nestedStart;
|
|
2762
|
+
if (keyedRows.rowReason && !hostBlocks) {
|
|
2763
|
+
nextId = keyedRowsStart;
|
|
2764
|
+
const nested2 = visitHost(child, parent, insideConditional);
|
|
2765
|
+
if (nested2.reason) return { dependencies, reason: nested2.reason };
|
|
2766
|
+
mergeDependencies(dependencies, nested2.dependencies);
|
|
2767
|
+
continue;
|
|
2768
|
+
}
|
|
1715
2769
|
plans.push({
|
|
1716
2770
|
kind: "keyed-rows",
|
|
1717
|
-
id:
|
|
2771
|
+
id: keyedRowsId,
|
|
1718
2772
|
parent,
|
|
1719
2773
|
dependencies: keyedRows.dependencies,
|
|
1720
2774
|
source: child,
|
|
1721
2775
|
collection: keyedRows.collection,
|
|
2776
|
+
structureDependencies: keyedRows.structureDependencies,
|
|
1722
2777
|
keyCallback: keyedRows.keyCallback,
|
|
1723
2778
|
renderCallback: keyedRows.renderCallback,
|
|
1724
|
-
row: keyedRows.row,
|
|
1725
|
-
bindings: keyedRows.bindings,
|
|
2779
|
+
row: hostBlocks?.row || keyedRows.row,
|
|
2780
|
+
bindings: hostBlocks?.bindings || keyedRows.bindings,
|
|
1726
2781
|
events: keyedRows.events,
|
|
1727
|
-
conditionals: keyedRows.conditionals,
|
|
2782
|
+
conditionals: hostBlocks ? [] : keyedRows.conditionals,
|
|
2783
|
+
descriptorBlocks: hostBlocks?.descriptorBlocks,
|
|
1728
2784
|
syntax: keyedRows.syntax
|
|
1729
2785
|
});
|
|
2786
|
+
plans.push(...hostBlocks?.nestedPlans || []);
|
|
1730
2787
|
ownedElements.add(child);
|
|
1731
2788
|
continue;
|
|
1732
2789
|
}
|
|
2790
|
+
nextId = keyedRowsStart;
|
|
1733
2791
|
const nested = visitHost(child, parent, insideConditional);
|
|
1734
2792
|
if (nested.reason) return { dependencies, reason: nested.reason };
|
|
1735
2793
|
mergeDependencies(dependencies, nested.dependencies);
|
|
@@ -1826,6 +2884,46 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1826
2884
|
}
|
|
1827
2885
|
return { dependencies };
|
|
1828
2886
|
};
|
|
2887
|
+
const rootMixedRangeStart = nextId;
|
|
2888
|
+
const rootMixedRangeId = nextId++;
|
|
2889
|
+
const rootMixedRanges = analyzeMixedRangesContainer(
|
|
2890
|
+
root,
|
|
2891
|
+
statesByValue,
|
|
2892
|
+
safeGlobals,
|
|
2893
|
+
listNames,
|
|
2894
|
+
rootMixedRangeId,
|
|
2895
|
+
() => nextId++
|
|
2896
|
+
);
|
|
2897
|
+
if (rootMixedRanges) {
|
|
2898
|
+
plans.push({
|
|
2899
|
+
kind: "mixed-ranges",
|
|
2900
|
+
id: rootMixedRangeId,
|
|
2901
|
+
dependencies: rootMixedRanges.dependencies,
|
|
2902
|
+
source: root,
|
|
2903
|
+
ranges: rootMixedRanges.ranges,
|
|
2904
|
+
trailing: rootMixedRanges.trailing,
|
|
2905
|
+
staticBindings: rootMixedRanges.staticBindings,
|
|
2906
|
+
descriptorBlocks: rootMixedRanges.descriptorBlocks
|
|
2907
|
+
});
|
|
2908
|
+
plans.push(...rootMixedRanges.nestedPlans);
|
|
2909
|
+
for (const range of rootMixedRanges.ranges) {
|
|
2910
|
+
if (range.rangeKind === "conditional") {
|
|
2911
|
+
conditionalExpressions.add(range.source);
|
|
2912
|
+
} else if (core.types.isJSXElement(range.source)) {
|
|
2913
|
+
ownedElements.add(range.source);
|
|
2914
|
+
} else {
|
|
2915
|
+
keyedExpressions.add(range.source);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
return {
|
|
2919
|
+
plans,
|
|
2920
|
+
componentElements,
|
|
2921
|
+
conditionalExpressions,
|
|
2922
|
+
ownedElements,
|
|
2923
|
+
keyedExpressions
|
|
2924
|
+
};
|
|
2925
|
+
}
|
|
2926
|
+
nextId = rootMixedRangeStart;
|
|
1829
2927
|
const rootRanges = analyzeKeyedRangesContainer(root, statesByValue, safeGlobals, listNames, true);
|
|
1830
2928
|
if (rootRanges) {
|
|
1831
2929
|
plans.push({
|
|
@@ -1834,7 +2932,8 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1834
2932
|
dependencies: rootRanges.dependencies,
|
|
1835
2933
|
source: root,
|
|
1836
2934
|
ranges: rootRanges.ranges,
|
|
1837
|
-
trailing: rootRanges.trailing
|
|
2935
|
+
trailing: rootRanges.trailing,
|
|
2936
|
+
staticBindings: rootRanges.staticBindings
|
|
1838
2937
|
});
|
|
1839
2938
|
for (const range of rootRanges.ranges) {
|
|
1840
2939
|
if (core.types.isJSXElement(range.source)) ownedElements.add(range.source);
|
|
@@ -1848,6 +2947,41 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
1848
2947
|
keyedExpressions
|
|
1849
2948
|
};
|
|
1850
2949
|
}
|
|
2950
|
+
const rootConditionalRangeStart = nextId;
|
|
2951
|
+
const rootConditionalRangeId = nextId++;
|
|
2952
|
+
const rootConditionalRanges = analyzeConditionalRangesContainer(
|
|
2953
|
+
root,
|
|
2954
|
+
statesByValue,
|
|
2955
|
+
safeGlobals,
|
|
2956
|
+
true,
|
|
2957
|
+
listNames,
|
|
2958
|
+
rootConditionalRangeId,
|
|
2959
|
+
() => nextId++
|
|
2960
|
+
);
|
|
2961
|
+
if (rootConditionalRanges) {
|
|
2962
|
+
plans.push({
|
|
2963
|
+
kind: "conditional-ranges",
|
|
2964
|
+
id: rootConditionalRangeId,
|
|
2965
|
+
dependencies: rootConditionalRanges.dependencies,
|
|
2966
|
+
source: root,
|
|
2967
|
+
ranges: rootConditionalRanges.ranges,
|
|
2968
|
+
trailing: rootConditionalRanges.trailing,
|
|
2969
|
+
staticBindings: rootConditionalRanges.staticBindings,
|
|
2970
|
+
descriptorBlocks: rootConditionalRanges.descriptorBlocks
|
|
2971
|
+
});
|
|
2972
|
+
plans.push(...rootConditionalRanges.nestedPlans || []);
|
|
2973
|
+
for (const range of rootConditionalRanges.ranges) {
|
|
2974
|
+
conditionalExpressions.add(range.source);
|
|
2975
|
+
}
|
|
2976
|
+
return {
|
|
2977
|
+
plans,
|
|
2978
|
+
componentElements,
|
|
2979
|
+
conditionalExpressions,
|
|
2980
|
+
ownedElements,
|
|
2981
|
+
keyedExpressions
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
nextId = rootConditionalRangeStart;
|
|
1851
2985
|
const result = visitHost(root, void 0, false);
|
|
1852
2986
|
if (result.reason) return { reason: result.reason };
|
|
1853
2987
|
return {
|
|
@@ -1885,9 +3019,15 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
1885
3019
|
plans.map((plan) => [plan.source, plan])
|
|
1886
3020
|
);
|
|
1887
3021
|
const rootPlan = planBySource.get(root);
|
|
3022
|
+
if (rootPlan?.kind === "mixed-ranges") {
|
|
3023
|
+
return mixedRangesBoundary(blockRuntime, rootPlan);
|
|
3024
|
+
}
|
|
1888
3025
|
if (rootPlan?.kind === "keyed-ranges") {
|
|
1889
3026
|
return keyedRangesBoundary(blockRuntime, rootPlan);
|
|
1890
3027
|
}
|
|
3028
|
+
if (rootPlan?.kind === "conditional-ranges") {
|
|
3029
|
+
return conditionalRangesBoundary(blockRuntime, rootPlan);
|
|
3030
|
+
}
|
|
1891
3031
|
const visit = (element) => {
|
|
1892
3032
|
element.children = element.children.map((child) => {
|
|
1893
3033
|
if (core.types.isJSXElement(child)) {
|
|
@@ -1895,12 +3035,18 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
1895
3035
|
if (plan2?.kind === "host-conditional") {
|
|
1896
3036
|
return hostConditionalBoundary(blockRuntime, plan2);
|
|
1897
3037
|
}
|
|
3038
|
+
if (plan2?.kind === "mixed-ranges") {
|
|
3039
|
+
return mixedRangesBoundary(blockRuntime, plan2);
|
|
3040
|
+
}
|
|
1898
3041
|
if (plan2?.kind === "keyed-rows") {
|
|
1899
3042
|
return keyedRowsBoundary(blockRuntime, plan2);
|
|
1900
3043
|
}
|
|
1901
3044
|
if (plan2?.kind === "keyed-ranges") {
|
|
1902
3045
|
return keyedRangesBoundary(blockRuntime, plan2);
|
|
1903
3046
|
}
|
|
3047
|
+
if (plan2?.kind === "conditional-ranges") {
|
|
3048
|
+
return conditionalRangesBoundary(blockRuntime, plan2);
|
|
3049
|
+
}
|
|
1904
3050
|
if (plan2?.kind === "component") {
|
|
1905
3051
|
return componentIslandBoundary(blockRuntime, plan2, child);
|
|
1906
3052
|
}
|
|
@@ -1941,6 +3087,31 @@ function assignStableBindingTargets(bindings) {
|
|
|
1941
3087
|
binding.target = target;
|
|
1942
3088
|
}
|
|
1943
3089
|
}
|
|
3090
|
+
function markShortCircuitBindings(bindings) {
|
|
3091
|
+
for (const binding of bindings) {
|
|
3092
|
+
if (binding.kind === "block" || binding.dependencies.length < 2) continue;
|
|
3093
|
+
let shortCircuits = false;
|
|
3094
|
+
core.traverse(expressionFile(core.types.cloneNode(binding.value, true)), {
|
|
3095
|
+
ConditionalExpression(path) {
|
|
3096
|
+
shortCircuits = true;
|
|
3097
|
+
path.stop();
|
|
3098
|
+
},
|
|
3099
|
+
LogicalExpression(path) {
|
|
3100
|
+
shortCircuits = true;
|
|
3101
|
+
path.stop();
|
|
3102
|
+
},
|
|
3103
|
+
OptionalCallExpression(path) {
|
|
3104
|
+
shortCircuits = true;
|
|
3105
|
+
path.stop();
|
|
3106
|
+
},
|
|
3107
|
+
OptionalMemberExpression(path) {
|
|
3108
|
+
shortCircuits = true;
|
|
3109
|
+
path.stop();
|
|
3110
|
+
}
|
|
3111
|
+
});
|
|
3112
|
+
if (shortCircuits) binding.tracking = "dynamic";
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
1944
3115
|
function lowerStableBindingTargets(root, bindings, blockRuntime, ownedElements) {
|
|
1945
3116
|
const targetByPath = /* @__PURE__ */ new Map();
|
|
1946
3117
|
for (const binding of bindings) {
|
|
@@ -2210,6 +3381,9 @@ function bindingObject(binding, propsParameter, stateParameter, statesByValue, s
|
|
|
2210
3381
|
core.types.objectProperty(core.types.identifier("target"), core.types.numericLiteral(binding.target))
|
|
2211
3382
|
);
|
|
2212
3383
|
}
|
|
3384
|
+
if (binding.tracking) {
|
|
3385
|
+
properties.push(core.types.objectProperty(core.types.identifier("tracking"), core.types.stringLiteral(binding.tracking)));
|
|
3386
|
+
}
|
|
2213
3387
|
if (binding.name)
|
|
2214
3388
|
properties.push(core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(binding.name)));
|
|
2215
3389
|
properties.push(
|
|
@@ -2228,7 +3402,7 @@ function wrapperElement(definitionIdentifier, props) {
|
|
|
2228
3402
|
const attributes = props ? [core.types.jsxSpreadAttribute(core.types.cloneNode(props))] : [];
|
|
2229
3403
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
2230
3404
|
}
|
|
2231
|
-
function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames, listNames, moduleId) {
|
|
3405
|
+
function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
2232
3406
|
const { path, name, statementPath } = candidate;
|
|
2233
3407
|
if (path.node.async || path.node.generator)
|
|
2234
3408
|
return "async and generator components are not supported";
|
|
@@ -2345,8 +3519,34 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2345
3519
|
);
|
|
2346
3520
|
const setterReason = validateSetterUsage(expandedRoot, statesBySetter);
|
|
2347
3521
|
if (setterReason) return setterReason;
|
|
3522
|
+
const referencedPropNames = collectDestructuredPropNames(
|
|
3523
|
+
expandedRoot,
|
|
3524
|
+
propsPlan.destructuredNames,
|
|
3525
|
+
propsPlan.definitionParameter
|
|
3526
|
+
);
|
|
3527
|
+
let propBindings = referencedPropNames.has("children") ? [] : [...propsPlan.destructuredNames].filter((propName) => referencedPropNames.has(propName)).map(
|
|
3528
|
+
(localName, propIndex) => ({
|
|
3529
|
+
localName,
|
|
3530
|
+
valueName: path.scope.generateUidIdentifier(`farmProp${propIndex}`).name,
|
|
3531
|
+
index: states.length + propIndex
|
|
3532
|
+
})
|
|
3533
|
+
);
|
|
3534
|
+
const propBindingsByName = new Map(propBindings.map((binding) => [binding.localName, binding]));
|
|
3535
|
+
let reactiveByValue = new Map(statesByValue);
|
|
3536
|
+
for (const binding of propBindings) {
|
|
3537
|
+
reactiveByValue.set(binding.valueName, {
|
|
3538
|
+
valueName: binding.valueName,
|
|
3539
|
+
setterName: "",
|
|
3540
|
+
index: binding.index
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
let expandedReactiveRoot = rewriteTrackedPropAccess(
|
|
3544
|
+
expandedRoot,
|
|
3545
|
+
propsPlan.definitionParameter,
|
|
3546
|
+
propBindingsByName
|
|
3547
|
+
);
|
|
2348
3548
|
const referencedComponentNames = /* @__PURE__ */ new Set();
|
|
2349
|
-
core.traverse(expressionFile(core.types.cloneNode(
|
|
3549
|
+
core.traverse(expressionFile(core.types.cloneNode(expandedReactiveRoot, true)), {
|
|
2350
3550
|
JSXOpeningElement(componentPath) {
|
|
2351
3551
|
const componentName = componentPath.node.name;
|
|
2352
3552
|
if (core.types.isJSXIdentifier(componentName) && isComponentName(componentName.name)) {
|
|
@@ -2363,32 +3563,54 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2363
3563
|
);
|
|
2364
3564
|
})
|
|
2365
3565
|
);
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
3566
|
+
let blockAnalysis = analyzeComposableBlocks(
|
|
3567
|
+
expandedReactiveRoot,
|
|
3568
|
+
reactiveByValue,
|
|
2369
3569
|
safeGlobals,
|
|
2370
3570
|
listNames,
|
|
2371
3571
|
allowedComponentNames
|
|
2372
3572
|
);
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
expandedRoot,
|
|
2377
|
-
statesByValue,
|
|
3573
|
+
let analysis = analyzeHostTree(
|
|
3574
|
+
expandedReactiveRoot,
|
|
3575
|
+
reactiveByValue,
|
|
2378
3576
|
safeGlobals,
|
|
2379
3577
|
blockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
2380
3578
|
blockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
2381
3579
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
2382
3580
|
blockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
2383
3581
|
);
|
|
3582
|
+
if (propBindings.length > 0 && (blockAnalysis.reason || analysis.reason)) {
|
|
3583
|
+
propBindings = [];
|
|
3584
|
+
reactiveByValue = new Map(statesByValue);
|
|
3585
|
+
expandedReactiveRoot = core.types.cloneNode(expandedRoot, true);
|
|
3586
|
+
blockAnalysis = analyzeComposableBlocks(
|
|
3587
|
+
expandedReactiveRoot,
|
|
3588
|
+
reactiveByValue,
|
|
3589
|
+
safeGlobals,
|
|
3590
|
+
listNames,
|
|
3591
|
+
allowedComponentNames
|
|
3592
|
+
);
|
|
3593
|
+
analysis = analyzeHostTree(
|
|
3594
|
+
expandedReactiveRoot,
|
|
3595
|
+
reactiveByValue,
|
|
3596
|
+
safeGlobals,
|
|
3597
|
+
blockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
3598
|
+
blockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
3599
|
+
blockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
3600
|
+
blockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
3601
|
+
);
|
|
3602
|
+
}
|
|
3603
|
+
if (blockAnalysis.reason) return blockAnalysis.reason;
|
|
2384
3604
|
if (analysis.reason) return analysis.reason;
|
|
3605
|
+
const blockPlans = blockAnalysis.plans || [];
|
|
3606
|
+
markShortCircuitBindings(analysis.bindings || []);
|
|
2385
3607
|
assignStableBindingTargets(analysis.bindings || []);
|
|
2386
3608
|
const stateParameter = path.scope.generateUidIdentifier("farmState");
|
|
2387
3609
|
const blockParameter = path.scope.generateUidIdentifier("farmBlocks");
|
|
2388
3610
|
const definitionIdentifier = path.scope.generateUidIdentifier(`${name}Compiled`);
|
|
2389
3611
|
const propsParameter = propsPlan.definitionParameter;
|
|
2390
3612
|
const rootWithTargets = lowerStableBindingTargets(
|
|
2391
|
-
|
|
3613
|
+
expandedReactiveRoot,
|
|
2392
3614
|
analysis.bindings || [],
|
|
2393
3615
|
blockParameter,
|
|
2394
3616
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set()
|
|
@@ -2402,12 +3624,13 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2402
3624
|
const rewrittenRoot = rewriteStateAccess(
|
|
2403
3625
|
rootWithBlocks,
|
|
2404
3626
|
stateParameter,
|
|
2405
|
-
|
|
3627
|
+
reactiveByValue,
|
|
2406
3628
|
statesBySetter
|
|
2407
3629
|
);
|
|
2408
3630
|
const definition = core.types.callExpression(core.types.cloneNode(createComponentIdentifier), [
|
|
2409
3631
|
core.types.objectExpression([
|
|
2410
3632
|
core.types.objectProperty(core.types.identifier("displayName"), core.types.stringLiteral(name)),
|
|
3633
|
+
core.types.objectProperty(core.types.identifier("reactivity"), core.types.stringLiteral(reactivity)),
|
|
2411
3634
|
core.types.spreadElement(
|
|
2412
3635
|
core.types.conditionalExpression(
|
|
2413
3636
|
core.types.memberExpression(
|
|
@@ -2418,7 +3641,9 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2418
3641
|
core.types.objectProperty(core.types.identifier("hmrId"), core.types.stringLiteral(`${moduleId}#${name}`)),
|
|
2419
3642
|
core.types.objectProperty(
|
|
2420
3643
|
core.types.identifier("stateSignature"),
|
|
2421
|
-
core.types.stringLiteral(
|
|
3644
|
+
core.types.stringLiteral(
|
|
3645
|
+
propBindings.length === 0 ? String(states.length) : `${states.length}:${propBindings.map((binding) => binding.localName).join(",")}`
|
|
3646
|
+
)
|
|
2422
3647
|
)
|
|
2423
3648
|
]),
|
|
2424
3649
|
core.types.objectExpression([])
|
|
@@ -2441,6 +3666,22 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2441
3666
|
)
|
|
2442
3667
|
)
|
|
2443
3668
|
),
|
|
3669
|
+
...propBindings.length > 0 ? [
|
|
3670
|
+
core.types.objectProperty(
|
|
3671
|
+
core.types.identifier("readProps"),
|
|
3672
|
+
core.types.arrowFunctionExpression(
|
|
3673
|
+
[core.types.cloneNode(propsParameter)],
|
|
3674
|
+
core.types.arrayExpression(
|
|
3675
|
+
propBindings.map(
|
|
3676
|
+
(binding) => core.types.memberExpression(
|
|
3677
|
+
core.types.cloneNode(propsParameter),
|
|
3678
|
+
core.types.identifier(binding.localName)
|
|
3679
|
+
)
|
|
3680
|
+
)
|
|
3681
|
+
)
|
|
3682
|
+
)
|
|
3683
|
+
)
|
|
3684
|
+
] : [],
|
|
2444
3685
|
core.types.objectProperty(
|
|
2445
3686
|
core.types.identifier("render"),
|
|
2446
3687
|
core.types.arrowFunctionExpression(
|
|
@@ -2460,7 +3701,7 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
2460
3701
|
dependencies: block.dependencies
|
|
2461
3702
|
}))
|
|
2462
3703
|
].map(
|
|
2463
|
-
(binding) => bindingObject(binding, propsParameter, stateParameter,
|
|
3704
|
+
(binding) => bindingObject(binding, propsParameter, stateParameter, reactiveByValue, statesBySetter)
|
|
2464
3705
|
)
|
|
2465
3706
|
)
|
|
2466
3707
|
)
|
|
@@ -2554,7 +3795,8 @@ async function compileReactModule(code, id, options) {
|
|
|
2554
3795
|
useStateNames,
|
|
2555
3796
|
reactNames,
|
|
2556
3797
|
listNames,
|
|
2557
|
-
id
|
|
3798
|
+
id,
|
|
3799
|
+
options.reactivity
|
|
2558
3800
|
);
|
|
2559
3801
|
if (reason) {
|
|
2560
3802
|
diagnostics.push({
|
|
@@ -2681,6 +3923,10 @@ function normalizeReactCompilerOptions(value) {
|
|
|
2681
3923
|
if (!["fallback", "warn", "error"].includes(onUnsupported)) {
|
|
2682
3924
|
throw new TypeError(`Unknown unsupported-component behavior: ${String(onUnsupported)}`);
|
|
2683
3925
|
}
|
|
3926
|
+
const reactivity = options.reactivity || "hybrid";
|
|
3927
|
+
if (reactivity !== "static" && reactivity !== "hybrid") {
|
|
3928
|
+
throw new TypeError(`Unknown React compiler reactivity mode: ${String(reactivity)}`);
|
|
3929
|
+
}
|
|
2684
3930
|
if (options.report !== void 0 && typeof options.report !== "boolean") {
|
|
2685
3931
|
throw new TypeError("The React compiler report option must be a boolean.");
|
|
2686
3932
|
}
|
|
@@ -2691,7 +3937,7 @@ function normalizeReactCompilerOptions(value) {
|
|
|
2691
3937
|
}
|
|
2692
3938
|
const reportFile = normalizeCompilerReportFile(options.reportFile);
|
|
2693
3939
|
const report = options.report === true || options.reportFile !== void 0;
|
|
2694
|
-
return { mode, directive, onUnsupported, report, reportFile };
|
|
3940
|
+
return { mode, directive, onUnsupported, reactivity, report, reportFile };
|
|
2695
3941
|
}
|
|
2696
3942
|
|
|
2697
3943
|
// src/vite.ts
|
|
@@ -2707,7 +3953,7 @@ function readCompilerOptions(rendererOptions) {
|
|
|
2707
3953
|
);
|
|
2708
3954
|
}
|
|
2709
3955
|
const normalized = compiler;
|
|
2710
|
-
if ((normalized.mode === "infer" || normalized.mode === "annotation") && typeof normalized.directive === "string" && (normalized.onUnsupported === "fallback" || normalized.onUnsupported === "warn" || normalized.onUnsupported === "error")) {
|
|
3956
|
+
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")) {
|
|
2711
3957
|
return normalized;
|
|
2712
3958
|
}
|
|
2713
3959
|
return normalizeReactCompilerOptions(compiler);
|