Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -433,64 +433,74 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
* recursively visits ReactiveValues and instructions
*/
this.recordTemporaries(instruction, state);
if (instruction.value.kind === 'StartMemoize') {
const value = instruction.value;
if (value.kind === 'StartMemoize') {
let depsFromSource: Array<ManualMemoDependency> | null = null;
if (instruction.value.deps != null) {
depsFromSource = instruction.value.deps;
if (value.deps != null) {
depsFromSource = value.deps;
}
CompilerError.invariant(state.manualMemoState == null, {
reason: 'Unexpected nested StartMemoize instructions',
description: `Bad manual memoization ids: ${state.manualMemoState?.manualMemoId}, ${instruction.value.manualMemoId}`,
loc: instruction.value.loc,
description: `Bad manual memoization ids: ${state.manualMemoState?.manualMemoId}, ${value.manualMemoId}`,
loc: value.loc,
suggestions: null,
});

state.manualMemoState = {
loc: instruction.loc,
decls: new Set(),
depsFromSource,
manualMemoId: instruction.value.manualMemoId,
manualMemoId: value.manualMemoId,
};
}
if (instruction.value.kind === 'FinishMemoize') {
CompilerError.invariant(
state.manualMemoState != null &&
state.manualMemoState.manualMemoId === instruction.value.manualMemoId,
{
reason: 'Unexpected mismatch between StartMemoize and FinishMemoize',
description: `Encountered StartMemoize id=${state.manualMemoState?.manualMemoId} followed by FinishMemoize id=${instruction.value.manualMemoId}`,
loc: instruction.value.loc,
suggestions: null,
},
);
state.manualMemoState = null;
}

const isDep = instruction.value.kind === 'StartMemoize';
const isDecl =
instruction.value.kind === 'FinishMemoize' && !instruction.value.pruned;
if (isDep || isDecl) {
for (const value of eachInstructionValueOperand(
instruction.value as InstructionValue,
for (const {identifier, loc} of eachInstructionValueOperand(
value as InstructionValue,
)) {
if (
(isDep &&
value.identifier.scope != null &&
!this.scopes.has(value.identifier.scope.id) &&
!this.prunedScopes.has(value.identifier.scope.id)) ||
(isDecl && isUnmemoized(value.identifier, this.scopes))
identifier.scope != null &&
!this.scopes.has(identifier.scope.id) &&
!this.prunedScopes.has(identifier.scope.id)
) {
state.errors.push({
reason:
'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly',
'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly',
description: null,
severity: ErrorSeverity.CannotPreserveMemoization,
loc: typeof instruction.loc !== 'symbol' ? instruction.loc : null,
loc,
suggestions: null,
});
}
}
}
if (value.kind === 'FinishMemoize') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: else if

CompilerError.invariant(
state.manualMemoState != null &&
state.manualMemoState.manualMemoId === value.manualMemoId,
{
reason: 'Unexpected mismatch between StartMemoize and FinishMemoize',
description: `Encountered StartMemoize id=${state.manualMemoState?.manualMemoId} followed by FinishMemoize id=${value.manualMemoId}`,
loc: value.loc,
suggestions: null,
},
);
state.manualMemoState = null;
if (!value.pruned) {
for (const {identifier, loc} of eachInstructionValueOperand(
value as InstructionValue,
)) {
if (isUnmemoized(identifier, this.scopes)) {
state.errors.push({
reason:
'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output.',
description: null,
severity: ErrorSeverity.CannotPreserveMemoization,
loc,
suggestions: null,
});
}
}
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const FIXTURE_ENTRYPOINT = {
9 | const a = useHook();
10 | // Because b is also part of that same mutable range, it can't be memoized either
> 11 | const b = useMemo(() => ({}), []);
| ^^^^^^^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (11:11)
| ^^^^^^^^^^^^^^^^^^^^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. (11:11)
12 |
13 | // Conditional assignment without a subsequent mutation normally doesn't create a mutable
14 | // range, but in this case we're reassigning a context variable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const FIXTURE_ENTRYPOINT = {
> 10 | ref.current.inner = event.target.value;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 11 | });
| ^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (7:11)
| ^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. (7:11)
12 |
13 | // The ref is modified later, extending its range and preventing memoization of onChange
14 | const reset = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const FIXTURE_ENTRYPOINT = {
> 10 | ref.current.inner = event.target.value;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 11 | });
| ^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (7:11)
| ^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. (7:11)
12 |
13 | // The ref is modified later, extending its range and preventing memoization of onChange
14 | ref.current.inner = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,10 @@ export const FIXTURE_ENTRYPOINT = {
## Error

```
10 | const val = [1, 2, 3];
11 |
> 12 | return useMemo(() => {
| ^^^^^^^
> 13 | return identity(val);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
12 | return useMemo(() => {
13 | return identity(val);
> 14 | }, [val]);
| ^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (12:14)
| ^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly (14:14)
15 | }
16 |
17 | export const FIXTURE_ENTRYPOINT = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ export const FIXTURE_ENTRYPOINT = {
10 |
11 | // makeArray() is captured, but depsList contains [props]
> 12 | const cb = useCallback(() => [x], [x]);
| ^^^^^^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (12:12)
| ^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly (12:12)

CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (12:12)
CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. (12:12)
13 |
14 | x = makeArray();
15 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const FIXTURE_ENTRYPOINT = {
11 | x.push(props);
12 |
> 13 | return useCallback(() => [x], [x]);
| ^^^^^^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value may be mutated later, which could cause the value to change unexpectedly (13:13)
| ^^^^^^^^^ CannotPreserveMemoization: React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. (13:13)
14 | }
15 |
16 | export const FIXTURE_ENTRYPOINT = {
Expand Down