@farm.js/react 0.1.0-beta.5 → 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 +200 -1
- package/dist/compiler-runtime.cjs +1751 -19
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +82 -1
- package/dist/compiler-runtime.d.ts +82 -1
- package/dist/compiler-runtime.mjs +1710 -20
- package/dist/compiler-runtime.mjs.map +1 -1
- package/dist/vite.cjs +1908 -47
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1908 -47
- package/dist/vite.mjs.map +1 -1
- package/package.json +4 -4
package/dist/vite.cjs
CHANGED
|
@@ -68,14 +68,46 @@ var COMPILER_RUNTIME_FEATURE_EXPORTS = {
|
|
|
68
68
|
"conditional-ranges": "conditionalRangesRuntimeFeature",
|
|
69
69
|
"keyed-list": "keyedListRuntimeFeature",
|
|
70
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",
|
|
71
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",
|
|
72
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",
|
|
73
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",
|
|
74
106
|
"keyed-ranges": "keyedRangesRuntimeFeature",
|
|
75
107
|
"mixed-ranges": "mixedRangesRuntimeFeature",
|
|
76
108
|
component: "componentRuntimeFeature"
|
|
77
109
|
};
|
|
78
|
-
function runtimeFeaturesForPlans(plans) {
|
|
110
|
+
function runtimeFeaturesForPlans(plans, keyedMapUpdateHints, keyedArrayFilterHints, keyedArrayPrependHints, keyedArrayPositionHints, keyedArrayReorderHints, keyedArrayRollingWindowHints) {
|
|
79
111
|
const features = /* @__PURE__ */ new Set();
|
|
80
112
|
let keyedRowsHaveConditionals = false;
|
|
81
113
|
let keyedRowsHaveHostBlocks = false;
|
|
@@ -90,9 +122,10 @@ function runtimeFeaturesForPlans(plans) {
|
|
|
90
122
|
}
|
|
91
123
|
}
|
|
92
124
|
if (plans.some((plan) => plan.kind === "keyed-rows")) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
);
|
|
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}`);
|
|
96
129
|
}
|
|
97
130
|
return [...features].sort();
|
|
98
131
|
}
|
|
@@ -141,6 +174,174 @@ function referencesIdentifier(expression, name) {
|
|
|
141
174
|
});
|
|
142
175
|
return referenced;
|
|
143
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
|
+
}
|
|
144
345
|
function collectReferencedLocals(expression, names) {
|
|
145
346
|
const references = /* @__PURE__ */ new Set();
|
|
146
347
|
core.traverse(expressionFile(cloneExpression(expression)), {
|
|
@@ -241,7 +442,9 @@ function rewriteHandlerAccess(root, handlersByName) {
|
|
|
241
442
|
path.skip();
|
|
242
443
|
}
|
|
243
444
|
});
|
|
244
|
-
return reason ? { reason } : {
|
|
445
|
+
return reason ? { reason } : {
|
|
446
|
+
root: file.program.body[0].expression
|
|
447
|
+
};
|
|
245
448
|
}
|
|
246
449
|
function isSafeCompilerCall(expression, safeGlobals) {
|
|
247
450
|
if (core.types.isIdentifier(expression.callee)) {
|
|
@@ -249,7 +452,7 @@ function isSafeCompilerCall(expression, safeGlobals) {
|
|
|
249
452
|
}
|
|
250
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);
|
|
251
454
|
}
|
|
252
|
-
function validateDerivedExpression(expression, safeGlobals) {
|
|
455
|
+
function validateDerivedExpression(expression, safeGlobals, additionalSafeCall) {
|
|
253
456
|
let unsupported;
|
|
254
457
|
const reject = (reason, path) => {
|
|
255
458
|
unsupported = reason;
|
|
@@ -260,7 +463,9 @@ function validateDerivedExpression(expression, safeGlobals) {
|
|
|
260
463
|
AssignmentExpression: (path) => reject("assignments", path),
|
|
261
464
|
AwaitExpression: (path) => reject("await expressions", path),
|
|
262
465
|
CallExpression(path) {
|
|
263
|
-
if (!isSafeCompilerCall(path.node, safeGlobals)
|
|
466
|
+
if (!isSafeCompilerCall(path.node, safeGlobals) && !additionalSafeCall?.(path.node)) {
|
|
467
|
+
reject("function calls", path);
|
|
468
|
+
}
|
|
264
469
|
},
|
|
265
470
|
ClassExpression: (path) => reject("class expressions", path),
|
|
266
471
|
Function: (path) => reject("function expressions", path),
|
|
@@ -300,6 +505,879 @@ function validateSetterUsage(root, statesBySetter) {
|
|
|
300
505
|
});
|
|
301
506
|
return reason;
|
|
302
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
|
+
}
|
|
303
1381
|
function rewriteStateAccess(expression, stateParameter, statesByValue, statesBySetter) {
|
|
304
1382
|
const file = expressionFile(cloneExpression(expression));
|
|
305
1383
|
core.traverse(file, {
|
|
@@ -550,21 +1628,28 @@ function analyzeMapList(expression, statesByValue, safeGlobals) {
|
|
|
550
1628
|
const collection = callee.object;
|
|
551
1629
|
const collectionUnsupported = validateCollectionPipeline(collection, safeGlobals);
|
|
552
1630
|
if (collectionUnsupported) {
|
|
553
|
-
return {
|
|
1631
|
+
return {
|
|
1632
|
+
reason: `keyed list collection cannot use ${collectionUnsupported}`
|
|
1633
|
+
};
|
|
554
1634
|
}
|
|
555
1635
|
if (expression.arguments.length !== 1 || !core.types.isArrowFunctionExpression(expression.arguments[0]) && !core.types.isFunctionExpression(expression.arguments[0])) {
|
|
556
1636
|
return { reason: "keyed list map must use one inline render callback" };
|
|
557
1637
|
}
|
|
558
1638
|
const callback = expression.arguments[0];
|
|
559
1639
|
if (containsDirectHookCall(callback)) {
|
|
560
|
-
return {
|
|
1640
|
+
return {
|
|
1641
|
+
reason: "Hooks cannot be called directly inside a keyed list callback"
|
|
1642
|
+
};
|
|
561
1643
|
}
|
|
562
1644
|
const row = returnedExpression(callback);
|
|
563
1645
|
if (!row || !core.types.isJSXElement(row)) {
|
|
564
1646
|
return { reason: "keyed list map callbacks must return one React element" };
|
|
565
1647
|
}
|
|
566
1648
|
const key = jsxKeyExpression(row);
|
|
567
|
-
if (!key)
|
|
1649
|
+
if (!key)
|
|
1650
|
+
return {
|
|
1651
|
+
reason: "automatically compiled lists require an explicit item key"
|
|
1652
|
+
};
|
|
568
1653
|
const keyReason = validateKeyFunction(callback, key, safeGlobals);
|
|
569
1654
|
if (keyReason) return { reason: keyReason };
|
|
570
1655
|
return { dependencies: collectStateDependencies(expression, statesByValue) };
|
|
@@ -579,7 +1664,9 @@ function listAttributeExpression(element, name) {
|
|
|
579
1664
|
}
|
|
580
1665
|
function analyzePublicList(element, statesByValue, safeGlobals) {
|
|
581
1666
|
if (element.openingElement.attributes.some((attribute) => core.types.isJSXSpreadAttribute(attribute))) {
|
|
582
|
-
return {
|
|
1667
|
+
return {
|
|
1668
|
+
reason: "compiled List boundaries do not support JSX attribute spreads"
|
|
1669
|
+
};
|
|
583
1670
|
}
|
|
584
1671
|
const each = listAttributeExpression(element, "each");
|
|
585
1672
|
const by = listAttributeExpression(element, "by");
|
|
@@ -597,7 +1684,9 @@ function analyzePublicList(element, statesByValue, safeGlobals) {
|
|
|
597
1684
|
if (keyReason) return { reason: keyReason };
|
|
598
1685
|
const children = meaningfulJsxChildren(element);
|
|
599
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)) {
|
|
600
|
-
return {
|
|
1687
|
+
return {
|
|
1688
|
+
reason: "compiled List children must use one inline render function"
|
|
1689
|
+
};
|
|
601
1690
|
}
|
|
602
1691
|
const render = children[0].expression;
|
|
603
1692
|
if (!returnedExpression(render)) {
|
|
@@ -711,13 +1800,20 @@ function stabilizeDeferredEventCurrentTargets(root, compilerSetters) {
|
|
|
711
1800
|
const expression = file.program.body[0].expression;
|
|
712
1801
|
return core.types.isJSXElement(expression) ? expression : core.types.cloneNode(root, true);
|
|
713
1802
|
}
|
|
714
|
-
function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters) {
|
|
1803
|
+
function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters, keyedTargetReactiveByValue) {
|
|
715
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])) {
|
|
716
|
-
return {
|
|
1805
|
+
return {
|
|
1806
|
+
reason: "compiled keyed rows require item and optional index identifiers"
|
|
1807
|
+
};
|
|
717
1808
|
}
|
|
718
1809
|
const bindings = [];
|
|
719
1810
|
const events = [];
|
|
720
1811
|
const conditionals = [];
|
|
1812
|
+
const validateBindingExpression = (expression) => validateDerivedExpression(
|
|
1813
|
+
expression,
|
|
1814
|
+
safeGlobals,
|
|
1815
|
+
keyedTargetReactiveByValue ? (call) => isPotentialKeyedMembershipCall(call, keyedTargetReactiveByValue) || isPotentialKeyedMapLookupCall(call, keyedTargetReactiveByValue) : void 0
|
|
1816
|
+
);
|
|
721
1817
|
const visit = (element, path) => {
|
|
722
1818
|
const tag = element.openingElement.name;
|
|
723
1819
|
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
@@ -796,7 +1892,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
796
1892
|
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
797
1893
|
return "compiled keyed row style names must use camelCase or a CSS custom property";
|
|
798
1894
|
}
|
|
799
|
-
const unsupported2 =
|
|
1895
|
+
const unsupported2 = validateBindingExpression(property.value);
|
|
800
1896
|
if (unsupported2) {
|
|
801
1897
|
return `compiled keyed row style ${propertyName} cannot use ${unsupported2}`;
|
|
802
1898
|
}
|
|
@@ -810,7 +1906,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
810
1906
|
continue;
|
|
811
1907
|
}
|
|
812
1908
|
if (name === "children") return "compiled keyed row children props are not supported yet";
|
|
813
|
-
const unsupported =
|
|
1909
|
+
const unsupported = validateBindingExpression(expression);
|
|
814
1910
|
if (unsupported) return `compiled keyed row ${name} cannot use ${unsupported}`;
|
|
815
1911
|
bindings.push({
|
|
816
1912
|
kind: "attribute",
|
|
@@ -860,7 +1956,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
860
1956
|
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
861
1957
|
);
|
|
862
1958
|
for (const child of expressions) {
|
|
863
|
-
const unsupported =
|
|
1959
|
+
const unsupported = validateBindingExpression(child.expression);
|
|
864
1960
|
if (unsupported) return `compiled keyed row text cannot use ${unsupported}`;
|
|
865
1961
|
}
|
|
866
1962
|
if (nestedElements.length > 0 && expressions.length > 0) {
|
|
@@ -876,7 +1972,11 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
876
1972
|
parts.push(cloneExpression(child.expression));
|
|
877
1973
|
}
|
|
878
1974
|
}
|
|
879
|
-
bindings.push({
|
|
1975
|
+
bindings.push({
|
|
1976
|
+
kind: "text",
|
|
1977
|
+
path: [...path],
|
|
1978
|
+
value: core.types.arrayExpression(parts)
|
|
1979
|
+
});
|
|
880
1980
|
}
|
|
881
1981
|
let elementIndex = 0;
|
|
882
1982
|
for (const child of element.children) {
|
|
@@ -890,7 +1990,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
890
1990
|
const reason = visit(row, []);
|
|
891
1991
|
return reason ? { reason } : { bindings, events, conditionals };
|
|
892
1992
|
}
|
|
893
|
-
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false) {
|
|
1993
|
+
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false, allowMembershipTargets = false) {
|
|
894
1994
|
let collection;
|
|
895
1995
|
let keyCallback;
|
|
896
1996
|
let renderCallback;
|
|
@@ -943,7 +2043,8 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acce
|
|
|
943
2043
|
row,
|
|
944
2044
|
renderCallback,
|
|
945
2045
|
safeGlobals,
|
|
946
|
-
new Set([...statesByValue.values()].map((state) => state.setterName))
|
|
2046
|
+
new Set([...statesByValue.values()].map((state) => state.setterName)),
|
|
2047
|
+
allowMembershipTargets ? statesByValue : void 0
|
|
947
2048
|
);
|
|
948
2049
|
if (rowAnalysis.reason && !acceptUnsupportedRow) return void 0;
|
|
949
2050
|
const keyExpression = returnedExpression(keyCallback);
|
|
@@ -956,6 +2057,7 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acce
|
|
|
956
2057
|
return {
|
|
957
2058
|
source,
|
|
958
2059
|
collection,
|
|
2060
|
+
collectionDependency: core.types.isIdentifier(collection) ? statesByValue.get(collection.name)?.index : void 0,
|
|
959
2061
|
structureDependencies: [...structureDependencies].sort((left, right) => left - right),
|
|
960
2062
|
keyCallback,
|
|
961
2063
|
renderCallback,
|
|
@@ -984,7 +2086,74 @@ function analyzeKeyedRowsContainer(container, statesByValue, safeGlobals, listNa
|
|
|
984
2086
|
}
|
|
985
2087
|
const children = meaningfulJsxChildren(container);
|
|
986
2088
|
if (children.length !== 1) return void 0;
|
|
987
|
-
|
|
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
|
+
};
|
|
988
2157
|
}
|
|
989
2158
|
function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, listNames, allowSingleRange = false) {
|
|
990
2159
|
if (container.openingElement.attributes.some(
|
|
@@ -1140,7 +2309,11 @@ function analyzeHostConditionalTree(branch, safeGlobals, allowStaticEvents = fal
|
|
|
1140
2309
|
parts.push(cloneExpression(child.expression));
|
|
1141
2310
|
}
|
|
1142
2311
|
}
|
|
1143
|
-
bindings.push({
|
|
2312
|
+
bindings.push({
|
|
2313
|
+
kind: "text",
|
|
2314
|
+
path: [...path],
|
|
2315
|
+
value: core.types.arrayExpression(parts)
|
|
2316
|
+
});
|
|
1144
2317
|
}
|
|
1145
2318
|
let elementIndex = 0;
|
|
1146
2319
|
for (const child of element.children) {
|
|
@@ -1312,7 +2485,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1312
2485
|
listNames,
|
|
1313
2486
|
id,
|
|
1314
2487
|
allocateId
|
|
1315
|
-
) : {
|
|
2488
|
+
) : {
|
|
2489
|
+
bindings: [],
|
|
2490
|
+
plans: [],
|
|
2491
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2492
|
+
};
|
|
1316
2493
|
const falsy = shape.falsy ? analyzeRecursiveHostTree(
|
|
1317
2494
|
shape.falsy,
|
|
1318
2495
|
statesByValue,
|
|
@@ -1320,7 +2497,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1320
2497
|
listNames,
|
|
1321
2498
|
id,
|
|
1322
2499
|
allocateId
|
|
1323
|
-
) : {
|
|
2500
|
+
) : {
|
|
2501
|
+
bindings: [],
|
|
2502
|
+
plans: [],
|
|
2503
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2504
|
+
};
|
|
1324
2505
|
if (truthy.reason) return truthy.reason;
|
|
1325
2506
|
if (falsy.reason) return falsy.reason;
|
|
1326
2507
|
plans.push(...truthy.plans, ...falsy.plans);
|
|
@@ -1478,7 +2659,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1478
2659
|
parts.push(cloneExpression(child.expression));
|
|
1479
2660
|
}
|
|
1480
2661
|
}
|
|
1481
|
-
bindings.push({
|
|
2662
|
+
bindings.push({
|
|
2663
|
+
kind: "text",
|
|
2664
|
+
path: [...path],
|
|
2665
|
+
value: core.types.arrayExpression(parts)
|
|
2666
|
+
});
|
|
1482
2667
|
}
|
|
1483
2668
|
let elementIndex = 0;
|
|
1484
2669
|
for (const child of element.children) {
|
|
@@ -1545,7 +2730,11 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals,
|
|
|
1545
2730
|
listNames,
|
|
1546
2731
|
parent,
|
|
1547
2732
|
allocateId
|
|
1548
|
-
) : {
|
|
2733
|
+
) : {
|
|
2734
|
+
bindings: [],
|
|
2735
|
+
plans: [],
|
|
2736
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2737
|
+
};
|
|
1549
2738
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1550
2739
|
shape.falsy,
|
|
1551
2740
|
statesByValue,
|
|
@@ -1553,7 +2742,11 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals,
|
|
|
1553
2742
|
listNames,
|
|
1554
2743
|
parent,
|
|
1555
2744
|
allocateId
|
|
1556
|
-
) : {
|
|
2745
|
+
) : {
|
|
2746
|
+
bindings: [],
|
|
2747
|
+
plans: [],
|
|
2748
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2749
|
+
};
|
|
1557
2750
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1558
2751
|
const dependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1559
2752
|
for (const binding of [...truthyAnalysis.bindings || [], ...falsyAnalysis.bindings || []]) {
|
|
@@ -1599,7 +2792,11 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1599
2792
|
listNames,
|
|
1600
2793
|
parent,
|
|
1601
2794
|
allocateId
|
|
1602
|
-
) : {
|
|
2795
|
+
) : {
|
|
2796
|
+
bindings: [],
|
|
2797
|
+
plans: [],
|
|
2798
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2799
|
+
};
|
|
1603
2800
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1604
2801
|
shape.falsy,
|
|
1605
2802
|
statesByValue,
|
|
@@ -1607,7 +2804,11 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1607
2804
|
listNames,
|
|
1608
2805
|
parent,
|
|
1609
2806
|
allocateId
|
|
1610
|
-
) : {
|
|
2807
|
+
) : {
|
|
2808
|
+
bindings: [],
|
|
2809
|
+
plans: [],
|
|
2810
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2811
|
+
};
|
|
1611
2812
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1612
2813
|
nestedPlans.push(...truthyAnalysis.plans, ...falsyAnalysis.plans);
|
|
1613
2814
|
for (const [element, plan] of truthyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
@@ -1700,7 +2901,11 @@ function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
1700
2901
|
listNames,
|
|
1701
2902
|
parent,
|
|
1702
2903
|
allocateId
|
|
1703
|
-
) : {
|
|
2904
|
+
) : {
|
|
2905
|
+
bindings: [],
|
|
2906
|
+
plans: [],
|
|
2907
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2908
|
+
};
|
|
1704
2909
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1705
2910
|
shape.falsy,
|
|
1706
2911
|
statesByValue,
|
|
@@ -1708,7 +2913,11 @@ function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
1708
2913
|
listNames,
|
|
1709
2914
|
parent,
|
|
1710
2915
|
allocateId
|
|
1711
|
-
) : {
|
|
2916
|
+
) : {
|
|
2917
|
+
bindings: [],
|
|
2918
|
+
plans: [],
|
|
2919
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2920
|
+
};
|
|
1712
2921
|
if (!mergeAnalysis(truthyAnalysis) || !mergeAnalysis(falsyAnalysis)) return void 0;
|
|
1713
2922
|
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1714
2923
|
dependencies.add(dependency);
|
|
@@ -1949,6 +3158,57 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1949
3158
|
if (binding.name) {
|
|
1950
3159
|
properties.push(core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(binding.name)));
|
|
1951
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
|
+
}
|
|
1952
3212
|
properties.push(
|
|
1953
3213
|
core.types.objectProperty(
|
|
1954
3214
|
core.types.identifier("read"),
|
|
@@ -2143,7 +3403,7 @@ function keyedRowConditionalObject(conditional, parameters) {
|
|
|
2143
3403
|
}
|
|
2144
3404
|
return core.types.objectExpression(properties);
|
|
2145
3405
|
}
|
|
2146
|
-
function keyedRowsBoundary(blockRuntime, plan) {
|
|
3406
|
+
function keyedRowsBoundary(blockRuntime, plan, keyedMapUpdateHints, keyedArrayFilterHintedStateIndices, keyedArrayPrependHintedStateIndices, keyedArrayPositionHintedStateIndices, keyedArrayReorderHintedStateIndices) {
|
|
2147
3407
|
const name = core.types.jsxMemberExpression(
|
|
2148
3408
|
core.types.jsxIdentifier(blockRuntime.name),
|
|
2149
3409
|
core.types.jsxIdentifier("KeyedRows")
|
|
@@ -2177,6 +3437,16 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
2177
3437
|
core.types.jsxIdentifier("items"),
|
|
2178
3438
|
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], cloneExpression(plan.collection)))
|
|
2179
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
|
+
] : [],
|
|
2180
3450
|
core.types.jsxAttribute(
|
|
2181
3451
|
core.types.jsxIdentifier("structureDependencies"),
|
|
2182
3452
|
core.types.jsxExpressionContainer(
|
|
@@ -2185,6 +3455,36 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
2185
3455
|
)
|
|
2186
3456
|
)
|
|
2187
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
|
+
] : [],
|
|
2188
3488
|
core.types.jsxAttribute(
|
|
2189
3489
|
core.types.jsxIdentifier("rowKey"),
|
|
2190
3490
|
core.types.jsxExpressionContainer(core.types.cloneNode(plan.keyCallback, true))
|
|
@@ -2511,7 +3811,9 @@ function conditionalRangesBoundary(blockRuntime, plan) {
|
|
|
2511
3811
|
function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allowedComponentNames) {
|
|
2512
3812
|
const name = element.openingElement.name;
|
|
2513
3813
|
if (!core.types.isJSXIdentifier(name) || !isComponentName(name.name)) {
|
|
2514
|
-
return {
|
|
3814
|
+
return {
|
|
3815
|
+
reason: "component islands require a direct component identifier"
|
|
3816
|
+
};
|
|
2515
3817
|
}
|
|
2516
3818
|
if (!allowedComponentNames.has(name.name)) {
|
|
2517
3819
|
return {
|
|
@@ -2519,19 +3821,27 @@ function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allo
|
|
|
2519
3821
|
};
|
|
2520
3822
|
}
|
|
2521
3823
|
if (meaningfulJsxChildren(element).length > 0) {
|
|
2522
|
-
return {
|
|
3824
|
+
return {
|
|
3825
|
+
reason: `component island ${name.name} does not support children yet`
|
|
3826
|
+
};
|
|
2523
3827
|
}
|
|
2524
3828
|
const dependencies = /* @__PURE__ */ new Set();
|
|
2525
3829
|
for (const attribute of element.openingElement.attributes) {
|
|
2526
3830
|
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
2527
|
-
return {
|
|
3831
|
+
return {
|
|
3832
|
+
reason: `component island ${name.name} does not support JSX attribute spreads`
|
|
3833
|
+
};
|
|
2528
3834
|
}
|
|
2529
3835
|
const attributeName = jsxAttributeName(attribute);
|
|
2530
3836
|
if (!attributeName) {
|
|
2531
|
-
return {
|
|
3837
|
+
return {
|
|
3838
|
+
reason: `component island ${name.name} does not support namespaced JSX attributes`
|
|
3839
|
+
};
|
|
2532
3840
|
}
|
|
2533
3841
|
if (attributeName === "ref" || attributeName === "key" || attributeName === "children") {
|
|
2534
|
-
return {
|
|
3842
|
+
return {
|
|
3843
|
+
reason: `component island ${name.name} does not support ${attributeName} yet`
|
|
3844
|
+
};
|
|
2535
3845
|
}
|
|
2536
3846
|
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
2537
3847
|
continue;
|
|
@@ -2550,7 +3860,9 @@ function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allo
|
|
|
2550
3860
|
(dependency) => dependencies.add(dependency)
|
|
2551
3861
|
);
|
|
2552
3862
|
}
|
|
2553
|
-
return {
|
|
3863
|
+
return {
|
|
3864
|
+
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
3865
|
+
};
|
|
2554
3866
|
}
|
|
2555
3867
|
function componentIslandBoundary(blockRuntime, plan, source) {
|
|
2556
3868
|
const name = core.types.jsxMemberExpression(
|
|
@@ -2807,6 +4119,7 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
2807
4119
|
dependencies: keyedRows.dependencies,
|
|
2808
4120
|
source: child,
|
|
2809
4121
|
collection: keyedRows.collection,
|
|
4122
|
+
collectionDependency: keyedRows.collectionDependency,
|
|
2810
4123
|
structureDependencies: keyedRows.structureDependencies,
|
|
2811
4124
|
keyCallback: keyedRows.keyCallback,
|
|
2812
4125
|
renderCallback: keyedRows.renderCallback,
|
|
@@ -3048,7 +4361,7 @@ function conditionalBlockBoundary(blockRuntime, plan, source) {
|
|
|
3048
4361
|
true
|
|
3049
4362
|
);
|
|
3050
4363
|
}
|
|
3051
|
-
function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
4364
|
+
function lowerComposableBlocks(root, plans, blockRuntime, listNames, keyedMapUpdateHints, keyedArrayFilterHintedStateIndices, keyedArrayPrependHintedStateIndices, keyedArrayPositionHintedStateIndices, keyedArrayReorderHintedStateIndices) {
|
|
3052
4365
|
const planBySource = new Map(
|
|
3053
4366
|
plans.map((plan) => [plan.source, plan])
|
|
3054
4367
|
);
|
|
@@ -3073,7 +4386,15 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
3073
4386
|
return mixedRangesBoundary(blockRuntime, plan2);
|
|
3074
4387
|
}
|
|
3075
4388
|
if (plan2?.kind === "keyed-rows") {
|
|
3076
|
-
return keyedRowsBoundary(
|
|
4389
|
+
return keyedRowsBoundary(
|
|
4390
|
+
blockRuntime,
|
|
4391
|
+
plan2,
|
|
4392
|
+
keyedMapUpdateHints,
|
|
4393
|
+
keyedArrayFilterHintedStateIndices,
|
|
4394
|
+
keyedArrayPrependHintedStateIndices,
|
|
4395
|
+
keyedArrayPositionHintedStateIndices,
|
|
4396
|
+
keyedArrayReorderHintedStateIndices
|
|
4397
|
+
);
|
|
3077
4398
|
}
|
|
3078
4399
|
if (plan2?.kind === "keyed-ranges") {
|
|
3079
4400
|
return keyedRangesBoundary(blockRuntime, plan2);
|
|
@@ -3436,7 +4757,7 @@ function wrapperElement(definitionIdentifier, props) {
|
|
|
3436
4757
|
const attributes = props ? [core.types.jsxSpreadAttribute(core.types.cloneNode(props))] : [];
|
|
3437
4758
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
3438
4759
|
}
|
|
3439
|
-
function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureIdentifiers, usedRuntimeFeatures, 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) {
|
|
3440
4761
|
const { path, name, statementPath } = candidate;
|
|
3441
4762
|
if (path.node.async || path.node.generator)
|
|
3442
4763
|
return "async and generator components are not supported";
|
|
@@ -3448,6 +4769,7 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3448
4769
|
const safeGlobals = new Set(
|
|
3449
4770
|
[...SAFE_GLOBAL_CALLS, "Math"].filter((name2) => !path.scope.getBinding(name2))
|
|
3450
4771
|
);
|
|
4772
|
+
const globalCollections = new Set(["Set", "Map"].filter((name2) => !path.scope.getBinding(name2)));
|
|
3451
4773
|
const states = [];
|
|
3452
4774
|
const locals = [];
|
|
3453
4775
|
let returned;
|
|
@@ -3495,9 +4817,17 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3495
4817
|
if (declaration.init.async || declaration.init.generator) {
|
|
3496
4818
|
return `event handler ${declaration.id.name} must be synchronous`;
|
|
3497
4819
|
}
|
|
3498
|
-
locals.push({
|
|
4820
|
+
locals.push({
|
|
4821
|
+
kind: "handler",
|
|
4822
|
+
name: declaration.id.name,
|
|
4823
|
+
value: declaration.init
|
|
4824
|
+
});
|
|
3499
4825
|
} else {
|
|
3500
|
-
locals.push({
|
|
4826
|
+
locals.push({
|
|
4827
|
+
kind: "derived",
|
|
4828
|
+
name: declaration.id.name,
|
|
4829
|
+
value: declaration.init
|
|
4830
|
+
});
|
|
3501
4831
|
}
|
|
3502
4832
|
}
|
|
3503
4833
|
if (states.length === 0) return "no local useState binding was found";
|
|
@@ -3636,8 +4966,378 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3636
4966
|
}
|
|
3637
4967
|
if (blockAnalysis.reason) return blockAnalysis.reason;
|
|
3638
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
|
+
}
|
|
3639
5317
|
const blockPlans = blockAnalysis.plans || [];
|
|
3640
|
-
|
|
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
|
+
);
|
|
3641
5341
|
markShortCircuitBindings(analysis.bindings || []);
|
|
3642
5342
|
assignStableBindingTargets(analysis.bindings || []);
|
|
3643
5343
|
const stateParameter = path.scope.generateUidIdentifier("farmState");
|
|
@@ -3650,11 +5350,21 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3650
5350
|
blockParameter,
|
|
3651
5351
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set()
|
|
3652
5352
|
);
|
|
5353
|
+
const appliedRemovalHintedStateIndices = /* @__PURE__ */ new Set([
|
|
5354
|
+
...appliedFilterHintedStateIndices,
|
|
5355
|
+
...appliedRollingWindowHintedStateIndices,
|
|
5356
|
+
...appliedSliceHintedStateIndices
|
|
5357
|
+
]);
|
|
3653
5358
|
const rootWithBlocks = lowerComposableBlocks(
|
|
3654
5359
|
rootWithTargets,
|
|
3655
5360
|
blockPlans,
|
|
3656
5361
|
blockParameter,
|
|
3657
|
-
listNames
|
|
5362
|
+
listNames,
|
|
5363
|
+
hasKeyedUpdateHints,
|
|
5364
|
+
appliedRemovalHintedStateIndices,
|
|
5365
|
+
appliedPrependHintedStateIndices,
|
|
5366
|
+
appliedPositionHintedStateIndices,
|
|
5367
|
+
appliedReorderHintedStateIndices
|
|
3658
5368
|
);
|
|
3659
5369
|
const rewrittenRoot = rewriteStateAccess(
|
|
3660
5370
|
rootWithBlocks,
|
|
@@ -3792,6 +5502,20 @@ function collectCandidates(programPath) {
|
|
|
3792
5502
|
async function compileReactModule(code, id, options) {
|
|
3793
5503
|
const compiled = [];
|
|
3794
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
|
+
};
|
|
3795
5519
|
const plugin = () => ({
|
|
3796
5520
|
name: "farm-react-aot",
|
|
3797
5521
|
visitor: {
|
|
@@ -3821,6 +5545,36 @@ async function compileReactModule(code, id, options) {
|
|
|
3821
5545
|
}
|
|
3822
5546
|
const candidates = collectCandidates(programPath);
|
|
3823
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
|
+
);
|
|
3824
5578
|
const runtimeFeatureIdentifiers = new Map(
|
|
3825
5579
|
Object.entries(COMPILER_RUNTIME_FEATURE_EXPORTS).map(([feature, exportName]) => [
|
|
3826
5580
|
feature,
|
|
@@ -3838,8 +5592,19 @@ async function compileReactModule(code, id, options) {
|
|
|
3838
5592
|
const reason = compileCandidate(
|
|
3839
5593
|
candidate,
|
|
3840
5594
|
createComponentIdentifier,
|
|
5595
|
+
keyedMapUpdateIdentifier,
|
|
5596
|
+
keyedArrayAppendIdentifier,
|
|
5597
|
+
keyedArrayFilterIdentifier,
|
|
5598
|
+
keyedArrayPrependIdentifier,
|
|
5599
|
+
keyedArrayPositionIdentifier,
|
|
5600
|
+
keyedArrayReorderIdentifier,
|
|
5601
|
+
keyedArrayRollingWindowIdentifier,
|
|
5602
|
+
keyedArraySliceIdentifier,
|
|
5603
|
+
keyedCollectionUpdateIdentifier,
|
|
5604
|
+
keyedCollectionMutationIdentifier,
|
|
3841
5605
|
runtimeFeatureIdentifiers,
|
|
3842
5606
|
usedRuntimeFeatures,
|
|
5607
|
+
optimizationCounts,
|
|
3843
5608
|
useStateNames,
|
|
3844
5609
|
reactNames,
|
|
3845
5610
|
listNames,
|
|
@@ -3865,6 +5630,64 @@ async function compileReactModule(code, id, options) {
|
|
|
3865
5630
|
createComponentIdentifier,
|
|
3866
5631
|
core.types.identifier("createCompiledComponentWithFeatures")
|
|
3867
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
|
+
] : [],
|
|
3868
5691
|
...[...usedRuntimeFeatures].sort().map(
|
|
3869
5692
|
(feature) => core.types.importSpecifier(
|
|
3870
5693
|
core.types.cloneNode(runtimeFeatureIdentifiers.get(feature)),
|
|
@@ -3901,7 +5724,8 @@ async function compileReactModule(code, id, options) {
|
|
|
3901
5724
|
code: result?.code || code,
|
|
3902
5725
|
map: result?.map || null,
|
|
3903
5726
|
compiled,
|
|
3904
|
-
diagnostics
|
|
5727
|
+
diagnostics,
|
|
5728
|
+
optimizations: optimizationCounts
|
|
3905
5729
|
};
|
|
3906
5730
|
}
|
|
3907
5731
|
function projectRelativeId(projectRoot, id) {
|
|
@@ -3912,10 +5736,34 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3912
5736
|
let componentsConsidered = 0;
|
|
3913
5737
|
let compiled = 0;
|
|
3914
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;
|
|
3915
5751
|
const modules = [...observations].map(({ id, result }) => {
|
|
3916
5752
|
componentsConsidered += result.compiled.length + result.diagnostics.length;
|
|
3917
5753
|
compiled += result.compiled.length;
|
|
3918
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;
|
|
3919
5767
|
const moduleId = projectRelativeId(projectRoot, id);
|
|
3920
5768
|
const fallbacks = result.diagnostics.map((diagnostic) => {
|
|
3921
5769
|
reasonCounts.set(diagnostic.reason, (reasonCounts.get(diagnostic.reason) || 0) + 1);
|
|
@@ -3924,6 +5772,7 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3924
5772
|
return {
|
|
3925
5773
|
id: moduleId,
|
|
3926
5774
|
compiled: [...result.compiled].sort(),
|
|
5775
|
+
optimizations: result.optimizations,
|
|
3927
5776
|
fallbacks
|
|
3928
5777
|
};
|
|
3929
5778
|
}).sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -3934,7 +5783,19 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3934
5783
|
modules: modules.length,
|
|
3935
5784
|
componentsConsidered,
|
|
3936
5785
|
compiled,
|
|
3937
|
-
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
|
|
3938
5799
|
},
|
|
3939
5800
|
fallbackReasons,
|
|
3940
5801
|
modules
|