@farm.js/react 0.1.0-beta.5 → 0.1.0-beta.7
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 +227 -1
- package/dist/compiler-runtime.cjs +1830 -19
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +84 -1
- package/dist/compiler-runtime.d.ts +84 -1
- package/dist/compiler-runtime.mjs +1788 -20
- package/dist/compiler-runtime.mjs.map +1 -1
- package/dist/vite.cjs +2026 -54
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +2026 -54
- 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,941 @@ 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 validateKeyedArrayPositionExpression(expression, safeGlobals) {
|
|
849
|
+
const isNumericLiteral = core.types.isNumericLiteral(expression) || core.types.isUnaryExpression(expression) && (expression.operator === "+" || expression.operator === "-") && core.types.isNumericLiteral(expression.argument);
|
|
850
|
+
if (isNumericLiteral && staticSliceIndex(expression) === void 0) {
|
|
851
|
+
return "non-safe-integer position literals";
|
|
852
|
+
}
|
|
853
|
+
return validateDerivedExpression(expression, safeGlobals);
|
|
854
|
+
}
|
|
855
|
+
function rewriteKeyedArrayPositionHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
856
|
+
if (hintedStateIndices.size === 0) {
|
|
857
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
858
|
+
}
|
|
859
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
860
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
861
|
+
let count = 0;
|
|
862
|
+
core.traverse(file, {
|
|
863
|
+
CallExpression(path) {
|
|
864
|
+
const callee = path.get("callee");
|
|
865
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
866
|
+
const state = statesBySetter.get(callee.node.name);
|
|
867
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
const updater = path.node.arguments[0];
|
|
871
|
+
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)) {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
const methodName = updater.body.callee.property.name;
|
|
875
|
+
const args = updater.body.arguments;
|
|
876
|
+
const kind = methodName === "with" && args.length === 2 ? "replace" : methodName === "toSpliced" && args.length === 3 && core.types.isNumericLiteral(args[1], { value: 0 }) ? "insert" : methodName === "toSpliced" && args.length === 2 && core.types.isNumericLiteral(args[1], { value: 1 }) ? "remove" : void 0;
|
|
877
|
+
if (!kind || !core.types.isExpression(args[0])) return;
|
|
878
|
+
const position = args[0];
|
|
879
|
+
const item = kind === "remove" ? void 0 : args.at(-1);
|
|
880
|
+
if (validateKeyedArrayPositionExpression(position, safeGlobals) !== void 0 || item !== void 0 && (!core.types.isExpression(item) || validateDerivedExpression(item, safeGlobals) !== void 0)) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
884
|
+
const method = path.scope.generateUidIdentifier(
|
|
885
|
+
methodName === "with" ? "farmWith" : "farmToSpliced"
|
|
886
|
+
);
|
|
887
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
888
|
+
[core.types.cloneNode(previous)],
|
|
889
|
+
core.types.blockStatement([
|
|
890
|
+
core.types.variableDeclaration("const", [
|
|
891
|
+
core.types.variableDeclarator(
|
|
892
|
+
core.types.cloneNode(method),
|
|
893
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier(methodName))
|
|
894
|
+
)
|
|
895
|
+
]),
|
|
896
|
+
core.types.returnStatement(
|
|
897
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
898
|
+
core.types.cloneNode(previous),
|
|
899
|
+
core.types.cloneNode(method),
|
|
900
|
+
core.types.stringLiteral(kind),
|
|
901
|
+
...args.map((argument) => core.types.cloneNode(argument, true))
|
|
902
|
+
])
|
|
903
|
+
)
|
|
904
|
+
])
|
|
905
|
+
);
|
|
906
|
+
count += 1;
|
|
907
|
+
stateIndices.add(state.index);
|
|
908
|
+
path.skip();
|
|
909
|
+
}
|
|
910
|
+
});
|
|
911
|
+
return {
|
|
912
|
+
root: file.program.body[0].expression,
|
|
913
|
+
count,
|
|
914
|
+
stateIndices
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
function rewriteKeyedArrayReorderHints(root, hintedStateIndices, statesBySetter, helperIdentifier) {
|
|
918
|
+
if (hintedStateIndices.size === 0) {
|
|
919
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
920
|
+
}
|
|
921
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
922
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
923
|
+
let count = 0;
|
|
924
|
+
core.traverse(file, {
|
|
925
|
+
CallExpression(path) {
|
|
926
|
+
const callee = path.get("callee");
|
|
927
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
928
|
+
const state = statesBySetter.get(callee.node.name);
|
|
929
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
const updater = path.node.arguments[0];
|
|
933
|
+
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" })) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
937
|
+
const method = path.scope.generateUidIdentifier("farmToReversed");
|
|
938
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
939
|
+
[core.types.cloneNode(previous)],
|
|
940
|
+
core.types.blockStatement([
|
|
941
|
+
core.types.variableDeclaration("const", [
|
|
942
|
+
core.types.variableDeclarator(
|
|
943
|
+
core.types.cloneNode(method),
|
|
944
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("toReversed"))
|
|
945
|
+
)
|
|
946
|
+
]),
|
|
947
|
+
core.types.returnStatement(
|
|
948
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
949
|
+
core.types.cloneNode(previous),
|
|
950
|
+
core.types.cloneNode(method)
|
|
951
|
+
])
|
|
952
|
+
)
|
|
953
|
+
])
|
|
954
|
+
);
|
|
955
|
+
count += 1;
|
|
956
|
+
stateIndices.add(state.index);
|
|
957
|
+
path.skip();
|
|
958
|
+
}
|
|
959
|
+
});
|
|
960
|
+
return {
|
|
961
|
+
root: file.program.body[0].expression,
|
|
962
|
+
count,
|
|
963
|
+
stateIndices
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
function rewriteKeyedArraySortHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
967
|
+
if (hintedStateIndices.size === 0) {
|
|
968
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
969
|
+
}
|
|
970
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
971
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
972
|
+
let count = 0;
|
|
973
|
+
core.traverse(file, {
|
|
974
|
+
CallExpression(path) {
|
|
975
|
+
const callee = path.get("callee");
|
|
976
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
977
|
+
const state = statesBySetter.get(callee.node.name);
|
|
978
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
const updater = path.node.arguments[0];
|
|
982
|
+
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, { name: updater.params[0].name }) || !core.types.isIdentifier(updater.body.callee.property, { name: "toSorted" })) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
const comparator = updater.body.arguments[0];
|
|
986
|
+
if (comparator && !core.types.isArrowFunctionExpression(comparator) && !core.types.isFunctionExpression(comparator)) {
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
if (comparator && validateCollectionCallback(comparator, "toSorted", safeGlobals)) return;
|
|
990
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
991
|
+
const method = path.scope.generateUidIdentifier("farmToSorted");
|
|
992
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
993
|
+
[core.types.cloneNode(previous)],
|
|
994
|
+
core.types.blockStatement([
|
|
995
|
+
core.types.variableDeclaration("const", [
|
|
996
|
+
core.types.variableDeclarator(
|
|
997
|
+
core.types.cloneNode(method),
|
|
998
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("toSorted"))
|
|
999
|
+
)
|
|
1000
|
+
]),
|
|
1001
|
+
core.types.returnStatement(
|
|
1002
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
1003
|
+
core.types.cloneNode(previous),
|
|
1004
|
+
core.types.cloneNode(method),
|
|
1005
|
+
...comparator ? [core.types.cloneNode(comparator, true)] : []
|
|
1006
|
+
])
|
|
1007
|
+
)
|
|
1008
|
+
])
|
|
1009
|
+
);
|
|
1010
|
+
count += 1;
|
|
1011
|
+
stateIndices.add(state.index);
|
|
1012
|
+
path.skip();
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
return {
|
|
1016
|
+
root: file.program.body[0].expression,
|
|
1017
|
+
count,
|
|
1018
|
+
stateIndices
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
function rewriteKeyedArraySliceHints(root, hintedStateIndices, statesBySetter, helperIdentifier) {
|
|
1022
|
+
if (hintedStateIndices.size === 0) {
|
|
1023
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
1024
|
+
}
|
|
1025
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1026
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
1027
|
+
let count = 0;
|
|
1028
|
+
core.traverse(file, {
|
|
1029
|
+
CallExpression(path) {
|
|
1030
|
+
const callee = path.get("callee");
|
|
1031
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
1032
|
+
const state = statesBySetter.get(callee.node.name);
|
|
1033
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
const updater = path.node.arguments[0];
|
|
1037
|
+
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" })) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
const indexes = [];
|
|
1041
|
+
for (const argument of updater.body.arguments) {
|
|
1042
|
+
if (!core.types.isExpression(argument)) return;
|
|
1043
|
+
const value = staticSliceIndex(argument);
|
|
1044
|
+
if (value === void 0) return;
|
|
1045
|
+
indexes.push(value);
|
|
1046
|
+
}
|
|
1047
|
+
if (indexes.length === 1 && indexes[0] === 0) return;
|
|
1048
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
1049
|
+
const sliceMethod = path.scope.generateUidIdentifier("farmSlice");
|
|
1050
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
1051
|
+
[core.types.cloneNode(previous)],
|
|
1052
|
+
core.types.blockStatement([
|
|
1053
|
+
core.types.variableDeclaration("const", [
|
|
1054
|
+
core.types.variableDeclarator(
|
|
1055
|
+
core.types.cloneNode(sliceMethod),
|
|
1056
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("slice"))
|
|
1057
|
+
)
|
|
1058
|
+
]),
|
|
1059
|
+
core.types.returnStatement(
|
|
1060
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
1061
|
+
core.types.cloneNode(previous),
|
|
1062
|
+
core.types.cloneNode(sliceMethod),
|
|
1063
|
+
...indexes.map((value) => core.types.numericLiteral(value))
|
|
1064
|
+
])
|
|
1065
|
+
)
|
|
1066
|
+
])
|
|
1067
|
+
);
|
|
1068
|
+
count += 1;
|
|
1069
|
+
stateIndices.add(state.index);
|
|
1070
|
+
path.skip();
|
|
1071
|
+
}
|
|
1072
|
+
});
|
|
1073
|
+
return {
|
|
1074
|
+
root: file.program.body[0].expression,
|
|
1075
|
+
count,
|
|
1076
|
+
stateIndices
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
function rewriteKeyedArrayFilterHints(root, hintedStateIndices, statesBySetter, helperIdentifier, safeGlobals) {
|
|
1080
|
+
if (hintedStateIndices.size === 0) {
|
|
1081
|
+
return { root: core.types.cloneNode(root, true), count: 0, stateIndices: /* @__PURE__ */ new Set() };
|
|
1082
|
+
}
|
|
1083
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1084
|
+
const stateIndices = /* @__PURE__ */ new Set();
|
|
1085
|
+
let count = 0;
|
|
1086
|
+
core.traverse(file, {
|
|
1087
|
+
CallExpression(path) {
|
|
1088
|
+
const callee = path.get("callee");
|
|
1089
|
+
if (!callee.isIdentifier() || callee.scope.hasBinding(callee.node.name)) return;
|
|
1090
|
+
const state = statesBySetter.get(callee.node.name);
|
|
1091
|
+
if (!state || !hintedStateIndices.has(state.index) || path.node.arguments.length !== 1) {
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
const updater = path.node.arguments[0];
|
|
1095
|
+
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, {
|
|
1096
|
+
name: updater.params[0].name
|
|
1097
|
+
}) || !core.types.isIdentifier(updater.body.callee.property, { name: "filter" })) {
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
const predicate = updater.body.arguments[0];
|
|
1101
|
+
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)) {
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
const previous = core.types.cloneNode(updater.params[0]);
|
|
1105
|
+
const filterMethod = path.scope.generateUidIdentifier("farmFilter");
|
|
1106
|
+
path.node.arguments[0] = core.types.arrowFunctionExpression(
|
|
1107
|
+
[core.types.cloneNode(previous)],
|
|
1108
|
+
core.types.blockStatement([
|
|
1109
|
+
core.types.variableDeclaration("const", [
|
|
1110
|
+
core.types.variableDeclarator(
|
|
1111
|
+
core.types.cloneNode(filterMethod),
|
|
1112
|
+
core.types.memberExpression(core.types.cloneNode(previous), core.types.identifier("filter"))
|
|
1113
|
+
)
|
|
1114
|
+
]),
|
|
1115
|
+
core.types.returnStatement(
|
|
1116
|
+
core.types.callExpression(core.types.cloneNode(helperIdentifier), [
|
|
1117
|
+
core.types.cloneNode(previous),
|
|
1118
|
+
core.types.cloneNode(filterMethod),
|
|
1119
|
+
core.types.cloneNode(predicate, true)
|
|
1120
|
+
])
|
|
1121
|
+
)
|
|
1122
|
+
])
|
|
1123
|
+
);
|
|
1124
|
+
count += 1;
|
|
1125
|
+
stateIndices.add(state.index);
|
|
1126
|
+
path.skip();
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
return {
|
|
1130
|
+
root: file.program.body[0].expression,
|
|
1131
|
+
count,
|
|
1132
|
+
stateIndices
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
function collectionConstructorName(kind) {
|
|
1136
|
+
return kind === "set" ? "Set" : "Map";
|
|
1137
|
+
}
|
|
1138
|
+
function isCollectionConstruction(expression, kind, previous) {
|
|
1139
|
+
if (!core.types.isNewExpression(expression) || !core.types.isIdentifier(expression.callee, {
|
|
1140
|
+
name: collectionConstructorName(kind)
|
|
1141
|
+
})) {
|
|
1142
|
+
return false;
|
|
1143
|
+
}
|
|
1144
|
+
if (!previous) return true;
|
|
1145
|
+
return expression.arguments.length === 1 && core.types.isIdentifier(expression.arguments[0], { name: previous.name });
|
|
1146
|
+
}
|
|
1147
|
+
function collectionStateInitializerIsOwned(initialValue, kind, constructorIsGlobal) {
|
|
1148
|
+
if (!initialValue || !constructorIsGlobal) return false;
|
|
1149
|
+
if (isCollectionConstruction(initialValue, kind)) return true;
|
|
1150
|
+
if (!core.types.isArrowFunctionExpression(initialValue) && !core.types.isFunctionExpression(initialValue)) {
|
|
1151
|
+
return false;
|
|
1152
|
+
}
|
|
1153
|
+
if (core.types.isBlockStatement(initialValue.body) && initialValue.body.body.length !== 1) return false;
|
|
1154
|
+
const value = returnedExpression(initialValue);
|
|
1155
|
+
return Boolean(value && isCollectionConstruction(value, kind));
|
|
1156
|
+
}
|
|
1157
|
+
function collectionStateHasOnlyOwnedReads(root, state, kind) {
|
|
1158
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1159
|
+
let valid = true;
|
|
1160
|
+
const readMethods = kind === "set" ? /* @__PURE__ */ new Set(["has"]) : /* @__PURE__ */ new Set(["get", "has"]);
|
|
1161
|
+
core.traverse(file, {
|
|
1162
|
+
ReferencedIdentifier(path) {
|
|
1163
|
+
if (!valid || !core.types.isIdentifier(path.node) || path.node.name !== state.valueName || path.scope.hasBinding(path.node.name)) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
const parent = path.parentPath;
|
|
1167
|
+
if (parent.isNewExpression() && core.types.isIdentifier(parent.node.callee, {
|
|
1168
|
+
name: collectionConstructorName(kind)
|
|
1169
|
+
}) && parent.node.arguments.length === 1 && parent.node.arguments[0] === path.node) {
|
|
1170
|
+
return;
|
|
1171
|
+
}
|
|
1172
|
+
if (!parent.isMemberExpression() || parent.node.object !== path.node || parent.node.computed || !core.types.isIdentifier(parent.node.property)) {
|
|
1173
|
+
valid = false;
|
|
1174
|
+
path.stop();
|
|
1175
|
+
return;
|
|
1176
|
+
}
|
|
1177
|
+
const property = parent.node.property.name;
|
|
1178
|
+
if (property === "size") return;
|
|
1179
|
+
const call = parent.parentPath;
|
|
1180
|
+
if (!readMethods.has(property) || !call?.isCallExpression() || call.node.callee !== parent.node) {
|
|
1181
|
+
valid = false;
|
|
1182
|
+
path.stop();
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
return valid;
|
|
1187
|
+
}
|
|
1188
|
+
function collectionMutationOperation(kind, method) {
|
|
1189
|
+
if (kind === "set" && method === "add") return "set-add";
|
|
1190
|
+
if (kind === "set" && method === "delete") return "set-delete";
|
|
1191
|
+
if (kind === "map" && method === "set") return "map-set";
|
|
1192
|
+
if (kind === "map" && method === "delete") return "map-delete";
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
function collectionMutationArgumentsAreValid(operation, args) {
|
|
1196
|
+
if (!operation || args.some((argument) => !core.types.isExpression(argument))) return false;
|
|
1197
|
+
return operation === "map-set" ? args.length === 2 : args.length === 1;
|
|
1198
|
+
}
|
|
1199
|
+
function prepareKeyedCollectionUpdater(updater, kind, updateHelper, mutationHelper) {
|
|
1200
|
+
if (updater.async || updater.generator || updater.params.length !== 1 || !core.types.isIdentifier(updater.params[0])) {
|
|
1201
|
+
return void 0;
|
|
1202
|
+
}
|
|
1203
|
+
const previous = updater.params[0];
|
|
1204
|
+
if (core.types.isExpression(updater.body)) {
|
|
1205
|
+
if (!core.types.isCallExpression(updater.body) || !core.types.isMemberExpression(updater.body.callee) || updater.body.callee.computed || !core.types.isIdentifier(updater.body.callee.property)) {
|
|
1206
|
+
return void 0;
|
|
1207
|
+
}
|
|
1208
|
+
const operation = collectionMutationOperation(kind, updater.body.callee.property.name);
|
|
1209
|
+
if (operation !== "set-add" && operation !== "map-set" || !collectionMutationArgumentsAreValid(operation, updater.body.arguments) || !isCollectionConstruction(updater.body.callee.object, kind, previous)) {
|
|
1210
|
+
return void 0;
|
|
1211
|
+
}
|
|
1212
|
+
const collection = uniqueLocalIdentifier("_farmCollection", [updater]);
|
|
1213
|
+
const body = core.types.blockStatement([
|
|
1214
|
+
core.types.variableDeclaration("const", [
|
|
1215
|
+
core.types.variableDeclarator(
|
|
1216
|
+
core.types.cloneNode(collection),
|
|
1217
|
+
core.types.cloneNode(updater.body.callee.object, true)
|
|
1218
|
+
)
|
|
1219
|
+
]),
|
|
1220
|
+
core.types.returnStatement(
|
|
1221
|
+
core.types.callExpression(core.types.cloneNode(updateHelper), [
|
|
1222
|
+
core.types.cloneNode(previous),
|
|
1223
|
+
core.types.callExpression(core.types.cloneNode(mutationHelper), [
|
|
1224
|
+
core.types.cloneNode(collection),
|
|
1225
|
+
core.types.memberExpression(core.types.cloneNode(collection), core.types.cloneNode(updater.body.callee.property)),
|
|
1226
|
+
core.types.stringLiteral(operation),
|
|
1227
|
+
...updater.body.arguments.map(
|
|
1228
|
+
(argument) => core.types.cloneNode(argument, true)
|
|
1229
|
+
)
|
|
1230
|
+
]),
|
|
1231
|
+
core.types.stringLiteral(kind)
|
|
1232
|
+
])
|
|
1233
|
+
)
|
|
1234
|
+
]);
|
|
1235
|
+
return {
|
|
1236
|
+
updater: core.types.arrowFunctionExpression([core.types.cloneNode(previous)], body),
|
|
1237
|
+
mutations: 1
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
const cloned = core.types.cloneNode(updater, true);
|
|
1241
|
+
const file = expressionFile(cloned);
|
|
1242
|
+
let functionPath;
|
|
1243
|
+
core.traverse(file, {
|
|
1244
|
+
Function(path) {
|
|
1245
|
+
if (functionPath) return;
|
|
1246
|
+
if (path.isArrowFunctionExpression() || path.isFunctionExpression()) {
|
|
1247
|
+
functionPath = path;
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
if (!functionPath || !core.types.isBlockStatement(functionPath.node.body)) return void 0;
|
|
1252
|
+
const clonedPrevious = functionPath.node.params[0];
|
|
1253
|
+
if (!core.types.isIdentifier(clonedPrevious)) return void 0;
|
|
1254
|
+
let collectionDeclaration;
|
|
1255
|
+
const updaterBody = functionPath.get("body");
|
|
1256
|
+
if (!updaterBody.isBlockStatement()) return void 0;
|
|
1257
|
+
for (const statement of updaterBody.get("body")) {
|
|
1258
|
+
if (!statement.isVariableDeclaration({ kind: "const" })) continue;
|
|
1259
|
+
for (const declaration of statement.get("declarations")) {
|
|
1260
|
+
if (declaration.isVariableDeclarator() && core.types.isIdentifier(declaration.node.id) && core.types.isExpression(declaration.node.init) && isCollectionConstruction(declaration.node.init, kind, clonedPrevious)) {
|
|
1261
|
+
if (collectionDeclaration) return void 0;
|
|
1262
|
+
collectionDeclaration = declaration;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
if (!collectionDeclaration || !core.types.isIdentifier(collectionDeclaration.node.id)) return void 0;
|
|
1267
|
+
if (collectionDeclaration.scope.getBinding(collectionConstructorName(kind))) return void 0;
|
|
1268
|
+
const collectionName = collectionDeclaration.node.id.name;
|
|
1269
|
+
const collectionBinding = collectionDeclaration.scope.getBinding(collectionName);
|
|
1270
|
+
const previousBinding = functionPath.scope.getBinding(clonedPrevious.name);
|
|
1271
|
+
if (!collectionBinding || !previousBinding) return void 0;
|
|
1272
|
+
let valid = true;
|
|
1273
|
+
let mutations = 0;
|
|
1274
|
+
core.traverse(file, {
|
|
1275
|
+
ReferencedIdentifier(path) {
|
|
1276
|
+
if (!valid) return;
|
|
1277
|
+
const binding = path.scope.getBinding(path.node.name);
|
|
1278
|
+
const belongsToUpdater = path.getFunctionParent()?.node === functionPath?.node;
|
|
1279
|
+
if (binding === collectionBinding) {
|
|
1280
|
+
if (!belongsToUpdater) {
|
|
1281
|
+
valid = false;
|
|
1282
|
+
path.stop();
|
|
1283
|
+
return;
|
|
1284
|
+
}
|
|
1285
|
+
const parent = path.parentPath;
|
|
1286
|
+
if (parent.isReturnStatement() && parent.node.argument === path.node) return;
|
|
1287
|
+
if (!parent.isMemberExpression() || parent.node.object !== path.node || parent.node.computed || !core.types.isIdentifier(parent.node.property)) {
|
|
1288
|
+
valid = false;
|
|
1289
|
+
path.stop();
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
const method = parent.node.property.name;
|
|
1293
|
+
if (method === "size") return;
|
|
1294
|
+
const call = parent.parentPath;
|
|
1295
|
+
if (!call?.isCallExpression() || call.node.callee !== parent.node) {
|
|
1296
|
+
valid = false;
|
|
1297
|
+
path.stop();
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
const operation = collectionMutationOperation(kind, method);
|
|
1301
|
+
const read = kind === "set" ? method === "has" : method === "get" || method === "has";
|
|
1302
|
+
if (read) return;
|
|
1303
|
+
if (!collectionMutationArgumentsAreValid(operation, call.node.arguments) || call.parentPath.isMemberExpression() && call.parentPath.node.object === call.node) {
|
|
1304
|
+
valid = false;
|
|
1305
|
+
path.stop();
|
|
1306
|
+
return;
|
|
1307
|
+
}
|
|
1308
|
+
mutations += 1;
|
|
1309
|
+
return;
|
|
1310
|
+
}
|
|
1311
|
+
if (binding === previousBinding) {
|
|
1312
|
+
if (!belongsToUpdater) {
|
|
1313
|
+
valid = false;
|
|
1314
|
+
path.stop();
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
const parent = path.parentPath;
|
|
1318
|
+
if (parent.isReturnStatement() && parent.node.argument === path.node) return;
|
|
1319
|
+
if (parent.isNewExpression() && parent.node.arguments.length === 1 && parent.node.arguments[0] === path.node && core.types.isIdentifier(parent.node.callee, {
|
|
1320
|
+
name: collectionConstructorName(kind)
|
|
1321
|
+
})) {
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
if (parent.isMemberExpression() && parent.node.object === path.node && !parent.node.computed && core.types.isIdentifier(parent.node.property)) {
|
|
1325
|
+
const method = parent.node.property.name;
|
|
1326
|
+
const call = parent.parentPath;
|
|
1327
|
+
if (method === "size" || (kind === "set" ? method === "has" : method === "get" || method === "has") && call?.isCallExpression() && call.node.callee === parent.node) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
valid = false;
|
|
1332
|
+
path.stop();
|
|
1333
|
+
}
|
|
1334
|
+
},
|
|
1335
|
+
ReturnStatement(path) {
|
|
1336
|
+
if (!valid || path.getFunctionParent()?.node !== functionPath?.node || !path.node.argument) {
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
const value = path.node.argument;
|
|
1340
|
+
const returnsOwnedCollection = core.types.isIdentifier(value) && (path.scope.getBinding(value.name) === collectionBinding || path.scope.getBinding(value.name) === previousBinding) || isCollectionConstruction(value, kind);
|
|
1341
|
+
if (!returnsOwnedCollection) {
|
|
1342
|
+
valid = false;
|
|
1343
|
+
path.stop();
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
});
|
|
1347
|
+
if (!valid || mutations === 0) return void 0;
|
|
1348
|
+
core.traverse(file, {
|
|
1349
|
+
CallExpression(path) {
|
|
1350
|
+
if (path.getFunctionParent()?.node !== functionPath?.node) return;
|
|
1351
|
+
const callee = path.node.callee;
|
|
1352
|
+
if (!core.types.isMemberExpression(callee) || callee.computed || !core.types.isIdentifier(callee.object, { name: collectionName }) || path.scope.getBinding(collectionName) !== collectionBinding || !core.types.isIdentifier(callee.property)) {
|
|
1353
|
+
return;
|
|
1354
|
+
}
|
|
1355
|
+
const operation = collectionMutationOperation(kind, callee.property.name);
|
|
1356
|
+
if (!collectionMutationArgumentsAreValid(operation, path.node.arguments)) return;
|
|
1357
|
+
path.replaceWith(
|
|
1358
|
+
core.types.callExpression(core.types.cloneNode(mutationHelper), [
|
|
1359
|
+
core.types.cloneNode(callee.object),
|
|
1360
|
+
core.types.memberExpression(core.types.cloneNode(callee.object), core.types.cloneNode(callee.property)),
|
|
1361
|
+
core.types.stringLiteral(operation),
|
|
1362
|
+
...path.node.arguments.map((argument) => core.types.cloneNode(argument, true))
|
|
1363
|
+
])
|
|
1364
|
+
);
|
|
1365
|
+
path.skip();
|
|
1366
|
+
},
|
|
1367
|
+
ReturnStatement(path) {
|
|
1368
|
+
if (path.getFunctionParent()?.node !== functionPath?.node || !path.node.argument) return;
|
|
1369
|
+
path.node.argument = core.types.callExpression(core.types.cloneNode(updateHelper), [
|
|
1370
|
+
core.types.cloneNode(clonedPrevious),
|
|
1371
|
+
core.types.cloneNode(path.node.argument, true),
|
|
1372
|
+
core.types.stringLiteral(kind)
|
|
1373
|
+
]);
|
|
1374
|
+
}
|
|
1375
|
+
});
|
|
1376
|
+
const prepared = file.program.body[0].expression;
|
|
1377
|
+
return core.types.isArrowFunctionExpression(prepared) || core.types.isFunctionExpression(prepared) ? { updater: prepared, mutations } : void 0;
|
|
1378
|
+
}
|
|
1379
|
+
function rewriteKeyedCollectionUpdateHints(root, targetKinds, states, statesBySetter, updateHelper, mutationHelper, globalCollections) {
|
|
1380
|
+
if (targetKinds.size === 0) return { root: core.types.cloneNode(root, true), count: 0 };
|
|
1381
|
+
const file = expressionFile(core.types.cloneNode(root, true));
|
|
1382
|
+
let count = 0;
|
|
1383
|
+
for (const [stateIndex, kind] of targetKinds) {
|
|
1384
|
+
const state = states[stateIndex];
|
|
1385
|
+
if (!state || !collectionStateInitializerIsOwned(
|
|
1386
|
+
state.initialValue,
|
|
1387
|
+
kind,
|
|
1388
|
+
globalCollections.has(collectionConstructorName(kind))
|
|
1389
|
+
) || !collectionStateHasOnlyOwnedReads(root, state, kind)) {
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
1393
|
+
let valid = true;
|
|
1394
|
+
core.traverse(file, {
|
|
1395
|
+
CallExpression(path) {
|
|
1396
|
+
if (!valid) return;
|
|
1397
|
+
const callee = path.get("callee");
|
|
1398
|
+
if (!callee.isIdentifier({ name: state.setterName }) || callee.scope.hasBinding(callee.node.name) || statesBySetter.get(callee.node.name)?.index !== stateIndex) {
|
|
1399
|
+
return;
|
|
1400
|
+
}
|
|
1401
|
+
if (path.node.arguments.length !== 1 || !core.types.isExpression(path.node.arguments[0])) {
|
|
1402
|
+
valid = false;
|
|
1403
|
+
path.stop();
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
const update = path.node.arguments[0];
|
|
1407
|
+
if (path.scope.getBinding(collectionConstructorName(kind))) {
|
|
1408
|
+
valid = false;
|
|
1409
|
+
path.stop();
|
|
1410
|
+
return;
|
|
1411
|
+
}
|
|
1412
|
+
if (isCollectionConstruction(update, kind)) return;
|
|
1413
|
+
if (!core.types.isArrowFunctionExpression(update) && !core.types.isFunctionExpression(update)) {
|
|
1414
|
+
valid = false;
|
|
1415
|
+
path.stop();
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
const prepared = prepareKeyedCollectionUpdater(update, kind, updateHelper, mutationHelper);
|
|
1419
|
+
if (!prepared) {
|
|
1420
|
+
valid = false;
|
|
1421
|
+
path.stop();
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
replacements.set(path.node, prepared);
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
if (!valid || replacements.size === 0) continue;
|
|
1428
|
+
core.traverse(file, {
|
|
1429
|
+
CallExpression(path) {
|
|
1430
|
+
const prepared = replacements.get(path.node);
|
|
1431
|
+
if (!prepared) return;
|
|
1432
|
+
path.node.arguments[0] = core.types.cloneNode(prepared.updater, true);
|
|
1433
|
+
count += prepared.mutations;
|
|
1434
|
+
path.skip();
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
return {
|
|
1439
|
+
root: file.program.body[0].expression,
|
|
1440
|
+
count
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
303
1443
|
function rewriteStateAccess(expression, stateParameter, statesByValue, statesBySetter) {
|
|
304
1444
|
const file = expressionFile(cloneExpression(expression));
|
|
305
1445
|
core.traverse(file, {
|
|
@@ -550,21 +1690,28 @@ function analyzeMapList(expression, statesByValue, safeGlobals) {
|
|
|
550
1690
|
const collection = callee.object;
|
|
551
1691
|
const collectionUnsupported = validateCollectionPipeline(collection, safeGlobals);
|
|
552
1692
|
if (collectionUnsupported) {
|
|
553
|
-
return {
|
|
1693
|
+
return {
|
|
1694
|
+
reason: `keyed list collection cannot use ${collectionUnsupported}`
|
|
1695
|
+
};
|
|
554
1696
|
}
|
|
555
1697
|
if (expression.arguments.length !== 1 || !core.types.isArrowFunctionExpression(expression.arguments[0]) && !core.types.isFunctionExpression(expression.arguments[0])) {
|
|
556
1698
|
return { reason: "keyed list map must use one inline render callback" };
|
|
557
1699
|
}
|
|
558
1700
|
const callback = expression.arguments[0];
|
|
559
1701
|
if (containsDirectHookCall(callback)) {
|
|
560
|
-
return {
|
|
1702
|
+
return {
|
|
1703
|
+
reason: "Hooks cannot be called directly inside a keyed list callback"
|
|
1704
|
+
};
|
|
561
1705
|
}
|
|
562
1706
|
const row = returnedExpression(callback);
|
|
563
1707
|
if (!row || !core.types.isJSXElement(row)) {
|
|
564
1708
|
return { reason: "keyed list map callbacks must return one React element" };
|
|
565
1709
|
}
|
|
566
1710
|
const key = jsxKeyExpression(row);
|
|
567
|
-
if (!key)
|
|
1711
|
+
if (!key)
|
|
1712
|
+
return {
|
|
1713
|
+
reason: "automatically compiled lists require an explicit item key"
|
|
1714
|
+
};
|
|
568
1715
|
const keyReason = validateKeyFunction(callback, key, safeGlobals);
|
|
569
1716
|
if (keyReason) return { reason: keyReason };
|
|
570
1717
|
return { dependencies: collectStateDependencies(expression, statesByValue) };
|
|
@@ -579,7 +1726,9 @@ function listAttributeExpression(element, name) {
|
|
|
579
1726
|
}
|
|
580
1727
|
function analyzePublicList(element, statesByValue, safeGlobals) {
|
|
581
1728
|
if (element.openingElement.attributes.some((attribute) => core.types.isJSXSpreadAttribute(attribute))) {
|
|
582
|
-
return {
|
|
1729
|
+
return {
|
|
1730
|
+
reason: "compiled List boundaries do not support JSX attribute spreads"
|
|
1731
|
+
};
|
|
583
1732
|
}
|
|
584
1733
|
const each = listAttributeExpression(element, "each");
|
|
585
1734
|
const by = listAttributeExpression(element, "by");
|
|
@@ -597,7 +1746,9 @@ function analyzePublicList(element, statesByValue, safeGlobals) {
|
|
|
597
1746
|
if (keyReason) return { reason: keyReason };
|
|
598
1747
|
const children = meaningfulJsxChildren(element);
|
|
599
1748
|
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 {
|
|
1749
|
+
return {
|
|
1750
|
+
reason: "compiled List children must use one inline render function"
|
|
1751
|
+
};
|
|
601
1752
|
}
|
|
602
1753
|
const render = children[0].expression;
|
|
603
1754
|
if (!returnedExpression(render)) {
|
|
@@ -711,13 +1862,20 @@ function stabilizeDeferredEventCurrentTargets(root, compilerSetters) {
|
|
|
711
1862
|
const expression = file.program.body[0].expression;
|
|
712
1863
|
return core.types.isJSXElement(expression) ? expression : core.types.cloneNode(root, true);
|
|
713
1864
|
}
|
|
714
|
-
function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters) {
|
|
1865
|
+
function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters, keyedTargetReactiveByValue) {
|
|
715
1866
|
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 {
|
|
1867
|
+
return {
|
|
1868
|
+
reason: "compiled keyed rows require item and optional index identifiers"
|
|
1869
|
+
};
|
|
717
1870
|
}
|
|
718
1871
|
const bindings = [];
|
|
719
1872
|
const events = [];
|
|
720
1873
|
const conditionals = [];
|
|
1874
|
+
const validateBindingExpression = (expression) => validateDerivedExpression(
|
|
1875
|
+
expression,
|
|
1876
|
+
safeGlobals,
|
|
1877
|
+
keyedTargetReactiveByValue ? (call) => isPotentialKeyedMembershipCall(call, keyedTargetReactiveByValue) || isPotentialKeyedMapLookupCall(call, keyedTargetReactiveByValue) : void 0
|
|
1878
|
+
);
|
|
721
1879
|
const visit = (element, path) => {
|
|
722
1880
|
const tag = element.openingElement.name;
|
|
723
1881
|
if (!core.types.isJSXIdentifier(tag) || !/^[a-z]/.test(tag.name)) {
|
|
@@ -796,7 +1954,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
796
1954
|
if (!propertyName || propertyName.includes("-") && !propertyName.startsWith("--")) {
|
|
797
1955
|
return "compiled keyed row style names must use camelCase or a CSS custom property";
|
|
798
1956
|
}
|
|
799
|
-
const unsupported2 =
|
|
1957
|
+
const unsupported2 = validateBindingExpression(property.value);
|
|
800
1958
|
if (unsupported2) {
|
|
801
1959
|
return `compiled keyed row style ${propertyName} cannot use ${unsupported2}`;
|
|
802
1960
|
}
|
|
@@ -810,7 +1968,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
810
1968
|
continue;
|
|
811
1969
|
}
|
|
812
1970
|
if (name === "children") return "compiled keyed row children props are not supported yet";
|
|
813
|
-
const unsupported =
|
|
1971
|
+
const unsupported = validateBindingExpression(expression);
|
|
814
1972
|
if (unsupported) return `compiled keyed row ${name} cannot use ${unsupported}`;
|
|
815
1973
|
bindings.push({
|
|
816
1974
|
kind: "attribute",
|
|
@@ -860,7 +2018,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
860
2018
|
(child) => core.types.isJSXExpressionContainer(child) && !core.types.isJSXEmptyExpression(child.expression)
|
|
861
2019
|
);
|
|
862
2020
|
for (const child of expressions) {
|
|
863
|
-
const unsupported =
|
|
2021
|
+
const unsupported = validateBindingExpression(child.expression);
|
|
864
2022
|
if (unsupported) return `compiled keyed row text cannot use ${unsupported}`;
|
|
865
2023
|
}
|
|
866
2024
|
if (nestedElements.length > 0 && expressions.length > 0) {
|
|
@@ -876,7 +2034,11 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
876
2034
|
parts.push(cloneExpression(child.expression));
|
|
877
2035
|
}
|
|
878
2036
|
}
|
|
879
|
-
bindings.push({
|
|
2037
|
+
bindings.push({
|
|
2038
|
+
kind: "text",
|
|
2039
|
+
path: [...path],
|
|
2040
|
+
value: core.types.arrayExpression(parts)
|
|
2041
|
+
});
|
|
880
2042
|
}
|
|
881
2043
|
let elementIndex = 0;
|
|
882
2044
|
for (const child of element.children) {
|
|
@@ -890,7 +2052,7 @@ function analyzeKeyedRowTree(row, renderCallback, safeGlobals, compilerSetters)
|
|
|
890
2052
|
const reason = visit(row, []);
|
|
891
2053
|
return reason ? { reason } : { bindings, events, conditionals };
|
|
892
2054
|
}
|
|
893
|
-
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false) {
|
|
2055
|
+
function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acceptUnsupportedRow = false, allowMembershipTargets = false) {
|
|
894
2056
|
let collection;
|
|
895
2057
|
let keyCallback;
|
|
896
2058
|
let renderCallback;
|
|
@@ -943,7 +2105,8 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acce
|
|
|
943
2105
|
row,
|
|
944
2106
|
renderCallback,
|
|
945
2107
|
safeGlobals,
|
|
946
|
-
new Set([...statesByValue.values()].map((state) => state.setterName))
|
|
2108
|
+
new Set([...statesByValue.values()].map((state) => state.setterName)),
|
|
2109
|
+
allowMembershipTargets ? statesByValue : void 0
|
|
947
2110
|
);
|
|
948
2111
|
if (rowAnalysis.reason && !acceptUnsupportedRow) return void 0;
|
|
949
2112
|
const keyExpression = returnedExpression(keyCallback);
|
|
@@ -956,6 +2119,7 @@ function analyzeKeyedRowChild(child, statesByValue, safeGlobals, listNames, acce
|
|
|
956
2119
|
return {
|
|
957
2120
|
source,
|
|
958
2121
|
collection,
|
|
2122
|
+
collectionDependency: core.types.isIdentifier(collection) ? statesByValue.get(collection.name)?.index : void 0,
|
|
959
2123
|
structureDependencies: [...structureDependencies].sort((left, right) => left - right),
|
|
960
2124
|
keyCallback,
|
|
961
2125
|
renderCallback,
|
|
@@ -975,16 +2139,83 @@ function analyzeKeyedRowsContainer(container, statesByValue, safeGlobals, listNa
|
|
|
975
2139
|
if (container.openingElement.attributes.some(
|
|
976
2140
|
(attribute) => core.types.isJSXSpreadAttribute(attribute) || core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && (attribute.name.name === "ref" || attribute.name.name === "dangerouslySetInnerHTML")
|
|
977
2141
|
)) {
|
|
978
|
-
return void 0;
|
|
2142
|
+
return void 0;
|
|
2143
|
+
}
|
|
2144
|
+
for (const attribute of container.openingElement.attributes) {
|
|
2145
|
+
if (core.types.isJSXAttribute(attribute) && core.types.isJSXIdentifier(attribute.name) && core.types.isJSXExpressionContainer(attribute.value) && !core.types.isJSXEmptyExpression(attribute.value.expression) && !/^on[A-Z]/.test(attribute.name.name) && collectStateDependencies(attribute.value.expression, statesByValue).length > 0) {
|
|
2146
|
+
return void 0;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
const children = meaningfulJsxChildren(container);
|
|
2150
|
+
if (children.length !== 1) return void 0;
|
|
2151
|
+
const shape = analyzeKeyedRowChild(
|
|
2152
|
+
children[0],
|
|
2153
|
+
statesByValue,
|
|
2154
|
+
safeGlobals,
|
|
2155
|
+
listNames,
|
|
2156
|
+
true,
|
|
2157
|
+
true
|
|
2158
|
+
);
|
|
2159
|
+
if (!shape || shape.rowReason) return shape;
|
|
2160
|
+
const needsMembershipProof = (binding) => containsPotentialKeyedMembershipCall(binding.value, statesByValue);
|
|
2161
|
+
const needsMapLookupProof = (binding) => containsPotentialKeyedMapLookupCall(binding.value, statesByValue);
|
|
2162
|
+
if (shape.conditionals.length > 0 || shape.events.length > 0 && !canDelegateKeyedRowEvents({
|
|
2163
|
+
conditionals: shape.conditionals,
|
|
2164
|
+
events: shape.events,
|
|
2165
|
+
source: container
|
|
2166
|
+
})) {
|
|
2167
|
+
return shape.bindings.some(
|
|
2168
|
+
(binding) => needsMembershipProof(binding) || needsMapLookupProof(binding)
|
|
2169
|
+
) ? {
|
|
2170
|
+
...shape,
|
|
2171
|
+
rowReason: "keyed collection targets require compiler-owned rows without React-owned branches or events"
|
|
2172
|
+
} : shape;
|
|
2173
|
+
}
|
|
2174
|
+
const structureDependencies = new Set(shape.structureDependencies);
|
|
2175
|
+
const bindings = shape.bindings.map((binding) => ({
|
|
2176
|
+
...binding,
|
|
2177
|
+
identityTarget: keyedIdentityTarget(
|
|
2178
|
+
binding,
|
|
2179
|
+
shape.keyCallback,
|
|
2180
|
+
shape.renderCallback,
|
|
2181
|
+
statesByValue,
|
|
2182
|
+
structureDependencies
|
|
2183
|
+
),
|
|
2184
|
+
membershipTarget: keyedMembershipTarget(
|
|
2185
|
+
binding,
|
|
2186
|
+
shape.keyCallback,
|
|
2187
|
+
shape.renderCallback,
|
|
2188
|
+
statesByValue,
|
|
2189
|
+
structureDependencies
|
|
2190
|
+
),
|
|
2191
|
+
mapLookupTarget: keyedMapLookupTarget(
|
|
2192
|
+
binding,
|
|
2193
|
+
shape.keyCallback,
|
|
2194
|
+
shape.renderCallback,
|
|
2195
|
+
statesByValue,
|
|
2196
|
+
structureDependencies
|
|
2197
|
+
)
|
|
2198
|
+
}));
|
|
2199
|
+
if (bindings.some(
|
|
2200
|
+
(binding, index) => needsMembershipProof(shape.bindings[index]) && !binding.membershipTarget
|
|
2201
|
+
)) {
|
|
2202
|
+
return {
|
|
2203
|
+
...shape,
|
|
2204
|
+
rowReason: "keyed membership targets must call one local Set state with the exact row key"
|
|
2205
|
+
};
|
|
979
2206
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
2207
|
+
if (bindings.some(
|
|
2208
|
+
(binding, index) => needsMapLookupProof(shape.bindings[index]) && !binding.mapLookupTarget
|
|
2209
|
+
)) {
|
|
2210
|
+
return {
|
|
2211
|
+
...shape,
|
|
2212
|
+
rowReason: "keyed Map lookup targets must call one local Map state with the exact row key"
|
|
2213
|
+
};
|
|
984
2214
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
2215
|
+
return {
|
|
2216
|
+
...shape,
|
|
2217
|
+
bindings
|
|
2218
|
+
};
|
|
988
2219
|
}
|
|
989
2220
|
function analyzeKeyedRangesContainer(container, statesByValue, safeGlobals, listNames, allowSingleRange = false) {
|
|
990
2221
|
if (container.openingElement.attributes.some(
|
|
@@ -1140,7 +2371,11 @@ function analyzeHostConditionalTree(branch, safeGlobals, allowStaticEvents = fal
|
|
|
1140
2371
|
parts.push(cloneExpression(child.expression));
|
|
1141
2372
|
}
|
|
1142
2373
|
}
|
|
1143
|
-
bindings.push({
|
|
2374
|
+
bindings.push({
|
|
2375
|
+
kind: "text",
|
|
2376
|
+
path: [...path],
|
|
2377
|
+
value: core.types.arrayExpression(parts)
|
|
2378
|
+
});
|
|
1144
2379
|
}
|
|
1145
2380
|
let elementIndex = 0;
|
|
1146
2381
|
for (const child of element.children) {
|
|
@@ -1312,7 +2547,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1312
2547
|
listNames,
|
|
1313
2548
|
id,
|
|
1314
2549
|
allocateId
|
|
1315
|
-
) : {
|
|
2550
|
+
) : {
|
|
2551
|
+
bindings: [],
|
|
2552
|
+
plans: [],
|
|
2553
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2554
|
+
};
|
|
1316
2555
|
const falsy = shape.falsy ? analyzeRecursiveHostTree(
|
|
1317
2556
|
shape.falsy,
|
|
1318
2557
|
statesByValue,
|
|
@@ -1320,7 +2559,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1320
2559
|
listNames,
|
|
1321
2560
|
id,
|
|
1322
2561
|
allocateId
|
|
1323
|
-
) : {
|
|
2562
|
+
) : {
|
|
2563
|
+
bindings: [],
|
|
2564
|
+
plans: [],
|
|
2565
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2566
|
+
};
|
|
1324
2567
|
if (truthy.reason) return truthy.reason;
|
|
1325
2568
|
if (falsy.reason) return falsy.reason;
|
|
1326
2569
|
plans.push(...truthy.plans, ...falsy.plans);
|
|
@@ -1478,7 +2721,11 @@ function analyzeRecursiveHostTree(branch, statesByValue, safeGlobals, listNames,
|
|
|
1478
2721
|
parts.push(cloneExpression(child.expression));
|
|
1479
2722
|
}
|
|
1480
2723
|
}
|
|
1481
|
-
bindings.push({
|
|
2724
|
+
bindings.push({
|
|
2725
|
+
kind: "text",
|
|
2726
|
+
path: [...path],
|
|
2727
|
+
value: core.types.arrayExpression(parts)
|
|
2728
|
+
});
|
|
1482
2729
|
}
|
|
1483
2730
|
let elementIndex = 0;
|
|
1484
2731
|
for (const child of element.children) {
|
|
@@ -1545,7 +2792,11 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals,
|
|
|
1545
2792
|
listNames,
|
|
1546
2793
|
parent,
|
|
1547
2794
|
allocateId
|
|
1548
|
-
) : {
|
|
2795
|
+
) : {
|
|
2796
|
+
bindings: [],
|
|
2797
|
+
plans: [],
|
|
2798
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2799
|
+
};
|
|
1549
2800
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1550
2801
|
shape.falsy,
|
|
1551
2802
|
statesByValue,
|
|
@@ -1553,7 +2804,11 @@ function analyzeHostConditionalContainer(container, statesByValue, safeGlobals,
|
|
|
1553
2804
|
listNames,
|
|
1554
2805
|
parent,
|
|
1555
2806
|
allocateId
|
|
1556
|
-
) : {
|
|
2807
|
+
) : {
|
|
2808
|
+
bindings: [],
|
|
2809
|
+
plans: [],
|
|
2810
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2811
|
+
};
|
|
1557
2812
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1558
2813
|
const dependencies = new Set(collectStateDependencies(shape.test, statesByValue));
|
|
1559
2814
|
for (const binding of [...truthyAnalysis.bindings || [], ...falsyAnalysis.bindings || []]) {
|
|
@@ -1599,7 +2854,11 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1599
2854
|
listNames,
|
|
1600
2855
|
parent,
|
|
1601
2856
|
allocateId
|
|
1602
|
-
) : {
|
|
2857
|
+
) : {
|
|
2858
|
+
bindings: [],
|
|
2859
|
+
plans: [],
|
|
2860
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2861
|
+
};
|
|
1603
2862
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1604
2863
|
shape.falsy,
|
|
1605
2864
|
statesByValue,
|
|
@@ -1607,7 +2866,11 @@ function analyzeConditionalRangesContainer(container, statesByValue, safeGlobals
|
|
|
1607
2866
|
listNames,
|
|
1608
2867
|
parent,
|
|
1609
2868
|
allocateId
|
|
1610
|
-
) : {
|
|
2869
|
+
) : {
|
|
2870
|
+
bindings: [],
|
|
2871
|
+
plans: [],
|
|
2872
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2873
|
+
};
|
|
1611
2874
|
if (truthyAnalysis.reason || falsyAnalysis.reason) return void 0;
|
|
1612
2875
|
nestedPlans.push(...truthyAnalysis.plans, ...falsyAnalysis.plans);
|
|
1613
2876
|
for (const [element, plan] of truthyAnalysis.blocks) descriptorBlocks.set(element, plan);
|
|
@@ -1700,7 +2963,11 @@ function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
1700
2963
|
listNames,
|
|
1701
2964
|
parent,
|
|
1702
2965
|
allocateId
|
|
1703
|
-
) : {
|
|
2966
|
+
) : {
|
|
2967
|
+
bindings: [],
|
|
2968
|
+
plans: [],
|
|
2969
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2970
|
+
};
|
|
1704
2971
|
const falsyAnalysis = shape.falsy ? analyzeRecursiveHostTree(
|
|
1705
2972
|
shape.falsy,
|
|
1706
2973
|
statesByValue,
|
|
@@ -1708,7 +2975,11 @@ function analyzeMixedRangesContainer(container, statesByValue, safeGlobals, list
|
|
|
1708
2975
|
listNames,
|
|
1709
2976
|
parent,
|
|
1710
2977
|
allocateId
|
|
1711
|
-
) : {
|
|
2978
|
+
) : {
|
|
2979
|
+
bindings: [],
|
|
2980
|
+
plans: [],
|
|
2981
|
+
blocks: /* @__PURE__ */ new Map()
|
|
2982
|
+
};
|
|
1712
2983
|
if (!mergeAnalysis(truthyAnalysis) || !mergeAnalysis(falsyAnalysis)) return void 0;
|
|
1713
2984
|
for (const dependency of collectStateDependencies(shape.test, statesByValue)) {
|
|
1714
2985
|
dependencies.add(dependency);
|
|
@@ -1949,6 +3220,57 @@ function keyedRowBindingObject(binding, parameters) {
|
|
|
1949
3220
|
if (binding.name) {
|
|
1950
3221
|
properties.push(core.types.objectProperty(core.types.identifier("name"), core.types.stringLiteral(binding.name)));
|
|
1951
3222
|
}
|
|
3223
|
+
if (binding.identityTarget) {
|
|
3224
|
+
properties.push(
|
|
3225
|
+
core.types.objectProperty(
|
|
3226
|
+
core.types.identifier("identityTarget"),
|
|
3227
|
+
core.types.objectExpression([
|
|
3228
|
+
core.types.objectProperty(
|
|
3229
|
+
core.types.identifier("dependency"),
|
|
3230
|
+
core.types.numericLiteral(binding.identityTarget.dependency)
|
|
3231
|
+
),
|
|
3232
|
+
core.types.objectProperty(
|
|
3233
|
+
core.types.identifier("read"),
|
|
3234
|
+
core.types.arrowFunctionExpression([], cloneExpression(binding.identityTarget.value))
|
|
3235
|
+
)
|
|
3236
|
+
])
|
|
3237
|
+
)
|
|
3238
|
+
);
|
|
3239
|
+
}
|
|
3240
|
+
if (binding.membershipTarget) {
|
|
3241
|
+
properties.push(
|
|
3242
|
+
core.types.objectProperty(
|
|
3243
|
+
core.types.identifier("membershipTarget"),
|
|
3244
|
+
core.types.objectExpression([
|
|
3245
|
+
core.types.objectProperty(
|
|
3246
|
+
core.types.identifier("dependency"),
|
|
3247
|
+
core.types.numericLiteral(binding.membershipTarget.dependency)
|
|
3248
|
+
),
|
|
3249
|
+
core.types.objectProperty(
|
|
3250
|
+
core.types.identifier("read"),
|
|
3251
|
+
core.types.arrowFunctionExpression([], cloneExpression(binding.membershipTarget.value))
|
|
3252
|
+
)
|
|
3253
|
+
])
|
|
3254
|
+
)
|
|
3255
|
+
);
|
|
3256
|
+
}
|
|
3257
|
+
if (binding.mapLookupTarget) {
|
|
3258
|
+
properties.push(
|
|
3259
|
+
core.types.objectProperty(
|
|
3260
|
+
core.types.identifier("mapLookupTarget"),
|
|
3261
|
+
core.types.objectExpression([
|
|
3262
|
+
core.types.objectProperty(
|
|
3263
|
+
core.types.identifier("dependency"),
|
|
3264
|
+
core.types.numericLiteral(binding.mapLookupTarget.dependency)
|
|
3265
|
+
),
|
|
3266
|
+
core.types.objectProperty(
|
|
3267
|
+
core.types.identifier("read"),
|
|
3268
|
+
core.types.arrowFunctionExpression([], cloneExpression(binding.mapLookupTarget.value))
|
|
3269
|
+
)
|
|
3270
|
+
])
|
|
3271
|
+
)
|
|
3272
|
+
);
|
|
3273
|
+
}
|
|
1952
3274
|
properties.push(
|
|
1953
3275
|
core.types.objectProperty(
|
|
1954
3276
|
core.types.identifier("read"),
|
|
@@ -2143,7 +3465,7 @@ function keyedRowConditionalObject(conditional, parameters) {
|
|
|
2143
3465
|
}
|
|
2144
3466
|
return core.types.objectExpression(properties);
|
|
2145
3467
|
}
|
|
2146
|
-
function keyedRowsBoundary(blockRuntime, plan) {
|
|
3468
|
+
function keyedRowsBoundary(blockRuntime, plan, keyedMapUpdateHints, keyedArrayFilterHintedStateIndices, keyedArrayPrependHintedStateIndices, keyedArrayPositionHintedStateIndices, keyedArrayReorderHintedStateIndices) {
|
|
2147
3469
|
const name = core.types.jsxMemberExpression(
|
|
2148
3470
|
core.types.jsxIdentifier(blockRuntime.name),
|
|
2149
3471
|
core.types.jsxIdentifier("KeyedRows")
|
|
@@ -2177,6 +3499,16 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
2177
3499
|
core.types.jsxIdentifier("items"),
|
|
2178
3500
|
core.types.jsxExpressionContainer(core.types.arrowFunctionExpression([], cloneExpression(plan.collection)))
|
|
2179
3501
|
),
|
|
3502
|
+
...keyedMapUpdateHints ? [
|
|
3503
|
+
core.types.jsxAttribute(
|
|
3504
|
+
core.types.jsxIdentifier("dependencies"),
|
|
3505
|
+
core.types.jsxExpressionContainer(
|
|
3506
|
+
core.types.arrayExpression(
|
|
3507
|
+
plan.dependencies.map((dependency) => core.types.numericLiteral(dependency))
|
|
3508
|
+
)
|
|
3509
|
+
)
|
|
3510
|
+
)
|
|
3511
|
+
] : [],
|
|
2180
3512
|
core.types.jsxAttribute(
|
|
2181
3513
|
core.types.jsxIdentifier("structureDependencies"),
|
|
2182
3514
|
core.types.jsxExpressionContainer(
|
|
@@ -2185,6 +3517,36 @@ function keyedRowsBoundary(blockRuntime, plan) {
|
|
|
2185
3517
|
)
|
|
2186
3518
|
)
|
|
2187
3519
|
),
|
|
3520
|
+
...!keyedMapUpdateHints || plan.collectionDependency === void 0 ? [] : [
|
|
3521
|
+
core.types.jsxAttribute(
|
|
3522
|
+
core.types.jsxIdentifier("collectionDependency"),
|
|
3523
|
+
core.types.jsxExpressionContainer(core.types.numericLiteral(plan.collectionDependency))
|
|
3524
|
+
)
|
|
3525
|
+
],
|
|
3526
|
+
...plan.collectionDependency !== void 0 && keyedArrayFilterHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3527
|
+
core.types.jsxAttribute(
|
|
3528
|
+
core.types.jsxIdentifier("filterIndexIndependent"),
|
|
3529
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3530
|
+
)
|
|
3531
|
+
] : [],
|
|
3532
|
+
...plan.collectionDependency !== void 0 && keyedArrayPrependHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3533
|
+
core.types.jsxAttribute(
|
|
3534
|
+
core.types.jsxIdentifier("prependIndexIndependent"),
|
|
3535
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3536
|
+
)
|
|
3537
|
+
] : [],
|
|
3538
|
+
...plan.collectionDependency !== void 0 && keyedArrayPositionHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3539
|
+
core.types.jsxAttribute(
|
|
3540
|
+
core.types.jsxIdentifier("positionIndexIndependent"),
|
|
3541
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3542
|
+
)
|
|
3543
|
+
] : [],
|
|
3544
|
+
...plan.collectionDependency !== void 0 && keyedArrayReorderHintedStateIndices.has(plan.collectionDependency) ? [
|
|
3545
|
+
core.types.jsxAttribute(
|
|
3546
|
+
core.types.jsxIdentifier("reorderIndexIndependent"),
|
|
3547
|
+
core.types.jsxExpressionContainer(core.types.booleanLiteral(true))
|
|
3548
|
+
)
|
|
3549
|
+
] : [],
|
|
2188
3550
|
core.types.jsxAttribute(
|
|
2189
3551
|
core.types.jsxIdentifier("rowKey"),
|
|
2190
3552
|
core.types.jsxExpressionContainer(core.types.cloneNode(plan.keyCallback, true))
|
|
@@ -2511,7 +3873,9 @@ function conditionalRangesBoundary(blockRuntime, plan) {
|
|
|
2511
3873
|
function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allowedComponentNames) {
|
|
2512
3874
|
const name = element.openingElement.name;
|
|
2513
3875
|
if (!core.types.isJSXIdentifier(name) || !isComponentName(name.name)) {
|
|
2514
|
-
return {
|
|
3876
|
+
return {
|
|
3877
|
+
reason: "component islands require a direct component identifier"
|
|
3878
|
+
};
|
|
2515
3879
|
}
|
|
2516
3880
|
if (!allowedComponentNames.has(name.name)) {
|
|
2517
3881
|
return {
|
|
@@ -2519,19 +3883,27 @@ function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allo
|
|
|
2519
3883
|
};
|
|
2520
3884
|
}
|
|
2521
3885
|
if (meaningfulJsxChildren(element).length > 0) {
|
|
2522
|
-
return {
|
|
3886
|
+
return {
|
|
3887
|
+
reason: `component island ${name.name} does not support children yet`
|
|
3888
|
+
};
|
|
2523
3889
|
}
|
|
2524
3890
|
const dependencies = /* @__PURE__ */ new Set();
|
|
2525
3891
|
for (const attribute of element.openingElement.attributes) {
|
|
2526
3892
|
if (core.types.isJSXSpreadAttribute(attribute)) {
|
|
2527
|
-
return {
|
|
3893
|
+
return {
|
|
3894
|
+
reason: `component island ${name.name} does not support JSX attribute spreads`
|
|
3895
|
+
};
|
|
2528
3896
|
}
|
|
2529
3897
|
const attributeName = jsxAttributeName(attribute);
|
|
2530
3898
|
if (!attributeName) {
|
|
2531
|
-
return {
|
|
3899
|
+
return {
|
|
3900
|
+
reason: `component island ${name.name} does not support namespaced JSX attributes`
|
|
3901
|
+
};
|
|
2532
3902
|
}
|
|
2533
3903
|
if (attributeName === "ref" || attributeName === "key" || attributeName === "children") {
|
|
2534
|
-
return {
|
|
3904
|
+
return {
|
|
3905
|
+
reason: `component island ${name.name} does not support ${attributeName} yet`
|
|
3906
|
+
};
|
|
2535
3907
|
}
|
|
2536
3908
|
if (!core.types.isJSXExpressionContainer(attribute.value) || core.types.isJSXEmptyExpression(attribute.value.expression)) {
|
|
2537
3909
|
continue;
|
|
@@ -2550,7 +3922,9 @@ function analyzeComponentIslandElement(element, statesByValue, safeGlobals, allo
|
|
|
2550
3922
|
(dependency) => dependencies.add(dependency)
|
|
2551
3923
|
);
|
|
2552
3924
|
}
|
|
2553
|
-
return {
|
|
3925
|
+
return {
|
|
3926
|
+
dependencies: [...dependencies].sort((left, right) => left - right)
|
|
3927
|
+
};
|
|
2554
3928
|
}
|
|
2555
3929
|
function componentIslandBoundary(blockRuntime, plan, source) {
|
|
2556
3930
|
const name = core.types.jsxMemberExpression(
|
|
@@ -2807,6 +4181,7 @@ function analyzeComposableBlocks(root, statesByValue, safeGlobals, listNames, al
|
|
|
2807
4181
|
dependencies: keyedRows.dependencies,
|
|
2808
4182
|
source: child,
|
|
2809
4183
|
collection: keyedRows.collection,
|
|
4184
|
+
collectionDependency: keyedRows.collectionDependency,
|
|
2810
4185
|
structureDependencies: keyedRows.structureDependencies,
|
|
2811
4186
|
keyCallback: keyedRows.keyCallback,
|
|
2812
4187
|
renderCallback: keyedRows.renderCallback,
|
|
@@ -3048,7 +4423,7 @@ function conditionalBlockBoundary(blockRuntime, plan, source) {
|
|
|
3048
4423
|
true
|
|
3049
4424
|
);
|
|
3050
4425
|
}
|
|
3051
|
-
function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
4426
|
+
function lowerComposableBlocks(root, plans, blockRuntime, listNames, keyedMapUpdateHints, keyedArrayFilterHintedStateIndices, keyedArrayPrependHintedStateIndices, keyedArrayPositionHintedStateIndices, keyedArrayReorderHintedStateIndices) {
|
|
3052
4427
|
const planBySource = new Map(
|
|
3053
4428
|
plans.map((plan) => [plan.source, plan])
|
|
3054
4429
|
);
|
|
@@ -3073,7 +4448,15 @@ function lowerComposableBlocks(root, plans, blockRuntime, listNames) {
|
|
|
3073
4448
|
return mixedRangesBoundary(blockRuntime, plan2);
|
|
3074
4449
|
}
|
|
3075
4450
|
if (plan2?.kind === "keyed-rows") {
|
|
3076
|
-
return keyedRowsBoundary(
|
|
4451
|
+
return keyedRowsBoundary(
|
|
4452
|
+
blockRuntime,
|
|
4453
|
+
plan2,
|
|
4454
|
+
keyedMapUpdateHints,
|
|
4455
|
+
keyedArrayFilterHintedStateIndices,
|
|
4456
|
+
keyedArrayPrependHintedStateIndices,
|
|
4457
|
+
keyedArrayPositionHintedStateIndices,
|
|
4458
|
+
keyedArrayReorderHintedStateIndices
|
|
4459
|
+
);
|
|
3077
4460
|
}
|
|
3078
4461
|
if (plan2?.kind === "keyed-ranges") {
|
|
3079
4462
|
return keyedRangesBoundary(blockRuntime, plan2);
|
|
@@ -3436,7 +4819,7 @@ function wrapperElement(definitionIdentifier, props) {
|
|
|
3436
4819
|
const attributes = props ? [core.types.jsxSpreadAttribute(core.types.cloneNode(props))] : [];
|
|
3437
4820
|
return core.types.jsxElement(core.types.jsxOpeningElement(name, attributes, true), null, [], true);
|
|
3438
4821
|
}
|
|
3439
|
-
function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureIdentifiers, usedRuntimeFeatures, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
4822
|
+
function compileCandidate(candidate, createComponentIdentifier, keyedMapUpdateIdentifier, keyedArrayAppendIdentifier, keyedArrayFilterIdentifier, keyedArrayPrependIdentifier, keyedArrayPositionIdentifier, keyedArrayReorderIdentifier, keyedArraySortIdentifier, keyedArrayRollingWindowIdentifier, keyedArraySliceIdentifier, keyedCollectionUpdateIdentifier, keyedCollectionMutationIdentifier, runtimeFeatureIdentifiers, usedRuntimeFeatures, optimizationCounts, useStateNames, reactNames, listNames, moduleId, reactivity) {
|
|
3440
4823
|
const { path, name, statementPath } = candidate;
|
|
3441
4824
|
if (path.node.async || path.node.generator)
|
|
3442
4825
|
return "async and generator components are not supported";
|
|
@@ -3448,6 +4831,7 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3448
4831
|
const safeGlobals = new Set(
|
|
3449
4832
|
[...SAFE_GLOBAL_CALLS, "Math"].filter((name2) => !path.scope.getBinding(name2))
|
|
3450
4833
|
);
|
|
4834
|
+
const globalCollections = new Set(["Set", "Map"].filter((name2) => !path.scope.getBinding(name2)));
|
|
3451
4835
|
const states = [];
|
|
3452
4836
|
const locals = [];
|
|
3453
4837
|
let returned;
|
|
@@ -3495,9 +4879,17 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3495
4879
|
if (declaration.init.async || declaration.init.generator) {
|
|
3496
4880
|
return `event handler ${declaration.id.name} must be synchronous`;
|
|
3497
4881
|
}
|
|
3498
|
-
locals.push({
|
|
4882
|
+
locals.push({
|
|
4883
|
+
kind: "handler",
|
|
4884
|
+
name: declaration.id.name,
|
|
4885
|
+
value: declaration.init
|
|
4886
|
+
});
|
|
3499
4887
|
} else {
|
|
3500
|
-
locals.push({
|
|
4888
|
+
locals.push({
|
|
4889
|
+
kind: "derived",
|
|
4890
|
+
name: declaration.id.name,
|
|
4891
|
+
value: declaration.init
|
|
4892
|
+
});
|
|
3501
4893
|
}
|
|
3502
4894
|
}
|
|
3503
4895
|
if (states.length === 0) return "no local useState binding was found";
|
|
@@ -3636,8 +5028,413 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3636
5028
|
}
|
|
3637
5029
|
if (blockAnalysis.reason) return blockAnalysis.reason;
|
|
3638
5030
|
if (analysis.reason) return analysis.reason;
|
|
5031
|
+
const hintedStateIndices = new Set(
|
|
5032
|
+
(blockAnalysis.plans || []).filter(
|
|
5033
|
+
(plan) => plan.kind === "keyed-rows" && plan.collectionDependency !== void 0
|
|
5034
|
+
).map((plan) => plan.collectionDependency)
|
|
5035
|
+
);
|
|
5036
|
+
const hintedRoot = rewriteKeyedMapUpdateHints(
|
|
5037
|
+
expandedReactiveRoot,
|
|
5038
|
+
hintedStateIndices,
|
|
5039
|
+
statesBySetter,
|
|
5040
|
+
keyedMapUpdateIdentifier,
|
|
5041
|
+
safeGlobals
|
|
5042
|
+
);
|
|
5043
|
+
let appliedKeyedMapUpdateHints = 0;
|
|
5044
|
+
if (hintedRoot.count > 0) {
|
|
5045
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5046
|
+
hintedRoot.root,
|
|
5047
|
+
reactiveByValue,
|
|
5048
|
+
safeGlobals,
|
|
5049
|
+
listNames,
|
|
5050
|
+
allowedComponentNames
|
|
5051
|
+
);
|
|
5052
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5053
|
+
hintedRoot.root,
|
|
5054
|
+
reactiveByValue,
|
|
5055
|
+
safeGlobals,
|
|
5056
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5057
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5058
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5059
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5060
|
+
);
|
|
5061
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5062
|
+
expandedReactiveRoot = hintedRoot.root;
|
|
5063
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5064
|
+
analysis = hintedAnalysis;
|
|
5065
|
+
appliedKeyedMapUpdateHints = hintedRoot.count;
|
|
5066
|
+
optimizationCounts.keyedMapUpdateHints += hintedRoot.count;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
const appendHintedStateIndices = new Set(hintedStateIndices);
|
|
5070
|
+
for (const plan of blockAnalysis.plans || []) {
|
|
5071
|
+
if (plan.kind !== "keyed-rows" || plan.collectionDependency === void 0) continue;
|
|
5072
|
+
const keyExpression = returnedExpression(plan.keyCallback);
|
|
5073
|
+
if (!keyExpression || collectStateDependencies(keyExpression, reactiveByValue).includes(plan.collectionDependency)) {
|
|
5074
|
+
appendHintedStateIndices.delete(plan.collectionDependency);
|
|
5075
|
+
}
|
|
5076
|
+
}
|
|
5077
|
+
const appendHintedRoot = rewriteKeyedArrayAppendHints(
|
|
5078
|
+
expandedReactiveRoot,
|
|
5079
|
+
appendHintedStateIndices,
|
|
5080
|
+
statesBySetter,
|
|
5081
|
+
keyedArrayAppendIdentifier,
|
|
5082
|
+
safeGlobals
|
|
5083
|
+
);
|
|
5084
|
+
let appliedKeyedArrayAppendHints = 0;
|
|
5085
|
+
if (appendHintedRoot.count > 0) {
|
|
5086
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5087
|
+
appendHintedRoot.root,
|
|
5088
|
+
reactiveByValue,
|
|
5089
|
+
safeGlobals,
|
|
5090
|
+
listNames,
|
|
5091
|
+
allowedComponentNames
|
|
5092
|
+
);
|
|
5093
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5094
|
+
appendHintedRoot.root,
|
|
5095
|
+
reactiveByValue,
|
|
5096
|
+
safeGlobals,
|
|
5097
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5098
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5099
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5100
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5101
|
+
);
|
|
5102
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5103
|
+
expandedReactiveRoot = appendHintedRoot.root;
|
|
5104
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5105
|
+
analysis = hintedAnalysis;
|
|
5106
|
+
appliedKeyedArrayAppendHints = appendHintedRoot.count;
|
|
5107
|
+
optimizationCounts.keyedArrayAppendHints += appendHintedRoot.count;
|
|
5108
|
+
}
|
|
5109
|
+
}
|
|
5110
|
+
const shiftedIndexIndependentStateIndices = new Set(hintedStateIndices);
|
|
5111
|
+
for (const plan of blockAnalysis.plans || []) {
|
|
5112
|
+
if (plan.kind !== "keyed-rows" || plan.collectionDependency === void 0) continue;
|
|
5113
|
+
const keyExpression = returnedExpression(plan.keyCallback);
|
|
5114
|
+
if (plan.renderCallback.params.length > 1 || !keyExpression || collectStateDependencies(keyExpression, reactiveByValue).includes(plan.collectionDependency)) {
|
|
5115
|
+
shiftedIndexIndependentStateIndices.delete(plan.collectionDependency);
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
const prependHintedRoot = rewriteKeyedArrayPrependHints(
|
|
5119
|
+
expandedReactiveRoot,
|
|
5120
|
+
shiftedIndexIndependentStateIndices,
|
|
5121
|
+
statesBySetter,
|
|
5122
|
+
keyedArrayPrependIdentifier,
|
|
5123
|
+
safeGlobals
|
|
5124
|
+
);
|
|
5125
|
+
let appliedKeyedArrayPrependHints = 0;
|
|
5126
|
+
let appliedPrependHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5127
|
+
if (prependHintedRoot.count > 0) {
|
|
5128
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5129
|
+
prependHintedRoot.root,
|
|
5130
|
+
reactiveByValue,
|
|
5131
|
+
safeGlobals,
|
|
5132
|
+
listNames,
|
|
5133
|
+
allowedComponentNames
|
|
5134
|
+
);
|
|
5135
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5136
|
+
prependHintedRoot.root,
|
|
5137
|
+
reactiveByValue,
|
|
5138
|
+
safeGlobals,
|
|
5139
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5140
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5141
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5142
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5143
|
+
);
|
|
5144
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5145
|
+
expandedReactiveRoot = prependHintedRoot.root;
|
|
5146
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5147
|
+
analysis = hintedAnalysis;
|
|
5148
|
+
appliedKeyedArrayPrependHints = prependHintedRoot.count;
|
|
5149
|
+
appliedPrependHintedStateIndices = prependHintedRoot.stateIndices;
|
|
5150
|
+
optimizationCounts.keyedArrayPrependHints += prependHintedRoot.count;
|
|
5151
|
+
}
|
|
5152
|
+
}
|
|
5153
|
+
const rollingWindowHintedRoot = rewriteKeyedArrayRollingWindowHints(
|
|
5154
|
+
expandedReactiveRoot,
|
|
5155
|
+
shiftedIndexIndependentStateIndices,
|
|
5156
|
+
statesBySetter,
|
|
5157
|
+
keyedArraySliceIdentifier,
|
|
5158
|
+
keyedArrayRollingWindowIdentifier,
|
|
5159
|
+
safeGlobals
|
|
5160
|
+
);
|
|
5161
|
+
let appliedKeyedArrayRollingWindowHints = 0;
|
|
5162
|
+
let appliedRollingWindowHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5163
|
+
if (rollingWindowHintedRoot.count > 0) {
|
|
5164
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5165
|
+
rollingWindowHintedRoot.root,
|
|
5166
|
+
reactiveByValue,
|
|
5167
|
+
safeGlobals,
|
|
5168
|
+
listNames,
|
|
5169
|
+
allowedComponentNames
|
|
5170
|
+
);
|
|
5171
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5172
|
+
rollingWindowHintedRoot.root,
|
|
5173
|
+
reactiveByValue,
|
|
5174
|
+
safeGlobals,
|
|
5175
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5176
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5177
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5178
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5179
|
+
);
|
|
5180
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5181
|
+
expandedReactiveRoot = rollingWindowHintedRoot.root;
|
|
5182
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5183
|
+
analysis = hintedAnalysis;
|
|
5184
|
+
appliedKeyedArrayRollingWindowHints = rollingWindowHintedRoot.count;
|
|
5185
|
+
appliedRollingWindowHintedStateIndices = rollingWindowHintedRoot.stateIndices;
|
|
5186
|
+
optimizationCounts.keyedArrayRollingWindowHints += rollingWindowHintedRoot.count;
|
|
5187
|
+
}
|
|
5188
|
+
}
|
|
5189
|
+
const positionHintedRoot = rewriteKeyedArrayPositionHints(
|
|
5190
|
+
expandedReactiveRoot,
|
|
5191
|
+
shiftedIndexIndependentStateIndices,
|
|
5192
|
+
statesBySetter,
|
|
5193
|
+
keyedArrayPositionIdentifier,
|
|
5194
|
+
safeGlobals
|
|
5195
|
+
);
|
|
5196
|
+
let appliedKeyedArrayPositionHints = 0;
|
|
5197
|
+
let appliedPositionHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5198
|
+
if (positionHintedRoot.count > 0) {
|
|
5199
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5200
|
+
positionHintedRoot.root,
|
|
5201
|
+
reactiveByValue,
|
|
5202
|
+
safeGlobals,
|
|
5203
|
+
listNames,
|
|
5204
|
+
allowedComponentNames
|
|
5205
|
+
);
|
|
5206
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5207
|
+
positionHintedRoot.root,
|
|
5208
|
+
reactiveByValue,
|
|
5209
|
+
safeGlobals,
|
|
5210
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5211
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5212
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5213
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5214
|
+
);
|
|
5215
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5216
|
+
expandedReactiveRoot = positionHintedRoot.root;
|
|
5217
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5218
|
+
analysis = hintedAnalysis;
|
|
5219
|
+
appliedKeyedArrayPositionHints = positionHintedRoot.count;
|
|
5220
|
+
appliedPositionHintedStateIndices = positionHintedRoot.stateIndices;
|
|
5221
|
+
optimizationCounts.keyedArrayPositionHints += positionHintedRoot.count;
|
|
5222
|
+
}
|
|
5223
|
+
}
|
|
5224
|
+
const reorderHintedRoot = rewriteKeyedArrayReorderHints(
|
|
5225
|
+
expandedReactiveRoot,
|
|
5226
|
+
shiftedIndexIndependentStateIndices,
|
|
5227
|
+
statesBySetter,
|
|
5228
|
+
keyedArrayReorderIdentifier
|
|
5229
|
+
);
|
|
5230
|
+
let appliedKeyedArrayReorderHints = 0;
|
|
5231
|
+
let appliedReorderHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5232
|
+
if (reorderHintedRoot.count > 0) {
|
|
5233
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5234
|
+
reorderHintedRoot.root,
|
|
5235
|
+
reactiveByValue,
|
|
5236
|
+
safeGlobals,
|
|
5237
|
+
listNames,
|
|
5238
|
+
allowedComponentNames
|
|
5239
|
+
);
|
|
5240
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5241
|
+
reorderHintedRoot.root,
|
|
5242
|
+
reactiveByValue,
|
|
5243
|
+
safeGlobals,
|
|
5244
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5245
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5246
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5247
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5248
|
+
);
|
|
5249
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5250
|
+
expandedReactiveRoot = reorderHintedRoot.root;
|
|
5251
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5252
|
+
analysis = hintedAnalysis;
|
|
5253
|
+
appliedKeyedArrayReorderHints = reorderHintedRoot.count;
|
|
5254
|
+
appliedReorderHintedStateIndices = reorderHintedRoot.stateIndices;
|
|
5255
|
+
optimizationCounts.keyedArrayReorderHints += reorderHintedRoot.count;
|
|
5256
|
+
}
|
|
5257
|
+
}
|
|
5258
|
+
const sortHintedRoot = rewriteKeyedArraySortHints(
|
|
5259
|
+
expandedReactiveRoot,
|
|
5260
|
+
shiftedIndexIndependentStateIndices,
|
|
5261
|
+
statesBySetter,
|
|
5262
|
+
keyedArraySortIdentifier,
|
|
5263
|
+
safeGlobals
|
|
5264
|
+
);
|
|
5265
|
+
let appliedKeyedArraySortHints = 0;
|
|
5266
|
+
let appliedSortHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5267
|
+
if (sortHintedRoot.count > 0) {
|
|
5268
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5269
|
+
sortHintedRoot.root,
|
|
5270
|
+
reactiveByValue,
|
|
5271
|
+
safeGlobals,
|
|
5272
|
+
listNames,
|
|
5273
|
+
allowedComponentNames
|
|
5274
|
+
);
|
|
5275
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5276
|
+
sortHintedRoot.root,
|
|
5277
|
+
reactiveByValue,
|
|
5278
|
+
safeGlobals,
|
|
5279
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5280
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5281
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5282
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5283
|
+
);
|
|
5284
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5285
|
+
expandedReactiveRoot = sortHintedRoot.root;
|
|
5286
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5287
|
+
analysis = hintedAnalysis;
|
|
5288
|
+
appliedKeyedArraySortHints = sortHintedRoot.count;
|
|
5289
|
+
appliedSortHintedStateIndices = sortHintedRoot.stateIndices;
|
|
5290
|
+
optimizationCounts.keyedArraySortHints += sortHintedRoot.count;
|
|
5291
|
+
}
|
|
5292
|
+
}
|
|
5293
|
+
const sliceHintedRoot = rewriteKeyedArraySliceHints(
|
|
5294
|
+
expandedReactiveRoot,
|
|
5295
|
+
shiftedIndexIndependentStateIndices,
|
|
5296
|
+
statesBySetter,
|
|
5297
|
+
keyedArraySliceIdentifier
|
|
5298
|
+
);
|
|
5299
|
+
let appliedKeyedArraySliceHints = 0;
|
|
5300
|
+
let appliedSliceHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5301
|
+
if (sliceHintedRoot.count > 0) {
|
|
5302
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5303
|
+
sliceHintedRoot.root,
|
|
5304
|
+
reactiveByValue,
|
|
5305
|
+
safeGlobals,
|
|
5306
|
+
listNames,
|
|
5307
|
+
allowedComponentNames
|
|
5308
|
+
);
|
|
5309
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5310
|
+
sliceHintedRoot.root,
|
|
5311
|
+
reactiveByValue,
|
|
5312
|
+
safeGlobals,
|
|
5313
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5314
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5315
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5316
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5317
|
+
);
|
|
5318
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5319
|
+
expandedReactiveRoot = sliceHintedRoot.root;
|
|
5320
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5321
|
+
analysis = hintedAnalysis;
|
|
5322
|
+
appliedKeyedArraySliceHints = sliceHintedRoot.count;
|
|
5323
|
+
appliedSliceHintedStateIndices = sliceHintedRoot.stateIndices;
|
|
5324
|
+
optimizationCounts.keyedArraySliceHints += sliceHintedRoot.count;
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
const filterHintedRoot = rewriteKeyedArrayFilterHints(
|
|
5328
|
+
expandedReactiveRoot,
|
|
5329
|
+
shiftedIndexIndependentStateIndices,
|
|
5330
|
+
statesBySetter,
|
|
5331
|
+
keyedArrayFilterIdentifier,
|
|
5332
|
+
safeGlobals
|
|
5333
|
+
);
|
|
5334
|
+
let appliedKeyedArrayFilterHints = 0;
|
|
5335
|
+
let appliedFilterHintedStateIndices = /* @__PURE__ */ new Set();
|
|
5336
|
+
if (filterHintedRoot.count > 0) {
|
|
5337
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5338
|
+
filterHintedRoot.root,
|
|
5339
|
+
reactiveByValue,
|
|
5340
|
+
safeGlobals,
|
|
5341
|
+
listNames,
|
|
5342
|
+
allowedComponentNames
|
|
5343
|
+
);
|
|
5344
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5345
|
+
filterHintedRoot.root,
|
|
5346
|
+
reactiveByValue,
|
|
5347
|
+
safeGlobals,
|
|
5348
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5349
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5350
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5351
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5352
|
+
);
|
|
5353
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5354
|
+
expandedReactiveRoot = filterHintedRoot.root;
|
|
5355
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5356
|
+
analysis = hintedAnalysis;
|
|
5357
|
+
appliedKeyedArrayFilterHints = filterHintedRoot.count;
|
|
5358
|
+
appliedFilterHintedStateIndices = filterHintedRoot.stateIndices;
|
|
5359
|
+
optimizationCounts.keyedArrayFilterHints += filterHintedRoot.count;
|
|
5360
|
+
}
|
|
5361
|
+
}
|
|
5362
|
+
const keyedCollectionTargetKinds = /* @__PURE__ */ new Map();
|
|
5363
|
+
const conflictingKeyedCollectionTargets = /* @__PURE__ */ new Set();
|
|
5364
|
+
for (const plan of blockAnalysis.plans || []) {
|
|
5365
|
+
if (plan.kind !== "keyed-rows") continue;
|
|
5366
|
+
for (const binding of plan.bindings) {
|
|
5367
|
+
const target = binding.membershipTarget || binding.mapLookupTarget;
|
|
5368
|
+
if (!target) continue;
|
|
5369
|
+
const kind = binding.membershipTarget ? "set" : "map";
|
|
5370
|
+
const previousKind = keyedCollectionTargetKinds.get(target.dependency);
|
|
5371
|
+
if (previousKind && previousKind !== kind) {
|
|
5372
|
+
conflictingKeyedCollectionTargets.add(target.dependency);
|
|
5373
|
+
} else {
|
|
5374
|
+
keyedCollectionTargetKinds.set(target.dependency, kind);
|
|
5375
|
+
}
|
|
5376
|
+
}
|
|
5377
|
+
}
|
|
5378
|
+
for (const dependency of conflictingKeyedCollectionTargets) {
|
|
5379
|
+
keyedCollectionTargetKinds.delete(dependency);
|
|
5380
|
+
}
|
|
5381
|
+
const keyedCollectionHintedRoot = rewriteKeyedCollectionUpdateHints(
|
|
5382
|
+
expandedReactiveRoot,
|
|
5383
|
+
keyedCollectionTargetKinds,
|
|
5384
|
+
states,
|
|
5385
|
+
statesBySetter,
|
|
5386
|
+
keyedCollectionUpdateIdentifier,
|
|
5387
|
+
keyedCollectionMutationIdentifier,
|
|
5388
|
+
globalCollections
|
|
5389
|
+
);
|
|
5390
|
+
if (keyedCollectionHintedRoot.count > 0) {
|
|
5391
|
+
const hintedBlockAnalysis = analyzeComposableBlocks(
|
|
5392
|
+
keyedCollectionHintedRoot.root,
|
|
5393
|
+
reactiveByValue,
|
|
5394
|
+
safeGlobals,
|
|
5395
|
+
listNames,
|
|
5396
|
+
allowedComponentNames
|
|
5397
|
+
);
|
|
5398
|
+
const hintedAnalysis = analyzeHostTree(
|
|
5399
|
+
keyedCollectionHintedRoot.root,
|
|
5400
|
+
reactiveByValue,
|
|
5401
|
+
safeGlobals,
|
|
5402
|
+
hintedBlockAnalysis.conditionalExpressions || /* @__PURE__ */ new Set(),
|
|
5403
|
+
hintedBlockAnalysis.keyedExpressions || /* @__PURE__ */ new Set(),
|
|
5404
|
+
hintedBlockAnalysis.ownedElements || /* @__PURE__ */ new Set(),
|
|
5405
|
+
hintedBlockAnalysis.componentElements || /* @__PURE__ */ new Set()
|
|
5406
|
+
);
|
|
5407
|
+
if (!hintedBlockAnalysis.reason && !hintedAnalysis.reason) {
|
|
5408
|
+
expandedReactiveRoot = keyedCollectionHintedRoot.root;
|
|
5409
|
+
blockAnalysis = hintedBlockAnalysis;
|
|
5410
|
+
analysis = hintedAnalysis;
|
|
5411
|
+
optimizationCounts.keyedCollectionUpdateHints += keyedCollectionHintedRoot.count;
|
|
5412
|
+
}
|
|
5413
|
+
}
|
|
3639
5414
|
const blockPlans = blockAnalysis.plans || [];
|
|
3640
|
-
|
|
5415
|
+
optimizationCounts.keyedIdentityTargets += blockPlans.reduce(
|
|
5416
|
+
(count, plan) => count + (plan.kind === "keyed-rows" ? plan.bindings.filter((binding) => binding.identityTarget !== void 0).length : 0),
|
|
5417
|
+
0
|
|
5418
|
+
);
|
|
5419
|
+
optimizationCounts.keyedMembershipTargets += blockPlans.reduce(
|
|
5420
|
+
(count, plan) => count + (plan.kind === "keyed-rows" ? plan.bindings.filter((binding) => binding.membershipTarget !== void 0).length : 0),
|
|
5421
|
+
0
|
|
5422
|
+
);
|
|
5423
|
+
optimizationCounts.keyedMapLookupTargets += blockPlans.reduce(
|
|
5424
|
+
(count, plan) => count + (plan.kind === "keyed-rows" ? plan.bindings.filter((binding) => binding.mapLookupTarget !== void 0).length : 0),
|
|
5425
|
+
0
|
|
5426
|
+
);
|
|
5427
|
+
const hasKeyedUpdateHints = appliedKeyedMapUpdateHints > 0 || appliedKeyedArrayAppendHints > 0 || appliedKeyedArrayFilterHints > 0 || appliedKeyedArrayPrependHints > 0 || appliedKeyedArrayPositionHints > 0 || appliedKeyedArrayReorderHints > 0 || appliedKeyedArraySortHints > 0 || appliedKeyedArrayRollingWindowHints > 0 || appliedKeyedArraySliceHints > 0;
|
|
5428
|
+
const hasKeyedArrayRemovalHints = appliedKeyedArrayFilterHints > 0 || appliedKeyedArrayRollingWindowHints > 0 || appliedKeyedArraySliceHints > 0;
|
|
5429
|
+
const runtimeFeatures = runtimeFeaturesForPlans(
|
|
5430
|
+
blockPlans,
|
|
5431
|
+
hasKeyedUpdateHints,
|
|
5432
|
+
hasKeyedArrayRemovalHints,
|
|
5433
|
+
appliedKeyedArrayPrependHints > 0,
|
|
5434
|
+
appliedKeyedArrayPositionHints > 0,
|
|
5435
|
+
appliedKeyedArrayReorderHints > 0 || appliedKeyedArraySortHints > 0,
|
|
5436
|
+
appliedKeyedArrayRollingWindowHints > 0
|
|
5437
|
+
);
|
|
3641
5438
|
markShortCircuitBindings(analysis.bindings || []);
|
|
3642
5439
|
assignStableBindingTargets(analysis.bindings || []);
|
|
3643
5440
|
const stateParameter = path.scope.generateUidIdentifier("farmState");
|
|
@@ -3650,11 +5447,21 @@ function compileCandidate(candidate, createComponentIdentifier, runtimeFeatureId
|
|
|
3650
5447
|
blockParameter,
|
|
3651
5448
|
blockAnalysis.ownedElements || /* @__PURE__ */ new Set()
|
|
3652
5449
|
);
|
|
5450
|
+
const appliedRemovalHintedStateIndices = /* @__PURE__ */ new Set([
|
|
5451
|
+
...appliedFilterHintedStateIndices,
|
|
5452
|
+
...appliedRollingWindowHintedStateIndices,
|
|
5453
|
+
...appliedSliceHintedStateIndices
|
|
5454
|
+
]);
|
|
3653
5455
|
const rootWithBlocks = lowerComposableBlocks(
|
|
3654
5456
|
rootWithTargets,
|
|
3655
5457
|
blockPlans,
|
|
3656
5458
|
blockParameter,
|
|
3657
|
-
listNames
|
|
5459
|
+
listNames,
|
|
5460
|
+
hasKeyedUpdateHints,
|
|
5461
|
+
appliedRemovalHintedStateIndices,
|
|
5462
|
+
appliedPrependHintedStateIndices,
|
|
5463
|
+
appliedPositionHintedStateIndices,
|
|
5464
|
+
/* @__PURE__ */ new Set([...appliedReorderHintedStateIndices, ...appliedSortHintedStateIndices])
|
|
3658
5465
|
);
|
|
3659
5466
|
const rewrittenRoot = rewriteStateAccess(
|
|
3660
5467
|
rootWithBlocks,
|
|
@@ -3792,6 +5599,21 @@ function collectCandidates(programPath) {
|
|
|
3792
5599
|
async function compileReactModule(code, id, options) {
|
|
3793
5600
|
const compiled = [];
|
|
3794
5601
|
const diagnostics = [];
|
|
5602
|
+
const optimizationCounts = {
|
|
5603
|
+
keyedArrayAppendHints: 0,
|
|
5604
|
+
keyedArrayFilterHints: 0,
|
|
5605
|
+
keyedArrayPrependHints: 0,
|
|
5606
|
+
keyedArrayPositionHints: 0,
|
|
5607
|
+
keyedArrayReorderHints: 0,
|
|
5608
|
+
keyedArraySortHints: 0,
|
|
5609
|
+
keyedArrayRollingWindowHints: 0,
|
|
5610
|
+
keyedArraySliceHints: 0,
|
|
5611
|
+
keyedCollectionUpdateHints: 0,
|
|
5612
|
+
keyedIdentityTargets: 0,
|
|
5613
|
+
keyedMapLookupTargets: 0,
|
|
5614
|
+
keyedMembershipTargets: 0,
|
|
5615
|
+
keyedMapUpdateHints: 0
|
|
5616
|
+
};
|
|
3795
5617
|
const plugin = () => ({
|
|
3796
5618
|
name: "farm-react-aot",
|
|
3797
5619
|
visitor: {
|
|
@@ -3821,6 +5643,39 @@ async function compileReactModule(code, id, options) {
|
|
|
3821
5643
|
}
|
|
3822
5644
|
const candidates = collectCandidates(programPath);
|
|
3823
5645
|
const createComponentIdentifier = programPath.scope.generateUidIdentifier("createCompiledComponent");
|
|
5646
|
+
const keyedMapUpdateIdentifier = programPath.scope.generateUidIdentifier(
|
|
5647
|
+
"createCompilerKeyedMapUpdate"
|
|
5648
|
+
);
|
|
5649
|
+
const keyedArrayAppendIdentifier = programPath.scope.generateUidIdentifier(
|
|
5650
|
+
"createCompilerKeyedArrayAppend"
|
|
5651
|
+
);
|
|
5652
|
+
const keyedArrayFilterIdentifier = programPath.scope.generateUidIdentifier(
|
|
5653
|
+
"createCompilerKeyedArrayFilter"
|
|
5654
|
+
);
|
|
5655
|
+
const keyedArrayPrependIdentifier = programPath.scope.generateUidIdentifier(
|
|
5656
|
+
"createCompilerKeyedArrayPrepend"
|
|
5657
|
+
);
|
|
5658
|
+
const keyedArrayPositionIdentifier = programPath.scope.generateUidIdentifier(
|
|
5659
|
+
"createCompilerKeyedArrayPositionUpdate"
|
|
5660
|
+
);
|
|
5661
|
+
const keyedArrayReorderIdentifier = programPath.scope.generateUidIdentifier(
|
|
5662
|
+
"createCompilerKeyedArrayReorder"
|
|
5663
|
+
);
|
|
5664
|
+
const keyedArraySortIdentifier = programPath.scope.generateUidIdentifier(
|
|
5665
|
+
"createCompilerKeyedArraySort"
|
|
5666
|
+
);
|
|
5667
|
+
const keyedArrayRollingWindowIdentifier = programPath.scope.generateUidIdentifier(
|
|
5668
|
+
"createCompilerKeyedArrayRollingWindow"
|
|
5669
|
+
);
|
|
5670
|
+
const keyedArraySliceIdentifier = programPath.scope.generateUidIdentifier(
|
|
5671
|
+
"createCompilerKeyedArraySlice"
|
|
5672
|
+
);
|
|
5673
|
+
const keyedCollectionUpdateIdentifier = programPath.scope.generateUidIdentifier(
|
|
5674
|
+
"createCompilerKeyedCollectionUpdate"
|
|
5675
|
+
);
|
|
5676
|
+
const keyedCollectionMutationIdentifier = programPath.scope.generateUidIdentifier(
|
|
5677
|
+
"applyCompilerKeyedCollectionMutation"
|
|
5678
|
+
);
|
|
3824
5679
|
const runtimeFeatureIdentifiers = new Map(
|
|
3825
5680
|
Object.entries(COMPILER_RUNTIME_FEATURE_EXPORTS).map(([feature, exportName]) => [
|
|
3826
5681
|
feature,
|
|
@@ -3838,8 +5693,20 @@ async function compileReactModule(code, id, options) {
|
|
|
3838
5693
|
const reason = compileCandidate(
|
|
3839
5694
|
candidate,
|
|
3840
5695
|
createComponentIdentifier,
|
|
5696
|
+
keyedMapUpdateIdentifier,
|
|
5697
|
+
keyedArrayAppendIdentifier,
|
|
5698
|
+
keyedArrayFilterIdentifier,
|
|
5699
|
+
keyedArrayPrependIdentifier,
|
|
5700
|
+
keyedArrayPositionIdentifier,
|
|
5701
|
+
keyedArrayReorderIdentifier,
|
|
5702
|
+
keyedArraySortIdentifier,
|
|
5703
|
+
keyedArrayRollingWindowIdentifier,
|
|
5704
|
+
keyedArraySliceIdentifier,
|
|
5705
|
+
keyedCollectionUpdateIdentifier,
|
|
5706
|
+
keyedCollectionMutationIdentifier,
|
|
3841
5707
|
runtimeFeatureIdentifiers,
|
|
3842
5708
|
usedRuntimeFeatures,
|
|
5709
|
+
optimizationCounts,
|
|
3843
5710
|
useStateNames,
|
|
3844
5711
|
reactNames,
|
|
3845
5712
|
listNames,
|
|
@@ -3865,6 +5732,70 @@ async function compileReactModule(code, id, options) {
|
|
|
3865
5732
|
createComponentIdentifier,
|
|
3866
5733
|
core.types.identifier("createCompiledComponentWithFeatures")
|
|
3867
5734
|
),
|
|
5735
|
+
...optimizationCounts.keyedMapUpdateHints > 0 ? [
|
|
5736
|
+
core.types.importSpecifier(
|
|
5737
|
+
keyedMapUpdateIdentifier,
|
|
5738
|
+
core.types.identifier("createCompilerKeyedMapUpdate")
|
|
5739
|
+
)
|
|
5740
|
+
] : [],
|
|
5741
|
+
...optimizationCounts.keyedArrayAppendHints > 0 ? [
|
|
5742
|
+
core.types.importSpecifier(
|
|
5743
|
+
keyedArrayAppendIdentifier,
|
|
5744
|
+
core.types.identifier("createCompilerKeyedArrayAppend")
|
|
5745
|
+
)
|
|
5746
|
+
] : [],
|
|
5747
|
+
...optimizationCounts.keyedArrayFilterHints > 0 ? [
|
|
5748
|
+
core.types.importSpecifier(
|
|
5749
|
+
keyedArrayFilterIdentifier,
|
|
5750
|
+
core.types.identifier("createCompilerKeyedArrayFilter")
|
|
5751
|
+
)
|
|
5752
|
+
] : [],
|
|
5753
|
+
...optimizationCounts.keyedArrayPrependHints > 0 ? [
|
|
5754
|
+
core.types.importSpecifier(
|
|
5755
|
+
keyedArrayPrependIdentifier,
|
|
5756
|
+
core.types.identifier("createCompilerKeyedArrayPrepend")
|
|
5757
|
+
)
|
|
5758
|
+
] : [],
|
|
5759
|
+
...optimizationCounts.keyedArrayPositionHints > 0 ? [
|
|
5760
|
+
core.types.importSpecifier(
|
|
5761
|
+
keyedArrayPositionIdentifier,
|
|
5762
|
+
core.types.identifier("createCompilerKeyedArrayPositionUpdate")
|
|
5763
|
+
)
|
|
5764
|
+
] : [],
|
|
5765
|
+
...optimizationCounts.keyedArrayReorderHints > 0 ? [
|
|
5766
|
+
core.types.importSpecifier(
|
|
5767
|
+
keyedArrayReorderIdentifier,
|
|
5768
|
+
core.types.identifier("createCompilerKeyedArrayReorder")
|
|
5769
|
+
)
|
|
5770
|
+
] : [],
|
|
5771
|
+
...optimizationCounts.keyedArraySortHints > 0 ? [
|
|
5772
|
+
core.types.importSpecifier(
|
|
5773
|
+
keyedArraySortIdentifier,
|
|
5774
|
+
core.types.identifier("createCompilerKeyedArraySort")
|
|
5775
|
+
)
|
|
5776
|
+
] : [],
|
|
5777
|
+
...optimizationCounts.keyedArrayRollingWindowHints > 0 ? [
|
|
5778
|
+
core.types.importSpecifier(
|
|
5779
|
+
keyedArrayRollingWindowIdentifier,
|
|
5780
|
+
core.types.identifier("createCompilerKeyedArrayRollingWindow")
|
|
5781
|
+
)
|
|
5782
|
+
] : [],
|
|
5783
|
+
...optimizationCounts.keyedArraySliceHints > 0 || optimizationCounts.keyedArrayRollingWindowHints > 0 ? [
|
|
5784
|
+
core.types.importSpecifier(
|
|
5785
|
+
keyedArraySliceIdentifier,
|
|
5786
|
+
core.types.identifier("createCompilerKeyedArraySlice")
|
|
5787
|
+
)
|
|
5788
|
+
] : [],
|
|
5789
|
+
...optimizationCounts.keyedCollectionUpdateHints > 0 ? [
|
|
5790
|
+
core.types.importSpecifier(
|
|
5791
|
+
keyedCollectionUpdateIdentifier,
|
|
5792
|
+
core.types.identifier("createCompilerKeyedCollectionUpdate")
|
|
5793
|
+
),
|
|
5794
|
+
core.types.importSpecifier(
|
|
5795
|
+
keyedCollectionMutationIdentifier,
|
|
5796
|
+
core.types.identifier("applyCompilerKeyedCollectionMutation")
|
|
5797
|
+
)
|
|
5798
|
+
] : [],
|
|
3868
5799
|
...[...usedRuntimeFeatures].sort().map(
|
|
3869
5800
|
(feature) => core.types.importSpecifier(
|
|
3870
5801
|
core.types.cloneNode(runtimeFeatureIdentifiers.get(feature)),
|
|
@@ -3901,7 +5832,8 @@ async function compileReactModule(code, id, options) {
|
|
|
3901
5832
|
code: result?.code || code,
|
|
3902
5833
|
map: result?.map || null,
|
|
3903
5834
|
compiled,
|
|
3904
|
-
diagnostics
|
|
5835
|
+
diagnostics,
|
|
5836
|
+
optimizations: optimizationCounts
|
|
3905
5837
|
};
|
|
3906
5838
|
}
|
|
3907
5839
|
function projectRelativeId(projectRoot, id) {
|
|
@@ -3912,10 +5844,36 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3912
5844
|
let componentsConsidered = 0;
|
|
3913
5845
|
let compiled = 0;
|
|
3914
5846
|
let fallback = 0;
|
|
5847
|
+
let keyedArrayAppendHints = 0;
|
|
5848
|
+
let keyedArrayFilterHints = 0;
|
|
5849
|
+
let keyedArrayPrependHints = 0;
|
|
5850
|
+
let keyedArrayPositionHints = 0;
|
|
5851
|
+
let keyedArrayReorderHints = 0;
|
|
5852
|
+
let keyedArraySortHints = 0;
|
|
5853
|
+
let keyedArrayRollingWindowHints = 0;
|
|
5854
|
+
let keyedArraySliceHints = 0;
|
|
5855
|
+
let keyedCollectionUpdateHints = 0;
|
|
5856
|
+
let keyedIdentityTargets = 0;
|
|
5857
|
+
let keyedMapLookupTargets = 0;
|
|
5858
|
+
let keyedMembershipTargets = 0;
|
|
5859
|
+
let keyedMapUpdateHints = 0;
|
|
3915
5860
|
const modules = [...observations].map(({ id, result }) => {
|
|
3916
5861
|
componentsConsidered += result.compiled.length + result.diagnostics.length;
|
|
3917
5862
|
compiled += result.compiled.length;
|
|
3918
5863
|
fallback += result.diagnostics.length;
|
|
5864
|
+
keyedArrayAppendHints += result.optimizations.keyedArrayAppendHints || 0;
|
|
5865
|
+
keyedArrayFilterHints += result.optimizations.keyedArrayFilterHints || 0;
|
|
5866
|
+
keyedArrayPrependHints += result.optimizations.keyedArrayPrependHints || 0;
|
|
5867
|
+
keyedArrayPositionHints += result.optimizations.keyedArrayPositionHints || 0;
|
|
5868
|
+
keyedArrayReorderHints += result.optimizations.keyedArrayReorderHints || 0;
|
|
5869
|
+
keyedArraySortHints += result.optimizations.keyedArraySortHints || 0;
|
|
5870
|
+
keyedArrayRollingWindowHints += result.optimizations.keyedArrayRollingWindowHints || 0;
|
|
5871
|
+
keyedArraySliceHints += result.optimizations.keyedArraySliceHints || 0;
|
|
5872
|
+
keyedCollectionUpdateHints += result.optimizations.keyedCollectionUpdateHints || 0;
|
|
5873
|
+
keyedIdentityTargets += result.optimizations.keyedIdentityTargets || 0;
|
|
5874
|
+
keyedMapLookupTargets += result.optimizations.keyedMapLookupTargets || 0;
|
|
5875
|
+
keyedMembershipTargets += result.optimizations.keyedMembershipTargets || 0;
|
|
5876
|
+
keyedMapUpdateHints += result.optimizations.keyedMapUpdateHints;
|
|
3919
5877
|
const moduleId = projectRelativeId(projectRoot, id);
|
|
3920
5878
|
const fallbacks = result.diagnostics.map((diagnostic) => {
|
|
3921
5879
|
reasonCounts.set(diagnostic.reason, (reasonCounts.get(diagnostic.reason) || 0) + 1);
|
|
@@ -3924,6 +5882,7 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3924
5882
|
return {
|
|
3925
5883
|
id: moduleId,
|
|
3926
5884
|
compiled: [...result.compiled].sort(),
|
|
5885
|
+
optimizations: result.optimizations,
|
|
3927
5886
|
fallbacks
|
|
3928
5887
|
};
|
|
3929
5888
|
}).sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -3934,7 +5893,20 @@ function createReactCompilerReport(projectRoot, observations) {
|
|
|
3934
5893
|
modules: modules.length,
|
|
3935
5894
|
componentsConsidered,
|
|
3936
5895
|
compiled,
|
|
3937
|
-
fallback
|
|
5896
|
+
fallback,
|
|
5897
|
+
keyedArrayAppendHints,
|
|
5898
|
+
keyedArrayFilterHints,
|
|
5899
|
+
keyedArrayPrependHints,
|
|
5900
|
+
keyedArrayPositionHints,
|
|
5901
|
+
keyedArrayReorderHints,
|
|
5902
|
+
keyedArraySortHints,
|
|
5903
|
+
keyedArrayRollingWindowHints,
|
|
5904
|
+
keyedArraySliceHints,
|
|
5905
|
+
keyedCollectionUpdateHints,
|
|
5906
|
+
keyedIdentityTargets,
|
|
5907
|
+
keyedMapLookupTargets,
|
|
5908
|
+
keyedMembershipTargets,
|
|
5909
|
+
keyedMapUpdateHints
|
|
3938
5910
|
},
|
|
3939
5911
|
fallbackReasons,
|
|
3940
5912
|
modules
|