8
import { CompilerError } from "..";
9
import {
10
Effect,
11
+ FunctionExpression,
12
HIRFunction,
13
IdentifierId,
14
Instruction,
15
Place,
16
SpreadPattern,
17
makeInstructionId,
17
- markInstructionIds,
18
} from "../HIR";
19
import { createTemporaryPlace } from "../HIR/HIRBuilder";
20
import { HookKind } from "../HIR/ObjectShape";
21
+import { eachInstructionValueOperand } from "../HIR/visitors";
22
23
/*
24
* Removes manual memoization using the `useMemo` and `useCallback` APIs. This pass is designed
29
* eg `React.useMemo()`.
30
*/
31
export function dropManualMemoization(func: HIRFunction): void {
32
+ const functions = new Map<IdentifierId, FunctionExpression>();
33
const hooks = new Map<IdentifierId, HookKind>();
34
const react = new Set<IdentifierId>();
35
let hasChanges = false;
37
let nextInstructions: Array<Instruction> | null = null;
38
for (let i = 0; i < block.instructions.length; i++) {
39
const instr = block.instructions[i]!;
38
- if (nextInstructions !== null) {
39
- nextInstructions.push(instr);
40
- }
40
switch (instr.value.kind) {
41
+ case "FunctionExpression": {
42
+ functions.set(instr.lvalue.identifier.id, instr.value);
43
+ break;
44
+ }
45
case "LoadGlobal": {
46
if (
47
instr.value.name === "useMemo" ||
112
args: [],
113
loc: instr.value.loc,
114
};
115
+
116
if (
117
func.env.config.enablePreserveExistingMemoizationGuarantees
118
) {
141
const temp = createTemporaryPlace(func.env);
142
instr.lvalue = { ...temp };
143
nextInstructions =
140
- nextInstructions ?? block.instructions.slice(0, i + 1);
144
+ nextInstructions ?? block.instructions.slice(0, i);
145
+
146
+ const functionExpression = functions.get(fn.identifier.id);
147
+ if (functionExpression !== undefined) {
148
+ for (const operand of eachInstructionValueOperand(
149
+ functionExpression
150
+ )) {
151
+ const operandLValue = createTemporaryPlace(func.env);
152
+ nextInstructions.push({
153
+ id: makeInstructionId(0),
154
+ lvalue: operandLValue,
155
+ value: {
156
+ kind: "Memoize",
157
+ value: { ...operand },
158
+ loc: instr.loc,
159
+ },
160
+ loc: instr.loc,
161
+ });
162
+ }
163
+ }
164
+
165
+ nextInstructions.push(instr);
166
+
167
nextInstructions.push({
168
id: makeInstructionId(0),
169
lvalue,
174
},
175
loc: instr.loc,
176
});
177
+ } else {
178
+ if (nextInstructions !== null) {
179
+ nextInstructions.push(instr);
180
+ }
181
}
182
+ continue;
183
}
184
} else if (hookKind === "useCallback") {
185
const [fn] = instr.value.args as Array<
260
break;
261
}
262
}
263
+ if (nextInstructions !== null) {
264
+ nextInstructions.push(instr);
265
+ }
266
}
267
if (nextInstructions !== null) {
268
block.instructions = nextInstructions;
270
}
271
}
272
if (hasChanges) {
239
- markInstructionIds(func.body);
273
+ // markInstructionIds(func.body);
274
}
275
}