@farm.js/react 0.1.0-beta.4 → 0.1.0-beta.6
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 +213 -1
- package/dist/compiler-runtime.cjs +1892 -65
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +112 -4
- package/dist/compiler-runtime.d.ts +112 -4
- package/dist/compiler-runtime.mjs +1839 -66
- package/dist/compiler-runtime.mjs.map +1 -1
- package/dist/vite.cjs +1959 -44
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1959 -44
- package/dist/vite.mjs.map +1 -1
- package/package.json +6 -4
package/dist/vite.cjs
CHANGED
|
@@ -62,6 +62,73 @@ function canDelegateKeyedRowEvents(plan) {
|
|
|
62
62
|
(event) => DELEGATABLE_KEYED_ROW_EVENTS.has(event.name.replace(/Capture$/, ""))
|
|
63
63
|
);
|
|
64
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-hinted": "keyedRowsHintedRuntimeFeature",
|
|
72
|
+
"keyed-rows-position-hinted": "keyedRowsPositionHintedRuntimeFeature",
|
|
73
|
+
"keyed-rows-reorder-hinted": "keyedRowsReorderHintedRuntimeFeature",
|
|
74
|
+
"keyed-rows-all-hinted": "keyedRowsAllHintedRuntimeFeature",
|
|
75
|
+
"keyed-rows-every-hinted": "keyedRowsEveryHintedRuntimeFeature",
|
|
76
|
+
"keyed-rows-filter-hinted": "keyedRowsFilterHintedRuntimeFeature",
|
|
77
|
+
"keyed-rows-prepend-hinted": "keyedRowsPrependHintedRuntimeFeature",
|
|
78
|
+
"keyed-rows-filter-prepend-hinted": "keyedRowsFilterPrependHintedRuntimeFeature",
|
|
79
|
+
"keyed-rows-conditional": "keyedRowsConditionalRuntimeFeature",
|
|
80
|
+
"keyed-rows-conditional-hinted": "keyedRowsConditionalHintedRuntimeFeature",
|
|
81
|
+
"keyed-rows-conditional-position-hinted": "keyedRowsConditionalPositionHintedRuntimeFeature",
|
|
82
|
+
"keyed-rows-conditional-reorder-hinted": "keyedRowsConditionalReorderHintedRuntimeFeature",
|
|
83
|
+
"keyed-rows-conditional-all-hinted": "keyedRowsConditionalAllHintedRuntimeFeature",
|
|
84
|
+
"keyed-rows-conditional-every-hinted": "keyedRowsConditionalEveryHintedRuntimeFeature",
|
|
85
|
+
"keyed-rows-conditional-filter-hinted": "keyedRowsConditionalFilterHintedRuntimeFeature",
|
|
86
|
+
"keyed-rows-conditional-prepend-hinted": "keyedRowsConditionalPrependHintedRuntimeFeature",
|
|
87
|
+
"keyed-rows-conditional-filter-prepend-hinted": "keyedRowsConditionalFilterPrependHintedRuntimeFeature",
|
|
88
|
+
"keyed-rows-host": "keyedRowsHostRuntimeFeature",
|
|
89
|
+
"keyed-rows-host-hinted": "keyedRowsHostHintedRuntimeFeature",
|
|
90
|
+
"keyed-rows-host-position-hinted": "keyedRowsHostPositionHintedRuntimeFeature",
|
|
91
|
+
"keyed-rows-host-reorder-hinted": "keyedRowsHostReorderHintedRuntimeFeature",
|
|
92
|
+
"keyed-rows-host-all-hinted": "keyedRowsHostAllHintedRuntimeFeature",
|
|
93
|
+
"keyed-rows-host-every-hinted": "keyedRowsHostEveryHintedRuntimeFeature",
|
|
94
|
+
"keyed-rows-host-filter-hinted": "keyedRowsHostFilterHintedRuntimeFeature",
|
|
95
|
+
"keyed-rows-host-prepend-hinted": "keyedRowsHostPrependHintedRuntimeFeature",
|
|
96
|
+
"keyed-rows-host-filter-prepend-hinted": "keyedRowsHostFilterPrependHintedRuntimeFeature",
|
|
97
|
+
"keyed-rows-complete": "keyedRowsCompleteRuntimeFeature",
|
|
98
|
+
"keyed-rows-complete-hinted": "keyedRowsCompleteHintedRuntimeFeature",
|
|
99
|
+
"keyed-rows-complete-position-hinted": "keyedRowsCompletePositionHintedRuntimeFeature",
|
|
100
|
+
"keyed-rows-complete-reorder-hinted": "keyedRowsCompleteReorderHintedRuntimeFeature",
|
|
101
|
+
"keyed-rows-complete-all-hinted": "keyedRowsCompleteAllHintedRuntimeFeature",
|
|
102
|
+
"keyed-rows-complete-every-hinted": "keyedRowsCompleteEveryHintedRuntimeFeature",
|
|
103
|
+
"keyed-rows-complete-filter-hinted": "keyedRowsCompleteFilterHintedRuntimeFeature",
|
|
104
|
+
"keyed-rows-complete-prepend-hinted": "keyedRowsCompletePrependHintedRuntimeFeature",
|
|
105
|
+
"keyed-rows-complete-filter-prepend-hinted": "keyedRowsCompleteFilterPrependHintedRuntimeFeature",
|
|
106
|
+
"keyed-ranges": "keyedRangesRuntimeFeature",
|
|
107
|
+
"mixed-ranges": "mixedRangesRuntimeFeature",
|
|
108
|
+
component: "componentRuntimeFeature"
|
|
109
|
+
};
|
|
110
|
+
function runtimeFeaturesForPlans(plans, keyedMapUpdateHints, keyedArrayFilterHints, keyedArrayPrependHints, keyedArrayPositionHints, keyedArrayReorderHints, keyedArrayRollingWindowHints) {
|
|
111
|
+
const features = /* @__PURE__ */ new Set();
|
|
112
|
+
let keyedRowsHaveConditionals = false;
|
|
113
|
+
let keyedRowsHaveHostBlocks = false;
|
|
114
|
+
for (const plan of plans) {
|
|
115
|
+
if (plan.kind === "keyed-rows") {
|
|
116
|
+
keyedRowsHaveConditionals || (keyedRowsHaveConditionals = plan.conditionals.length > 0);
|
|
117
|
+
keyedRowsHaveHostBlocks || (keyedRowsHaveHostBlocks = Boolean(plan.descriptorBlocks?.size));
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (plan.kind in COMPILER_RUNTIME_FEATURE_EXPORTS) {
|
|
121
|
+
features.add(plan.kind);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (plans.some((plan) => plan.kind === "keyed-rows")) {
|
|
125
|
+
const keyedRowsFeature = keyedRowsHaveConditionals && keyedRowsHaveHostBlocks ? "keyed-rows-complete" : keyedRowsHaveConditionals ? "keyed-rows-conditional" : keyedRowsHaveHostBlocks ? "keyed-rows-host" : "keyed-rows";
|
|
126
|
+
const arrayRangeHints = keyedArrayRollingWindowHints || keyedArrayFilterHints || keyedArrayPrependHints;
|
|
127
|
+
const hintSuffix = keyedArrayPositionHints && (arrayRangeHints || keyedArrayReorderHints) || keyedArrayReorderHints && arrayRangeHints ? "-every-hinted" : keyedArrayRollingWindowHints ? "-all-hinted" : keyedArrayPositionHints ? "-position-hinted" : keyedArrayReorderHints ? "-reorder-hinted" : keyedArrayFilterHints && keyedArrayPrependHints ? "-filter-prepend-hinted" : keyedArrayFilterHints ? "-filter-hinted" : keyedArrayPrependHints ? "-prepend-hinted" : keyedMapUpdateHints ? "-hinted" : "";
|
|
128
|
+
features.add(`${keyedRowsFeature}${hintSuffix}`);
|
|
129
|
+
}
|
|
130
|
+
return [...features].sort();
|
|
131
|
+
}
|
|
65
132
|
var SAFE_GLOBAL_CALLS = /* @__PURE__ */ new Set(["Boolean", "Number", "String"]);
|
|
66
133
|
var SAFE_MATH_CALLS = /* @__PURE__ */ new Set(["abs", "ceil", "floor", "max", "min", "round", "sign", "trunc"]);
|
|
67
134
|
function isComponentName(name) {
|
|
@@ -107,6 +174,174 @@ function referencesIdentifier(expression, name) {
|
|
|
107
174
|
});
|
|
108
175
|
return referenced;
|
|
109
176
|
}
|
|
177
|
+
function rewriteFreeIdentifierNames(expression, replacements) {
|
|
178
|
+
if (replacements.size === 0) return cloneExpression(expression);
|
|
179
|
+
const file = expressionFile(cloneExpression(expression));
|
|
180
|
+
core.traverse(file, {
|
|
181
|
+
ReferencedIdentifier(path) {
|
|
182
|
+
if (path.scope.hasBinding(path.node.name)) return;
|
|
183
|
+
const replacement = replacements.get(path.node.name);
|
|
184
|
+
if (!replacement) return;
|
|
185
|
+
path.replaceWith(core.types.cloneNode(replacement));
|
|
186
|
+
path.skip();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
return file.program.body[0].expression;
|
|
190
|
+
}
|
|
191
|
+
function keyedIdentityTarget(binding, keyCallback, renderCallback, reactiveByValue, structureDependencies) {
|
|
192
|
+
const dependencies = binding.dependencies || [];
|
|
193
|
+
if (dependencies.length !== 1 || structureDependencies.has(dependencies[0])) return void 0;
|
|
194
|
+
const keyExpression = returnedExpression(keyCallback);
|
|
195
|
+
const keyItem = keyCallback.params[0];
|
|
196
|
+
const rowItem = renderCallback.params[0];
|
|
197
|
+
if (!keyExpression || !core.types.isIdentifier(keyItem) || !core.types.isIdentifier(rowItem)) return void 0;
|
|
198
|
+
const replacements = /* @__PURE__ */ new Map([[keyItem.name, rowItem]]);
|
|
199
|
+
const keyIndex = keyCallback.params[1];
|
|
200
|
+
const rowIndex = renderCallback.params[1];
|
|
201
|
+
if (core.types.isIdentifier(keyIndex) && core.types.isIdentifier(rowIndex)) {
|
|
202
|
+
replacements.set(keyIndex.name, rowIndex);
|
|
203
|
+
}
|
|
204
|
+
const rowKeyExpression = rewriteFreeIdentifierNames(keyExpression, replacements);
|
|
205
|
+
const file = expressionFile(cloneExpression(binding.value));
|
|
206
|
+
let target;
|
|
207
|
+
let valid = true;
|
|
208
|
+
let comparisons = 0;
|
|
209
|
+
core.traverse(file, {
|
|
210
|
+
ReferencedIdentifier(path) {
|
|
211
|
+
if (!valid || path.scope.hasBinding(path.node.name)) return;
|
|
212
|
+
const reactive = reactiveByValue.get(path.node.name);
|
|
213
|
+
if (!reactive) return;
|
|
214
|
+
if (reactive.index !== dependencies[0] || target && target !== reactive) {
|
|
215
|
+
valid = false;
|
|
216
|
+
path.stop();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const parent = path.parentPath;
|
|
220
|
+
if (!parent.isBinaryExpression() || parent.node.operator !== "===" && parent.node.operator !== "!==") {
|
|
221
|
+
valid = false;
|
|
222
|
+
path.stop();
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const other = parent.node.left === path.node ? parent.node.right : parent.node.left;
|
|
226
|
+
if (!core.types.isExpression(other) || !core.types.isNodesEquivalent(other, rowKeyExpression)) {
|
|
227
|
+
valid = false;
|
|
228
|
+
path.stop();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
target = reactive;
|
|
232
|
+
comparisons += 1;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
return valid && target && comparisons > 0 ? { dependency: target.index, value: core.types.identifier(target.valueName) } : void 0;
|
|
236
|
+
}
|
|
237
|
+
function isPotentialKeyedMembershipCall(expression, reactiveByValue) {
|
|
238
|
+
if (expression.arguments.length !== 1 || !core.types.isExpression(expression.arguments[0]) || !core.types.isMemberExpression(expression.callee) || expression.callee.computed || !core.types.isIdentifier(expression.callee.object) || !core.types.isIdentifier(expression.callee.property, { name: "has" })) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
const reactive = reactiveByValue.get(expression.callee.object.name);
|
|
242
|
+
return Boolean(reactive?.setterName);
|
|
243
|
+
}
|
|
244
|
+
function containsPotentialKeyedMembershipCall(expression, reactiveByValue) {
|
|
245
|
+
let found = false;
|
|
246
|
+
core.traverse(expressionFile(cloneExpression(expression)), {
|
|
247
|
+
CallExpression(path) {
|
|
248
|
+
if (!isPotentialKeyedMembershipCall(path.node, reactiveByValue)) return;
|
|
249
|
+
found = true;
|
|
250
|
+
path.stop();
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
return found;
|
|
254
|
+
}
|
|
255
|
+
function isPotentialKeyedMapLookupCall(expression, reactiveByValue) {
|
|
256
|
+
if (expression.arguments.length !== 1 || !core.types.isExpression(expression.arguments[0]) || !core.types.isMemberExpression(expression.callee) || expression.callee.computed || !core.types.isIdentifier(expression.callee.object) || !core.types.isIdentifier(expression.callee.property, { name: "get" })) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
const reactive = reactiveByValue.get(expression.callee.object.name);
|
|
260
|
+
return Boolean(reactive?.setterName);
|
|
261
|
+
}
|
|
262
|
+
function containsPotentialKeyedMapLookupCall(expression, reactiveByValue) {
|
|
263
|
+
let found = false;
|
|
264
|
+
core.traverse(expressionFile(cloneExpression(expression)), {
|
|
265
|
+
CallExpression(path) {
|
|
266
|
+
if (!isPotentialKeyedMapLookupCall(path.node, reactiveByValue)) return;
|
|
267
|
+
found = true;
|
|
268
|
+
path.stop();
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
return found;
|
|
272
|
+
}
|
|
273
|
+
function keyedMembershipTarget(binding, keyCallback, renderCallback, reactiveByValue, structureDependencies) {
|
|
274
|
+
const dependencies = binding.dependencies || [];
|
|
275
|
+
if (dependencies.length !== 1 || structureDependencies.has(dependencies[0])) return void 0;
|
|
276
|
+
const keyExpression = returnedExpression(keyCallback);
|
|
277
|
+
const keyItem = keyCallback.params[0];
|
|
278
|
+
const rowItem = renderCallback.params[0];
|
|
279
|
+
if (!keyExpression || !core.types.isIdentifier(keyItem) || !core.types.isIdentifier(rowItem)) return void 0;
|
|
280
|
+
const replacements = /* @__PURE__ */ new Map([[keyItem.name, rowItem]]);
|
|
281
|
+
const keyIndex = keyCallback.params[1];
|
|
282
|
+
const rowIndex = renderCallback.params[1];
|
|
283
|
+
if (core.types.isIdentifier(keyIndex) && core.types.isIdentifier(rowIndex)) {
|
|
284
|
+
replacements.set(keyIndex.name, rowIndex);
|
|
285
|
+
}
|
|
286
|
+
const rowKeyExpression = rewriteFreeIdentifierNames(keyExpression, replacements);
|
|
287
|
+
const file = expressionFile(cloneExpression(binding.value));
|
|
288
|
+
let target;
|
|
289
|
+
let valid = true;
|
|
290
|
+
let calls = 0;
|
|
291
|
+
core.traverse(file, {
|
|
292
|
+
ReferencedIdentifier(path) {
|
|
293
|
+
if (!valid || path.scope.hasBinding(path.node.name)) return;
|
|
294
|
+
const reactive = reactiveByValue.get(path.node.name);
|
|
295
|
+
if (!reactive) return;
|
|
296
|
+
const member = path.parentPath;
|
|
297
|
+
const call = member.parentPath;
|
|
298
|
+
if (!reactive.setterName || reactive.index !== dependencies[0] || target && target !== reactive || !member.isMemberExpression() || member.node.object !== path.node || member.node.computed || !core.types.isIdentifier(member.node.property, { name: "has" }) || !call || !call.isCallExpression() || call.node.callee !== member.node || call.node.arguments.length !== 1 || !core.types.isExpression(call.node.arguments[0]) || !core.types.isNodesEquivalent(call.node.arguments[0], rowKeyExpression)) {
|
|
299
|
+
valid = false;
|
|
300
|
+
path.stop();
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
target = reactive;
|
|
304
|
+
calls += 1;
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
return valid && target && calls > 0 ? { dependency: target.index, value: core.types.identifier(target.valueName) } : void 0;
|
|
308
|
+
}
|
|
309
|
+
function keyedMapLookupTarget(binding, keyCallback, renderCallback, reactiveByValue, structureDependencies) {
|
|
310
|
+
const dependencies = binding.dependencies || [];
|
|
311
|
+
if (dependencies.length !== 1 || structureDependencies.has(dependencies[0])) return void 0;
|
|
312
|
+
const keyExpression = returnedExpression(keyCallback);
|
|
313
|
+
const keyItem = keyCallback.params[0];
|
|
314
|
+
const rowItem = renderCallback.params[0];
|
|
315
|
+
if (!keyExpression || !core.types.isIdentifier(keyItem) || !core.types.isIdentifier(rowItem)) return void 0;
|
|
316
|
+
const replacements = /* @__PURE__ */ new Map([[keyItem.name, rowItem]]);
|
|
317
|
+
const keyIndex = keyCallback.params[1];
|
|
318
|
+
const rowIndex = renderCallback.params[1];
|
|
319
|
+
if (core.types.isIdentifier(keyIndex) && core.types.isIdentifier(rowIndex)) {
|
|
320
|
+
replacements.set(keyIndex.name, rowIndex);
|
|
321
|
+
}
|
|
322
|
+
const rowKeyExpression = rewriteFreeIdentifierNames(keyExpression, replacements);
|
|
323
|
+
const file = expressionFile(cloneExpression(binding.value));
|
|
324
|
+
let target;
|
|
325
|
+
let valid = true;
|
|
326
|
+
let calls = 0;
|
|
327
|
+
core.traverse(file, {
|
|
328
|
+
ReferencedIdentifier(path) {
|
|
329
|
+
if (!valid || path.scope.hasBinding(path.node.name)) return;
|
|
330
|
+
const reactive = reactiveByValue.get(path.node.name);
|
|
331
|
+
if (!reactive) return;
|
|
332
|
+
const member = path.parentPath;
|
|
333
|
+
const call = member.parentPath;
|
|
334
|
+
if (!reactive.setterName || reactive.index !== dependencies[0] || target && target !== reactive || !member.isMemberExpression() || member.node.object !== path.node || member.node.computed || !core.types.isIdentifier(member.node.property, { name: "get" }) || !call || !call.isCallExpression() || call.node.callee !== member.node || call.node.arguments.length !== 1 || !core.types.isExpression(call.node.arguments[0]) || !core.types.isNodesEquivalent(call.node.arguments[0], rowKeyExpression)) {
|
|
335
|
+
valid = false;
|
|
336
|
+
path.stop();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
target = reactive;
|
|
340
|
+
calls += 1;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
return valid && target && calls > 0 ? { dependency: target.index, value: core.types.identifier(target.valueName) } : void 0;
|
|
344
|
+
}
|
|
110
345
|
function collectReferencedLocals(expression, names) {
|
|
111
346
|
const references = /* @__PURE__ */ new Set();
|
|
112
347
|
core.traverse(expressionFile(cloneExpression(expression)), {
|
|
@@ -207,7 +442,9 @@ function rewriteHandlerAccess(root, handlersByName) {
|
|
|
207
442
|
path.skip();
|
|
208
443
|
}
|
|
209
444
|
});
|
|
210
|
-
return reason ? { reason } : {
|
|
445
|
+
return reason ? { reason } : {
|
|
446
|
+
root: file.program.body[0].expression
|
|
447
|
+
};
|
|
211
448
|
}
|
|
212
449
|
function isSafeCompilerCall(expression, safeGlobals) {
|
|
213
450
|
if (core.types.isIdentifier(expression.callee)) {
|
|
@@ -215,7 +452,7 @@ function isSafeCompilerCall(expression, safeGlobals) {
|
|
|
215
452
|
}
|
|
216
453
|
return core.types.isMemberExpression(expression.callee) && !expression.callee.computed && core.types.isIdentifier(expression.callee.object, { name: "Math" }) && safeGlobals.has("Math") && core.types.isIdentifier(expression.callee.property) && SAFE_MATH_CALLS.has(expression.callee.property.name);
|
|
217
454
|
}
|
|
218
|
-
function validateDerivedExpression(expression, safeGlobals) {
|
|
455
|
+
function validateDerivedExpression(expression, safeGlobals, additionalSafeCall) {
|
|
219
456
|
let unsupported;
|
|
220
457
|
const reject = (reason, path) => {
|
|
221
458
|
unsupported = reason;
|
|
@@ -226,7 +463,9 @@ function validateDerivedExpression(expression, safeGlobals) {
|
|
|
226
463
|
AssignmentExpression: (path) => reject("assignments", path),
|
|
227
464
|
AwaitExpression: (path) => reject("await expressions", path),
|
|
228
465
|
CallExpression(path) {
|
|
229
|
-
if (!isSafeCompilerCall(path.node, safeGlobals)
|
|
466
|
+
if (!isSafeCompilerCall(path.node, safeGlobals) && !additionalSafeCall?.(path.node)) {
|
|
467
|
+
reject("function calls", path);
|
|
468
|
+
}
|
|
230
469
|
},
|
|
231
470
|
ClassExpression: (path) => reject("class expressions", path),
|
|
232
471
|
Function: (path) => reject("function expressions", path),
|
|
@@ -266,6 +505,879 @@ function validateSetterUsage(root, statesBySetter) {
|
|
|
266
505
|
});
|
|
267
506
|
return reason;
|
|
268
507
|
}
|
|
508
|
+
function isUnchangedMapItem(expression, item) {
|
|
509
|
+
return core.types.isIdentifier(expression, { name: item.name });
|
|
510
|
+
}
|
|
511
|
+
function isSafeKeyedMapReplacement(expression, item, safeGlobals) {
|
|
512
|
+
if (!core.types.isObjectExpression(expression)) return false;
|
|
513
|
+
let spreadsItem = false;
|
|
514
|
+
for (const property of expression.properties) {
|
|
515
|
+
if (core.types.isSpreadElement(property)) {
|
|
516
|
+
if (!core.types.isIdentifier(property.argument, { name: item.name })) return false;
|
|
517
|
+
spreadsItem = true;
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
if (!core.types.isObjectProperty(property) || property.computed || !core.types.isExpression(property.value)) {
|
|
521
|
+
return false;
|
|
522
|
+
}
|
|
523
|
+
if (validateDerivedExpression(property.value, safeGlobals)) return false;
|
|
524
|
+
}
|
|
525
|
+
return spreadsItem;
|
|
526
|
+
}
|
|
527
|
+
function isSafeKeyedMapResult(expression, item, safeGlobals) {
|
|
528
|
+
if (!core.types.isConditionalExpression(expression)) return false;
|
|
529
|
+
if (validateDerivedExpression(expression.test, safeGlobals)) return false;
|
|
530
|
+
return isUnchangedMapItem(expression.consequent, item) && isSafeKeyedMapReplacement(expression.alternate, item, safeGlobals) || isUnchangedMapItem(expression.alternate, item) && isSafeKeyedMapReplacement(expression.consequent, item, safeGlobals);
|
|
531
|
+
}
|
|
532
|
+
function rewriteKeyedMapUpdateHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
533
|
+
if (hintedStateIndices.size === 0) return { root: core.types.cloneNode(root, true), count: 0 };
|
|
534
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
535
|
+
let count = 0;
|
|
536
|
+
core.traverse(file, {
|
|
537
|
+
CallExpression(path) {
|
|
538
|
+
const callee = path.get("callee");
|
|
539
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
540
|
+
const state = statesBySetter.get(callee.node.name);
|
|
541
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
const updater = path.node.arguments[0];
|
|
545
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isCallExpression(updater.body) || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.object, {
|
|
546
|
+
name: updater.params[0].name
|
|
547
|
+
}) || !core.types.isIdentifier(updater.body.callee.property, { name: "map" })) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const callback = updater.body.arguments[0];
|
|
551
|
+
if (!core.types.isArrowFunctionExpression(callback) || callback.async || callback.generator || callback.params.length === 0 || callback.params.length > 3 || callback.params.some((parameter) => !core.types.isIdentifier(parameter)) || !core.types.isExpression(callback.body)) {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
const item = callback.params[0];
|
|
555
|
+
if (!isSafeKeyedMapResult(callback.body, item, safeGlobals)) return;
|
|
556
|
+
const changedIndices = path.scope.generateUidIdentifier("farmChangedIndices");
|
|
557
|
+
const mappedItem = path.scope.generateUidIdentifier("farmMappedItem");
|
|
558
|
+
const nextValue = path.scope.generateUidIdentifier("farmNextItems");
|
|
559
|
+
const index = core.types.isIdentifier(callback.params[1]) ? core.types.cloneNode(callback.params[1]) : path.scope.generateUidIdentifier("farmMapIndex");
|
|
560
|
+
const wrappedCallback = core.types.cloneNode(callback, true);
|
|
561
|
+
if (wrappedCallback.params.length === 1) wrappedCallback.params.push(core.types.cloneNode(index));
|
|
562
|
+
wrappedCallback.body = core.types.blockStatement([
|
|
563
|
+
core.types.variableDeclaration("const", [
|
|
564
|
+
core.types.variableDeclarator(core.types.cloneNode(mappedItem), core.types.cloneNode(callback.body, true))
|
|
565
|
+
]),
|
|
566
|
+
core.types.ifStatement(
|
|
567
|
+
core.types.binaryExpression("!==", core.types.cloneNode(mappedItem), core.types.cloneNode(item)),
|
|
568
|
+
core.types.expressionStatement(
|
|
569
|
+
core.types.callExpression(
|
|
570
|
+
core.types.memberExpression(core.types.cloneNode(changedIndices), core.types.identifier("push")),
|
|
571
|
+
[core.types.cloneNode(index)]
|
|
572
|
+
)
|
|
573
|
+
)
|
|
574
|
+
),
|
|
575
|
+
core.types.returnStatement(core.types.cloneNode(mappedItem))
|
|
576
|
+
]);
|
|
577
|
+
const mapCall = core.types.cloneNode(updater.body, true);
|
|
578
|
+
mapCall.arguments[0] = wrappedCallback;
|
|
579
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
580
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
581
|
+
[core.types.cloneNode(previous)],
|
|
582
|
+
core.types.blockStatement([
|
|
583
|
+
core.types.variableDeclaration("const", [
|
|
584
|
+
core.types.variableDeclarator(core.types.cloneNode(changedIndices), core.types.arrayExpression([]))
|
|
585
|
+
]),
|
|
586
|
+
core.types.variableDeclaration("const", [core.types.variableDeclarator(core.types.cloneNode(nextValue), mapCall)]),
|
|
587
|
+
core.types.returnStatement(
|
|
588
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
589
|
+
core.types.cloneNode(previous),
|
|
590
|
+
core.types.cloneNode(nextValue),
|
|
591
|
+
core.types.cloneNode(changedIndices)
|
|
592
|
+
])
|
|
593
|
+
)
|
|
594
|
+
])
|
|
595
|
+
);
|
|
596
|
+
count += 1;
|
|
597
|
+
path.skip();
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
return {
|
|
601
|
+
root: file.program.body[0].expression,
|
|
602
|
+
count
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
function rewriteKeyedArrayAppendHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
606
|
+
if (hintedStateIndices.size === 0) return { root: core.types.cloneNode(root, true), count: 0 };
|
|
607
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
608
|
+
let count = 0;
|
|
609
|
+
core.traverse(file, {
|
|
610
|
+
CallExpression(path) {
|
|
611
|
+
const callee = path.get("callee");
|
|
612
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
613
|
+
const state = statesBySetter.get(callee.node.name);
|
|
614
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const updater = path.node.arguments[0];
|
|
618
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isArrayExpression(updater.body) || updater.body.elements.length < 2 || updater.body.elements.some((element) => element === null) || !core.types.isSpreadElement(updater.body.elements[0]) || !core.types.isIdentifier(updater.body.elements[0].argument, {
|
|
619
|
+
name: updater.params[0].name
|
|
620
|
+
})) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
const safeAppendValue = (value) => {
|
|
624
|
+
if (core.types.isArrayExpression(value)) {
|
|
625
|
+
return value.elements.every(
|
|
626
|
+
(element) => element !== null && !core.types.isJSXNamespacedName(element) && !core.types.isArgumentPlaceholder(element) && safeAppendValue(core.types.isSpreadElement(element) ? element.argument : element)
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
if (core.types.isObjectExpression(value)) {
|
|
630
|
+
return value.properties.every((property) => {
|
|
631
|
+
if (core.types.isSpreadElement(property)) return safeAppendValue(property.argument);
|
|
632
|
+
if (!core.types.isObjectProperty(property) || !core.types.isExpression(property.value)) return false;
|
|
633
|
+
return (!property.computed || core.types.isExpression(property.key) && safeAppendValue(property.key)) && safeAppendValue(property.value);
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
return validateDerivedExpression(value, safeGlobals) === void 0;
|
|
637
|
+
};
|
|
638
|
+
if (updater.body.elements.slice(1).some((element) => {
|
|
639
|
+
if (!element || core.types.isJSXNamespacedName(element) || core.types.isArgumentPlaceholder(element)) {
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
return !safeAppendValue(core.types.isSpreadElement(element) ? element.argument : element);
|
|
643
|
+
})) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
647
|
+
const nextValue = path.scope.generateUidIdentifier("farmNextItems");
|
|
648
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
649
|
+
[core.types.cloneNode(previous)],
|
|
650
|
+
core.types.blockStatement([
|
|
651
|
+
core.types.variableDeclaration("const", [
|
|
652
|
+
core.types.variableDeclarator(core.types.cloneNode(nextValue), core.types.cloneNode(updater.body, true))
|
|
653
|
+
]),
|
|
654
|
+
core.types.returnStatement(
|
|
655
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
656
|
+
core.types.cloneNode(previous),
|
|
657
|
+
core.types.cloneNode(nextValue)
|
|
658
|
+
])
|
|
659
|
+
)
|
|
660
|
+
])
|
|
661
|
+
);
|
|
662
|
+
count += 1;
|
|
663
|
+
path.skip();
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
return {
|
|
667
|
+
root: file.program.body[0].expression,
|
|
668
|
+
count
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
function rewriteKeyedArrayPrependHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
672
|
+
if (hintedStateIndices.size === 0) {
|
|
673
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
674
|
+
}
|
|
675
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
676
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
677
|
+
let count = 0;
|
|
678
|
+
core.traverse(file, {
|
|
679
|
+
CallExpression(path) {
|
|
680
|
+
const callee = path.get("callee");
|
|
681
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
682
|
+
const state = statesBySetter.get(callee.node.name);
|
|
683
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
const updater = path.node.arguments[0];
|
|
687
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isArrayExpression(updater.body) || updater.body.elements.length < 2 || updater.body.elements.some((element) => element === null)) {
|
|
688
|
+
return;
|
|
689
|
+
}
|
|
690
|
+
const suffix = updater.body.elements[updater.body.elements.length - 1];
|
|
691
|
+
if (!core.types.isSpreadElement(suffix) || !core.types.isIdentifier(suffix.argument, { name: updater.params[0].name })) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
const safePrependValue = (value) => {
|
|
695
|
+
if (core.types.isArrayExpression(value)) {
|
|
696
|
+
return value.elements.every(
|
|
697
|
+
(element) => element !== null && !core.types.isJSXNamespacedName(element) && !core.types.isArgumentPlaceholder(element) && safePrependValue(core.types.isSpreadElement(element) ? element.argument : element)
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
if (core.types.isObjectExpression(value)) {
|
|
701
|
+
return value.properties.every((property) => {
|
|
702
|
+
if (core.types.isSpreadElement(property)) return safePrependValue(property.argument);
|
|
703
|
+
if (!core.types.isObjectProperty(property) || !core.types.isExpression(property.value)) return false;
|
|
704
|
+
return (!property.computed || core.types.isExpression(property.key) && safePrependValue(property.key)) && safePrependValue(property.value);
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
return validateDerivedExpression(value, safeGlobals) === void 0;
|
|
708
|
+
};
|
|
709
|
+
if (updater.body.elements.slice(0, -1).some((element) => {
|
|
710
|
+
if (!element || core.types.isJSXNamespacedName(element) || core.types.isArgumentPlaceholder(element)) {
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
return !safePrependValue(core.types.isSpreadElement(element) ? element.argument : element);
|
|
714
|
+
})) {
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
718
|
+
const nextValue = path.scope.generateUidIdentifier("farmNextItems");
|
|
719
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
720
|
+
[core.types.cloneNode(previous)],
|
|
721
|
+
core.types.blockStatement([
|
|
722
|
+
core.types.variableDeclaration("const", [
|
|
723
|
+
core.types.variableDeclarator(core.types.cloneNode(nextValue), core.types.cloneNode(updater.body, true))
|
|
724
|
+
]),
|
|
725
|
+
core.types.returnStatement(
|
|
726
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
727
|
+
core.types.cloneNode(previous),
|
|
728
|
+
core.types.cloneNode(nextValue)
|
|
729
|
+
])
|
|
730
|
+
)
|
|
731
|
+
])
|
|
732
|
+
);
|
|
733
|
+
count += 1;
|
|
734
|
+
stateIndices.add(state.index);
|
|
735
|
+
path.skip();
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
return {
|
|
739
|
+
root: file.program.body[0].expression,
|
|
740
|
+
count,
|
|
741
|
+
stateIndices
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
function rewriteKeyedArrayRollingWindowHints(root, hintedStateIndices, statesBySetter, sliceHelperIdentifier, rollingWindowHelperIdentifier, safeGlobals) {
|
|
745
|
+
if (hintedStateIndices.size === 0) {
|
|
746
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
747
|
+
}
|
|
748
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
749
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
750
|
+
let count = 0;
|
|
751
|
+
core.traverse(file, {
|
|
752
|
+
CallExpression(path) {
|
|
753
|
+
const callee = path.get("callee");
|
|
754
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
755
|
+
const state = statesBySetter.get(callee.node.name);
|
|
756
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
const updater = path.node.arguments[0];
|
|
760
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isArrayExpression(updater.body) || updater.body.elements.length < 2 || updater.body.elements.some((element) => element === null)) {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
const retainedSpread = updater.body.elements[0];
|
|
764
|
+
if (!core.types.isSpreadElement(retainedSpread) || !core.types.isCallExpression(retainedSpread.argument) || retainedSpread.argument.arguments.length !== 1 || !core.types.isMemberExpression(retainedSpread.argument.callee) || retainedSpread.argument.callee.computed || !core.types.isIdentifier(retainedSpread.argument.callee.object, {
|
|
765
|
+
name: updater.params[0].name
|
|
766
|
+
}) || !core.types.isIdentifier(retainedSpread.argument.callee.property, { name: "slice" }) || !core.types.isExpression(retainedSpread.argument.arguments[0])) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
const retainedStart = staticSliceIndex(retainedSpread.argument.arguments[0]);
|
|
770
|
+
if (retainedStart === void 0 || retainedStart === 0) return;
|
|
771
|
+
const safeIncomingValue = (value) => {
|
|
772
|
+
if (core.types.isArrayExpression(value)) {
|
|
773
|
+
return value.elements.every(
|
|
774
|
+
(element) => element !== null && !core.types.isJSXNamespacedName(element) && !core.types.isArgumentPlaceholder(element) && safeIncomingValue(core.types.isSpreadElement(element) ? element.argument : element)
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
if (core.types.isObjectExpression(value)) {
|
|
778
|
+
return value.properties.every((property) => {
|
|
779
|
+
if (core.types.isSpreadElement(property)) return safeIncomingValue(property.argument);
|
|
780
|
+
if (!core.types.isObjectProperty(property) || !core.types.isExpression(property.value)) return false;
|
|
781
|
+
return (!property.computed || core.types.isExpression(property.key) && safeIncomingValue(property.key)) && safeIncomingValue(property.value);
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
return validateDerivedExpression(value, safeGlobals) === void 0;
|
|
785
|
+
};
|
|
786
|
+
if (updater.body.elements.slice(1).some((element) => {
|
|
787
|
+
if (!element || core.types.isJSXNamespacedName(element) || core.types.isArgumentPlaceholder(element)) {
|
|
788
|
+
return true;
|
|
789
|
+
}
|
|
790
|
+
return !safeIncomingValue(core.types.isSpreadElement(element) ? element.argument : element);
|
|
791
|
+
})) {
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
795
|
+
const sliceMethod = path.scope.generateUidIdentifier("farmSlice");
|
|
796
|
+
const retained = path.scope.generateUidIdentifier("farmRetainedItems");
|
|
797
|
+
const nextValue = path.scope.generateUidIdentifier("farmNextItems");
|
|
798
|
+
const nextElements = core.types.cloneNode(updater.body, true).elements;
|
|
799
|
+
nextElements[0] = core.types.spreadElement(core.types.cloneNode(retained));
|
|
800
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
801
|
+
[core.types.cloneNode(previous)],
|
|
802
|
+
core.types.blockStatement([
|
|
803
|
+
core.types.variableDeclaration("const", [
|
|
804
|
+
core.types.variableDeclarator(
|
|
805
|
+
core.types.cloneNode(sliceMethod),
|
|
806
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("slice"))
|
|
807
|
+
),
|
|
808
|
+
core.types.variableDeclarator(
|
|
809
|
+
core.types.cloneNode(retained),
|
|
810
|
+
core.types.callExpression(core.types.cloneNode(sliceHelperIdentifier), [
|
|
811
|
+
core.types.cloneNode(previous),
|
|
812
|
+
core.types.cloneNode(sliceMethod),
|
|
813
|
+
core.types.numericLiteral(retainedStart)
|
|
814
|
+
])
|
|
815
|
+
),
|
|
816
|
+
core.types.variableDeclarator(core.types.cloneNode(nextValue), core.types.arrayExpression(nextElements))
|
|
817
|
+
]),
|
|
818
|
+
core.types.returnStatement(
|
|
819
|
+
core.types.callExpression(core.types.cloneNode(rollingWindowHelperIdentifier), [
|
|
820
|
+
core.types.cloneNode(previous),
|
|
821
|
+
core.types.cloneNode(retained),
|
|
822
|
+
core.types.cloneNode(nextValue)
|
|
823
|
+
])
|
|
824
|
+
)
|
|
825
|
+
])
|
|
826
|
+
);
|
|
827
|
+
count += 1;
|
|
828
|
+
stateIndices.add(state.index);
|
|
829
|
+
path.skip();
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
return {
|
|
833
|
+
root: file.program.body[0].expression,
|
|
834
|
+
count,
|
|
835
|
+
stateIndices
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
function staticSliceIndex(expression) {
|
|
839
|
+
if (core.types.isNumericLiteral(expression) && Number.isSafeInteger(expression.value)) {
|
|
840
|
+
return expression.value;
|
|
841
|
+
}
|
|
842
|
+
if (core.types.isUnaryExpression(expression) && (expression.operator === "+" || expression.operator === "-") && core.types.isNumericLiteral(expression.argument)) {
|
|
843
|
+
const value = expression.operator === "-" ? -expression.argument.value : expression.argument.value;
|
|
844
|
+
return Number.isSafeInteger(value) ? value : void 0;
|
|
845
|
+
}
|
|
846
|
+
return void 0;
|
|
847
|
+
}
|
|
848
|
+
function rewriteKeyedArrayPositionHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
849
|
+
if (hintedStateIndices.size === 0) {
|
|
850
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
851
|
+
}
|
|
852
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
853
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
854
|
+
let count = 0;
|
|
855
|
+
core.traverse(file, {
|
|
856
|
+
CallExpression(path) {
|
|
857
|
+
const callee = path.get("callee");
|
|
858
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
859
|
+
const state = statesBySetter.get(callee.node.name);
|
|
860
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
863
|
+
const updater = path.node.arguments[0];
|
|
864
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isCallExpression(updater.body) || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.object, { name: updater.params[0].name }) || !core.types.isIdentifier(updater.body.callee.property)) {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
const methodName = updater.body.callee.property.name;
|
|
868
|
+
const args = updater.body.arguments;
|
|
869
|
+
const kind = methodName === "with" && args.length === 2 ? "replace" : methodName === "toSpliced" && args.length === 3 && core.types.isNumericLiteral(args[1], { value: 0 }) ? "insert" : void 0;
|
|
870
|
+
if (!kind || !core.types.isExpression(args[0]) || !core.types.isExpression(args.at(-1))) return;
|
|
871
|
+
const position = staticSliceIndex(args[0]);
|
|
872
|
+
const item = args.at(-1);
|
|
873
|
+
if (position === void 0 || !core.types.isExpression(item) || validateDerivedExpression(item, safeGlobals) !== void 0) {
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
877
|
+
const method = path.scope.generateUidIdentifier(
|
|
878
|
+
methodName === "with" ? "farmWith" : "farmToSpliced"
|
|
879
|
+
);
|
|
880
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
881
|
+
[core.types.cloneNode(previous)],
|
|
882
|
+
core.types.blockStatement([
|
|
883
|
+
core.types.variableDeclaration("const", [
|
|
884
|
+
core.types.variableDeclarator(
|
|
885
|
+
core.types.cloneNode(method),
|
|
886
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier(methodName))
|
|
887
|
+
)
|
|
888
|
+
]),
|
|
889
|
+
core.types.returnStatement(
|
|
890
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
891
|
+
core.types.cloneNode(previous),
|
|
892
|
+
core.types.cloneNode(method),
|
|
893
|
+
core.types.stringLiteral(kind),
|
|
894
|
+
...args.map((argument) => core.types.cloneNode(argument, true))
|
|
895
|
+
])
|
|
896
|
+
)
|
|
897
|
+
])
|
|
898
|
+
);
|
|
899
|
+
count += 1;
|
|
900
|
+
stateIndices.add(state.index);
|
|
901
|
+
path.skip();
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
return {
|
|
905
|
+
root: file.program.body[0].expression,
|
|
906
|
+
count,
|
|
907
|
+
stateIndices
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
function rewriteKeyedArrayReorderHints(root, hintedStateIndices, statesBySetter, helperIdentifier) {
|
|
911
|
+
if (hintedStateIndices.size === 0) {
|
|
912
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
913
|
+
}
|
|
914
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
915
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
916
|
+
let count = 0;
|
|
917
|
+
core.traverse(file, {
|
|
918
|
+
CallExpression(path) {
|
|
919
|
+
const callee = path.get("callee");
|
|
920
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
921
|
+
const state = statesBySetter.get(callee.node.name);
|
|
922
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
const updater = path.node.arguments[0];
|
|
926
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isCallExpression(updater.body) || updater.body.arguments.length !== 0 || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.object, { name: updater.params[0].name }) || !core.types.isIdentifier(updater.body.callee.property, { name: "toReversed" })) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
930
|
+
const method = path.scope.generateUidIdentifier("farmToReversed");
|
|
931
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
932
|
+
[core.types.cloneNode(previous)],
|
|
933
|
+
core.types.blockStatement([
|
|
934
|
+
core.types.variableDeclaration("const", [
|
|
935
|
+
core.types.variableDeclarator(
|
|
936
|
+
core.types.cloneNode(method),
|
|
937
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("toReversed"))
|
|
938
|
+
)
|
|
939
|
+
]),
|
|
940
|
+
core.types.returnStatement(
|
|
941
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
942
|
+
core.types.cloneNode(previous),
|
|
943
|
+
core.types.cloneNode(method)
|
|
944
|
+
])
|
|
945
|
+
)
|
|
946
|
+
])
|
|
947
|
+
);
|
|
948
|
+
count += 1;
|
|
949
|
+
stateIndices.add(state.index);
|
|
950
|
+
path.skip();
|
|
951
|
+
}
|
|
952
|
+
});
|
|
953
|
+
return {
|
|
954
|
+
root: file.program.body[0].expression,
|
|
955
|
+
count,
|
|
956
|
+
stateIndices
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
function rewriteKeyedArraySliceHints(root, hintedStateIndices, statesBySetter, helperIdentifier) {
|
|
960
|
+
if (hintedStateIndices.size === 0) {
|
|
961
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
962
|
+
}
|
|
963
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
964
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
965
|
+
let count = 0;
|
|
966
|
+
core.traverse(file, {
|
|
967
|
+
CallExpression(path) {
|
|
968
|
+
const callee = path.get("callee");
|
|
969
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
970
|
+
const state = statesBySetter.get(callee.node.name);
|
|
971
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const updater = path.node.arguments[0];
|
|
975
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isCallExpression(updater.body) || updater.body.arguments.length < 1 || updater.body.arguments.length > 2 || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.object, { name: updater.params[0].name }) || !core.types.isIdentifier(updater.body.callee.property, { name: "slice" })) {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const indexes = [];
|
|
979
|
+
for (const argument of updater.body.arguments) {
|
|
980
|
+
if (!core.types.isExpression(argument)) return;
|
|
981
|
+
const value = staticSliceIndex(argument);
|
|
982
|
+
if (value === void 0) return;
|
|
983
|
+
indexes.push(value);
|
|
984
|
+
}
|
|
985
|
+
if (indexes.length === 1 && indexes[0] === 0) return;
|
|
986
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
987
|
+
const sliceMethod = path.scope.generateUidIdentifier("farmSlice");
|
|
988
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
989
|
+
[core.types.cloneNode(previous)],
|
|
990
|
+
core.types.blockStatement([
|
|
991
|
+
core.types.variableDeclaration("const", [
|
|
992
|
+
core.types.variableDeclarator(
|
|
993
|
+
core.types.cloneNode(sliceMethod),
|
|
994
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("slice"))
|
|
995
|
+
)
|
|
996
|
+
]),
|
|
997
|
+
core.types.returnStatement(
|
|
998
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
999
|
+
core.types.cloneNode(previous),
|
|
1000
|
+
core.types.cloneNode(sliceMethod),
|
|
1001
|
+
...indexes.map((value) => core.types.numericLiteral(value))
|
|
1002
|
+
])
|
|
1003
|
+
)
|
|
1004
|
+
])
|
|
1005
|
+
);
|
|
1006
|
+
count += 1;
|
|
1007
|
+
stateIndices.add(state.index);
|
|
1008
|
+
path.skip();
|
|
1009
|
+
}
|
|
1010
|
+
});
|
|
1011
|
+
return {
|
|
1012
|
+
root: file.program.body[0].expression,
|
|
1013
|
+
count,
|
|
1014
|
+
stateIndices
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
function rewriteKeyedArrayFilterHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
1018
|
+
if (hintedStateIndices.size === 0) {
|
|
1019
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
1020
|
+
}
|
|
1021
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1022
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
1023
|
+
let count = 0;
|
|
1024
|
+
core.traverse(file, {
|
|
1025
|
+
CallExpression(path) {
|
|
1026
|
+
const callee = path.get("callee");
|
|
1027
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
1028
|
+
const state = statesBySetter.get(callee.node.name);
|
|
1029
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
1032
|
+
const updater = path.node.arguments[0];
|
|
1033
|
+
if (!core.types.isArrowFunctionExpression(updater) || updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0]) || !core.types.isCallExpression(updater.body) || updater.body.arguments.length !== 1 || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.object, {
|
|
1034
|
+
name: updater.params[0].name
|
|
1035
|
+
}) || !core.types.isIdentifier(updater.body.callee.property, { name: "filter" })) {
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
const predicate = updater.body.arguments[0];
|
|
1039
|
+
if (!core.types.isArrowFunctionExpression(predicate) || predicate.async || predicate.generator || predicate.params.length !== 1 || !core.types.isIdentifier(predicate.params[0]) || !core.types.isExpression(predicate.body) || validateDerivedExpression(predicate.body, safeGlobals)) {
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
1043
|
+
const filterMethod = path.scope.generateUidIdentifier("farmFilter");
|
|
1044
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
1045
|
+
[core.types.cloneNode(previous)],
|
|
1046
|
+
core.types.blockStatement([
|
|
1047
|
+
core.types.variableDeclaration("const", [
|
|
1048
|
+
core.types.variableDeclarator(
|
|
1049
|
+
core.types.cloneNode(filterMethod),
|
|
1050
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("filter"))
|
|
1051
|
+
)
|
|
1052
|
+
]),
|
|
1053
|
+
core.types.returnStatement(
|
|
1054
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
1055
|
+
core.types.cloneNode(previous),
|
|
1056
|
+
core.types.cloneNode(filterMethod),
|
|
1057
|
+
core.types.cloneNode(predicate, true)
|
|
1058
|
+
])
|
|
1059
|
+
)
|
|
1060
|
+
])
|
|
1061
|
+
);
|
|
1062
|
+
count += 1;
|
|
1063
|
+
stateIndices.add(state.index);
|
|
1064
|
+
path.skip();
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
return {
|
|
1068
|
+
root: file.program.body[0].expression,
|
|
1069
|
+
count,
|
|
1070
|
+
stateIndices
|
|
1071
|
+
};
|
|
1072
|
+
}
|
|
1073
|
+
function collectionConstructorName(kind) {
|
|
1074
|
+
return kind === "set" ? "Set" : "Map";
|
|
1075
|
+
}
|
|
1076
|
+
function isCollectionConstruction(expression, kind, previous) {
|
|
1077
|
+
if (!core.types.isNewExpression(expression) || !core.types.isIdentifier(expression.callee, {
|
|
1078
|
+
name: collectionConstructorName(kind)
|
|
1079
|
+
})) {
|
|
1080
|
+
return false;
|
|
1081
|
+
}
|
|
1082
|
+
if (!previous) return true;
|
|
1083
|
+
return expression.arguments.length === 1 && core.types.isIdentifier(expression.arguments[0], { name: previous.name });
|
|
1084
|
+
}
|
|
1085
|
+
function collectionStateInitializerIsOwned(initialValue, kind, constructorIsGlobal) {
|
|
1086
|
+
if (!initialValue || !constructorIsGlobal) return false;
|
|
1087
|
+
if (isCollectionConstruction(initialValue, kind)) return true;
|
|
1088
|
+
if (!core.types.isArrowFunctionExpression(initialValue) && !core.types.isFunctionExpression(initialValue)) {
|
|
1089
|
+
return false;
|
|
1090
|
+
}
|
|
1091
|
+
if (core.types.isBlockStatement(initialValue.body) && initialValue.body.body.length !== 1) return false;
|
|
1092
|
+
const value = returnedExpression(initialValue);
|
|
1093
|
+
return Boolean(value && isCollectionConstruction(value, kind));
|
|
1094
|
+
}
|
|
1095
|
+
function collectionStateHasOnlyOwnedReads(root, state, kind) {
|
|
1096
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1097
|
+
let valid = true;
|
|
1098
|
+
const readMethods = kind === "set" ? /* @__PURE__ */ new Set(["has"]) : /* @__PURE__ */ new Set(["get", "has"]);
|
|
1099
|
+
core.traverse(file, {
|
|
1100
|
+
ReferencedIdentifier(path) {
|
|
1101
|
+
if (!valid || !core.types.isIdentifier(path.node) || path.node.name !== state.valueName || path.scope.hasBinding(path.node.name)) {
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
const parent = path.parentPath;
|
|
1105
|
+
if (parent.isNewExpression() && core.types.isIdentifier(parent.node.callee, {
|
|
1106
|
+
name: collectionConstructorName(kind)
|
|
1107
|
+
}) && parent.node.arguments.length === 1 && parent.node.arguments[0] === path.node) {
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
if (!parent.isMemberExpression() || parent.node.object !== path.node || parent.node.computed || !core.types.isIdentifier(parent.node.property)) {
|
|
1111
|
+
valid = false;
|
|
1112
|
+
path.stop();
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
const property = parent.node.property.name;
|
|
1116
|
+
if (property === "size") return;
|
|
1117
|
+
const call = parent.parentPath;
|
|
1118
|
+
if (!readMethods.has(property) || !call?.isCallExpression() || call.node.callee !== parent.node) {
|
|
1119
|
+
valid = false;
|
|
1120
|
+
path.stop();
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
});
|
|
1124
|
+
return valid;
|
|
1125
|
+
}
|
|
1126
|
+
function collectionMutationOperation(kind, method) {
|
|
1127
|
+
if (kind === "set" && method === "add") return "set-add";
|
|
1128
|
+
if (kind === "set" && method === "delete") return "set-delete";
|
|
1129
|
+
if (kind === "map" && method === "set") return "map-set";
|
|
1130
|
+
if (kind === "map" && method === "delete") return "map-delete";
|
|
1131
|
+
return void 0;
|
|
1132
|
+
}
|
|
1133
|
+
function collectionMutationArgumentsAreValid(operation, args) {
|
|
1134
|
+
if (!operation || args.some((argument) => !core.types.isExpression(argument))) return false;
|
|
1135
|
+
return operation === "map-set" ? args.length === 2 : args.length === 1;
|
|
1136
|
+
}
|
|
1137
|
+
function prepareKeyedCollectionUpdater(updater, kind, updateHelper, mutationHelper) {
|
|
1138
|
+
if (updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0])) {
|
|
1139
|
+
return void 0;
|
|
1140
|
+
}
|
|
1141
|
+
const previous = updater.params[0];
|
|
1142
|
+
if (core.types.isExpression(updater.body)) {
|
|
1143
|
+
if (!core.types.isCallExpression(updater.body) || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.property)) {
|
|
1144
|
+
return void 0;
|
|
1145
|
+
}
|
|
1146
|
+
const operation = collectionMutationOperation(kind, updater.body.callee.property.name);
|
|
1147
|
+
if (operation !== "set-add" && operation !== "map-set" || !collectionMutationArgumentsAreValid(operation, updater.body.arguments) || !isCollectionConstruction(updater.body.callee.object, kind, previous)) {
|
|
1148
|
+
return void 0;
|
|
1149
|
+
}
|
|
1150
|
+
const collection = uniqueLocalIdentifier("_farmCollection", [updater]);
|
|
1151
|
+
const body = core.types.blockStatement([
|
|
1152
|
+
core.types.variableDeclaration("const", [
|
|
1153
|
+
core.types.variableDeclarator(
|
|
1154
|
+
core.types.cloneNode(collection),
|
|
1155
|
+
core.types.cloneNode(updater.body.callee.object, true)
|
|
1156
|
+
)
|
|
1157
|
+
]),
|
|
1158
|
+
core.types.returnStatement(
|
|
1159
|
+
core.types.callExpression(core.types.cloneNode(updateHelper), [
|
|
1160
|
+
core.types.cloneNode(previous),
|
|
1161
|
+
core.types.callExpression(core.types.cloneNode(mutationHelper), [
|
|
1162
|
+
core.types.cloneNode(collection),
|
|
1163
|
+
core.types.memberExpression(core.types.cloneNode(collection), core.types.cloneNode(updater.body.callee.property)),
|
|
1164
|
+
core.types.stringLiteral(operation),
|
|
1165
|
+
...updater.body.arguments.map(
|
|
1166
|
+
(argument) => core.types.cloneNode(argument, true)
|
|
1167
|
+
)
|
|
1168
|
+
]),
|
|
1169
|
+
core.types.stringLiteral(kind)
|
|
1170
|
+
])
|
|
1171
|
+
)
|
|
1172
|
+
]);
|
|
1173
|
+
return {
|
|
1174
|
+
updater: core.types.arrowFunctionExpression([core.types.cloneNode(previous)], body),
|
|
1175
|
+
mutations: 1
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
const cloned = core.types.cloneNode(updater, true);
|
|
1179
|
+
const file = expressionFile(cloned);
|
|
1180
|
+
let functionPath;
|
|
1181
|
+
core.traverse(file, {
|
|
1182
|
+
Function(path) {
|
|
1183
|
+
if (functionPath) return;
|
|
1184
|
+
if (path.isArrowFunctionExpression() || path.isFunctionExpression()) {
|
|
1185
|
+
functionPath = path;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1189
|
+
if (!functionPath || !core.types.isBlockStatement(functionPath.node.body)) return void 0;
|
|
1190
|
+
const clonedPrevious = functionPath.node.params[0];
|
|
1191
|
+
if (!core.types.isIdentifier(clonedPrevious)) return void 0;
|
|
1192
|
+
let collectionDeclaration;
|
|
1193
|
+
const updaterBody = functionPath.get("body");
|
|
1194
|
+
if (!updaterBody.isBlockStatement()) return void 0;
|
|
1195
|
+
for (const statement of updaterBody.get("body")) {
|
|
1196
|
+
if (!statement.isVariableDeclaration({ kind: "const" })) continue;
|
|
1197
|
+
for (const declaration of statement.get("declarations")) {
|
|
1198
|
+
if (declaration.isVariableDeclarator() && core.types.isIdentifier(declaration.node.id) && core.types.isExpression(declaration.node.init) && isCollectionConstruction(declaration.node.init, kind, clonedPrevious)) {
|
|
1199
|
+
if (collectionDeclaration) return void 0;
|
|
1200
|
+
collectionDeclaration = declaration;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
if (!collectionDeclaration || !core.types.isIdentifier(collectionDeclaration.node.id)) return void 0;
|
|
1205
|
+
if (collectionDeclaration.scope.getBinding(collectionConstructorName(kind))) return void 0;
|
|
1206
|
+
const collectionName = collectionDeclaration.node.id.name;
|
|
1207
|
+
const collectionBinding = collectionDeclaration.scope.getBinding(collectionName);
|
|
1208
|
+
const previousBinding = functionPath.scope.getBinding(clonedPrevious.name);
|
|
1209
|
+
if (!collectionBinding || !previousBinding) return void 0;
|
|
1210
|
+
let valid = true;
|
|
1211
|
+
let mutations = 0;
|
|
1212
|
+
core.traverse(file, {
|
|
1213
|
+
ReferencedIdentifier(path) {
|
|
1214
|
+
if (!valid) return;
|
|
1215
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
1216
|
+
const belongsToUpdater = path.getFunctionParent()?.node === functionPath?.node;
|
|
1217
|
+
if (binding === collectionBinding) {
|
|
1218
|
+
if (!belongsToUpdater) {
|
|
1219
|
+
valid = false;
|
|
1220
|
+
path.stop();
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
const parent = path.parentPath;
|
|
1224
|
+
if (parent.isReturnStatement() && parent.node.argument === path.node) return;
|
|
1225
|
+
if (!parent.isMemberExpression() || parent.node.object !== path.node || parent.node.computed || !core.types.isIdentifier(parent.node.property)) {
|
|
1226
|
+
valid = false;
|
|
1227
|
+
path.stop();
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
const method = parent.node.property.name;
|
|
1231
|
+
if (method === "size") return;
|
|
1232
|
+
const call = parent.parentPath;
|
|
1233
|
+
if (!call?.isCallExpression() || call.node.callee !== parent.node) {
|
|
1234
|
+
valid = false;
|
|
1235
|
+
path.stop();
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
const operation = collectionMutationOperation(kind, method);
|
|
1239
|
+
const read = kind === "set" ? method === "has" : method === "get" || method === "has";
|
|
1240
|
+
if (read) return;
|
|
1241
|
+
if (!collectionMutationArgumentsAreValid(operation, call.node.arguments) || call.parentPath.isMemberExpression() && call.parentPath.node.object === call.node) {
|
|
1242
|
+
valid = false;
|
|
1243
|
+
path.stop();
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
mutations += 1;
|
|
1247
|
+
return;
|
|
1248
|
+
}
|
|
1249
|
+
if (binding === previousBinding) {
|
|
1250
|
+
if (!belongsToUpdater) {
|
|
1251
|
+
valid = false;
|
|
1252
|
+
path.stop();
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
const parent = path.parentPath;
|
|
1256
|
+
if (parent.isReturnStatement() && parent.node.argument === path.node) return;
|
|
1257
|
+
if (parent.isNewExpression() && parent.node.arguments.length === 1 && parent.node.arguments[0] === path.node && core.types.isIdentifier(parent.node.callee, {
|
|
1258
|
+
name: collectionConstructorName(kind)
|
|
1259
|
+
})) {
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
if (parent.isMemberExpression() && parent.node.object === path.node && !parent.node.computed && core.types.isIdentifier(parent.node.property)) {
|
|
1263
|
+
const method = parent.node.property.name;
|
|
1264
|
+
const call = parent.parentPath;
|
|
1265
|
+
if (method === "size" || (kind === "set" ? method === "has" : method === "get" || method === "has") && call?.isCallExpression() && call.node.callee === parent.node) {
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
valid = false;
|
|
1270
|
+
path.stop();
|
|
1271
|
+
}
|
|
1272
|
+
},
|
|
1273
|
+
ReturnStatement(path) {
|
|
1274
|
+
if (!valid || path.getFunctionParent()?.node !== functionPath?.node || !path.node.argument) {
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
const value = path.node.argument;
|
|
1278
|
+
const returnsOwnedCollection = core.types.isIdentifier(value) && (path.scope.getBinding(value.name) === collectionBinding || path.scope.getBinding(value.name) === previousBinding) || isCollectionConstruction(value, kind);
|
|
1279
|
+
if (!returnsOwnedCollection) {
|
|
1280
|
+
valid = false;
|
|
1281
|
+
path.stop();
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1285
|
+
if (!valid || mutations === 0) return void 0;
|
|
1286
|
+
core.traverse(file, {
|
|
1287
|
+
CallExpression(path) {
|
|
1288
|
+
if (path.getFunctionParent()?.node !== functionPath?.node) return;
|
|
1289
|
+
const callee = path.node.callee;
|
|
1290
|
+
if (!core.types.isMemberExpression(callee) || callee.computed || !core.types.isIdentifier(callee.object, { name: collectionName }) || path.scope.getBinding(collectionName) !== collectionBinding || !core.types.isIdentifier(callee.property)) {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const operation = collectionMutationOperation(kind, callee.property.name);
|
|
1294
|
+
if (!collectionMutationArgumentsAreValid(operation, path.node.arguments)) return;
|
|
1295
|
+
path.replaceWith(
|
|
1296
|
+
core.types.callExpression(core.types.cloneNode(mutationHelper), [
|
|
1297
|
+
core.types.cloneNode(callee.object),
|
|
1298
|
+
core.types.memberExpression(core.types.cloneNode(callee.object), core.types.cloneNode(callee.property)),
|
|
1299
|
+
core.types.stringLiteral(operation),
|
|
1300
|
+
...path.node.arguments.map((argument) => core.types.cloneNode(argument, true))
|
|
1301
|
+
])
|
|
1302
|
+
);
|
|
1303
|
+
path.skip();
|
|
1304
|
+
},
|
|
1305
|
+
ReturnStatement(path) {
|
|
1306
|
+
if (path.getFunctionParent()?.node !== functionPath?.node || !path.node.argument) return;
|
|
1307
|
+
path.node.argument = core.types.callExpression(core.types.cloneNode(updateHelper), [
|
|
1308
|
+
core.types.cloneNode(clonedPrevious),
|
|
1309
|
+
core.types.cloneNode(path.node.argument, true),
|
|
1310
|
+
core.types.stringLiteral(kind)
|
|
1311
|
+
]);
|
|
1312
|
+
}
|
|
1313
|
+
});
|
|
1314
|
+
const prepared = file.program.body[0].expression;
|
|
1315
|
+
return core.types.isArrowFunctionExpression(prepared) || core.types.isFunctionExpression(prepared) ? { updater: prepared, mutations } : void 0;
|
|
1316
|
+
}
|
|
1317
|
+
function rewriteKeyedCollectionUpdateHints(root, targetKinds, states, statesBySetter, updateHelper, mutationHelper, globalCollections) {
|
|
1318
|
+
if (targetKinds.size === 0) return { root: core.types.cloneNode(root, true), count: 0 };
|
|
1319
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1320
|
+
let count = 0;
|
|
1321
|
+
for (const [stateIndex, kind] of targetKinds) {
|
|
1322
|
+
const state = states[stateIndex];
|
|
1323
|
+
if (!state || !collectionStateInitializerIsOwned(
|
|
1324
|
+
state.initialValue,
|
|
1325
|
+
kind,
|
|
1326
|
+
globalCollections.has(collectionConstructorName(kind))
|
|
1327
|
+
) || !collectionStateHasOnlyOwnedReads(root, state, kind)) {
|
|
1328
|
+
continue;
|
|
1329
|
+
}
|
|
1330
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
1331
|
+
let valid = true;
|
|
1332
|
+
core.traverse(file, {
|
|
1333
|
+
CallExpression(path) {
|
|
1334
|
+
if (!valid) return;
|
|
1335
|
+
const callee = path.get("callee");
|
|
1336
|
+
if (!callee.isIdentifier({ name: state.setterName }) || callee.scope.hasBinding(callee.node.name) || statesBySetter.get(callee.node.name)?.index !== stateIndex) {
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
if (path.node.arguments.length !== 1 || !core.types.isExpression(path.node.arguments[0])) {
|
|
1340
|
+
valid = false;
|
|
1341
|
+
path.stop();
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
const update = path.node.arguments[0];
|
|
1345
|
+
if (path.scope.getBinding(collectionConstructorName(kind))) {
|
|
1346
|
+
valid = false;
|
|
1347
|
+
path.stop();
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
if (isCollectionConstruction(update, kind)) return;
|
|
1351
|
+
if (!core.types.isArrowFunctionExpression(update) && !core.types.isFunctionExpression(update)) {
|
|
1352
|
+
valid = false;
|
|
1353
|
+
path.stop();
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
const prepared = prepareKeyedCollectionUpdater(update, kind, updateHelper, mutationHelper);
|
|
1357
|
+
if (!prepared) {
|
|
1358
|
+
valid = false;
|
|
1359
|
+
path.stop();
|
|
1360
|
+
return;
|
|
1361
|
+
}
|
|
1362
|
+
replacements.set(path.node, prepared);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
if (!valid || replacements.size === 0) continue;
|
|
1366
|
+
core.traverse(file, {
|
|
1367
|
+
CallExpression(path) {
|
|
1368
|
+
const prepared = replacements.get(path.node);
|
|
1369
|
+
if (!prepared) return;
|
|
1370
|
+
path.node.arguments[0] = core.types.cloneNode(prepared.updater, true);
|
|
1371
|
+
count += prepared.mutations;
|
|
1372
|
+
path.skip();
|
|
1373
|
+
}
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
return {
|
|
1377
|
+
root: file.program.body[0].expression,
|
|
1378
|
+
count
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
269
1381
|
function rewriteStateAccess(expression, stateParameter, statesByValue, statesBySetter) {
|
|
270
1382
|
const file = expressionFile(cloneExpression(expression));
|
|
271
1383
|
core.traverse(file, {
|
|
@@ -516,21 +1628,28 @@ function analyzeMapList(expression, statesByValue, safeGlobals) {
|
|
|
516
1628
|
const collection = callee.object;
|
|
517
1629
|
const collectionUnsupported = validateCollectionPipeline(collection, safeGlobals);
|
|
518
1630
|
if (collectionUnsupported) {
|
|
519
|
-
return {
|
|
1631
|
+
return {
|
|
1632
|
+
reason: `keyed list collection cannot use ${collectionUnsupported}`
|
|
1633
|
+
};
|
|
520
1634
|
}
|
|
521
1635
|
if (expression.arguments.length !== 1 || !core.types.isArrowFunctionExpression(expression.arguments[0]) && !core.types.isFunctionExpression(expression.arguments[0])) {
|
|
522
1636
|
return { reason: "keyed list map must use one inline render callback" };
|
|
523
1637
|
}
|
|
524
1638
|
const callback = expression.arguments[0];
|
|
525
1639
|
if (containsDirectHookCall(callback)) {
|
|
526
|
-
return {
|
|
1640
|
+
return {
|
|
1641
|
+
reason: "Hooks cannot be called directly inside a keyed list callback"
|
|
1642
|
+
};
|
|
527
1643
|
}
|
|
528
1644
|
const row = returnedExpression(callback);
|
|
529
1645
|
if (!row || !core.types.isJSXElement(row)) {
|
|
530
1646
|
return { reason: "keyed list map callbacks must return one React element" };
|
|
531
1647
|
}
|
|
532
1648
|
const key = jsxKeyExpression(row);
|
|
533
|
-
if (!key)
|
|
1649
|
+
if (!key)
|
|
1650
|
+
return {
|
|
1651
|
+
reason: "automatically compiled lists require an explicit item key"
|
|
1652
|
+
};
|
|
534
1653
|
const keyReason = validateKeyFunction(callback, key, safeGlobals);
|
|
535
1654
|
if (keyReason) return { reason: keyReason };
|
|
536
1655
|
return { dependencies: collectStateDependencies(expression, statesByValue) };
|
|
@@ -545,7 +1664,9 @@ function listAttributeExpression(element, name) {
|
|
|
545
1664
|
}
|
|
546
1665
|
function analyzePublicList(element, statesByValue, safeGlobals) {
|
|
547
1666
|
if (element.openingElement.attributes.some((attribute) => core.types.isJSXSpreadAttribute(attribute))) {
|
|
548
|
-
return {
|
|
1667
|
+
return {
|
|
1668
|
+
reason: "compiled List boundaries do not support JSX attribute spreads"
|
|
1669
|
+
};
|
|
549
1670
|
}
|
|
550
1671
|
const each = listAttributeExpression(element, "each");
|
|
551
1672
|
const by = listAttributeExpression(element, "by");
|
|
@@ -563,7 +1684,9 @@ function analyzePublicList(element, statesByValue, safeGlobals) {
|
|
|
563
1684
|
if (keyReason) return { reason: keyReason };
|
|
564
1685
|
const children = meaningfulJsxChildren(element);
|
|
565
1686
|
if (children.length !== 1 || !core.types.isJSXExpressionContainer(children[0]) || core.types.isJSXEmptyExpression(children[0].expression) || !core.types.isArrowFunctionExpression(children[0].expression) && !core.types.isFunctionExpression(children[0].expression)) {
|
|
566
|
-
return {
|
|
1687
|
+
return {
|
|
1688
|
+
reason: "compiled List children must use one inline render function"
|
|
1689
|
+
};
|
|
567
1690
|
}
|
|
568
1691
|
const render = children[0].expression;
|
|
569
1692
|
if (!returnedExpression(render)) {
|
|
@@ -677,13 +1800,20 @@ function stabilizeDeferredEventCurrentTargets(root, compilerSetters) {
|
|
|
677
1800
|
const expression = file.program.body[0].expression;
|
|
678
1801
|
return core.types.isJSXElement(expression) ? expression : core.types.cloneNode(root, true);
|
|
679
1802
|
}
|
|
680
|
-
function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters) {
|
|
1803
|
+
function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters, keyedTargetReactiveByValue) {
|
|
681
1804
|
if (renderCallback.async || renderCallback.generator || renderCallback.params.length < 1 || renderCallback.params.length > 2 || !core.types.isIdentifier(renderCallback.params[0]) || renderCallback.params[1] !== void 0 && !core.types.isIdentifier(renderCallback.params[1])) {
|
|
682
|
-
return {
|
|
1805
|
+
return {
|
|
1806
|
+
reason: "compiled keyed rows require item and optional index identifiers"
|
|
1807
|
+
};
|
|
683
1808
|
}
|
|
684
1809
|
const bindings = [];
|
|
685
1810
|
const events = [];
|
|
686
1811
|
const conditionals = [];
|
|
1812
|
+
const validateBindingExpression = (expression) => validateDerivedExpression(
|
|
1813
|
+
expression,
|
|
1814
|
+
safeGlobals,
|
|
1815
|
+
keyedTargetReactiveByValue ? (call) => isPotentialKeyedMembershipCall(call, keyedTargetReactiveByValue) || isPotentialKeyedMapLookupCall(call, keyedTargetReactiveByValue) : void 0
|
|
1816
|
+
);
|
|
687
1817
|
const visit = (element, path) => {
|
|
688
1818
|
const tag = element.openingElement.name;
|
|
689
1819
|
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
@@ -762,7 +1892,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
762
1892
|
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
763
1893
|
return "compiled keyed row style names must use camelCase or a CSS custom property";
|
|
764
1894
|
}
|
|
765
|
-
const unsupported2 =
|
|
1895
|
+
const unsupported2 = validateBindingExpression(property.value);
|
|
766
1896
|
if (unsupported2) {
|
|
767
1897
|
return `compiled keyed row style ${propertyName} cannot use ${unsupported2}`;
|
|
768
1898
|
}
|
|
@@ -776,7 +1906,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
776
1906
|
continue;
|
|
777
1907
|
}
|
|
778
1908
|
if (name === "children") return "compiled keyed row children props are not supported yet";
|
|
779
|
-
const unsupported =
|
|
1909
|
+
const unsupported = validateBindingExpression(expression);
|
|
780
1910
|
if (unsupported) return `compiled keyed row ${name} cannot use ${unsupported}`;
|
|
781
1911
|
bindings.push({
|
|
782
1912
|
kind: "attribute",
|
|
@@ -826,7 +1956,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
826
1956
|
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
827
1957
|
);
|
|
828
1958
|
for (const child of expressions) {
|
|
829
|
-
const unsupported =
|
|
1959
|
+
const unsupported = validateBindingExpression(child.expression);
|
|
830
1960
|
if (unsupported) return `compiled keyed row text cannot use ${unsupported}`;
|
|
831
1961
|
}
|
|
832
1962
|
if (nestedElements.length > 0 && expressions.length > 0) {
|
|
@@ -842,7 +1972,11 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
842
1972
|
parts.push(cloneExpression(child.expression));
|
|
843
1973
|
}
|
|
844
1974
|
}
|
|
845
|
-
bindings.push({
|
|
1975
|
+
bindings.push({
|
|
1976
|
+
kind: "text",
|
|
1977
|
+
path: [...path],
|
|
1978
|
+
value: core.types.arrayExpression(parts)
|
|
1979
|
+
});
|
|
846
1980
|
}
|
|
847
1981
|
let elementIndex = 0;
|
|
848
1982
|
for (const child of element.children) {
|
|
@@ -856,7 +1990,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
856
1990
|
const reason = visit(row, []);
|
|
857
1991
|
return reason ? { reason } : { bindings, events, conditionals };
|
|
858
1992
|
}
|
|
859
|
-
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false) {
|
|
1993
|
+
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false, allowMembershipTargets = false) {
|
|
860
1994
|
let collection;
|
|
861
1995
|
let keyCallback;
|
|
862
1996
|
let renderCallback;
|
|
@@ -909,7 +2043,8 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acce
|
|
|
909
2043
|
row,
|
|
910
2044
|
renderCallback,
|
|
911
2045
|
safeGlobals,
|
|
912
|
-
new Set([...statesByValue.values()].map((state) => state.setterName))
|
|
2046
|
+
new Set([...statesByValue.values()].map((state) => state.setterName)),
|
|
2047
|
+
allowMembershipTargets ? statesByValue : void 0
|
|
913
2048
|
);
|
|
914
2049
|
if (rowAnalysis.reason && !acceptUnsupportedRow) return void 0;
|
|
915
2050
|
const keyExpression = returnedExpression(keyCallback);
|
|
@@ -922,6 +2057,7 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acce
|
|
|
922
2057
|
return {
|
|
923
2058
|
source,
|
|
924
2059
|
collection,
|
|
2060
|
+
collectionDependency: core.types.isIdentifier(collection) ? statesByValue.get(collection.name)?.index : void 0,
|
|
925
2061
|
structureDependencies: [...structureDependencies].sort((left, right) => left - right),
|
|
926
2062
|
keyCallback,
|
|
927
2063
|
renderCallback,
|
|
@@ -950,7 +2086,74 @@ function analyzeKeyedRowsContainer(container, statesByValue, safeGlobals, listNa
|
|
|
950
2086
|
}
|
|
951
2087
|
const children = meaningfulJsxChildren(container);
|
|
952
2088
|
if (children.length !== 1) return void 0;
|
|
953
|
-
|
|
2089
|
+
const shape = analyzeKeyedRowChild(
|
|
2090
|
+
children[0],
|
|
2091
|
+
statesByValue,
|
|
2092
|
+
safeGlobals,
|
|
2093
|
+
listNames,
|
|
2094
|
+
true,
|
|
2095
|
+
true
|
|
2096
|
+
);
|
|
2097
|
+
if (!shape || shape.rowReason) return shape;
|
|
2098
|
+
const needsMembershipProof = (binding) => containsPotentialKeyedMembershipCall(binding.value, statesByValue);
|
|
2099
|
+
const needsMapLookupProof = (binding) => containsPotentialKeyedMapLookupCall(binding.value, statesByValue);
|
|
2100
|
+
if (shape.conditionals.length > 0 || shape.events.length > 0 && !canDelegateKeyedRowEvents({
|
|
2101
|
+
conditionals: shape.conditionals,
|
|
2102
|
+
events: shape.events,
|
|
2103
|
+
source: container
|
|
2104
|
+
})) {
|
|
2105
|
+
return shape.bindings.some(
|
|
2106
|
+
(binding) => needsMembershipProof(binding) || needsMapLookupProof(binding)
|
|
2107
|
+
) ? {
|
|
2108
|
+
...shape,
|
|
2109
|
+
rowReason: "keyed collection targets require compiler-owned rows without React-owned branches or events"
|
|
2110
|
+
} : shape;
|
|
2111
|
+
}
|
|
2112
|
+
const structureDependencies = new Set(shape.structureDependencies);
|
|
2113
|
+
const bindings = shape.bindings.map((binding) => ({
|
|
2114
|
+
...binding,
|
|
2115
|
+
identityTarget: keyedIdentityTarget(
|
|
2116
|
+
binding,
|
|
2117
|
+
shape.keyCallback,
|
|
2118
|
+
shape.renderCallback,
|
|
2119
|
+
statesByValue,
|
|
2120
|
+
structureDependencies
|
|
2121
|
+
),
|
|
2122
|
+
membershipTarget: keyedMembershipTarget(
|
|
2123
|
+
binding,
|
|
2124
|
+
shape.keyCallback,
|
|
2125
|
+
shape.renderCallback,
|
|
2126
|
+
statesByValue,
|
|
2127
|
+
structureDependencies
|
|
2128
|
+
),
|
|
2129
|
+
mapLookupTarget: keyedMapLookupTarget(
|
|
2130
|
+
binding,
|
|
2131
|
+
shape.keyCallback,
|
|
2132
|
+
shape.renderCallback,
|
|
2133
|
+
statesByValue,
|
|
2134
|
+
structureDependencies
|
|
2135
|
+
)
|
|
2136
|
+
}));
|
|
2137
|
+
if (bindings.some(
|
|
2138
|
+
(binding, index) => needsMembershipProof(shape.bindings[index]) && !binding.membershipTarget
|
|
2139
|
+
)) {
|
|
2140
|
+
return {
|
|
2141
|
+
...shape,
|
|
2142
|
+
rowReason: "keyed membership targets must call one local Set state with the exact row key"
|
|
2143
|
+
};
|
|
2144
|
+
}
|
|
2145
|
+
if (bindings.some(
|
|
2146
|
+
(binding, index) => needsMapLookupProof(shape.bindings[index]) && !binding.mapLookupTarget
|
|
2147
|
+
)) {
|
|
2148
|
+
return {
|
|
2149
|
+
...shape,
|
|
2150
|
+
rowReason: "keyed Map lookup targets must call one local Map state with the exact row key"
|
|
2151
|
+
};
|
|
2152
|
+
}
|
|
2153
|
+
return {
|
|
2154
|
+
...shape,
|
|
2155
|
+
bindings
|
|
2156
|
+
};
|
|
954
2157
|
}
|
|
955
2158
|
function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, listNames, allowSingleRange = false) {
|
|
956
2159
|
if (container.openingElement.attributes.some(
|
|
@@ -1106,7 +2309,11 @@ function analyzeHostConditionalTree(branch, safeGlobals, allowStaticEvents = fal
|
|
|
1106
2309
|
parts.push(cloneExpression(child.expression));
|
|
1107
2310
|
}
|
|
1108
2311
|
}
|
|
1109
|
-
bindings.push({
|
|
2312
|
+
bindings.push({
|
|
2313
|
+
kind: "text",
|
|
2314
|
+
path: [...path],
|
|
2315
|
+
value: core.types.arrayExpression(parts)
|
|
2316
|
+
});
|
|
1110
2317
|
}
|
|
1111
2318
|
let elementIndex = 0;
|
|
1112
2319
|
for (const child of element.children) {
|
|
@@ -1278,7 +2485,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1278
2485
|
listNames,
|
|
1279
2486
|
id,
|
|
1280
2487
|
allocateId
|
|
1281
|
-
) : {
|
|
2488
|
+
) : {
|
|
2489
|
+
bindings: [],
|
|
2490
|
+
plans: [],
|
|
2491
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2492
|
+
};
|
|
1282
2493
|
const falsy = shape.falsy ? analyzeRecursiveHostTree(
|
|
1283
2494
|
shape.falsy,
|
|
1284
2495
|
statesByValue,
|
|
@@ -1286,7 +2497,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1286
2497
|
listNames,
|
|
1287
2498
|
id,
|
|
1288
2499
|
allocateId
|
|
1289
|
-
) : {
|
|
2500
|
+
) : {
|
|
2501
|
+
bindings: [],
|
|
2502
|
+
plans: [],
|
|
2503
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2504
|
+
};
|
|
1290
2505
|
if (truthy.reason) return truthy.reason;
|
|
1291
2506
|
if (falsy.reason) return falsy.reason;
|
|
1292
2507
|
plans.push(...truthy.plans, ...falsy.plans);
|
|
@@ -1444,7 +2659,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1444
2659
|
parts.push(cloneExpression(child.expression));
|
|
1445
2660
|
}
|
|
1446
2661
|
}
|
|
1447
|
-
bindings.push({
|
|
2662
|
+
bindings.push({
|
|
2663
|
+
kind: "text",
|
|
2664
|
+
path: [...path],
|
|
2665
|
+
value: core.types.arrayExpression(parts)
|
|
2666
|
+
});
|
|
1448
2667
|
}
|
|
1449
2668
|
let elementIndex = 0;
|
|
1450
2669
|
for (const child of element.children) {
|
|
@@ -1511,7 +2730,11 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals,
|
|
|
1511
2730
|
listNames,
|
|
1512
2731
|
parent,
|
|
1513
2732
|
allocateId
|
|
1514
|
-
) : {
|
|
2733
|
+
) : {
|
|
2734
|
+
bindings: [],
|
|
2735
|
+
plans: [],
|
|
2736
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2737
|
+
};
|
|
1515
2738
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1516
2739
|
shape.falsy,
|
|
1517
2740
|
statesByValue,
|
|
@@ -1519,7 +2742,11 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals,
|
|
|
1519
2742
|
listNames,
|
|
1520
2743
|
parent,
|
|
1521
2744
|
allocateId
|
|
1522
|
-
) : {
|
|
2745
|
+
) : {
|
|
2746
|
+
bindings: [],
|
|
2747
|
+
plans: [],
|
|
2748
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2749
|
+
};
|
|
1523
2750
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1524
2751
|
const dependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1525
2752
|
for (const binding of [...truthyAnalysis.bindings || [], ...falsyAnalysis.bindings || []]) {
|
|
@@ -1565,7 +2792,11 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1565
2792
|
listNames,
|
|
1566
2793
|
parent,
|
|
1567
2794
|
allocateId
|
|
1568
|
-
) : {
|
|
2795
|
+
) : {
|
|
2796
|
+
bindings: [],
|
|
2797
|
+
plans: [],
|
|
2798
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2799
|
+
};
|
|
1569
2800
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1570
2801
|
shape.falsy,
|
|
1571
2802
|
statesByValue,
|
|
@@ -1573,7 +2804,11 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1573
2804
|
listNames,
|
|
1574
2805
|
parent,
|
|
1575
2806
|
allocateId
|
|
1576
|
-
) : {
|
|
2807
|
+
) : {
|
|
2808
|
+
bindings: [],
|
|
2809
|
+
plans: [],
|
|
2810
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2811
|
+
};
|
|
1577
2812
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1578
2813
|
nestedPlans.push(...truthyAnalysis.plans, ...falsyAnalysis.plans);
|
|
1579
2814
|
for (const [element, plan] of truthyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
@@ -1666,7 +2901,11 @@ function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
1666
2901
|
listNames,
|
|
1667
2902
|
parent,
|
|
1668
2903
|
allocateId
|
|
1669
|
-
) : {
|
|
2904
|
+
) : {
|
|
2905
|
+
bindings: [],
|
|
2906
|
+
plans: [],
|
|
2907
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2908
|
+
};
|
|
1670
2909
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1671
2910
|
shape.falsy,
|
|
1672
2911
|
statesByValue,
|
|
@@ -1674,7 +2913,11 @@ function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
1674
2913
|
listNames,
|
|
1675
2914
|
parent,
|
|
1676
2915
|
allocateId
|
|
1677
|
-
) : {
|
|
2916
|
+
) : {
|
|
2917
|
+
bindings: [],
|
|
2918
|
+
plans: [],
|
|
2919
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2920
|
+
};
|
|
1678
2921
|
if (!mergeAnalysis(truthyAnalysis) || !mergeAnalysis(falsyAnalysis)) return void 0;
|
|
1679
2922
|
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1680
2923
|
dependencies.add(dependency);
|
|
@@ -1915,6 +3158,57 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1915
3158
|
if (binding.name) {
|
|
1916
3159
|
properties.push(core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(binding.name)));
|
|
1917
3160
|
}
|
|
3161
|
+
if (binding.identityTarget) {
|
|
3162
|
+
properties.push(
|
|
3163
|
+
core.types.objectProperty(
|
|
3164
|
+
core.types.identifier("identityTarget"),
|
|
3165
|
+
core.types.objectExpression([
|
|
3166
|
+
core.types.objectProperty(
|
|
3167
|
+
core.types.identifier("dependency"),
|
|
3168
|
+
core.types.numericLiteral(binding.identityTarget.dependency)
|
|
3169
|
+
),
|
|
3170
|
+
core.types.objectProperty(
|
|
3171
|
+
core.types.identifier("read"),
|
|
3172
|
+
core.types.arrowFunctionExpression([], cloneExpression(binding.identityTarget.value))
|
|
3173
|
+
)
|
|
3174
|
+
])
|
|
3175
|
+
)
|
|
3176
|
+
);
|
|
3177
|
+
}
|
|
3178
|
+
if (binding.membershipTarget) {
|
|
3179
|
+
properties.push(
|
|
3180
|
+
core.types.objectProperty(
|
|
3181
|
+
core.types.identifier("membershipTarget"),
|
|
3182
|
+
core.types.objectExpression([
|
|
3183
|
+
core.types.objectProperty(
|
|
3184
|
+
core.types.identifier("dependency"),
|
|
3185
|
+
core.types.numericLiteral(binding.membershipTarget.dependency)
|
|
3186
|
+
),
|
|
3187
|
+
core.types.objectProperty(
|
|
3188
|
+
core.types.identifier("read"),
|
|
3189
|
+
core.types.arrowFunctionExpression([], cloneExpression(binding.membershipTarget.value))
|
|
3190
|
+
)
|
|
3191
|
+
])
|
|
3192
|
+
)
|
|
3193
|
+
);
|
|
3194
|
+
}
|
|
3195
|
+
if (binding.mapLookupTarget) {
|
|
3196
|
+
properties.push(
|
|
3197
|
+
core.types.objectProperty(
|
|
3198
|
+
core.types.identifier("mapLookupTarget"),
|
|
3199
|
+
core.types.objectExpression([
|
|
3200
|
+
core.types.objectProperty(
|
|
3201
|
+
core.types.identifier("dependency"),
|
|
3202
|
+
core.types.numericLiteral(binding.mapLookupTarget.dependency)
|
|
3203
|
+
),
|
|
3204
|
+
core.types.objectProperty(
|
|
3205
|
+
core.types.identifier("read"),
|
|
3206
|
+
core.types.arrowFunctionExpression([], cloneExpression(binding.mapLookupTarget.value))
|
|
3207
|
+
)
|
|
3208
|
+
])
|
|
3209
|
+
)
|
|
3210
|
+
);
|
|
3211
|
+
}
|
|
1918
3212
|
properties.push(
|
|
1919
3213
|
core.types.objectProperty(
|
|
1920
3214
|
core.types.identifier("read"),
|
|
@@ -2109,7 +3403,7 @@ function keyedRowConditionalObject(conditional, parameters) {
|
|
|
2109
3403
|
}
|
|
2110
3404
|
return core.types.objectExpression(properties);
|
|
2111
3405
|
}
|
|
2112
|
-
function keyedRowsBoundary(blockRuntime, plan) {
|
|
3406
|
+
function keyedRowsBoundary(blockRuntime, plan, keyedMapUpdateHints, keyedArrayFilterHintedStateIndices, keyedArrayPrependHintedStateIndices, keyedArrayPositionHintedStateIndices, keyedArrayReorderHintedStateIndices) {
|
|
2113
3407
|
const name = core.types.jsxMemberExpression(
|
|
2114
3408
|
core.types.jsxIdentifier(blockRuntime.name),
|
|
2115
3409
|
core.types.jsxIdentifier("KeyedRows")
|
|
@@ -2143,6 +3437,16 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
2143
3437
|
core.types.jsxIdentifier("items"),
|
|
2144
3438
|
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], cloneExpression(plan.collection)))
|
|
2145
3439
|
),
|
|
3440
|
+
...keyedMapUpdateHints ? [
|
|
3441
|
+
core.types.jsxAttribute(
|
|
3442
|
+
core.types.jsxIdentifier("dependencies"),
|
|
3443
|
+
core.types.jsxExpressionContainer(
|
|
3444
|
+
core.types.arrayExpression(
|
|
3445
|
+
plan.dependencies.map((dependency) => core.types.numericLiteral(dependency))
|
|
3446
|
+
)
|
|
3447
|
+
)
|
|
3448
|
+
)
|
|
3449
|
+
] : [],
|
|
2146
3450
|
core.types.jsxAttribute(
|
|
2147
3451
|
core.types.jsxIdentifier("structureDependencies"),
|
|
2148
3452
|
core.types.jsxExpressionContainer(
|
|
@@ -2151,6 +3455,36 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
2151
3455
|
)
|
|
2152
3456
|
)
|
|
2153
3457
|
),
|
|
3458
|
+
...!keyedMapUpdateHints || plan.collectionDependency === void 0 ? [] : [
|
|
3459
|
+
core.types.jsxAttribute(
|
|
3460
|
+
core.types.jsxIdentifier("collectionDependency"),
|
|
3461
|
+
core.types.jsxExpressionContainer(core.types.numericLiteral(plan.collectionDependency))
|
|
3462
|
+
)
|
|
3463
|
+
],
|
|
3464
|
+
...plan.collectionDependency !== void 0 && keyedArrayFilterHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3465
|
+
core.types.jsxAttribute(
|
|
3466
|
+
core.types.jsxIdentifier("filterIndexIndependent"),
|
|
3467
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3468
|
+
)
|
|
3469
|
+
] : [],
|
|
3470
|
+
...plan.collectionDependency !== void 0 && keyedArrayPrependHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3471
|
+
core.types.jsxAttribute(
|
|
3472
|
+
core.types.jsxIdentifier("prependIndexIndependent"),
|
|
3473
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3474
|
+
)
|
|
3475
|
+
] : [],
|
|
3476
|
+
...plan.collectionDependency !== void 0 && keyedArrayPositionHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3477
|
+
core.types.jsxAttribute(
|
|
3478
|
+
core.types.jsxIdentifier("positionIndexIndependent"),
|
|
3479
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3480
|
+
)
|
|
3481
|
+
] : [],
|
|
3482
|
+
...plan.collectionDependency !== void 0 && keyedArrayReorderHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3483
|
+
core.types.jsxAttribute(
|
|
3484
|
+
core.types.jsxIdentifier("reorderIndexIndependent"),
|
|
3485
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3486
|
+
)
|
|
3487
|
+
] : [],
|
|
2154
3488
|
core.types.jsxAttribute(
|
|
2155
3489
|
core.types.jsxIdentifier("rowKey"),
|
|
2156
3490
|
core.types.jsxExpressionContainer(core.types.cloneNode(plan.keyCallback, true))
|
|
@@ -2477,7 +3811,9 @@ function conditionalRangesBoundary(blockRuntime, plan) {
|
|
|
2477
3811
|
function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allowedComponentNames) {
|
|
2478
3812
|
const name = element.openingElement.name;
|
|
2479
3813
|
if (!core.types.isJSXIdentifier(name) || !isComponentName(name.name)) {
|
|
2480
|
-
return {
|
|
3814
|
+
return {
|
|
3815
|
+
reason: "component islands require a direct component identifier"
|
|
3816
|
+
};
|
|
2481
3817
|
}
|
|
2482
3818
|
if (!allowedComponentNames.has(name.name)) {
|
|
2483
3819
|
return {
|
|
@@ -2485,19 +3821,27 @@ function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allo
|
|
|
2485
3821
|
};
|
|
2486
3822
|
}
|
|
2487
3823
|
if (meaningfulJsxChildren(element).length > 0) {
|
|
2488
|
-
return {
|
|
3824
|
+
return {
|
|
3825
|
+
reason: `component island ${name.name} does not support children yet`
|
|
3826
|
+
};
|
|
2489
3827
|
}
|
|
2490
3828
|
const dependencies = /* @__PURE__ */ new Set();
|
|
2491
3829
|
for (const attribute of element.openingElement.attributes) {
|
|
2492
3830
|
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
2493
|
-
return {
|
|
3831
|
+
return {
|
|
3832
|
+
reason: `component island ${name.name} does not support JSX attribute spreads`
|
|
3833
|
+
};
|
|
2494
3834
|
}
|
|
2495
3835
|
const attributeName = jsxAttributeName(attribute);
|
|
2496
3836
|
if (!attributeName) {
|
|
2497
|
-
return {
|
|
3837
|
+
return {
|
|
3838
|
+
reason: `component island ${name.name} does not support namespaced JSX attributes`
|
|
3839
|
+
};
|
|
2498
3840
|
}
|
|
2499
3841
|
if (attributeName === "ref" || attributeName === "key" || attributeName === "children") {
|
|
2500
|
-
return {
|
|
3842
|
+
return {
|
|
3843
|
+
reason: `component island ${name.name} does not support ${attributeName} yet`
|
|
3844
|
+
};
|
|
2501
3845
|
}
|
|
2502
3846
|
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
2503
3847
|
continue;
|
|
@@ -2516,7 +3860,9 @@ function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allo
|
|
|
2516
3860
|
(dependency) => dependencies.add(dependency)
|
|
2517
3861
|
);
|
|
2518
3862
|
}
|
|
2519
|
-
return {
|
|
3863
|
+
return {
|
|
3864
|
+
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
3865
|
+
};
|
|
2520
3866
|
}
|
|
2521
3867
|
function componentIslandBoundary(blockRuntime, plan, source) {
|
|
2522
3868
|
const name = core.types.jsxMemberExpression(
|
|
@@ -2773,6 +4119,7 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
2773
4119
|
dependencies: keyedRows.dependencies,
|
|
2774
4120
|
source: child,
|
|
2775
4121
|
collection: keyedRows.collection,
|
|
4122
|
+
collectionDependency: keyedRows.collectionDependency,
|
|
2776
4123
|
structureDependencies: keyedRows.structureDependencies,
|
|
2777
4124
|
keyCallback: keyedRows.keyCallback,
|
|
2778
4125
|
renderCallback: keyedRows.renderCallback,
|
|
@@ -3014,7 +4361,7 @@ function conditionalBlockBoundary(blockRuntime, plan, source) {
|
|
|
3014
4361
|
true
|
|
3015
4362
|
);
|
|
3016
4363
|
}
|
|
3017
|
-
function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
4364
|
+
function lowerComposableBlocks(root, plans, blockRuntime, listNames, keyedMapUpdateHints, keyedArrayFilterHintedStateIndices, keyedArrayPrependHintedStateIndices, keyedArrayPositionHintedStateIndices, keyedArrayReorderHintedStateIndices) {
|
|
3018
4365
|
const planBySource = new Map(
|
|
3019
4366
|
plans.map((plan) => [plan.source, plan])
|
|
3020
4367
|
);
|
|
@@ -3039,7 +4386,15 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
3039
4386
|
return mixedRangesBoundary(blockRuntime, plan2);
|
|
3040
4387
|
}
|
|
3041
4388
|
if (plan2?.kind === "keyed-rows") {
|
|
3042
|
-
return keyedRowsBoundary(
|
|
4389
|
+
return keyedRowsBoundary(
|
|
4390
|
+
blockRuntime,
|
|
4391
|
+
plan2,
|
|
4392
|
+
keyedMapUpdateHints,
|
|
4393
|
+
keyedArrayFilterHintedStateIndices,
|
|
4394
|
+
keyedArrayPrependHintedStateIndices,
|
|
4395
|
+
keyedArrayPositionHintedStateIndices,
|
|
4396
|
+
keyedArrayReorderHintedStateIndices
|
|
4397
|
+
);
|
|
3043
4398
|
}
|
|
3044
4399
|
if (plan2?.kind === "keyed-ranges") {
|
|
3045
4400
|
return keyedRangesBoundary(blockRuntime, plan2);
|
|
@@ -3402,7 +4757,7 @@ function wrapperElement(definitionIdentifier, props) {
|
|
|
3402
4757
|
const attributes = props ? [core.types.jsxSpreadAttribute(core.types.cloneNode(props))] : [];
|
|
3403
4758
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
3404
4759
|
}
|
|
3405
|
-
function compileCandidate(candidate, createComponentIdentifier, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
4760
|
+
function compileCandidate(candidate, createComponentIdentifier, keyedMapUpdateIdentifier, keyedArrayAppendIdentifier, keyedArrayFilterIdentifier, keyedArrayPrependIdentifier, keyedArrayPositionIdentifier, keyedArrayReorderIdentifier, keyedArrayRollingWindowIdentifier, keyedArraySliceIdentifier, keyedCollectionUpdateIdentifier, keyedCollectionMutationIdentifier, runtimeFeatureIdentifiers, usedRuntimeFeatures, optimizationCounts, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
3406
4761
|
const { path, name, statementPath } = candidate;
|
|
3407
4762
|
if (path.node.async || path.node.generator)
|
|
3408
4763
|
return "async and generator components are not supported";
|
|
@@ -3414,6 +4769,7 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
3414
4769
|
const safeGlobals = new Set(
|
|
3415
4770
|
[...SAFE_GLOBAL_CALLS, "Math"].filter((name2) => !path.scope.getBinding(name2))
|
|
3416
4771
|
);
|
|
4772
|
+
const globalCollections = new Set(["Set", "Map"].filter((name2) => !path.scope.getBinding(name2)));
|
|
3417
4773
|
const states = [];
|
|
3418
4774
|
const locals = [];
|
|
3419
4775
|
let returned;
|
|
@@ -3461,9 +4817,17 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
3461
4817
|
if (declaration.init.async || declaration.init.generator) {
|
|
3462
4818
|
return `event handler ${declaration.id.name} must be synchronous`;
|
|
3463
4819
|
}
|
|
3464
|
-
locals.push({
|
|
4820
|
+
locals.push({
|
|
4821
|
+
kind: "handler",
|
|
4822
|
+
name: declaration.id.name,
|
|
4823
|
+
value: declaration.init
|
|
4824
|
+
});
|
|
3465
4825
|
} else {
|
|
3466
|
-
locals.push({
|
|
4826
|
+
locals.push({
|
|
4827
|
+
kind: "derived",
|
|
4828
|
+
name: declaration.id.name,
|
|
4829
|
+
value: declaration.init
|
|
4830
|
+
});
|
|
3467
4831
|
}
|
|
3468
4832
|
}
|
|
3469
4833
|
if (states.length === 0) return "no local useState binding was found";
|
|
@@ -3602,7 +4966,378 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
3602
4966
|
}
|
|
3603
4967
|
if (blockAnalysis.reason) return blockAnalysis.reason;
|
|
3604
4968
|
if (analysis.reason) return analysis.reason;
|
|
4969
|
+
const hintedStateIndices = new Set(
|
|
4970
|
+
(blockAnalysis.plans || []).filter(
|
|
4971
|
+
(plan) => plan.kind === "keyed-rows" && plan.collectionDependency !== void 0
|
|
4972
|
+
).map((plan) => plan.collectionDependency)
|
|
4973
|
+
);
|
|
4974
|
+
const hintedRoot = rewriteKeyedMapUpdateHints(
|
|
4975
|
+
expandedReactiveRoot,
|
|
4976
|
+
hintedStateIndices,
|
|
4977
|
+
statesBySetter,
|
|
4978
|
+
keyedMapUpdateIdentifier,
|
|
4979
|
+
safeGlobals
|
|
4980
|
+
);
|
|
4981
|
+
let appliedKeyedMapUpdateHints = 0;
|
|
4982
|
+
if (hintedRoot.count > 0) {
|
|
4983
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
4984
|
+
hintedRoot.root,
|
|
4985
|
+
reactiveByValue,
|
|
4986
|
+
safeGlobals,
|
|
4987
|
+
listNames,
|
|
4988
|
+
allowedComponentNames
|
|
4989
|
+
);
|
|
4990
|
+
const hintedAnalysis = analyzeHostTree(
|
|
4991
|
+
hintedRoot.root,
|
|
4992
|
+
reactiveByValue,
|
|
4993
|
+
safeGlobals,
|
|
4994
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
4995
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
4996
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
4997
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
4998
|
+
);
|
|
4999
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5000
|
+
expandedReactiveRoot = hintedRoot.root;
|
|
5001
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5002
|
+
analysis = hintedAnalysis;
|
|
5003
|
+
appliedKeyedMapUpdateHints = hintedRoot.count;
|
|
5004
|
+
optimizationCounts.keyedMapUpdateHints += hintedRoot.count;
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
const appendHintedStateIndices = new Set(hintedStateIndices);
|
|
5008
|
+
for (const plan of blockAnalysis.plans || []) {
|
|
5009
|
+
if (plan.kind !== "keyed-rows" || plan.collectionDependency === void 0) continue;
|
|
5010
|
+
const keyExpression = returnedExpression(plan.keyCallback);
|
|
5011
|
+
if (!keyExpression || collectStateDependencies(keyExpression, reactiveByValue).includes(plan.collectionDependency)) {
|
|
5012
|
+
appendHintedStateIndices.delete(plan.collectionDependency);
|
|
5013
|
+
}
|
|
5014
|
+
}
|
|
5015
|
+
const appendHintedRoot = rewriteKeyedArrayAppendHints(
|
|
5016
|
+
expandedReactiveRoot,
|
|
5017
|
+
appendHintedStateIndices,
|
|
5018
|
+
statesBySetter,
|
|
5019
|
+
keyedArrayAppendIdentifier,
|
|
5020
|
+
safeGlobals
|
|
5021
|
+
);
|
|
5022
|
+
let appliedKeyedArrayAppendHints = 0;
|
|
5023
|
+
if (appendHintedRoot.count > 0) {
|
|
5024
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5025
|
+
appendHintedRoot.root,
|
|
5026
|
+
reactiveByValue,
|
|
5027
|
+
safeGlobals,
|
|
5028
|
+
listNames,
|
|
5029
|
+
allowedComponentNames
|
|
5030
|
+
);
|
|
5031
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5032
|
+
appendHintedRoot.root,
|
|
5033
|
+
reactiveByValue,
|
|
5034
|
+
safeGlobals,
|
|
5035
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5036
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5037
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5038
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5039
|
+
);
|
|
5040
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5041
|
+
expandedReactiveRoot = appendHintedRoot.root;
|
|
5042
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5043
|
+
analysis = hintedAnalysis;
|
|
5044
|
+
appliedKeyedArrayAppendHints = appendHintedRoot.count;
|
|
5045
|
+
optimizationCounts.keyedArrayAppendHints += appendHintedRoot.count;
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
const shiftedIndexIndependentStateIndices = new Set(hintedStateIndices);
|
|
5049
|
+
for (const plan of blockAnalysis.plans || []) {
|
|
5050
|
+
if (plan.kind !== "keyed-rows" || plan.collectionDependency === void 0) continue;
|
|
5051
|
+
const keyExpression = returnedExpression(plan.keyCallback);
|
|
5052
|
+
if (plan.renderCallback.params.length > 1 || !keyExpression || collectStateDependencies(keyExpression, reactiveByValue).includes(plan.collectionDependency)) {
|
|
5053
|
+
shiftedIndexIndependentStateIndices.delete(plan.collectionDependency);
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
const prependHintedRoot = rewriteKeyedArrayPrependHints(
|
|
5057
|
+
expandedReactiveRoot,
|
|
5058
|
+
shiftedIndexIndependentStateIndices,
|
|
5059
|
+
statesBySetter,
|
|
5060
|
+
keyedArrayPrependIdentifier,
|
|
5061
|
+
safeGlobals
|
|
5062
|
+
);
|
|
5063
|
+
let appliedKeyedArrayPrependHints = 0;
|
|
5064
|
+
let appliedPrependHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5065
|
+
if (prependHintedRoot.count > 0) {
|
|
5066
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5067
|
+
prependHintedRoot.root,
|
|
5068
|
+
reactiveByValue,
|
|
5069
|
+
safeGlobals,
|
|
5070
|
+
listNames,
|
|
5071
|
+
allowedComponentNames
|
|
5072
|
+
);
|
|
5073
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5074
|
+
prependHintedRoot.root,
|
|
5075
|
+
reactiveByValue,
|
|
5076
|
+
safeGlobals,
|
|
5077
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5078
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5079
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5080
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5081
|
+
);
|
|
5082
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5083
|
+
expandedReactiveRoot = prependHintedRoot.root;
|
|
5084
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5085
|
+
analysis = hintedAnalysis;
|
|
5086
|
+
appliedKeyedArrayPrependHints = prependHintedRoot.count;
|
|
5087
|
+
appliedPrependHintedStateIndices = prependHintedRoot.stateIndices;
|
|
5088
|
+
optimizationCounts.keyedArrayPrependHints += prependHintedRoot.count;
|
|
5089
|
+
}
|
|
5090
|
+
}
|
|
5091
|
+
const rollingWindowHintedRoot = rewriteKeyedArrayRollingWindowHints(
|
|
5092
|
+
expandedReactiveRoot,
|
|
5093
|
+
shiftedIndexIndependentStateIndices,
|
|
5094
|
+
statesBySetter,
|
|
5095
|
+
keyedArraySliceIdentifier,
|
|
5096
|
+
keyedArrayRollingWindowIdentifier,
|
|
5097
|
+
safeGlobals
|
|
5098
|
+
);
|
|
5099
|
+
let appliedKeyedArrayRollingWindowHints = 0;
|
|
5100
|
+
let appliedRollingWindowHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5101
|
+
if (rollingWindowHintedRoot.count > 0) {
|
|
5102
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5103
|
+
rollingWindowHintedRoot.root,
|
|
5104
|
+
reactiveByValue,
|
|
5105
|
+
safeGlobals,
|
|
5106
|
+
listNames,
|
|
5107
|
+
allowedComponentNames
|
|
5108
|
+
);
|
|
5109
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5110
|
+
rollingWindowHintedRoot.root,
|
|
5111
|
+
reactiveByValue,
|
|
5112
|
+
safeGlobals,
|
|
5113
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5114
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5115
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5116
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5117
|
+
);
|
|
5118
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5119
|
+
expandedReactiveRoot = rollingWindowHintedRoot.root;
|
|
5120
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5121
|
+
analysis = hintedAnalysis;
|
|
5122
|
+
appliedKeyedArrayRollingWindowHints = rollingWindowHintedRoot.count;
|
|
5123
|
+
appliedRollingWindowHintedStateIndices = rollingWindowHintedRoot.stateIndices;
|
|
5124
|
+
optimizationCounts.keyedArrayRollingWindowHints += rollingWindowHintedRoot.count;
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
const positionHintedRoot = rewriteKeyedArrayPositionHints(
|
|
5128
|
+
expandedReactiveRoot,
|
|
5129
|
+
shiftedIndexIndependentStateIndices,
|
|
5130
|
+
statesBySetter,
|
|
5131
|
+
keyedArrayPositionIdentifier,
|
|
5132
|
+
safeGlobals
|
|
5133
|
+
);
|
|
5134
|
+
let appliedKeyedArrayPositionHints = 0;
|
|
5135
|
+
let appliedPositionHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5136
|
+
if (positionHintedRoot.count > 0) {
|
|
5137
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5138
|
+
positionHintedRoot.root,
|
|
5139
|
+
reactiveByValue,
|
|
5140
|
+
safeGlobals,
|
|
5141
|
+
listNames,
|
|
5142
|
+
allowedComponentNames
|
|
5143
|
+
);
|
|
5144
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5145
|
+
positionHintedRoot.root,
|
|
5146
|
+
reactiveByValue,
|
|
5147
|
+
safeGlobals,
|
|
5148
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5149
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5150
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5151
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5152
|
+
);
|
|
5153
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5154
|
+
expandedReactiveRoot = positionHintedRoot.root;
|
|
5155
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5156
|
+
analysis = hintedAnalysis;
|
|
5157
|
+
appliedKeyedArrayPositionHints = positionHintedRoot.count;
|
|
5158
|
+
appliedPositionHintedStateIndices = positionHintedRoot.stateIndices;
|
|
5159
|
+
optimizationCounts.keyedArrayPositionHints += positionHintedRoot.count;
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
const reorderHintedRoot = rewriteKeyedArrayReorderHints(
|
|
5163
|
+
expandedReactiveRoot,
|
|
5164
|
+
shiftedIndexIndependentStateIndices,
|
|
5165
|
+
statesBySetter,
|
|
5166
|
+
keyedArrayReorderIdentifier
|
|
5167
|
+
);
|
|
5168
|
+
let appliedKeyedArrayReorderHints = 0;
|
|
5169
|
+
let appliedReorderHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5170
|
+
if (reorderHintedRoot.count > 0) {
|
|
5171
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5172
|
+
reorderHintedRoot.root,
|
|
5173
|
+
reactiveByValue,
|
|
5174
|
+
safeGlobals,
|
|
5175
|
+
listNames,
|
|
5176
|
+
allowedComponentNames
|
|
5177
|
+
);
|
|
5178
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5179
|
+
reorderHintedRoot.root,
|
|
5180
|
+
reactiveByValue,
|
|
5181
|
+
safeGlobals,
|
|
5182
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5183
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5184
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5185
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5186
|
+
);
|
|
5187
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5188
|
+
expandedReactiveRoot = reorderHintedRoot.root;
|
|
5189
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5190
|
+
analysis = hintedAnalysis;
|
|
5191
|
+
appliedKeyedArrayReorderHints = reorderHintedRoot.count;
|
|
5192
|
+
appliedReorderHintedStateIndices = reorderHintedRoot.stateIndices;
|
|
5193
|
+
optimizationCounts.keyedArrayReorderHints += reorderHintedRoot.count;
|
|
5194
|
+
}
|
|
5195
|
+
}
|
|
5196
|
+
const sliceHintedRoot = rewriteKeyedArraySliceHints(
|
|
5197
|
+
expandedReactiveRoot,
|
|
5198
|
+
shiftedIndexIndependentStateIndices,
|
|
5199
|
+
statesBySetter,
|
|
5200
|
+
keyedArraySliceIdentifier
|
|
5201
|
+
);
|
|
5202
|
+
let appliedKeyedArraySliceHints = 0;
|
|
5203
|
+
let appliedSliceHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5204
|
+
if (sliceHintedRoot.count > 0) {
|
|
5205
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5206
|
+
sliceHintedRoot.root,
|
|
5207
|
+
reactiveByValue,
|
|
5208
|
+
safeGlobals,
|
|
5209
|
+
listNames,
|
|
5210
|
+
allowedComponentNames
|
|
5211
|
+
);
|
|
5212
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5213
|
+
sliceHintedRoot.root,
|
|
5214
|
+
reactiveByValue,
|
|
5215
|
+
safeGlobals,
|
|
5216
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5217
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5218
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5219
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5220
|
+
);
|
|
5221
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5222
|
+
expandedReactiveRoot = sliceHintedRoot.root;
|
|
5223
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5224
|
+
analysis = hintedAnalysis;
|
|
5225
|
+
appliedKeyedArraySliceHints = sliceHintedRoot.count;
|
|
5226
|
+
appliedSliceHintedStateIndices = sliceHintedRoot.stateIndices;
|
|
5227
|
+
optimizationCounts.keyedArraySliceHints += sliceHintedRoot.count;
|
|
5228
|
+
}
|
|
5229
|
+
}
|
|
5230
|
+
const filterHintedRoot = rewriteKeyedArrayFilterHints(
|
|
5231
|
+
expandedReactiveRoot,
|
|
5232
|
+
shiftedIndexIndependentStateIndices,
|
|
5233
|
+
statesBySetter,
|
|
5234
|
+
keyedArrayFilterIdentifier,
|
|
5235
|
+
safeGlobals
|
|
5236
|
+
);
|
|
5237
|
+
let appliedKeyedArrayFilterHints = 0;
|
|
5238
|
+
let appliedFilterHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5239
|
+
if (filterHintedRoot.count > 0) {
|
|
5240
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5241
|
+
filterHintedRoot.root,
|
|
5242
|
+
reactiveByValue,
|
|
5243
|
+
safeGlobals,
|
|
5244
|
+
listNames,
|
|
5245
|
+
allowedComponentNames
|
|
5246
|
+
);
|
|
5247
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5248
|
+
filterHintedRoot.root,
|
|
5249
|
+
reactiveByValue,
|
|
5250
|
+
safeGlobals,
|
|
5251
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5252
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5253
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5254
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5255
|
+
);
|
|
5256
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5257
|
+
expandedReactiveRoot = filterHintedRoot.root;
|
|
5258
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5259
|
+
analysis = hintedAnalysis;
|
|
5260
|
+
appliedKeyedArrayFilterHints = filterHintedRoot.count;
|
|
5261
|
+
appliedFilterHintedStateIndices = filterHintedRoot.stateIndices;
|
|
5262
|
+
optimizationCounts.keyedArrayFilterHints += filterHintedRoot.count;
|
|
5263
|
+
}
|
|
5264
|
+
}
|
|
5265
|
+
const keyedCollectionTargetKinds = /* @__PURE__ */ new Map();
|
|
5266
|
+
const conflictingKeyedCollectionTargets = /* @__PURE__ */ new Set();
|
|
5267
|
+
for (const plan of blockAnalysis.plans || []) {
|
|
5268
|
+
if (plan.kind !== "keyed-rows") continue;
|
|
5269
|
+
for (const binding of plan.bindings) {
|
|
5270
|
+
const target = binding.membershipTarget || binding.mapLookupTarget;
|
|
5271
|
+
if (!target) continue;
|
|
5272
|
+
const kind = binding.membershipTarget ? "set" : "map";
|
|
5273
|
+
const previousKind = keyedCollectionTargetKinds.get(target.dependency);
|
|
5274
|
+
if (previousKind && previousKind !== kind) {
|
|
5275
|
+
conflictingKeyedCollectionTargets.add(target.dependency);
|
|
5276
|
+
} else {
|
|
5277
|
+
keyedCollectionTargetKinds.set(target.dependency, kind);
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
for (const dependency of conflictingKeyedCollectionTargets) {
|
|
5282
|
+
keyedCollectionTargetKinds.delete(dependency);
|
|
5283
|
+
}
|
|
5284
|
+
const keyedCollectionHintedRoot = rewriteKeyedCollectionUpdateHints(
|
|
5285
|
+
expandedReactiveRoot,
|
|
5286
|
+
keyedCollectionTargetKinds,
|
|
5287
|
+
states,
|
|
5288
|
+
statesBySetter,
|
|
5289
|
+
keyedCollectionUpdateIdentifier,
|
|
5290
|
+
keyedCollectionMutationIdentifier,
|
|
5291
|
+
globalCollections
|
|
5292
|
+
);
|
|
5293
|
+
if (keyedCollectionHintedRoot.count > 0) {
|
|
5294
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5295
|
+
keyedCollectionHintedRoot.root,
|
|
5296
|
+
reactiveByValue,
|
|
5297
|
+
safeGlobals,
|
|
5298
|
+
listNames,
|
|
5299
|
+
allowedComponentNames
|
|
5300
|
+
);
|
|
5301
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5302
|
+
keyedCollectionHintedRoot.root,
|
|
5303
|
+
reactiveByValue,
|
|
5304
|
+
safeGlobals,
|
|
5305
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5306
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5307
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5308
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5309
|
+
);
|
|
5310
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5311
|
+
expandedReactiveRoot = keyedCollectionHintedRoot.root;
|
|
5312
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5313
|
+
analysis = hintedAnalysis;
|
|
5314
|
+
optimizationCounts.keyedCollectionUpdateHints += keyedCollectionHintedRoot.count;
|
|
5315
|
+
}
|
|
5316
|
+
}
|
|
3605
5317
|
const blockPlans = blockAnalysis.plans || [];
|
|
5318
|
+
optimizationCounts.keyedIdentityTargets += blockPlans.reduce(
|
|
5319
|
+
(count, plan) => count + (plan.kind === "keyed-rows" ? plan.bindings.filter((binding) => binding.identityTarget !== void 0).length : 0),
|
|
5320
|
+
0
|
|
5321
|
+
);
|
|
5322
|
+
optimizationCounts.keyedMembershipTargets += blockPlans.reduce(
|
|
5323
|
+
(count, plan) => count + (plan.kind === "keyed-rows" ? plan.bindings.filter((binding) => binding.membershipTarget !== void 0).length : 0),
|
|
5324
|
+
0
|
|
5325
|
+
);
|
|
5326
|
+
optimizationCounts.keyedMapLookupTargets += blockPlans.reduce(
|
|
5327
|
+
(count, plan) => count + (plan.kind === "keyed-rows" ? plan.bindings.filter((binding) => binding.mapLookupTarget !== void 0).length : 0),
|
|
5328
|
+
0
|
|
5329
|
+
);
|
|
5330
|
+
const hasKeyedUpdateHints = appliedKeyedMapUpdateHints > 0 || appliedKeyedArrayAppendHints > 0 || appliedKeyedArrayFilterHints > 0 || appliedKeyedArrayPrependHints > 0 || appliedKeyedArrayPositionHints > 0 || appliedKeyedArrayReorderHints > 0 || appliedKeyedArrayRollingWindowHints > 0 || appliedKeyedArraySliceHints > 0;
|
|
5331
|
+
const hasKeyedArrayRemovalHints = appliedKeyedArrayFilterHints > 0 || appliedKeyedArrayRollingWindowHints > 0 || appliedKeyedArraySliceHints > 0;
|
|
5332
|
+
const runtimeFeatures = runtimeFeaturesForPlans(
|
|
5333
|
+
blockPlans,
|
|
5334
|
+
hasKeyedUpdateHints,
|
|
5335
|
+
hasKeyedArrayRemovalHints,
|
|
5336
|
+
appliedKeyedArrayPrependHints > 0,
|
|
5337
|
+
appliedKeyedArrayPositionHints > 0,
|
|
5338
|
+
appliedKeyedArrayReorderHints > 0,
|
|
5339
|
+
appliedKeyedArrayRollingWindowHints > 0
|
|
5340
|
+
);
|
|
3606
5341
|
markShortCircuitBindings(analysis.bindings || []);
|
|
3607
5342
|
assignStableBindingTargets(analysis.bindings || []);
|
|
3608
5343
|
const stateParameter = path.scope.generateUidIdentifier("farmState");
|
|
@@ -3615,11 +5350,21 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
3615
5350
|
blockParameter,
|
|
3616
5351
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set()
|
|
3617
5352
|
);
|
|
5353
|
+
const appliedRemovalHintedStateIndices = /* @__PURE__ */ new Set([
|
|
5354
|
+
...appliedFilterHintedStateIndices,
|
|
5355
|
+
...appliedRollingWindowHintedStateIndices,
|
|
5356
|
+
...appliedSliceHintedStateIndices
|
|
5357
|
+
]);
|
|
3618
5358
|
const rootWithBlocks = lowerComposableBlocks(
|
|
3619
5359
|
rootWithTargets,
|
|
3620
5360
|
blockPlans,
|
|
3621
5361
|
blockParameter,
|
|
3622
|
-
listNames
|
|
5362
|
+
listNames,
|
|
5363
|
+
hasKeyedUpdateHints,
|
|
5364
|
+
appliedRemovalHintedStateIndices,
|
|
5365
|
+
appliedPrependHintedStateIndices,
|
|
5366
|
+
appliedPositionHintedStateIndices,
|
|
5367
|
+
appliedReorderHintedStateIndices
|
|
3623
5368
|
);
|
|
3624
5369
|
const rewrittenRoot = rewriteStateAccess(
|
|
3625
5370
|
rootWithBlocks,
|
|
@@ -3705,7 +5450,10 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
3705
5450
|
)
|
|
3706
5451
|
)
|
|
3707
5452
|
)
|
|
3708
|
-
])
|
|
5453
|
+
]),
|
|
5454
|
+
core.types.arrayExpression(
|
|
5455
|
+
runtimeFeatures.map((feature) => core.types.cloneNode(runtimeFeatureIdentifiers.get(feature)))
|
|
5456
|
+
)
|
|
3709
5457
|
]);
|
|
3710
5458
|
path.get("body").replaceWith(
|
|
3711
5459
|
core.types.blockStatement([
|
|
@@ -3715,6 +5463,7 @@ function compileCandidate(candidate, createComponentIdentifier, useStateNames, r
|
|
|
3715
5463
|
statementPath.insertAfter(
|
|
3716
5464
|
core.types.variableDeclaration("const", [core.types.variableDeclarator(definitionIdentifier, definition)])
|
|
3717
5465
|
);
|
|
5466
|
+
for (const feature of runtimeFeatures) usedRuntimeFeatures.add(feature);
|
|
3718
5467
|
return void 0;
|
|
3719
5468
|
}
|
|
3720
5469
|
function collectCandidates(programPath) {
|
|
@@ -3753,6 +5502,20 @@ function collectCandidates(programPath) {
|
|
|
3753
5502
|
async function compileReactModule(code, id, options) {
|
|
3754
5503
|
const compiled = [];
|
|
3755
5504
|
const diagnostics = [];
|
|
5505
|
+
const optimizationCounts = {
|
|
5506
|
+
keyedArrayAppendHints: 0,
|
|
5507
|
+
keyedArrayFilterHints: 0,
|
|
5508
|
+
keyedArrayPrependHints: 0,
|
|
5509
|
+
keyedArrayPositionHints: 0,
|
|
5510
|
+
keyedArrayReorderHints: 0,
|
|
5511
|
+
keyedArrayRollingWindowHints: 0,
|
|
5512
|
+
keyedArraySliceHints: 0,
|
|
5513
|
+
keyedCollectionUpdateHints: 0,
|
|
5514
|
+
keyedIdentityTargets: 0,
|
|
5515
|
+
keyedMapLookupTargets: 0,
|
|
5516
|
+
keyedMembershipTargets: 0,
|
|
5517
|
+
keyedMapUpdateHints: 0
|
|
5518
|
+
};
|
|
3756
5519
|
const plugin = () => ({
|
|
3757
5520
|
name: "farm-react-aot",
|
|
3758
5521
|
visitor: {
|
|
@@ -3782,6 +5545,43 @@ async function compileReactModule(code, id, options) {
|
|
|
3782
5545
|
}
|
|
3783
5546
|
const candidates = collectCandidates(programPath);
|
|
3784
5547
|
const createComponentIdentifier = programPath.scope.generateUidIdentifier("createCompiledComponent");
|
|
5548
|
+
const keyedMapUpdateIdentifier = programPath.scope.generateUidIdentifier(
|
|
5549
|
+
"createCompilerKeyedMapUpdate"
|
|
5550
|
+
);
|
|
5551
|
+
const keyedArrayAppendIdentifier = programPath.scope.generateUidIdentifier(
|
|
5552
|
+
"createCompilerKeyedArrayAppend"
|
|
5553
|
+
);
|
|
5554
|
+
const keyedArrayFilterIdentifier = programPath.scope.generateUidIdentifier(
|
|
5555
|
+
"createCompilerKeyedArrayFilter"
|
|
5556
|
+
);
|
|
5557
|
+
const keyedArrayPrependIdentifier = programPath.scope.generateUidIdentifier(
|
|
5558
|
+
"createCompilerKeyedArrayPrepend"
|
|
5559
|
+
);
|
|
5560
|
+
const keyedArrayPositionIdentifier = programPath.scope.generateUidIdentifier(
|
|
5561
|
+
"createCompilerKeyedArrayPositionUpdate"
|
|
5562
|
+
);
|
|
5563
|
+
const keyedArrayReorderIdentifier = programPath.scope.generateUidIdentifier(
|
|
5564
|
+
"createCompilerKeyedArrayReorder"
|
|
5565
|
+
);
|
|
5566
|
+
const keyedArrayRollingWindowIdentifier = programPath.scope.generateUidIdentifier(
|
|
5567
|
+
"createCompilerKeyedArrayRollingWindow"
|
|
5568
|
+
);
|
|
5569
|
+
const keyedArraySliceIdentifier = programPath.scope.generateUidIdentifier(
|
|
5570
|
+
"createCompilerKeyedArraySlice"
|
|
5571
|
+
);
|
|
5572
|
+
const keyedCollectionUpdateIdentifier = programPath.scope.generateUidIdentifier(
|
|
5573
|
+
"createCompilerKeyedCollectionUpdate"
|
|
5574
|
+
);
|
|
5575
|
+
const keyedCollectionMutationIdentifier = programPath.scope.generateUidIdentifier(
|
|
5576
|
+
"applyCompilerKeyedCollectionMutation"
|
|
5577
|
+
);
|
|
5578
|
+
const runtimeFeatureIdentifiers = new Map(
|
|
5579
|
+
Object.entries(COMPILER_RUNTIME_FEATURE_EXPORTS).map(([feature, exportName]) => [
|
|
5580
|
+
feature,
|
|
5581
|
+
programPath.scope.generateUidIdentifier(exportName)
|
|
5582
|
+
])
|
|
5583
|
+
);
|
|
5584
|
+
const usedRuntimeFeatures = /* @__PURE__ */ new Set();
|
|
3785
5585
|
for (const candidate of candidates) {
|
|
3786
5586
|
const functionDirectives = new Set(
|
|
3787
5587
|
core.types.isBlockStatement(candidate.path.node.body) ? directiveValues(candidate.path.node.body) : []
|
|
@@ -3792,6 +5592,19 @@ async function compileReactModule(code, id, options) {
|
|
|
3792
5592
|
const reason = compileCandidate(
|
|
3793
5593
|
candidate,
|
|
3794
5594
|
createComponentIdentifier,
|
|
5595
|
+
keyedMapUpdateIdentifier,
|
|
5596
|
+
keyedArrayAppendIdentifier,
|
|
5597
|
+
keyedArrayFilterIdentifier,
|
|
5598
|
+
keyedArrayPrependIdentifier,
|
|
5599
|
+
keyedArrayPositionIdentifier,
|
|
5600
|
+
keyedArrayReorderIdentifier,
|
|
5601
|
+
keyedArrayRollingWindowIdentifier,
|
|
5602
|
+
keyedArraySliceIdentifier,
|
|
5603
|
+
keyedCollectionUpdateIdentifier,
|
|
5604
|
+
keyedCollectionMutationIdentifier,
|
|
5605
|
+
runtimeFeatureIdentifiers,
|
|
5606
|
+
usedRuntimeFeatures,
|
|
5607
|
+
optimizationCounts,
|
|
3795
5608
|
useStateNames,
|
|
3796
5609
|
reactNames,
|
|
3797
5610
|
listNames,
|
|
@@ -3815,7 +5628,71 @@ async function compileReactModule(code, id, options) {
|
|
|
3815
5628
|
[
|
|
3816
5629
|
core.types.importSpecifier(
|
|
3817
5630
|
createComponentIdentifier,
|
|
3818
|
-
core.types.identifier("
|
|
5631
|
+
core.types.identifier("createCompiledComponentWithFeatures")
|
|
5632
|
+
),
|
|
5633
|
+
...optimizationCounts.keyedMapUpdateHints > 0 ? [
|
|
5634
|
+
core.types.importSpecifier(
|
|
5635
|
+
keyedMapUpdateIdentifier,
|
|
5636
|
+
core.types.identifier("createCompilerKeyedMapUpdate")
|
|
5637
|
+
)
|
|
5638
|
+
] : [],
|
|
5639
|
+
...optimizationCounts.keyedArrayAppendHints > 0 ? [
|
|
5640
|
+
core.types.importSpecifier(
|
|
5641
|
+
keyedArrayAppendIdentifier,
|
|
5642
|
+
core.types.identifier("createCompilerKeyedArrayAppend")
|
|
5643
|
+
)
|
|
5644
|
+
] : [],
|
|
5645
|
+
...optimizationCounts.keyedArrayFilterHints > 0 ? [
|
|
5646
|
+
core.types.importSpecifier(
|
|
5647
|
+
keyedArrayFilterIdentifier,
|
|
5648
|
+
core.types.identifier("createCompilerKeyedArrayFilter")
|
|
5649
|
+
)
|
|
5650
|
+
] : [],
|
|
5651
|
+
...optimizationCounts.keyedArrayPrependHints > 0 ? [
|
|
5652
|
+
core.types.importSpecifier(
|
|
5653
|
+
keyedArrayPrependIdentifier,
|
|
5654
|
+
core.types.identifier("createCompilerKeyedArrayPrepend")
|
|
5655
|
+
)
|
|
5656
|
+
] : [],
|
|
5657
|
+
...optimizationCounts.keyedArrayPositionHints > 0 ? [
|
|
5658
|
+
core.types.importSpecifier(
|
|
5659
|
+
keyedArrayPositionIdentifier,
|
|
5660
|
+
core.types.identifier("createCompilerKeyedArrayPositionUpdate")
|
|
5661
|
+
)
|
|
5662
|
+
] : [],
|
|
5663
|
+
...optimizationCounts.keyedArrayReorderHints > 0 ? [
|
|
5664
|
+
core.types.importSpecifier(
|
|
5665
|
+
keyedArrayReorderIdentifier,
|
|
5666
|
+
core.types.identifier("createCompilerKeyedArrayReorder")
|
|
5667
|
+
)
|
|
5668
|
+
] : [],
|
|
5669
|
+
...optimizationCounts.keyedArrayRollingWindowHints > 0 ? [
|
|
5670
|
+
core.types.importSpecifier(
|
|
5671
|
+
keyedArrayRollingWindowIdentifier,
|
|
5672
|
+
core.types.identifier("createCompilerKeyedArrayRollingWindow")
|
|
5673
|
+
)
|
|
5674
|
+
] : [],
|
|
5675
|
+
...optimizationCounts.keyedArraySliceHints > 0 || optimizationCounts.keyedArrayRollingWindowHints > 0 ? [
|
|
5676
|
+
core.types.importSpecifier(
|
|
5677
|
+
keyedArraySliceIdentifier,
|
|
5678
|
+
core.types.identifier("createCompilerKeyedArraySlice")
|
|
5679
|
+
)
|
|
5680
|
+
] : [],
|
|
5681
|
+
...optimizationCounts.keyedCollectionUpdateHints > 0 ? [
|
|
5682
|
+
core.types.importSpecifier(
|
|
5683
|
+
keyedCollectionUpdateIdentifier,
|
|
5684
|
+
core.types.identifier("createCompilerKeyedCollectionUpdate")
|
|
5685
|
+
),
|
|
5686
|
+
core.types.importSpecifier(
|
|
5687
|
+
keyedCollectionMutationIdentifier,
|
|
5688
|
+
core.types.identifier("applyCompilerKeyedCollectionMutation")
|
|
5689
|
+
)
|
|
5690
|
+
] : [],
|
|
5691
|
+
...[...usedRuntimeFeatures].sort().map(
|
|
5692
|
+
(feature) => core.types.importSpecifier(
|
|
5693
|
+
core.types.cloneNode(runtimeFeatureIdentifiers.get(feature)),
|
|
5694
|
+
core.types.identifier(COMPILER_RUNTIME_FEATURE_EXPORTS[feature])
|
|
5695
|
+
)
|
|
3819
5696
|
)
|
|
3820
5697
|
],
|
|
3821
5698
|
core.types.stringLiteral("@farm.js/react/compiler-runtime")
|
|
@@ -3847,7 +5724,8 @@ async function compileReactModule(code, id, options) {
|
|
|
3847
5724
|
code: result?.code || code,
|
|
3848
5725
|
map: result?.map || null,
|
|
3849
5726
|
compiled,
|
|
3850
|
-
diagnostics
|
|
5727
|
+
diagnostics,
|
|
5728
|
+
optimizations: optimizationCounts
|
|
3851
5729
|
};
|
|
3852
5730
|
}
|
|
3853
5731
|
function projectRelativeId(projectRoot, id) {
|
|
@@ -3858,10 +5736,34 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3858
5736
|
let componentsConsidered = 0;
|
|
3859
5737
|
let compiled = 0;
|
|
3860
5738
|
let fallback = 0;
|
|
5739
|
+
let keyedArrayAppendHints = 0;
|
|
5740
|
+
let keyedArrayFilterHints = 0;
|
|
5741
|
+
let keyedArrayPrependHints = 0;
|
|
5742
|
+
let keyedArrayPositionHints = 0;
|
|
5743
|
+
let keyedArrayReorderHints = 0;
|
|
5744
|
+
let keyedArrayRollingWindowHints = 0;
|
|
5745
|
+
let keyedArraySliceHints = 0;
|
|
5746
|
+
let keyedCollectionUpdateHints = 0;
|
|
5747
|
+
let keyedIdentityTargets = 0;
|
|
5748
|
+
let keyedMapLookupTargets = 0;
|
|
5749
|
+
let keyedMembershipTargets = 0;
|
|
5750
|
+
let keyedMapUpdateHints = 0;
|
|
3861
5751
|
const modules = [...observations].map(({ id, result }) => {
|
|
3862
5752
|
componentsConsidered += result.compiled.length + result.diagnostics.length;
|
|
3863
5753
|
compiled += result.compiled.length;
|
|
3864
5754
|
fallback += result.diagnostics.length;
|
|
5755
|
+
keyedArrayAppendHints += result.optimizations.keyedArrayAppendHints || 0;
|
|
5756
|
+
keyedArrayFilterHints += result.optimizations.keyedArrayFilterHints || 0;
|
|
5757
|
+
keyedArrayPrependHints += result.optimizations.keyedArrayPrependHints || 0;
|
|
5758
|
+
keyedArrayPositionHints += result.optimizations.keyedArrayPositionHints || 0;
|
|
5759
|
+
keyedArrayReorderHints += result.optimizations.keyedArrayReorderHints || 0;
|
|
5760
|
+
keyedArrayRollingWindowHints += result.optimizations.keyedArrayRollingWindowHints || 0;
|
|
5761
|
+
keyedArraySliceHints += result.optimizations.keyedArraySliceHints || 0;
|
|
5762
|
+
keyedCollectionUpdateHints += result.optimizations.keyedCollectionUpdateHints || 0;
|
|
5763
|
+
keyedIdentityTargets += result.optimizations.keyedIdentityTargets || 0;
|
|
5764
|
+
keyedMapLookupTargets += result.optimizations.keyedMapLookupTargets || 0;
|
|
5765
|
+
keyedMembershipTargets += result.optimizations.keyedMembershipTargets || 0;
|
|
5766
|
+
keyedMapUpdateHints += result.optimizations.keyedMapUpdateHints;
|
|
3865
5767
|
const moduleId = projectRelativeId(projectRoot, id);
|
|
3866
5768
|
const fallbacks = result.diagnostics.map((diagnostic) => {
|
|
3867
5769
|
reasonCounts.set(diagnostic.reason, (reasonCounts.get(diagnostic.reason) || 0) + 1);
|
|
@@ -3870,6 +5772,7 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3870
5772
|
return {
|
|
3871
5773
|
id: moduleId,
|
|
3872
5774
|
compiled: [...result.compiled].sort(),
|
|
5775
|
+
optimizations: result.optimizations,
|
|
3873
5776
|
fallbacks
|
|
3874
5777
|
};
|
|
3875
5778
|
}).sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -3880,7 +5783,19 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3880
5783
|
modules: modules.length,
|
|
3881
5784
|
componentsConsidered,
|
|
3882
5785
|
compiled,
|
|
3883
|
-
fallback
|
|
5786
|
+
fallback,
|
|
5787
|
+
keyedArrayAppendHints,
|
|
5788
|
+
keyedArrayFilterHints,
|
|
5789
|
+
keyedArrayPrependHints,
|
|
5790
|
+
keyedArrayPositionHints,
|
|
5791
|
+
keyedArrayReorderHints,
|
|
5792
|
+
keyedArrayRollingWindowHints,
|
|
5793
|
+
keyedArraySliceHints,
|
|
5794
|
+
keyedCollectionUpdateHints,
|
|
5795
|
+
keyedIdentityTargets,
|
|
5796
|
+
keyedMapLookupTargets,
|
|
5797
|
+
keyedMembershipTargets,
|
|
5798
|
+
keyedMapUpdateHints
|
|
3884
5799
|
},
|
|
3885
5800
|
fallbackReasons,
|
|
3886
5801
|
modules
|